Fix AUX volume mixing in AXWii: implement volume ramping and MixAdd properly. Home menu sounds now work properly.

This commit is contained in:
Pierre Bourdon 2013-03-29 22:22:24 +01:00
parent ef501137be
commit 4b09f525f6
2 changed files with 29 additions and 3 deletions

View File

@ -29,7 +29,8 @@
CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 l_CRC) CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 l_CRC)
: CUCode_AX(dsp_hle, l_CRC) : CUCode_AX(dsp_hle, l_CRC),
m_last_aux_volume(0x8000)
{ {
WARN_LOG(DSPHLE, "Instantiating CUCode_AXWii"); WARN_LOG(DSPHLE, "Instantiating CUCode_AXWii");
} }
@ -269,6 +270,22 @@ void CUCode_AXWii::ProcessPBList(u32 pb_addr)
void CUCode_AXWii::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr, u16 volume) void CUCode_AXWii::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr, u16 volume)
{ {
u16 prev_volume = m_last_aux_volume;
// Generate a volume ramp going from prev_volume to volume.
//
// The AXWii UCode uses integer arithmetic with 2 multipliers because it
// can't get enough precision to represent 1 / 96. We can use floating
// point arithmetic, so we will - it makes the code more readable and more
// precise.
u16 volume_ramp[96];
float curr_volume = prev_volume;
for (int i = 0; i < 96; ++i)
{
volume_ramp[i] = (u16)curr_volume;
curr_volume += (volume - prev_volume) / 96.0;
}
int* buffers[3] = { 0 }; int* buffers[3] = { 0 };
int* main_buffers[3] = { int* main_buffers[3] = {
m_samples_left, m_samples_left,
@ -311,9 +328,12 @@ void CUCode_AXWii::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr, u16
for (u32 i = 0; i < 3; ++i) for (u32 i = 0; i < 3; ++i)
for (u32 j = 0; j < 3 * 32; ++j) for (u32 j = 0; j < 3 * 32; ++j)
{ {
s64 new_val = main_buffers[i][j] + Common::swap32(*ptr++); s64 sample = (s64)(s32)Common::swap32(*ptr++);
main_buffers[i][j] = (new_val * volume) >> 15; sample *= volume_ramp[j];
main_buffers[i][j] += (s32)(sample >> 15);
} }
m_last_aux_volume = volume;
} }
void CUCode_AXWii::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume) void CUCode_AXWii::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume)
@ -397,4 +417,6 @@ void CUCode_AXWii::DoState(PointerWrap &p)
p.Do(m_samples_aux1); p.Do(m_samples_aux1);
p.Do(m_samples_aux2); p.Do(m_samples_aux2);
p.Do(m_samples_aux3); p.Do(m_samples_aux3);
p.Do(m_last_aux_volume);
} }

View File

@ -29,6 +29,7 @@ public:
virtual void DoState(PointerWrap &p); virtual void DoState(PointerWrap &p);
protected: protected:
// Additional AUX buffers
int m_samples_auxC_left[32 * 3]; int m_samples_auxC_left[32 * 3];
int m_samples_auxC_right[32 * 3]; int m_samples_auxC_right[32 * 3];
int m_samples_auxC_surround[32 * 3]; int m_samples_auxC_surround[32 * 3];
@ -43,6 +44,9 @@ protected:
int m_samples_wm3[6 * 3]; int m_samples_wm3[6 * 3];
int m_samples_aux3[6 * 3]; int m_samples_aux3[6 * 3];
// Last MixAUXSamples volume value. Used to generate volume ramps.
u16 m_last_aux_volume;
// Convert a mixer_control bitfield to our internal representation for that // Convert a mixer_control bitfield to our internal representation for that
// value. Required because that bitfield has a different meaning in some // value. Required because that bitfield has a different meaning in some
// versions of AX. // versions of AX.