Interpolating resampler: un-break it.

The interpolation was performed only on the samples in a buffer,
without "linking" with the previous one. This can't work.
* Remember the last sample from a buffer to be able to use it when
interpolating the first samples of the next one
* Adjust the kernel to properly loop over all samples in the buffer

Fixes #9438.
This commit is contained in:
Adrien Destugues
2014-12-08 19:07:45 +01:00
parent dab42bf05b
commit d23c413188
2 changed files with 10 additions and 7 deletions
@@ -43,13 +43,14 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
return;
}
register float delta = float(srcSampleCount - 1) / float(destSampleCount - 1);
register float delta = float(srcSampleCount) / float(destSampleCount);
register float current = 0.0f;
float oldSample = ((Interpolate*)object)->fOldSample;
#define SRC(n) *(const inType*)(src + n * srcSampleOffset)
#define SRC *(const inType*)(src)
while (--count) {
float tmp = (gain * (SRC(0) + (SRC(1) - SRC(0)) * current) + offset);
while (count--) {
float tmp = (gain * (oldSample + (SRC - oldSample) * current) + offset);
if (tmp < min) tmp = min;
if (tmp > max) tmp = max;
*(outType *)dest = (outType)tmp;
@@ -59,17 +60,19 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
if (current >= 1.0f) {
double ipart;
current = modf(current, &ipart);
oldSample = SRC;
src += srcSampleOffset * (int)ipart;
}
}
*(outType*)dest = (outType)(SRC(0) * gain + offset);
((Interpolate*)object)->fOldSample = oldSample;
}
Interpolate::Interpolate(uint32 src_format, uint32 dst_format)
:
Resampler()
Resampler(),
fOldSample(0)
{
if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) {
switch (src_format) {
@@ -13,8 +13,8 @@ class Interpolate: public Resampler {
public:
Interpolate(uint32 sourceFormat,
uint32 destFormat);
private:
float fOldSample;
};