mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 15:19:42 -06:00
Add volume ramping for MAIN output, separate old volume values for each AUX channel and refactor
This commit is contained in:
@ -30,8 +30,10 @@
|
|||||||
|
|
||||||
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)
|
m_last_main_volume(0x8000)
|
||||||
{
|
{
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
m_last_aux_volumes[i] = 0x8000;
|
||||||
WARN_LOG(DSPHLE, "Instantiating CUCode_AXWii");
|
WARN_LOG(DSPHLE, "Instantiating CUCode_AXWii");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,6 +230,16 @@ AXMixControl CUCode_AXWii::ConvertMixerControl(u32 mixer_control)
|
|||||||
return (AXMixControl)ret;
|
return (AXMixControl)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CUCode_AXWii::GenerateVolumeRamp(u16* output, u16 vol1, u16 vol2, size_t nvals)
|
||||||
|
{
|
||||||
|
float curr = vol1;
|
||||||
|
for (size_t i = 0; i < nvals; ++i)
|
||||||
|
{
|
||||||
|
curr += (vol2 - vol1) / (float)nvals;
|
||||||
|
output[i] = curr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CUCode_AXWii::ProcessPBList(u32 pb_addr)
|
void CUCode_AXWii::ProcessPBList(u32 pb_addr)
|
||||||
{
|
{
|
||||||
AXPBWii pb;
|
AXPBWii pb;
|
||||||
@ -270,21 +282,9 @@ 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];
|
u16 volume_ramp[96];
|
||||||
float curr_volume = prev_volume;
|
GenerateVolumeRamp(volume_ramp, m_last_aux_volumes[aux_id], volume, 96);
|
||||||
for (int i = 0; i < 96; ++i)
|
m_last_aux_volumes[aux_id] = volume;
|
||||||
{
|
|
||||||
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] = {
|
||||||
@ -332,12 +332,14 @@ void CUCode_AXWii::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr, u16
|
|||||||
sample *= volume_ramp[j];
|
sample *= volume_ramp[j];
|
||||||
main_buffers[i][j] += (s32)(sample >> 15);
|
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)
|
||||||
{
|
{
|
||||||
|
u16 volume_ramp[96];
|
||||||
|
GenerateVolumeRamp(volume_ramp, m_last_main_volume, volume, 96);
|
||||||
|
m_last_main_volume = volume;
|
||||||
|
|
||||||
int surround_buffer[3 * 32] = { 0 };
|
int surround_buffer[3 * 32] = { 0 };
|
||||||
|
|
||||||
for (u32 i = 0; i < 3 * 32; ++i)
|
for (u32 i = 0; i < 3 * 32; ++i)
|
||||||
@ -353,8 +355,8 @@ void CUCode_AXWii::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume)
|
|||||||
int right = m_samples_right[i];
|
int right = m_samples_right[i];
|
||||||
|
|
||||||
// Apply global volume. Cast to s64 to avoid overflow.
|
// Apply global volume. Cast to s64 to avoid overflow.
|
||||||
left = ((s64)left * volume) >> 15;
|
left = ((s64)left * volume_ramp[i]) >> 15;
|
||||||
right = ((s64)right * volume) >> 15;
|
right = ((s64)right * volume_ramp[i]) >> 15;
|
||||||
|
|
||||||
if (left < -32767) left = -32767;
|
if (left < -32767) left = -32767;
|
||||||
if (left > 32767) left = 32767;
|
if (left > 32767) left = 32767;
|
||||||
@ -418,5 +420,6 @@ void CUCode_AXWii::DoState(PointerWrap &p)
|
|||||||
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);
|
p.Do(m_last_main_volume);
|
||||||
|
p.Do(m_last_aux_volumes);
|
||||||
}
|
}
|
||||||
|
@ -44,14 +44,21 @@ 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.
|
// Last volume values for MAIN and AUX. Used to generate volume ramps to
|
||||||
u16 m_last_aux_volume;
|
// interpolate nicely between old and new volume values.
|
||||||
|
u16 m_last_main_volume;
|
||||||
|
u16 m_last_aux_volumes[3];
|
||||||
|
|
||||||
// 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.
|
||||||
AXMixControl ConvertMixerControl(u32 mixer_control);
|
AXMixControl ConvertMixerControl(u32 mixer_control);
|
||||||
|
|
||||||
|
// Generate a volume ramp from vol1 to vol2, interpolating n volume values.
|
||||||
|
// Uses floating point arithmetic, which isn't exactly what the UCode does,
|
||||||
|
// but this gives better precision and nicer code.
|
||||||
|
void GenerateVolumeRamp(u16* output, u16 vol1, u16 vol2, size_t nvals);
|
||||||
|
|
||||||
virtual void HandleCommandList();
|
virtual void HandleCommandList();
|
||||||
|
|
||||||
void SetupProcessing(u32 init_addr);
|
void SetupProcessing(u32 init_addr);
|
||||||
|
Reference in New Issue
Block a user