DSPHLE: Early implementation of volume. I'm sure there's something missing but this makes the Zelda games sound a lot better, except WW which loses a lot of audio on the title screen and link's noises are too soft.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3635 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
de83d1cda4
commit
5ca6d2761e
|
@ -264,6 +264,7 @@ void CUCode_Zelda::Update(int cycles)
|
|||
|
||||
void CUCode_Zelda::HandleMail(u32 _uMail)
|
||||
{
|
||||
// WARN_LOG(DSPHLE, "Zelda uCode: Handle mail %08X", _uMail);
|
||||
// When we used to lose sync, the last mails we get before the audio goes bye-bye
|
||||
// 0
|
||||
// 0x00000
|
||||
|
@ -640,7 +641,7 @@ void CUCode_Zelda::MixAdd(short* _Buffer, int _Size)
|
|||
if (pb.KeyOff != 0)
|
||||
continue;
|
||||
|
||||
MixAddVoice(pb, m_LeftBuffer, m_RightBuffer, _Size);
|
||||
RenderAddVoice(pb, m_LeftBuffer, m_RightBuffer, _Size);
|
||||
WritebackVoicePB(m_VoicePBsAddr + (i * 0x180), pb);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,9 +38,11 @@ struct ZeldaVoicePB
|
|||
u16 IsBlank; // 0x06 | 0 = normal sound, 1 = samples are always the same
|
||||
u16 Unk07; // 0x07 | unknown, in zelda always 0x0010
|
||||
u16 SoundType; // 0x08 | Sound type: so far in zww: 0x0d00 for music, 0x4861 for sfx
|
||||
u32 volumeRight; // 0x09 | Right Volume
|
||||
u16 volumeLeft1; // 0x09 | Left Volume 1 // There's probably two of each because they should be ramped within each frame.
|
||||
u16 volumeLeft2; // 0x0A | Left Volume 2
|
||||
u16 Unk0B[2]; // 0x0B | unknown
|
||||
u32 volumeLeft; // 0x0D | Left Volume
|
||||
u16 volumeRight1; // 0x0D | Right Volume 1
|
||||
u16 volumeRight2; // 0x0E | Right Volume 2
|
||||
u16 Unk0F[0x8]; // 0x0F | unknown // Buffer / something, see 036e/ZWW. there's a pattern here
|
||||
u16 Unk18[0x10]; // 0x18 | unknown
|
||||
u16 Unk28; // 0x28 | unknown
|
||||
|
@ -145,6 +147,7 @@ private:
|
|||
u32 m_CRC;
|
||||
|
||||
s32* m_TempBuffer;
|
||||
|
||||
s32* m_LeftBuffer;
|
||||
s32* m_RightBuffer;
|
||||
|
||||
|
@ -208,13 +211,14 @@ private:
|
|||
void ReadVoicePB(u32 _Addr, ZeldaVoicePB& PB);
|
||||
void WritebackVoicePB(u32 _Addr, ZeldaVoicePB& PB);
|
||||
|
||||
void MixAddVoice_PCM16(ZeldaVoicePB& PB, s32* _Buffer, int _Size);
|
||||
void MixAddVoice_AFC(ZeldaVoicePB& PB, s32* _Buffer, int _Size);
|
||||
void MixAddVoice(ZeldaVoicePB& PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size);
|
||||
// Voice formats
|
||||
void RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size);
|
||||
void RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size);
|
||||
void RenderVoice_PCM16(ZeldaVoicePB& PB, s32* _Buffer, int _Size);
|
||||
void RenderVoice_AFC(ZeldaVoicePB& PB, s32* _Buffer, int _Size);
|
||||
|
||||
|
||||
void MixAddSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size);
|
||||
void MixAddSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size);
|
||||
// Renders a voice and mixes it into LeftBuffer, RightBuffer
|
||||
void RenderAddVoice(ZeldaVoicePB& PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "../Globals.h"
|
||||
#include "UCodes.h"
|
||||
#include "UCode_Zelda.h"
|
||||
#include "UCode_Zelda_ADPCM.h"
|
||||
|
||||
#include "../main.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
void CUCode_Zelda::MixAddSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
{
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "../Globals.h"
|
||||
#include "UCodes.h"
|
||||
#include "UCode_Zelda.h"
|
||||
#include "UCode_Zelda_ADPCM.h"
|
||||
|
||||
#include "../main.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
void CUCode_Zelda::RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
{
|
||||
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
||||
u32 _ratio = (((PB.RatioInt * 80) + PB.RatioFrac) << 4) & 0xFFFF0000;
|
||||
u64 ratio = (u64)(((_ratio / 80) << 16) * ratioFactor);
|
||||
int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1;
|
||||
|
||||
u64 ratio = (u64)(((_ratio / 80) << 16) * ratioFactor);
|
||||
int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1;
|
||||
|
||||
u32 pos[2] = {0, 0};
|
||||
int i = 0;
|
||||
|
||||
|
@ -87,16 +87,16 @@ _lRestart:
|
|||
PB.RemLength -= pos[1];
|
||||
|
||||
PB.CurAddr += pos[1] << 1;
|
||||
// There should be a position fraction as well.
|
||||
}
|
||||
|
||||
|
||||
void CUCode_Zelda::MixAddSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
{
|
||||
// TODO: Header, footer and cases this synth actually happens
|
||||
for (int i = 0; i < _Size; i++)
|
||||
_Buffer[i++] = (s32)PB.RatioInt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// There should be a position fraction as well.
|
||||
}
|
||||
|
||||
|
||||
void CUCode_Zelda::RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
{
|
||||
// TODO: Header, footer and cases this synth actually happens
|
||||
for (int i = 0; i < _Size; i++)
|
||||
_Buffer[i++] = (s32)PB.RatioInt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ void CUCode_Zelda::WritebackVoicePB(u32 _Addr, ZeldaVoicePB& PB)
|
|||
memory[i] = Common::swap16(((u16*)&PB)[i]);
|
||||
}
|
||||
|
||||
void CUCode_Zelda::MixAddVoice_PCM16(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
void CUCode_Zelda::RenderVoice_PCM16(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
{
|
||||
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
||||
u32 _ratio = (((PB.RatioInt * 80) + PB.RatioFrac) << 4) & 0xFFFF0000;
|
||||
|
@ -126,7 +126,7 @@ _lRestart:
|
|||
// There should be a position fraction as well.
|
||||
}
|
||||
|
||||
void CUCode_Zelda::MixAddVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
void CUCode_Zelda::RenderVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||
{
|
||||
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
||||
u32 _ratio = (PB.RatioInt<<16) + PB.RatioFrac;
|
||||
|
@ -151,6 +151,25 @@ void CUCode_Zelda::MixAddVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
|||
// Copy ARAM addr from r to rw area.
|
||||
PB.CurAddr = PB.StartAddr;
|
||||
PB.ReachedEnd = 0;
|
||||
|
||||
// Looking at Zelda Four Swords
|
||||
// WARN_LOG(DSPHLE, "PB -----: %04x", PB.Unk03);
|
||||
// WARN_LOG(DSPHLE, "PB Unk03: %04x", PB.Unk03); 0
|
||||
// WARN_LOG(DSPHLE, "PB Unk07: %04x", PB.Unk07[0]); 0
|
||||
|
||||
//WARN_LOG(DSPHLE, "PB Unk09: %04x", PB.volumeLeft1); // often same value as 0a
|
||||
//WARN_LOG(DSPHLE, "PB Unk0a: %04x", PB.volumeLeft2);
|
||||
|
||||
//WARN_LOG(DSPHLE, "PB Unk0d: %04x", PB.volumeRight1); // often same value as 0e
|
||||
//WARN_LOG(DSPHLE, "PB Unk0e: %04x", PB.volumeRight2);
|
||||
|
||||
/// WARN_LOG(DSPHLE, "PB Unk78: %04x", PB.Unk78);
|
||||
// WARN_LOG(DSPHLE, "PB Unk79: %04x", PB.Unk79);
|
||||
// WARN_LOG(DSPHLE, "PB Unk31: %04x", PB.Unk31);
|
||||
// WARN_LOG(DSPHLE, "PB Unk36: %04x", PB.Unk36[0]);
|
||||
// WARN_LOG(DSPHLE, "PB Unk37: %04x", PB.Unk36[1]);
|
||||
// WARN_LOG(DSPHLE, "PB Unk3c: %04x", PB.Unk3C[0]);
|
||||
// WARN_LOG(DSPHLE, "PB Unk3d: %04x", PB.Unk3C[1]);
|
||||
}
|
||||
|
||||
if (PB.KeyOff != 0) // 0747 early out... i dunno if this can happen because we filter it above
|
||||
|
@ -160,8 +179,6 @@ void CUCode_Zelda::MixAddVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
|||
// u32 frac = NumberOfSamples & 0xF;
|
||||
// NumberOfSamples = (NumberOfSamples + 0xf) >> 4; // i think the lower 4 are the fraction
|
||||
|
||||
u32 sampleCount = 0;
|
||||
|
||||
u8 *source;
|
||||
u32 ram_mask = 1024 * 1024 * 16 - 1;
|
||||
if (m_CRC == 0xD643001F) {
|
||||
|
@ -171,13 +188,6 @@ void CUCode_Zelda::MixAddVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
|||
else
|
||||
source = g_dspInitialize.pGetARAMPointer();
|
||||
|
||||
// It must be something like this:
|
||||
|
||||
// The PB contains a small sample buffer of 0x4D decoded samples.
|
||||
// If it's empty or "used", decode to it.
|
||||
// Then, resample from this buffer to the output as you go. When it needs
|
||||
// wrapping, decode more.
|
||||
|
||||
restart:
|
||||
if (PB.ReachedEnd)
|
||||
{
|
||||
|
@ -196,7 +206,7 @@ restart:
|
|||
// This needs adjustment. It's not right for AFC, was just copied from PCM16.
|
||||
// We should also probably reinitialize YN1 and YN2 with something - but with what?
|
||||
PB.RestartPos = PB.LoopStartPos;
|
||||
PB.RemLength = PB.Length - PB.RestartPos;
|
||||
PB.RemLength = PB.Length - PB.RestartPos;
|
||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
||||
// pos[1] = 0; pos[0] = 0;
|
||||
}
|
||||
|
@ -209,11 +219,12 @@ restart:
|
|||
u32 prev_addr = PB.CurAddr;
|
||||
|
||||
// Prefill the decode buffer.
|
||||
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, 9);
|
||||
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
|
||||
PB.CurAddr += 9;
|
||||
|
||||
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 32;
|
||||
s64 delta = ratio; // 0x100000000ULL;
|
||||
int sampleCount = 0;
|
||||
while (sampleCount < _Size)
|
||||
{
|
||||
int SamplePosition = TrueSamplePosition >> 32;
|
||||
|
@ -241,7 +252,7 @@ restart:
|
|||
prev_yn2 = PB.YN2;
|
||||
prev_addr = PB.CurAddr;
|
||||
|
||||
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, 9);
|
||||
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
|
||||
PB.CurAddr += 9;
|
||||
}
|
||||
}
|
||||
|
@ -267,7 +278,7 @@ restart:
|
|||
// end of block (Zelda 03b2)
|
||||
}
|
||||
|
||||
void CUCode_Zelda::MixAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size)
|
||||
void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size)
|
||||
{
|
||||
memset(m_TempBuffer, 0, _Size * sizeof(s32));
|
||||
|
||||
|
@ -285,12 +296,12 @@ void CUCode_Zelda::MixAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBu
|
|||
case 0x0000: // Example: Magic meter filling up in ZWW
|
||||
case 0x0001: // Example: "Denied" sound when trying to pull out a sword
|
||||
// indoors in ZWW
|
||||
MixAddSynth_Waveform(PB, m_TempBuffer, _Size);
|
||||
RenderSynth_Waveform(PB, m_TempBuffer, _Size);
|
||||
break;
|
||||
|
||||
case 0x0006:
|
||||
WARN_LOG(DSPHLE, "Synthesizing 0x0006 (constant sound)");
|
||||
MixAddSynth_Constant(PB, m_TempBuffer, _Size);
|
||||
RenderSynth_Constant(PB, m_TempBuffer, _Size);
|
||||
break;
|
||||
|
||||
// These are more "synth" formats - square wave, saw wave etc.
|
||||
|
@ -308,11 +319,11 @@ void CUCode_Zelda::MixAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBu
|
|||
//if(PB.SoundType == 0x0d00)
|
||||
// break;
|
||||
|
||||
MixAddVoice_AFC(PB, m_TempBuffer, _Size);
|
||||
RenderVoice_AFC(PB, m_TempBuffer, _Size);
|
||||
break;
|
||||
|
||||
case 0x0010: // PCM16 - normal PCM 16-bit audio.
|
||||
MixAddVoice_PCM16(PB, m_TempBuffer, _Size);
|
||||
RenderVoice_PCM16(PB, m_TempBuffer, _Size);
|
||||
break;
|
||||
|
||||
|
||||
|
@ -334,8 +345,13 @@ void CUCode_Zelda::MixAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBu
|
|||
|
||||
for (int i = 0; i < _Size; i++)
|
||||
{
|
||||
s32 left = _LeftBuffer[i] + m_TempBuffer[i];
|
||||
s32 right = _RightBuffer[i] + m_TempBuffer[i];
|
||||
// TODO: Some noises in Zelda WW (birds, etc) have a volume of 0
|
||||
// Really not sure about the masking here, but it seems to kill off some overly loud
|
||||
// sounds in Zelda TP. Needs investigation.
|
||||
s32 left = _LeftBuffer[i] + (m_TempBuffer[i] * (float)(
|
||||
(PB.volumeLeft1 & 0x1FFF) + (PB.volumeLeft2 & 0x1FFF)) * 0.00005);
|
||||
s32 right = _RightBuffer[i] + (m_TempBuffer[i] * (float)(
|
||||
(PB.volumeRight1 & 0x1FFF) + (PB.volumeRight2 & 0x1FFF)) * 0.00005);
|
||||
|
||||
if (left < -32768) left = -32768;
|
||||
if (left > 32767) left = 32767;
|
||||
|
|
|
@ -32,12 +32,15 @@ IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler)
|
|||
switch (_CRC)
|
||||
{
|
||||
case UCODE_ROM:
|
||||
INFO_LOG(DSPHLE, "Switching to ROM ucode");
|
||||
return new CUCode_Rom(_rMailHandler);
|
||||
|
||||
case UCODE_INIT_AUDIO_SYSTEM:
|
||||
INFO_LOG(DSPHLE, "Switching to INIT ucode");
|
||||
return new CUCode_InitAudioSystem(_rMailHandler);
|
||||
|
||||
case 0x65d6cc6f: // CARD
|
||||
INFO_LOG(DSPHLE, "Switching to CARD ucode");
|
||||
return new CUCode_CARD(_rMailHandler);
|
||||
|
||||
case 0x3ad3b7ac: // Naruto3, Paper Mario - The Thousand Year Door
|
||||
|
@ -49,28 +52,29 @@ IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler)
|
|||
case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2,
|
||||
// Zelda:OOT, Tony hawk, viewtiful joe
|
||||
case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080
|
||||
INFO_LOG(CONSOLE, "AX ucode chosen, yay!\n");
|
||||
INFO_LOG(DSPHLE, "CRC %08x: AX ucode chosen", _CRC);
|
||||
return new CUCode_AX(_rMailHandler);
|
||||
|
||||
case 0x088e38a5: // IPL - JAP
|
||||
case 0xd73338cf: // IPL
|
||||
case 0x42f64ac4: // Luigi
|
||||
case 0x0267d05a: // http://forums.dolphin-emu.com/thread-2134.html Pikmin PAL
|
||||
case 0x4be6a5cb: // AC, Pikmin
|
||||
INFO_LOG(CONSOLE, "JAC (early Zelda) ucode chosen\n");
|
||||
INFO_LOG(DSPHLE, "CRC %08x: JAC (early Zelda) ucode chosen", _CRC);
|
||||
return new CUCode_Jac(_rMailHandler);
|
||||
// return new CUCode_Zelda(_rMailHandler, false);
|
||||
// return new CUCode_Zelda(_rMailHandler, _CRC);
|
||||
|
||||
case 0x6CA33A6D: // DK Jungle Beat
|
||||
case 0x86840740: // Zelda WW - US
|
||||
case 0x56d36052: // Mario Sunshine
|
||||
case 0x2fcdf1ec: // Mario Kart, zelda 4 swords
|
||||
INFO_LOG(CONSOLE, "Zelda ucode chosen\n");
|
||||
INFO_LOG(DSPHLE, "CRC %08x: Zelda ucode chosen", _CRC);
|
||||
return new CUCode_Zelda(_rMailHandler, _CRC);
|
||||
|
||||
// WII CRCs
|
||||
case 0x6c3f6f94: // zelda - PAL
|
||||
case 0xd643001f: // mario galaxy - PAL
|
||||
INFO_LOG(CONSOLE, "Zelda Wii ucode chosen\n");
|
||||
INFO_LOG(DSPHLE, "CRC %08x: Zelda Wii ucode chosen\n", _CRC);
|
||||
return new CUCode_Zelda(_rMailHandler, _CRC);
|
||||
|
||||
case 0x5ef56da3: // AX demo
|
||||
|
@ -80,7 +84,7 @@ IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler)
|
|||
case 0xb7eb9a9c: // Wii Pikmin - JAP
|
||||
case 0x4cc52064: // Bleach: Versus Crusade
|
||||
case 0xd9c4bf34: // WiiMenu ... pray
|
||||
INFO_LOG(CONSOLE, "Wii - AXWii chosen\n");
|
||||
INFO_LOG(DSPHLE, "CRC %08x: Wii - AXWii chosen", _CRC);
|
||||
return new CUCode_AXWii(_rMailHandler, _CRC);
|
||||
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue