186eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung/*
286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung * Copyright (C) 2013 The Android Open Source Project
386eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung *
486eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung * Licensed under the Apache License, Version 2.0 (the "License");
586eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung * you may not use this file except in compliance with the License.
686eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung * You may obtain a copy of the License at
786eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung *
886eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung *      http://www.apache.org/licenses/LICENSE-2.0
986eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung *
1086eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung * Unless required by applicable law or agreed to in writing, software
1186eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung * distributed under the License is distributed on an "AS IS" BASIS,
1286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1386eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung * See the License for the specific language governing permissions and
1486eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung * limitations under the License.
1586eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung */
1686eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
1786eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung#ifndef ANDROID_AUDIO_RESAMPLER_DYN_H
1886eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung#define ANDROID_AUDIO_RESAMPLER_DYN_H
1986eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
2086eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung#include <stdint.h>
2186eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung#include <sys/types.h>
2286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung#include <cutils/log.h>
2386eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
2486eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung#include "AudioResampler.h"
2586eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
2686eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hungnamespace android {
2786eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
28771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung/* AudioResamplerDyn
29771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung *
30771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung * This class template is used for floating point and integer resamplers.
31771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung *
32771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung * Type variables:
33771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung * TC = filter coefficient type (one of int16_t, int32_t, or float)
34771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung * TI = input data type (one of int16_t or float)
35771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung * TO = output data type (one of int32_t or float)
36771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung *
37771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung * For integer input data types TI, the coefficient type TC is either int16_t or int32_t.
38771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung * For float input data types TI, the coefficient type TC is float.
39771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung */
40771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung
41771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hungtemplate<typename TC, typename TI, typename TO>
4286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hungclass AudioResamplerDyn: public AudioResampler {
4386eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hungpublic:
443348e36c51e91e78020bcc6578eda83d97c31becAndy Hung    AudioResamplerDyn(int inChannelCount,
45771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung            int32_t sampleRate, src_quality quality);
4686eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
4786eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung    virtual ~AudioResamplerDyn();
4886eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
4986eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung    virtual void init();
5086eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
5186eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung    virtual void setSampleRate(int32_t inSampleRate);
5286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
535e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung    virtual void setVolume(float left, float right);
5486eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
556b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung    virtual size_t resample(int32_t* out, size_t outFrameCount,
5686eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung            AudioBufferProvider* provider);
5786eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
5886eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hungprivate:
5986eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
6086eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung    class Constants { // stores the filter constants.
6186eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung    public:
6286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        Constants() :
63771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung            mL(0), mShift(0), mHalfNumCoefs(0), mFirCoefs(NULL)
6486eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        {}
6586eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        void set(int L, int halfNumCoefs,
6686eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung                int inSampleRate, int outSampleRate);
6786eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
68771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung                 int mL;            // interpolation phases in the filter.
69771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung                 int mShift;        // right shift to get polyphase index
7086eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        unsigned int mHalfNumCoefs; // filter half #coefs
71771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung           const TC* mFirCoefs;     // polyphase filter bank
7286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung    };
7386eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
74771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung    class InBuffer { // buffer management for input type TI
7586eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung    public:
7686eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        InBuffer();
7786eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        ~InBuffer();
7886eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        void init();
79771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung
8086eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        void resize(int CHANNELS, int halfNumCoefs);
8186eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
8286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        // used for direct management of the mImpulse pointer
8386eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        inline TI* getImpulse() {
8486eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung            return mImpulse;
8586eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        }
86771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung
8786eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        inline void setImpulse(TI *impulse) {
8886eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung            mImpulse = impulse;
8986eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        }
90771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung
9186eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        template<int CHANNELS>
9286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        inline void readAgain(TI*& impulse, const int halfNumCoefs,
9386eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung                const TI* const in, const size_t inputIndex);
94771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung
9586eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        template<int CHANNELS>
9686eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        inline void readAdvance(TI*& impulse, const int halfNumCoefs,
9786eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung                const TI* const in, const size_t inputIndex);
9886eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
9986eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung    private:
10086eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        // tuning parameter guidelines: 2 <= multiple <= 8
10186eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        static const int kStateSizeMultipleOfFilterLength = 4;
10286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
10386eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung        // in general, mRingFull = mState + mStateSize - halfNumCoefs*CHANNELS.
104771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung           TI* mState;      // base pointer for the input buffer storage
105771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung           TI* mImpulse;    // current location of the impulse response (centered)
106771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung           TI* mRingFull;   // mState <= mImpulse < mRingFull
107771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung        size_t mStateCount; // size of state in units of TI.
10886eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung    };
10986eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
11086eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung    void createKaiserFir(Constants &c, double stopBandAtten,
11186eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung            int inSampleRate, int outSampleRate, double tbwCheat);
11286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
113771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung    template<int CHANNELS, bool LOCKED, int STRIDE>
1146b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung    size_t resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider);
115771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung
116075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    // define a pointer to member function type for resample
1176b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung    typedef size_t (AudioResamplerDyn<TC, TI, TO>::*resample_ABP_t)(TO* out,
118771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung            size_t outFrameCount, AudioBufferProvider* provider);
119771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung
120771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung    // data - the contiguous storage and layout of these is important.
121771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung           InBuffer mInBuffer;
122771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung          Constants mConstants;        // current set of coefficient parameters
123771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung    TO __attribute__ ((aligned (8))) mVolumeSimd[2]; // must be aligned or NEON may crash
124771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung     resample_ABP_t mResampleFunc;     // called function for resampling
125771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung            int32_t mFilterSampleRate; // designed filter sample rate.
126771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung        src_quality mFilterQuality;    // designed filter quality.
127771386e6e6e79697e2d839ef0f25a242946ba1e5Andy Hung              void* mCoefBuffer;       // if a filter is created, this is not null
12886eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung};
12986eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
13063238efb0d674758902918e3cdaac322126484b7Glenn Kasten} // namespace android
13186eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung
13286eae0e5931103e040ac2cdd023ef5db252e09f6Andy Hung#endif /*ANDROID_AUDIO_RESAMPLER_DYN_H*/
133