summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2013-01-25 19:16:07 +0100
committerPierre Bourdon <delroth@gmail.com>2013-01-25 19:16:07 +0100
commitbad4f7f790b6038450488d1c23d8b65329cea4b4 (patch)
tree07fc78414d4d243114b055684bd35a7a43214f2c /Source/Core
parent9776f135e231d7da2cb31573c4cef65ae1674c33 (diff)
Rewrite the linear interpolation SRC to give the exact same results as the one in AXWii
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h62
1 files changed, 42 insertions, 20 deletions
diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h
index 649ad3c37f..92c797ad14 100644
--- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h
+++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h
@@ -307,38 +307,60 @@ void GetInputSamples(PB_TYPE& pb, s16* samples, const s16* coeffs)
// samples.
u32 curr_pos = pb.src.cur_addr_frac;
- // These are the two samples between which we interpolate. The initial
- // values are stored in the PB, and we update them when resampling the
- // input data.
- s16 curr0 = pb.src.last_samples[2];
- s16 curr1 = pb.src.last_samples[3];
+ // This is the circular buffer containing samples to use for the
+ // interpolation. It is initialized with the values from the PB, and it
+ // will be stored back to the PB at the end.
+ s16 temp[4];
+ u32 idx = 0;
+
+ temp[idx++ & 3] = pb.src.last_samples[0];
+ temp[idx++ & 3] = pb.src.last_samples[1];
+ temp[idx++ & 3] = pb.src.last_samples[2];
+ temp[idx++ & 3] = pb.src.last_samples[3];
for (u32 i = 0; i < SAMPLES_PER_FRAME; ++i)
{
+ curr_pos += ratio;
+
+ // While our current position is >= 1.0, push new samples to the
+ // circular buffer.
+ while (curr_pos >= 0x10000)
+ {
+ temp[idx++ & 3] = AcceleratorGetSample();
+ curr_pos -= 0x10000;
+ }
+
// Get our current fractional position, used to know how much of
// curr0 and how much of curr1 the output sample should be.
- s32 curr_frac_pos = curr_pos & 0xFFFF;
-
- // Linear interpolation: s1 + (s2 - s1) * pos
- s16 sample = curr0 + (s16)(((curr1 - curr0) * (s32)curr_frac_pos) >> 16);
- samples[i] = sample;
+ u16 curr_frac = curr_pos & 0xFFFF;
+ u16 inv_curr_frac = -curr_frac;
- curr_pos += ratio;
+ // Interpolate! If curr_frac is 0, we can simply take the last
+ // sample without any multiplying.
+ s16 sample;
+ if (curr_frac)
+ {
+ s32 s0 = temp[idx++ & 3];
+ s32 s1 = temp[idx++ & 3];
- // While our current position is >= 1.0, shift to the next 2
- // samples for interpolation.
- while ((curr_pos >> 16) != 0)
+ sample = ((s0 * inv_curr_frac) + (s1 * curr_frac)) >> 16;
+ idx += 2;
+ }
+ else
{
- curr0 = curr1;
- curr1 = AcceleratorGetSample();
- curr_pos -= 0x10000;
+ sample = temp[idx++ & 3];
+ idx += 3;
}
+
+ samples[i] = sample;
}
- // Update the two last_samples values in the PB as well as the current
+ // Update the four last_samples values in the PB as well as the current
// position.
- pb.src.last_samples[2] = curr0;
- pb.src.last_samples[3] = curr1;
+ pb.src.last_samples[3] = temp[--idx & 3];
+ pb.src.last_samples[2] = temp[--idx & 3];
+ pb.src.last_samples[1] = temp[--idx & 3];
+ pb.src.last_samples[0] = temp[--idx & 3];
pb.src.cur_addr_frac = curr_pos & 0xFFFF;
}
else // SRCTYPE_NEAREST