summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2013-03-30 00:55:55 +0100
committerPierre Bourdon <delroth@gmail.com>2013-03-30 00:55:55 +0100
commitc271082ec50bda616233fbf883ad0c58cda8fcd0 (patch)
tree55c718afdf566d9b6452528f0fd16bcaa0826b42 /Source/Core
parent4b09f525f6e63a1e3686d84f12463ba127eeda36 (diff)
Add volume ramping for MAIN output, separate old volume values for each AUX channel and refactor
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp43
-rw-r--r--Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h11
2 files changed, 32 insertions, 22 deletions
diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp
index 8381564f3f..df9a6b5409 100644
--- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp
+++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp
@@ -30,8 +30,10 @@
CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 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");
}
@@ -228,6 +230,16 @@ AXMixControl CUCode_AXWii::ConvertMixerControl(u32 mixer_control)
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)
{
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)
{
- 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;
- }
+ GenerateVolumeRamp(volume_ramp, m_last_aux_volumes[aux_id], volume, 96);
+ m_last_aux_volumes[aux_id] = volume;
int* buffers[3] = { 0 };
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];
main_buffers[i][j] += (s32)(sample >> 15);
}
-
- m_last_aux_volume = 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 };
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];
// Apply global volume. Cast to s64 to avoid overflow.
- left = ((s64)left * volume) >> 15;
- right = ((s64)right * volume) >> 15;
+ left = ((s64)left * volume_ramp[i]) >> 15;
+ right = ((s64)right * volume_ramp[i]) >> 15;
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_aux3);
- p.Do(m_last_aux_volume);
+ p.Do(m_last_main_volume);
+ p.Do(m_last_aux_volumes);
}
diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h
index 031971a2a4..c1d281d9c3 100644
--- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h
+++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h
@@ -44,14 +44,21 @@ protected:
int m_samples_wm3[6 * 3];
int m_samples_aux3[6 * 3];
- // Last MixAUXSamples volume value. Used to generate volume ramps.
- u16 m_last_aux_volume;
+ // Last volume values for MAIN and AUX. Used to generate volume ramps to
+ // 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
// value. Required because that bitfield has a different meaning in some
// versions of AX.
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();
void SetupProcessing(u32 init_addr);