resampler: use integer phase accumulation for all resamplers

Remove ContinuousResampler
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 65d843d..c555692 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,7 +32,6 @@
     src/flowgraph/SourceFloat.cpp
     src/flowgraph/SourceI16.cpp
     src/flowgraph/SourceI24.cpp
-    src/flowgraph/resampler/ContinuousResampler.cpp
     src/flowgraph/resampler/IntegerRatio.cpp
     src/flowgraph/resampler/LinearResampler.cpp
     src/flowgraph/resampler/MultiChannelResampler.cpp
diff --git a/apps/OboeTester/app/CMakeLists.txt b/apps/OboeTester/app/CMakeLists.txt
index 38616c4..a3accd9 100644
--- a/apps/OboeTester/app/CMakeLists.txt
+++ b/apps/OboeTester/app/CMakeLists.txt
@@ -26,7 +26,6 @@
     ${OBOE_DIR}/src
 )
 
-
 ### END OBOE INCLUDE SECTION ###
 
 # link to oboe
diff --git a/src/flowgraph/resampler/ContinuousResampler.cpp b/src/flowgraph/resampler/ContinuousResampler.cpp
deleted file mode 100644
index a23b291..0000000
--- a/src/flowgraph/resampler/ContinuousResampler.cpp
+++ /dev/null
@@ -1,24 +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 "ContinuousResampler.h"
-
-using namespace resampler;
-
-ContinuousResampler::ContinuousResampler(const MultiChannelResampler::Builder &builder)
-        : MultiChannelResampler(builder) {
-    mPhaseIncrement = (double) builder.getInputRate() / (double)  builder.getOutputRate();
-}
diff --git a/src/flowgraph/resampler/ContinuousResampler.h b/src/flowgraph/resampler/ContinuousResampler.h
deleted file mode 100644
index de7a973..0000000
--- a/src/flowgraph/resampler/ContinuousResampler.h
+++ /dev/null
@@ -1,57 +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_CONTINUOUS_RESAMPLER_H
-#define OBOE_CONTINUOUS_RESAMPLER_H
-
-#include <sys/types.h>
-#include <unistd.h>
-#include "MultiChannelResampler.h"
-
-namespace resampler {
-
-/*
- * Resampler that uses a double precision phase internally.
- */
-class ContinuousResampler : public MultiChannelResampler {
-public:
-    explicit ContinuousResampler(const MultiChannelResampler::Builder &builder);
-
-    virtual ~ContinuousResampler() = default;
-
-    bool isWriteNeeded() const override {
-        return mPhase >= 1.0;
-    }
-
-    virtual void advanceWrite() override {
-        mPhase -= 1.0;
-    }
-
-    virtual void advanceRead() override {
-        mPhase += mPhaseIncrement;
-    }
-
-    double getPhase() {
-        return (float) mPhase;
-    }
-
-private:
-    double mPhase = 1.0;
-    double mPhaseIncrement = 1.0;
-};
-
-}
-#endif //OBOE_CONTINUOUS_RESAMPLER_H
diff --git a/src/flowgraph/resampler/LinearResampler.cpp b/src/flowgraph/resampler/LinearResampler.cpp
index af2ccb0..33e23e6 100644
--- a/src/flowgraph/resampler/LinearResampler.cpp
+++ b/src/flowgraph/resampler/LinearResampler.cpp
@@ -19,9 +19,9 @@
 using namespace resampler;
 
 LinearResampler::LinearResampler(const MultiChannelResampler::Builder &builder)
