flowgraph: add PolyphaseResamplerStereo
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5303f26..50b758f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,7 +28,8 @@
src/flowgraph/ManyToMultiConverter.cpp
src/flowgraph/MonoToMultiConverter.cpp
src/flowgraph/MultiChannelResampler.cpp
- src/flowgraph/PolyphaseSincResampler.cpp
+ src/flowgraph/PolyphaseResampler.cpp
+ src/flowgraph/PolyphaseResamplerStereo.cpp
src/flowgraph/RampLinear.cpp
src/flowgraph/SampleRateConverter.cpp
src/flowgraph/SincResampler.cpp
diff --git a/src/flowgraph/MultiChannelResampler.cpp b/src/flowgraph/MultiChannelResampler.cpp
index a4b15ab..7987ecd 100644
--- a/src/flowgraph/MultiChannelResampler.cpp
+++ b/src/flowgraph/MultiChannelResampler.cpp
@@ -16,10 +16,12 @@
#include <math.h>
-#include "MultiChannelResampler.h"
+#include "IntegerRatio.h"
#include "LinearResampler.h"
+#include "MultiChannelResampler.h"
+#include "PolyphaseResampler.h"
+#include "PolyphaseResamplerStereo.h"
#include "SincResampler.h"
-#include "PolyphaseSincResampler.h"
#include "SincResamplerStereo.h"
using namespace flowgraph;
@@ -34,7 +36,11 @@
return new LinearResampler(channelCount, inputRate, outputRate);
default:
case Quality::High:
- return new PolyphaseSincResampler(channelCount, inputRate, outputRate); // TODO
+ if (channelCount == 2) {
+ return new PolyphaseResamplerStereo(inputRate, outputRate);
+ } else {
+ return new PolyphaseResampler(channelCount, inputRate, outputRate);
+ }
case Quality::Best:
if (channelCount == 2) {
return new SincResamplerStereo( inputRate, outputRate); // TODO pass spread
diff --git a/src/flowgraph/PolyphaseSincResampler.cpp b/src/flowgraph/PolyphaseResampler.cpp
similarity index 86%
rename from src/flowgraph/PolyphaseSincResampler.cpp
rename to src/flowgraph/PolyphaseResampler.cpp
index 9ed3212..af9b699 100644
--- a/src/flowgraph/PolyphaseSincResampler.cpp
+++ b/src/flowgraph/PolyphaseResampler.cpp
@@ -15,11 +15,11 @@
*/
#include "IntegerRatio.h"
-#include "PolyphaseSincResampler.h"
+#include "PolyphaseResampler.h"
using namespace flowgraph;
-PolyphaseSincResampler::PolyphaseSincResampler(int32_t channelCount,
+PolyphaseResampler::PolyphaseResampler(int32_t channelCount,
int32_t inputRate,
int32_t outputRate)
: MultiChannelResampler(channelCount, kNumTaps, inputRate, outputRate)
@@ -27,7 +27,7 @@
generateCoefficients(inputRate, outputRate);
}
-void PolyphaseSincResampler::generateCoefficients(int32_t inputRate, int32_t outputRate) {
+void PolyphaseResampler::generateCoefficients(int32_t inputRate, int32_t outputRate) {
IntegerRatio ratio(inputRate, outputRate);
ratio.reduce();
mNumerator = ratio.getNumerator();
@@ -49,7 +49,7 @@
}
}
}
-void PolyphaseSincResampler::readFrame(float *frame) {
+void PolyphaseResampler::readFrame(float *frame) {
// Clear accumulator for mix.
for (int channel = 0; channel < getChannelCount(); channel++) {
mSingleFrame[channel] = 0.0;
@@ -67,10 +67,7 @@
xIndex -= getChannelCount();
}
- mCoefficientCursor += kNumTaps;
- if (mCoefficientCursor >= mCoefficients.size()) {
- mCoefficientCursor = 0;
- }
+ mCoefficientCursor = (mCoefficientCursor + kNumTaps) % mCoefficients.size();
// Copy accumulator to output.
for (int channel = 0; channel < getChannelCount(); channel++) {
diff --git a/src/flowgraph/PolyphaseSincResampler.h b/src/flowgraph/PolyphaseResampler.h
similarity index 84%
rename from src/flowgraph/PolyphaseSincResampler.h
rename to src/flowgraph/PolyphaseResampler.h
index e64966f..e7b1e8e 100644
--- a/src/flowgraph/PolyphaseSincResampler.h
+++ b/src/flowgraph/PolyphaseResampler.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef FLOWGRAPH_POLYPHASE_SINC_RESAMPLER_H
-#define FLOWGRAPH_POLYPHASE_SINC_RESAMPLER_H
+#ifndef FLOWGRAPH_POLYPHASE_RESAMPLER_H
+#define FLOWGRAPH_POLYPHASE_RESAMPLER_H
#include <memory>
@@ -26,11 +26,11 @@
namespace flowgraph {
-class PolyphaseSincResampler : public MultiChannelResampler {
+class PolyphaseResampler : public MultiChannelResampler {
public:
- PolyphaseSincResampler(int32_t channelCount, int32_t inputRate, int32_t outputRate);
+ PolyphaseResampler(int32_t channelCount, int32_t inputRate, int32_t outputRate);
- virtual ~PolyphaseSincResampler() = default;
+ virtual ~PolyphaseResampler() = default;
void readFrame(float *frame) override;
@@ -74,4 +74,4 @@
}
-#endif //FLOWGRAPH_POLYPHASE_SINC_RESAMPLER_H
+#endif //FLOWGRAPH_POLYPHASE_RESAMPLER_H
diff --git a/src/flowgraph/PolyphaseResamplerStereo.cpp b/src/flowgraph/PolyphaseResamplerStereo.cpp
new file mode 100644
index 0000000..a64edec
--- /dev/null
+++ b/src/flowgraph/PolyphaseResamplerStereo.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PolyphaseResamplerStereo.h"
+
+using namespace flowgraph;
+
+#define STEREO 2
+
+PolyphaseResamplerStereo::PolyphaseResamplerStereo(
+ int32_t inputRate,
+ int32_t outputRate)
+ : PolyphaseResampler(STEREO, inputRate, outputRate) {}
+
+
+void PolyphaseResamplerStereo::writeFrame(const float *frame) {
+ float *dest = &mX[mCursor * STEREO];
+ // Write each channel twice so we avoid having to wrap when running the FIR.
+ const int offset = kNumTaps * STEREO;
+ const float left = frame[0];
+ const float right = frame[1];
+ // Put ordered writes together.
+ dest[0] = left;
+ dest[1] = right;
+ dest[offset] = left;
+ dest[1 + offset] = right;
+ if (++mCursor >= kNumTaps) {
+ mCursor = 0;
+ }
+}
+
+void PolyphaseResamplerStereo::readFrame(float *frame) {
+ // Clear accumulators.
+ float left = 0.0;
+ float right = 0.0;
+
+ // Multiply input times precomputed windowed sinc function.
+ const float *coefficients = &mCoefficients[mCoefficientCursor];
+ int xIndex = (mCursor + kNumTaps) * STEREO;
+ for (int i = 0; i < kNumTaps; i++) {
+ float coefficient = *coefficients++;
+ float *xFrame = &mX[xIndex];
+ left += coefficient * xFrame[0];
+ right += coefficient * xFrame[1];
+ xIndex -= STEREO;
+ }
+
+ mCoefficientCursor = (mCoefficientCursor + kNumTaps) % mCoefficients.size();
+
+ // Copy accumulators to output.
+ frame[0] = left;
+ frame[1] = right;
+}
diff --git a/src/flowgraph/PolyphaseResamplerStereo.h b/src/flowgraph/PolyphaseResamplerStereo.h
new file mode 100644
index 0000000..59452e8
--- /dev/null
+++ b/src/flowgraph/PolyphaseResamplerStereo.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLOWGRAPH_POLYPHASE_RESAMPLER_STEREO_H
+#define FLOWGRAPH_POLYPHASE_RESAMPLER_STEREO_H
+
+#include <sys/types.h>
+#include <unistd.h>
+#include "PolyphaseResampler.h"
+
+namespace flowgraph {
+
+ class PolyphaseResamplerStereo : public PolyphaseResampler {
+ public:
+ PolyphaseResamplerStereo(int32_t inputRate, int32_t outputRate);
+
+ virtual ~PolyphaseResamplerStereo() = default;
+
+ void writeFrame(const float *frame) override;
+
+ void readFrame(float *frame) override;
+ };
+
+}
+
+#endif //FLOWGRAPH_POLYPHASE_RESAMPLER_STEREO_H
diff --git a/src/flowgraph/SampleRateConverterVariable.cpp b/src/flowgraph/SampleRateConverterVariable.cpp
deleted file mode 100644
index 4a3f103..0000000
--- a/src/flowgraph/SampleRateConverterVariable.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SampleRateConverterVariable.h"
-
-using namespace flowgraph;
-
-SampleRateConverterVariable::SampleRateConverterVariable(int32_t channelCount, MultiChannelResampler &resampler)
- : SampleRateConverterVariable(channelCount, resampler) {
-}
-
-int32_t SampleRateConverterVariable::onProcess(int32_t numFrames) {
- float *outputBuffer = output.getBuffer();
- int32_t channelCount = output.getSamplesPerFrame();
- int framesLeft = numFrames;
- while (framesLeft > 0) {
- // Gather input samples as needed.
- if(mResampler.isWriteReady()) {
- if (!isInputAvailable()) break;
- const float *frame = getNextInputFrame();
- mResampler.writeFrame(frame);
- }
-
- // If phase >= 1.0 then we are waiting for input data.
- if (mResampler.isReadReady()) {
- // Output frame is interpolated from input samples based on phase.
- mResampler.readFrame(outputBuffer);
- outputBuffer += channelCount;
- framesLeft--;
- } else {
- break;
- }
- }
- return numFrames - framesLeft;
-}
diff --git a/src/flowgraph/SampleRateConverterVariable.h b/src/flowgraph/SampleRateConverterVariable.h
deleted file mode 100644
index a215ac1..0000000
--- a/src/flowgraph/SampleRateConverterVariable.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef OBOE_SAMPLE_RATE_CONVERTER_VARIABLE_H
-#define OBOE_SAMPLE_RATE_CONVERTER_VARIABLE_H
-
-#include <unistd.h>
-#include <sys/types.h>
-
-#include "AudioProcessorBase.h"
-#include "MultiChannelResampler.h"
-#include "LinearResampler.h"
-#include "SincResampler.h"
-
-namespace flowgraph {
-
-class SampleRateConverterVariable : public SampleRateConverterVariable {
-public:
- explicit SampleRateConverterVariable(int32_t channelCount, MultiChannelResampler &mResampler);
-
- double getPhaseIncrement() {
- return mPhaseIncrement;
- }
-
- void setPhaseIncrement(double phaseIncrement) {
- mPhaseIncrement = phaseIncrement;
- }
-
- int32_t onProcess(int32_t numFrames) override;
-
-private:
- double mPhase = 1.0;
- double mPhaseIncrement = 1.0;
-};
-
-} /* namespace flowgraph */
-
-#endif //OBOE_SAMPLE_RATE_CONVERTER_VARIABLE_H
diff --git a/src/flowgraph/SincResampler.h b/src/flowgraph/SincResampler.h
index a887a04..53357a3 100644
--- a/src/flowgraph/SincResampler.h
+++ b/src/flowgraph/SincResampler.h
@@ -52,7 +52,7 @@
static constexpr int kSpread = 10;
static constexpr int kNumTaps = kSpread * 2; // TODO should be odd, not even
- std::vector<float> mWindowedSinc;
+ std::vector<float> mWindowedSinc;
private: