oboe: fix stereo SincResampler
diff --git a/src/common/DataConversionFlowGraph.cpp b/src/common/DataConversionFlowGraph.cpp
index 6653746..3cb5277 100644
--- a/src/common/DataConversionFlowGraph.cpp
+++ b/src/common/DataConversionFlowGraph.cpp
@@ -97,8 +97,9 @@
// Sample Rate conversion
if (sourceSampleRate != sinkSampleRate) {
mResampler = std::make_unique<SincResampler>(sourceChannelCount);
- mRateConverter = std::make_unique<SampleRateConverter>(sourceChannelCount, *mResampler.get());
- mRateConverter->setPhaseIncrement((double)sourceSampleRate / sinkSampleRate);
+ mRateConverter = std::make_unique<SampleRateConverter>(sourceChannelCount,
+ *mResampler.get());
+ mRateConverter->setPhaseIncrement((double) sourceSampleRate / sinkSampleRate);
lastOutput->connect(&mRateConverter->input);
lastOutput = &mRateConverter->output;
}
diff --git a/src/flowgraph/SincResampler.cpp b/src/flowgraph/SincResampler.cpp
index fc5aebd..fc766bb 100644
--- a/src/flowgraph/SincResampler.cpp
+++ b/src/flowgraph/SincResampler.cpp
@@ -15,7 +15,7 @@
*/
#include <math.h>
-#include "common/OboeDebug.h"
+//#include "common/OboeDebug.h"
#include "SincResampler.h"
using namespace flowgraph;
@@ -30,34 +30,31 @@
void SincResampler::writeFrame(const float *frame) {
int xIndex = mCursor * getChannelCount();
+ int offset = kNumTaps * getChannelCount();
float *dest = &mX[xIndex];
for (int channel = 0; channel < getChannelCount(); channel++) {
- *dest++ = frame[channel];
+ // Write twice so we avoid having to wrap.
+ dest[channel] = dest[channel + offset] = frame[channel];
}
- // Write twice so we avoid having to wrap.
- xIndex = (mCursor + kNumTaps) * getChannelCount();
- dest = &mX[xIndex];
- for (int channel = 0; channel < getChannelCount(); channel++) {
- *dest++ = frame[channel];
- }
-
if (++mCursor >= kNumTaps) {
mCursor = 0;
}
}
void SincResampler::readFrame(float *frame, float phase) {
- // Zero accumulator
+ // Clear accumulator for mix.
for (int channel = 0; channel < getChannelCount(); channel++) {
- mSingleFrame[channel] = 0.0f;
+ mSingleFrame[channel] = 0.0;
}
// Multiply input times windowed sinc function.
- int xIndex = mCursor * getChannelCount();
+ int xIndex = (mCursor + kNumTaps - 1) * getChannelCount();
for (int i = 0; i < kNumTaps; i++) {
- float coefficient = calculateWindowedSinc(phase);
+ float coefficient = interpolateWindowedSinc(phase);
+ float *xFrame = &mX[xIndex];
for (int channel = 0; channel < getChannelCount(); channel++) {
- mSingleFrame[channel] += coefficient * mX[xIndex++];
+ mSingleFrame[channel] += coefficient * xFrame[channel];
}
+ xIndex -= getChannelCount();
phase += 1.0;
}
// Copy accumulator to output.
@@ -67,7 +64,7 @@
}
float SincResampler::interpolateWindowedSinc(float phase) {
- float tablePhase = (phase * kNumPoints) / (2 * kSpread);
+ float tablePhase = phase * kTablePhaseScaler;
int tableIndex = int(tablePhase);
float fraction = tablePhase - tableIndex;
float low = mWindowedSinc[tableIndex];
@@ -77,20 +74,19 @@
float SincResampler::calculateWindowedSinc(float phase) {
const float realPhase = phase - kSpread;
- if (abs(realPhase) < 0.00000001) return 1.0f; // avoid /0
-
- static const float alpha = 0.54f;
- const float windowPhase = (realPhase * M_PI);
- // const float window = (float) (alpha + ((1.0 - alpha) * cosf(windowPhase)));
- const float sincPhase = (realPhase * M_PI) * kSpread;
+ if (abs(realPhase) < 0.00000001) return 1.0f; // avoid divide by zero
+ // Hamming window TODO try Kaiser window
+ const float alpha = 0.54f;
+ const float windowPhase = realPhase * M_PI * kSpreadInverse;
+ const float window = (float) (alpha + ((1.0 - alpha) * cosf(windowPhase)));
+ const float sincPhase = realPhase * M_PI;
const float sinc = sinf(sincPhase) / sincPhase;
- return sinc;
+ return window * sinc;
}
void SincResampler::generateLookupTable() {
for (int i = 0; i < mWindowedSinc.size(); i++) {
float phase = (i * 2.0 * kSpread) / kNumPoints;
mWindowedSinc[i] = calculateWindowedSinc(phase);
- LOGD("SincResampler::%s() %f => %f", __func__, phase, mWindowedSinc[i]);
}
}
diff --git a/src/flowgraph/SincResampler.h b/src/flowgraph/SincResampler.h
index c69174a..c7239c7 100644
--- a/src/flowgraph/SincResampler.h
+++ b/src/flowgraph/SincResampler.h
@@ -52,10 +52,12 @@
private:
void generateLookupTable();
- static constexpr int kSpread = 3; // number of zero crossing on one side of central lobe
- static constexpr int kNumTaps = kSpread * 2;
+ static constexpr int kSpread = 10; // number of zero crossing on one side of central lobe
+ static constexpr int kNumTaps = (kSpread * 2) + 1;
+ static constexpr float kSpreadInverse = 1.0 / kSpread;
static constexpr int kNumGuardPoints = 1;
- static constexpr int kNumPoints = 1024;
+ static constexpr int kNumPoints = 4096;
+ static constexpr float kTablePhaseScaler = kNumPoints / (2.0 * kSpread);
std::vector<float> mX;
std::vector<float> mSingleFrame;