-        : ContinuousResampler(builder) {
-        mPreviousFrame = std::make_unique<float[]>(getChannelCount());
-        mCurrentFrame = std::make_unique<float[]>(getChannelCount());
+        : MultiChannelResampler(builder) {
+    mPreviousFrame = std::make_unique<float[]>(getChannelCount());
+    mCurrentFrame = std::make_unique<float[]>(getChannelCount());
 }
 
 void LinearResampler::writeFrame(const float *frame) {
@@ -32,7 +32,7 @@
 void LinearResampler::readFrame(float *frame) {
     float *previous = mPreviousFrame.get();
     float *current = mCurrentFrame.get();
-    float phase = (float) getPhase();
+    float phase = (float) getIntegerPhase() / mDenominator;
     for (int channel = 0; channel < getChannelCount(); channel++) {
         float f0 = *previous++;
         float f1 = *current++;
diff --git a/src/flowgraph/resampler/LinearResampler.h b/src/flowgraph/resampler/LinearResampler.h
index b4d0394..6dc8d29 100644
--- a/src/flowgraph/resampler/LinearResampler.h
+++ b/src/flowgraph/resampler/LinearResampler.h
@@ -20,11 +20,11 @@
 #include <memory>
 #include <sys/types.h>
 #include <unistd.h>
-#include "ContinuousResampler.h"
+#include "MultiChannelResampler.h"
 
 namespace resampler {
 
-class LinearResampler : public ContinuousResampler {
+class LinearResampler : public MultiChannelResampler {
 public:
     LinearResampler(const MultiChannelResampler::Builder &builder);
 
diff --git a/src/flowgraph/resampler/MultiChannelResampler.cpp b/src/flowgraph/resampler/MultiChannelResampler.cpp
index 42c756b..e461975 100644
--- a/src/flowgraph/resampler/MultiChannelResampler.cpp
+++ b/src/flowgraph/resampler/MultiChannelResampler.cpp
@@ -32,8 +32,17 @@
         , mX(builder.getChannelCount() * builder.getNumTaps() * 2)
         , mSingleFrame(builder.getChannelCount())
         , mChannelCount(builder.getChannelCount())
-        {}
+        {
+    // Reduce sample rates to the smallest ratio.
+    // For example 44100/48000 would become 147/160.
+    IntegerRatio ratio(builder.getInputRate(), builder.getOutputRate());
+    ratio.reduce();
+    mNumerator = ratio.getNumerator();
+    mDenominator = ratio.getDenominator();
+    mIntegerPhase = mDenominator;
+}
 
+// static factory method
 MultiChannelResampler *MultiChannelResampler::make(int32_t channelCount,
                                                    int32_t inputRate,
                                                    int32_t outputRate,
@@ -115,9 +124,9 @@
 }
 
 // Unoptimized calculation used to construct lookup tables.
-float MultiChannelResampler::calculateWindowedSinc(float radians, int spread) {
-    return sinc(radians) * hammingWindow(radians, spread); // TODO try Kaiser window
-}
+//float MultiChannelResampler::calculateWindowedSinc(float radians, int spread) {
+//    return sinc(radians) * hammingWindow(radians, spread); // TODO try Kaiser window
+//}
 
 
 // Generate coefficients in the order they will be used by readFrame().
diff --git a/src/flowgraph/resampler/MultiChannelResampler.h b/src/flowgraph/resampler/MultiChannelResampler.h
index a18ed6a..d4e3aa4 100644
--- a/src/flowgraph/resampler/MultiChannelResampler.h
+++ b/src/flowgraph/resampler/MultiChannelResampler.h
@@ -137,10 +137,10 @@
     /**
      * Factory method for making a resampler that is optimal for the given inputs.
      *
-     * @param channelCount
-     * @param inputRate
-     * @param outputRate
-     * @param quality
+     * @param channelCount number of channels, 2 for stereo
+     * @param inputRate sample rate of the input stream
+     * @param outputRate  sample rate of the output stream
+     * @param quality higher quality sounds better but uses more CPU
      * @return an optimal resampler
      */
     static MultiChannelResampler *make(int32_t channelCount,
@@ -148,7 +148,9 @@
                                        int32_t outputRate,
                                        Quality quality);
 
-    virtual bool isWriteNeeded() const = 0;
+    bool isWriteNeeded() const {
+        return mIntegerPhase >= mDenominator;
+    }
 
     /**
      * Write a frame containing N samples.
@@ -190,7 +192,7 @@
      * @param phase between 0.0 and  2*spread // TODO use centered phase, maybe
      * @return windowedSinc
      */
-    static float calculateWindowedSinc(float phase, int spread); // TODO remove
+    // static float calculateWindowedSinc(float phase, int spread); // TODO remove
 
     /**
      * Write a frame containing N samples.
@@ -203,26 +205,23 @@
      * Read a frame containing N samples using interpolation.
      * Call advanceRead() after calling this.
      * @param frame pointer to the first sample in a frame
-     * @param phase phase between 0.0 and 1.0 for interpolation
      */
     virtual void readFrame(float *frame) = 0;
 
-    virtual void advanceWrite() = 0;
-    virtual void advanceRead() = 0;
+    void advanceWrite() {
+        mIntegerPhase -= mDenominator;
+    }
 
-    const int            mNumTaps;
-    int                  mCursor = 0;
-    std::vector<float>   mX;
-    std::vector<float>   mSingleFrame;
-
-    std::vector<float>     mCoefficients;
-    static constexpr int   kMaxCoefficients = 8 * 1024;
-
+    void advanceRead() {
+        mIntegerPhase += mNumerator;
+    }
 
     /**
      * Generate the filter coefficients in optimal order.
-     * @param inputRate
-     * @param outputRate
+     * @param inputRate sample rate of the input stream
+     * @param outputRate  sample rate of the output stream
+     * @param numRows number of rows in the array that contain a set of tap coefficients
+     * @param phaseIncrement how much to increment the phase between rows
      * @param normalizedCutoff filter cutoff frequency normalized to Nyquist rate of output
      */
     void generateCoefficients(int32_t inputRate,
@@ -231,13 +230,29 @@
                               double phaseIncrement,
                               float normalizedCutoff);
 
+
+    int32_t getIntegerPhase() {
+        return mIntegerPhase;
+    }
+
+    static constexpr int kMaxCoefficients = 8 * 1024;
+    std::vector<float>   mCoefficients;
+
+    const int            mNumTaps;
+    int                  mCursor = 0;
+    std::vector<float>   mX;
+    std::vector<float>   mSingleFrame;
+    int32_t              mIntegerPhase = 0;
+    int32_t              mNumerator = 0;
+    int32_t              mDenominator = 0;
+
+
 private:
 
     // max coefficients for polyphase filter
     static constexpr float kDefaultNormalizedCutoff = 0.90f;
 
     const int              mChannelCount;
-
 };
 
 }
diff --git a/src/flowgraph/resampler/PolyphaseResampler.cpp b/src/flowgraph/resampler/PolyphaseResampler.cpp
index 18ebe4c..4862ad8 100644
--- a/src/flowgraph/resampler/PolyphaseResampler.cpp
+++ b/src/flowgraph/resampler/PolyphaseResampler.cpp
@@ -28,14 +28,6 @@
     int32_t inputRate = builder.getInputRate();
     int32_t outputRate = builder.getOutputRate();
 
-    // Reduce sample rates to the smallest ratio.
-    // For example 44100/48000 would become 147/160.
-    IntegerRatio ratio(inputRate, outputRate);
-    ratio.reduce();
-    mNumerator = ratio.getNumerator();
-    mDenominator = ratio.getDenominator();
-    mIntegerPhase = mDenominator;
-
     int32_t numRows = mDenominator;
     double phaseIncrement = (double) inputRate / (double) outputRate;
     generateCoefficients(inputRate, outputRate,
diff --git a/src/flowgraph/resampler/PolyphaseResampler.h b/src/flowgraph/resampler/PolyphaseResampler.h
index fa267a1..13ab5e1 100644
--- a/src/flowgraph/resampler/PolyphaseResampler.h
+++ b/src/flowgraph/resampler/PolyphaseResampler.h
@@ -29,10 +29,7 @@
 public:
     /**
      *
-     * @param channelCount
-     * @param numTaps
-     * @param inputRate inputRate/outputRate should be a reduced fraction
-     * @param outputRate
+     * @param builder containing lots of parameters
      */
     explicit PolyphaseResampler(const MultiChannelResampler::Builder &builder);
 
@@ -40,24 +37,9 @@
 
     void readFrame(float *frame) override;
 
-    bool isWriteNeeded() const override {
-        return mIntegerPhase >= mDenominator;
-    }
-
-    virtual void advanceWrite() override {
-        mIntegerPhase -= mDenominator;
-    }
-
-    virtual void advanceRead() override {
-        mIntegerPhase += mNumerator;
-    }
-
 protected:
 
     int32_t                mCoefficientCursor = 0;
-    int32_t                mIntegerPhase = 0;
-    int32_t                mNumerator = 0;
-    int32_t                mDenominator = 0;
 
 };
 
diff --git a/src/flowgraph/resampler/SincResampler.cpp b/src/flowgraph/resampler/SincResampler.cpp
index 9acd192..d1938b9 100644
--- a/src/flowgraph/resampler/SincResampler.cpp
+++ b/src/flowgraph/resampler/SincResampler.cpp
@@ -20,11 +20,12 @@
 using namespace resampler;
 
 SincResampler::SincResampler(const MultiChannelResampler::Builder &builder)
-        : ContinuousResampler(builder)
+        : MultiChannelResampler(builder)
         , mSingleFrame2(builder.getChannelCount()) {
     assert((getNumTaps() % 4) == 0); // Required for loop unrolling.
     mNumRows = kMaxCoefficients / getNumTaps(); // no guard row needed
 //    printf("SincResampler: numRows = %d\n", mNumRows);
+    mPhaseScaler = (double) mNumRows / mDenominator;
     double phaseIncrement = 1.0 / mNumRows;
     generateCoefficients(builder.getInputRate(),
                          builder.getOutputRate(),
@@ -40,7 +41,7 @@
     std::fill(mSingleFrame2.begin(), mSingleFrame2.end(), 0.0);
 
     // Determine indices into coefficients table.
-    double tablePhase = getPhase() * mNumRows;
+    double tablePhase = getIntegerPhase() * mPhaseScaler;
     int index1 = static_cast<int>(floor(tablePhase));
     if (index1 >= mNumRows) { // no guard row needed because we wrap the indices
         tablePhase -= mNumRows;
diff --git a/src/flowgraph/resampler/SincResampler.h b/src/flowgraph/resampler/SincResampler.h
index cbfcc0b..edeb840 100644
--- a/src/flowgraph/resampler/SincResampler.h
+++ b/src/flowgraph/resampler/SincResampler.h
@@ -20,11 +20,11 @@
 #include <memory>
 #include <sys/types.h>
 #include <unistd.h>
-#include "ContinuousResampler.h"
+#include "MultiChannelResampler.h"
 
 namespace resampler {
 
-class SincResampler : public ContinuousResampler {
+class SincResampler : public MultiChannelResampler {
 public:
     explicit SincResampler(const MultiChannelResampler::Builder &builder);
 
@@ -36,7 +36,7 @@
 
     std::vector<float> mSingleFrame2; // for interpolation
     int32_t            mNumRows = 0;
-
+    double             mPhaseScaler = 1.0;
 };
 
 }
diff --git a/src/flowgraph/resampler/SincResamplerStereo.cpp b/src/flowgraph/resampler/SincResamplerStereo.cpp
index 5af7ff7..bde658a 100644
--- a/src/flowgraph/resampler/SincResamplerStereo.cpp
+++ b/src/flowgraph/resampler/SincResamplerStereo.cpp
@@ -51,7 +51,7 @@
     std::fill(mSingleFrame2.begin(), mSingleFrame2.end(), 0.0);
 
     // Determine indices into coefficients table.
-    double tablePhase = getPhase() * mNumRows;
+    double tablePhase = getIntegerPhase() * mPhaseScaler;
     int index1 = static_cast<int>(floor(tablePhase));
     float *coefficients1 = &mCoefficients[index1 * getNumTaps()];
     int index2 = (index1 + 1);
diff --git a/src/flowgraph/resampler/SincResamplerStereo.h b/src/flowgraph/resampler/SincResamplerStereo.h
index 6014b94..7d66c26 100644
--- a/src/flowgraph/resampler/SincResamplerStereo.h
+++ b/src/flowgraph/resampler/SincResamplerStereo.h
@@ -32,6 +32,7 @@
     void writeFrame(const float *frame) override;
 
     void readFrame(float *frame) override;
+
 };
 
 }