1*05767d91SRobert Wu /* 2*05767d91SRobert Wu * Copyright 2019 The Android Open Source Project 3*05767d91SRobert Wu * 4*05767d91SRobert Wu * Licensed under the Apache License, Version 2.0 (the "License"); 5*05767d91SRobert Wu * you may not use this file except in compliance with the License. 6*05767d91SRobert Wu * You may obtain a copy of the License at 7*05767d91SRobert Wu * 8*05767d91SRobert Wu * http://www.apache.org/licenses/LICENSE-2.0 9*05767d91SRobert Wu * 10*05767d91SRobert Wu * Unless required by applicable law or agreed to in writing, software 11*05767d91SRobert Wu * distributed under the License is distributed on an "AS IS" BASIS, 12*05767d91SRobert Wu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*05767d91SRobert Wu * See the License for the specific language governing permissions and 14*05767d91SRobert Wu * limitations under the License. 15*05767d91SRobert Wu */ 16*05767d91SRobert Wu 17*05767d91SRobert Wu #ifndef RESAMPLER_MULTICHANNEL_RESAMPLER_H 18*05767d91SRobert Wu #define RESAMPLER_MULTICHANNEL_RESAMPLER_H 19*05767d91SRobert Wu 20*05767d91SRobert Wu #include <memory> 21*05767d91SRobert Wu #include <vector> 22*05767d91SRobert Wu #include <sys/types.h> 23*05767d91SRobert Wu #include <unistd.h> 24*05767d91SRobert Wu 25*05767d91SRobert Wu #ifndef MCR_USE_KAISER 26*05767d91SRobert Wu // It appears from the spectrogram that the HyperbolicCosine window leads to fewer artifacts. 27*05767d91SRobert Wu // And it is faster to calculate. 28*05767d91SRobert Wu #define MCR_USE_KAISER 0 29*05767d91SRobert Wu #endif 30*05767d91SRobert Wu 31*05767d91SRobert Wu #if MCR_USE_KAISER 32*05767d91SRobert Wu #include "KaiserWindow.h" 33*05767d91SRobert Wu #else 34*05767d91SRobert Wu #include "HyperbolicCosineWindow.h" 35*05767d91SRobert Wu #endif 36*05767d91SRobert Wu 37*05767d91SRobert Wu #include "ResamplerDefinitions.h" 38*05767d91SRobert Wu 39*05767d91SRobert Wu namespace RESAMPLER_OUTER_NAMESPACE::resampler { 40*05767d91SRobert Wu 41*05767d91SRobert Wu class MultiChannelResampler { 42*05767d91SRobert Wu 43*05767d91SRobert Wu public: 44*05767d91SRobert Wu 45*05767d91SRobert Wu enum class Quality : int32_t { 46*05767d91SRobert Wu Fastest, 47*05767d91SRobert Wu Low, 48*05767d91SRobert Wu Medium, 49*05767d91SRobert Wu High, 50*05767d91SRobert Wu Best, 51*05767d91SRobert Wu }; 52*05767d91SRobert Wu 53*05767d91SRobert Wu class Builder { 54*05767d91SRobert Wu public: 55*05767d91SRobert Wu /** 56*05767d91SRobert Wu * Construct an optimal resampler based on the specified parameters. 57*05767d91SRobert Wu * @return address of a resampler 58*05767d91SRobert Wu */ 59*05767d91SRobert Wu MultiChannelResampler *build(); 60*05767d91SRobert Wu 61*05767d91SRobert Wu /** 62*05767d91SRobert Wu * The number of taps in the resampling filter. 63*05767d91SRobert Wu * More taps gives better quality but uses more CPU time. 64*05767d91SRobert Wu * This typically ranges from 4 to 64. Default is 16. 65*05767d91SRobert Wu * 66*05767d91SRobert Wu * For polyphase filters, numTaps must be a multiple of four for loop unrolling. 67*05767d91SRobert Wu * @param numTaps number of taps for the filter 68*05767d91SRobert Wu * @return address of this builder for chaining calls 69*05767d91SRobert Wu */ setNumTaps(int32_t numTaps)70*05767d91SRobert Wu Builder *setNumTaps(int32_t numTaps) { 71*05767d91SRobert Wu mNumTaps = numTaps; 72*05767d91SRobert Wu return this; 73*05767d91SRobert Wu } 74*05767d91SRobert Wu 75*05767d91SRobert Wu /** 76*05767d91SRobert Wu * Use 1 for mono, 2 for stereo, etc. Default is 1. 77*05767d91SRobert Wu * 78*05767d91SRobert Wu * @param channelCount number of channels 79*05767d91SRobert Wu * @return address of this builder for chaining calls 80*05767d91SRobert Wu */ setChannelCount(int32_t channelCount)81*05767d91SRobert Wu Builder *setChannelCount(int32_t channelCount) { 82*05767d91SRobert Wu mChannelCount = channelCount; 83*05767d91SRobert Wu return this; 84*05767d91SRobert Wu } 85*05767d91SRobert Wu 86*05767d91SRobert Wu /** 87*05767d91SRobert Wu * Default is 48000. 88*05767d91SRobert Wu * 89*05767d91SRobert Wu * @param inputRate sample rate of the input stream 90*05767d91SRobert Wu * @return address of this builder for chaining calls 91*05767d91SRobert Wu */ setInputRate(int32_t inputRate)92*05767d91SRobert Wu Builder *setInputRate(int32_t inputRate) { 93*05767d91SRobert Wu mInputRate = inputRate; 94*05767d91SRobert Wu return this; 95*05767d91SRobert Wu } 96*05767d91SRobert Wu 97*05767d91SRobert Wu /** 98*05767d91SRobert Wu * Default is 48000. 99*05767d91SRobert Wu * 100*05767d91SRobert Wu * @param outputRate sample rate of the output stream 101*05767d91SRobert Wu * @return address of this builder for chaining calls 102*05767d91SRobert Wu */ setOutputRate(int32_t outputRate)103*05767d91SRobert Wu Builder *setOutputRate(int32_t outputRate) { 104*05767d91SRobert Wu mOutputRate = outputRate; 105*05767d91SRobert Wu return this; 106*05767d91SRobert Wu } 107*05767d91SRobert Wu 108*05767d91SRobert Wu /** 109*05767d91SRobert Wu * Set cutoff frequency relative to the Nyquist rate of the output sample rate. 110*05767d91SRobert Wu * Set to 1.0 to match the Nyquist frequency. 111*05767d91SRobert Wu * Set lower to reduce aliasing. 112*05767d91SRobert Wu * Default is 0.70. 113*05767d91SRobert Wu * 114*05767d91SRobert Wu * Note that this value is ignored when upsampling, which is when 115*05767d91SRobert Wu * the outputRate is higher than the inputRate. 116*05767d91SRobert Wu * 117*05767d91SRobert Wu * @param normalizedCutoff anti-aliasing filter cutoff 118*05767d91SRobert Wu * @return address of this builder for chaining calls 119*05767d91SRobert Wu */ setNormalizedCutoff(float normalizedCutoff)120*05767d91SRobert Wu Builder *setNormalizedCutoff(float normalizedCutoff) { 121*05767d91SRobert Wu mNormalizedCutoff = normalizedCutoff; 122*05767d91SRobert Wu return this; 123*05767d91SRobert Wu } 124*05767d91SRobert Wu getNumTaps()125*05767d91SRobert Wu int32_t getNumTaps() const { 126*05767d91SRobert Wu return mNumTaps; 127*05767d91SRobert Wu } 128*05767d91SRobert Wu getChannelCount()129*05767d91SRobert Wu int32_t getChannelCount() const { 130*05767d91SRobert Wu return mChannelCount; 131*05767d91SRobert Wu } 132*05767d91SRobert Wu getInputRate()133*05767d91SRobert Wu int32_t getInputRate() const { 134*05767d91SRobert Wu return mInputRate; 135*05767d91SRobert Wu } 136*05767d91SRobert Wu getOutputRate()137*05767d91SRobert Wu int32_t getOutputRate() const { 138*05767d91SRobert Wu return mOutputRate; 139*05767d91SRobert Wu } 140*05767d91SRobert Wu getNormalizedCutoff()141*05767d91SRobert Wu float getNormalizedCutoff() const { 142*05767d91SRobert Wu return mNormalizedCutoff; 143*05767d91SRobert Wu } 144*05767d91SRobert Wu 145*05767d91SRobert Wu protected: 146*05767d91SRobert Wu int32_t mChannelCount = 1; 147*05767d91SRobert Wu int32_t mNumTaps = 16; 148*05767d91SRobert Wu int32_t mInputRate = 48000; 149*05767d91SRobert Wu int32_t mOutputRate = 48000; 150*05767d91SRobert Wu float mNormalizedCutoff = kDefaultNormalizedCutoff; 151*05767d91SRobert Wu }; 152*05767d91SRobert Wu 153*05767d91SRobert Wu virtual ~MultiChannelResampler() = default; 154*05767d91SRobert Wu 155*05767d91SRobert Wu /** 156*05767d91SRobert Wu * Factory method for making a resampler that is optimal for the given inputs. 157*05767d91SRobert Wu * 158*05767d91SRobert Wu * @param channelCount number of channels, 2 for stereo 159*05767d91SRobert Wu * @param inputRate sample rate of the input stream 160*05767d91SRobert Wu * @param outputRate sample rate of the output stream 161*05767d91SRobert Wu * @param quality higher quality sounds better but uses more CPU 162*05767d91SRobert Wu * @return an optimal resampler 163*05767d91SRobert Wu */ 164*05767d91SRobert Wu static MultiChannelResampler *make(int32_t channelCount, 165*05767d91SRobert Wu int32_t inputRate, 166*05767d91SRobert Wu int32_t outputRate, 167*05767d91SRobert Wu Quality quality); 168*05767d91SRobert Wu isWriteNeeded()169*05767d91SRobert Wu bool isWriteNeeded() const { 170*05767d91SRobert Wu return mIntegerPhase >= mDenominator; 171*05767d91SRobert Wu } 172*05767d91SRobert Wu 173*05767d91SRobert Wu /** 174*05767d91SRobert Wu * Write a frame containing N samples. 175*05767d91SRobert Wu * 176*05767d91SRobert Wu * @param frame pointer to the first sample in a frame 177*05767d91SRobert Wu */ writeNextFrame(const float * frame)178*05767d91SRobert Wu void writeNextFrame(const float *frame) { 179*05767d91SRobert Wu writeFrame(frame); 180*05767d91SRobert Wu advanceWrite(); 181*05767d91SRobert Wu } 182*05767d91SRobert Wu 183*05767d91SRobert Wu /** 184*05767d91SRobert Wu * Read a frame containing N samples. 185*05767d91SRobert Wu * 186*05767d91SRobert Wu * @param frame pointer to the first sample in a frame 187*05767d91SRobert Wu */ readNextFrame(float * frame)188*05767d91SRobert Wu void readNextFrame(float *frame) { 189*05767d91SRobert Wu readFrame(frame); 190*05767d91SRobert Wu advanceRead(); 191*05767d91SRobert Wu } 192*05767d91SRobert Wu getNumTaps()193*05767d91SRobert Wu int getNumTaps() const { 194*05767d91SRobert Wu return mNumTaps; 195*05767d91SRobert Wu } 196*05767d91SRobert Wu getChannelCount()197*05767d91SRobert Wu int getChannelCount() const { 198*05767d91SRobert Wu return mChannelCount; 199*05767d91SRobert Wu } 200*05767d91SRobert Wu 201*05767d91SRobert Wu static float hammingWindow(float radians, float spread); 202*05767d91SRobert Wu 203*05767d91SRobert Wu static float sinc(float radians); 204*05767d91SRobert Wu 205*05767d91SRobert Wu protected: 206*05767d91SRobert Wu 207*05767d91SRobert Wu explicit MultiChannelResampler(const MultiChannelResampler::Builder &builder); 208*05767d91SRobert Wu 209*05767d91SRobert Wu /** 210*05767d91SRobert Wu * Write a frame containing N samples. 211*05767d91SRobert Wu * Call advanceWrite() after calling this. 212*05767d91SRobert Wu * @param frame pointer to the first sample in a frame 213*05767d91SRobert Wu */ 214*05767d91SRobert Wu virtual void writeFrame(const float *frame); 215*05767d91SRobert Wu 216*05767d91SRobert Wu /** 217*05767d91SRobert Wu * Read a frame containing N samples using interpolation. 218*05767d91SRobert Wu * Call advanceRead() after calling this. 219*05767d91SRobert Wu * @param frame pointer to the first sample in a frame 220*05767d91SRobert Wu */ 221*05767d91SRobert Wu virtual void readFrame(float *frame) = 0; 222*05767d91SRobert Wu advanceWrite()223*05767d91SRobert Wu void advanceWrite() { 224*05767d91SRobert Wu mIntegerPhase -= mDenominator; 225*05767d91SRobert Wu } 226*05767d91SRobert Wu advanceRead()227*05767d91SRobert Wu void advanceRead() { 228*05767d91SRobert Wu mIntegerPhase += mNumerator; 229*05767d91SRobert Wu } 230*05767d91SRobert Wu 231*05767d91SRobert Wu /** 232*05767d91SRobert Wu * Generate the filter coefficients in optimal order. 233*05767d91SRobert Wu * 234*05767d91SRobert Wu * Note that normalizedCutoff is ignored when upsampling, which is when 235*05767d91SRobert Wu * the outputRate is higher than the inputRate. 236*05767d91SRobert Wu * 237*05767d91SRobert Wu * @param inputRate sample rate of the input stream 238*05767d91SRobert Wu * @param outputRate sample rate of the output stream 239*05767d91SRobert Wu * @param numRows number of rows in the array that contain a set of tap coefficients 240*05767d91SRobert Wu * @param phaseIncrement how much to increment the phase between rows 241*05767d91SRobert Wu * @param normalizedCutoff filter cutoff frequency normalized to Nyquist rate of output 242*05767d91SRobert Wu */ 243*05767d91SRobert Wu void generateCoefficients(int32_t inputRate, 244*05767d91SRobert Wu int32_t outputRate, 245*05767d91SRobert Wu int32_t numRows, 246*05767d91SRobert Wu double phaseIncrement, 247*05767d91SRobert Wu float normalizedCutoff); 248*05767d91SRobert Wu 249*05767d91SRobert Wu getIntegerPhase()250*05767d91SRobert Wu int32_t getIntegerPhase() { 251*05767d91SRobert Wu return mIntegerPhase; 252*05767d91SRobert Wu } 253*05767d91SRobert Wu 254*05767d91SRobert Wu static constexpr int kMaxCoefficients = 8 * 1024; 255*05767d91SRobert Wu std::vector<float> mCoefficients; 256*05767d91SRobert Wu 257*05767d91SRobert Wu const int mNumTaps; 258*05767d91SRobert Wu int mCursor = 0; 259*05767d91SRobert Wu std::vector<float> mX; // delayed input values for the FIR 260*05767d91SRobert Wu std::vector<float> mSingleFrame; // one frame for temporary use 261*05767d91SRobert Wu int32_t mIntegerPhase = 0; 262*05767d91SRobert Wu int32_t mNumerator = 0; 263*05767d91SRobert Wu int32_t mDenominator = 0; 264*05767d91SRobert Wu 265*05767d91SRobert Wu 266*05767d91SRobert Wu private: 267*05767d91SRobert Wu 268*05767d91SRobert Wu #if MCR_USE_KAISER 269*05767d91SRobert Wu KaiserWindow mKaiserWindow; 270*05767d91SRobert Wu #else 271*05767d91SRobert Wu HyperbolicCosineWindow mCoshWindow; 272*05767d91SRobert Wu #endif 273*05767d91SRobert Wu 274*05767d91SRobert Wu static constexpr float kDefaultNormalizedCutoff = 0.70f; 275*05767d91SRobert Wu 276*05767d91SRobert Wu const int mChannelCount; 277*05767d91SRobert Wu }; 278*05767d91SRobert Wu 279*05767d91SRobert Wu } /* namespace RESAMPLER_OUTER_NAMESPACE::resampler */ 280*05767d91SRobert Wu 281*05767d91SRobert Wu #endif //RESAMPLER_MULTICHANNEL_RESAMPLER_H 282