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:
@@ -43,13 +43,14 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
register float delta = float(srcSampleCount - 1) / float(destSampleCount - 1);
|
register float delta = float(srcSampleCount) / float(destSampleCount);
|
||||||
register float current = 0.0f;
|
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) {
|
while (count--) {
|
||||||
float tmp = (gain * (SRC(0) + (SRC(1) - SRC(0)) * current) + offset);
|
float tmp = (gain * (oldSample + (SRC - oldSample) * current) + offset);
|
||||||
if (tmp < min) tmp = min;
|
if (tmp < min) tmp = min;
|
||||||
if (tmp > max) tmp = max;
|
if (tmp > max) tmp = max;
|
||||||
*(outType *)dest = (outType)tmp;
|
*(outType *)dest = (outType)tmp;
|
||||||
@@ -59,17 +60,19 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
|
|||||||
if (current >= 1.0f) {
|
if (current >= 1.0f) {
|
||||||
double ipart;
|
double ipart;
|
||||||
current = modf(current, &ipart);
|
current = modf(current, &ipart);
|
||||||
|
oldSample = SRC;
|
||||||
src += srcSampleOffset * (int)ipart;
|
src += srcSampleOffset * (int)ipart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*(outType*)dest = (outType)(SRC(0) * gain + offset);
|
((Interpolate*)object)->fOldSample = oldSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Interpolate::Interpolate(uint32 src_format, uint32 dst_format)
|
Interpolate::Interpolate(uint32 src_format, uint32 dst_format)
|
||||||
:
|
:
|
||||||
Resampler()
|
Resampler(),
|
||||||
|
fOldSample(0)
|
||||||
{
|
{
|
||||||
if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) {
|
if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) {
|
||||||
switch (src_format) {
|
switch (src_format) {
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ class Interpolate: public Resampler {
|
|||||||
public:
|
public:
|
||||||
Interpolate(uint32 sourceFormat,
|
Interpolate(uint32 sourceFormat,
|
||||||
uint32 destFormat);
|
uint32 destFormat);
|
||||||
private:
|
|
||||||
|
|
||||||
|
float fOldSample;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user