1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_AUDIO_RESAMPLER_DYN_H
18 #define ANDROID_AUDIO_RESAMPLER_DYN_H
19 
20 #include <stdint.h>
21 #include <sys/types.h>
22 #include <android/log.h>
23 
24 #include <media/AudioResampler.h>
25 
26 namespace android {
27 
28 /* AudioResamplerDyn
29  *
30  * This class template is used for floating point and integer resamplers.
31  *
32  * Type variables:
33  * TC = filter coefficient type (one of int16_t, int32_t, or float)
34  * TI = input data type (one of int16_t or float)
35  * TO = output data type (one of int32_t or float)
36  *
37  * For integer input data types TI, the coefficient type TC is either int16_t or int32_t.
38  * For float input data types TI, the coefficient type TC is float.
39  */
40 
41 template<typename TC, typename TI, typename TO>
42 class AudioResamplerDyn: public AudioResampler {
43 public:
44     AudioResamplerDyn(int inChannelCount,
45             int32_t sampleRate, src_quality quality);
46 
47     virtual ~AudioResamplerDyn();
48 
49     virtual void init();
50 
51     virtual void setSampleRate(int32_t inSampleRate);
52 
53     virtual void setVolume(float left, float right);
54 
55     virtual size_t resample(int32_t* out, size_t outFrameCount,
56             AudioBufferProvider* provider);
57 
reset()58     void reset() override {
59         AudioResampler::reset();
60         mInBuffer.reset();
61     }
62 
63     // Make available key design criteria for testing
getHalfLength()64     int getHalfLength() const {
65         return mConstants.mHalfNumCoefs;
66     }
67 
getFilterCoefs()68     const TC *getFilterCoefs() const {
69         return mConstants.mFirCoefs;
70     }
71 
getPhases()72     int getPhases() const {
73         return mConstants.mL;
74     }
75 
getStopbandAttenuationDb()76     double getStopbandAttenuationDb() const {
77         return mStopbandAttenuationDb;
78     }
79 
getPassbandRippleDb()80     double getPassbandRippleDb() const {
81         return mPassbandRippleDb;
82     }
83 
getNormalizedTransitionBandwidth()84     double getNormalizedTransitionBandwidth() const {
85         return mNormalizedTransitionBandwidth;
86     }
87 
getFilterAttenuation()88     double getFilterAttenuation() const {
89         return mFilterAttenuation;
90     }
91 
getNormalizedCutoffFrequency()92     double getNormalizedCutoffFrequency() const {
93         return mNormalizedCutoffFrequency;
94     }
95 
96 private:
97 
98     class Constants { // stores the filter constants.
99     public:
Constants()100         Constants() :
101             mL(0), mShift(0), mHalfNumCoefs(0), mFirCoefs(NULL)
102         {}
103         void set(int L, int halfNumCoefs,
104                 int inSampleRate, int outSampleRate);
105 
106                  int mL;            // interpolation phases in the filter.
107                  int mShift;        // right shift to get polyphase index
108         unsigned int mHalfNumCoefs; // filter half #coefs
109            const TC* mFirCoefs;     // polyphase filter bank
110     };
111 
112     class InBuffer { // buffer management for input type TI
113     public:
114         InBuffer();
115         ~InBuffer();
116         void init();
117 
118         void resize(int CHANNELS, int halfNumCoefs);
119 
120         // used for direct management of the mImpulse pointer
getImpulse()121         inline TI* getImpulse() {
122             return mImpulse;
123         }
124 
setImpulse(TI * impulse)125         inline void setImpulse(TI *impulse) {
126             mImpulse = impulse;
127         }
128 
129         template<int CHANNELS>
130         inline void readAgain(TI*& impulse, const int halfNumCoefs,
131                 const TI* const in, const size_t inputIndex);
132 
133         template<int CHANNELS>
134         inline void readAdvance(TI*& impulse, const int halfNumCoefs,
135                 const TI* const in, const size_t inputIndex);
136 
137         void reset();
138 
139     private:
140         // tuning parameter guidelines: 2 <= multiple <= 8
141         static const int kStateSizeMultipleOfFilterLength = 4;
142 
143         // in general, mRingFull = mState + mStateSize - halfNumCoefs*CHANNELS.
144            TI* mState;      // base pointer for the input buffer storage
145            TI* mImpulse;    // current location of the impulse response (centered)
146            TI* mRingFull;   // mState <= mImpulse < mRingFull
147         size_t mStateCount; // size of state in units of TI.
148     };
149 
150     void createKaiserFir(Constants &c, double stopBandAtten,
151             int inSampleRate, int outSampleRate, double tbwCheat);
152 
153     void createKaiserFir(Constants &c, double stopBandAtten, double fcr);
154 
155     template<int CHANNELS, bool LOCKED, int STRIDE>
156     size_t resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider);
157 
158     // define a pointer to member function type for resample
159     typedef size_t (AudioResamplerDyn<TC, TI, TO>::*resample_ABP_t)(TO* out,
160             size_t outFrameCount, AudioBufferProvider* provider);
161 
162     // data - the contiguous storage and layout of these is important.
163            InBuffer mInBuffer;
164           Constants mConstants;        // current set of coefficient parameters
165     TO __attribute__ ((aligned (8))) mVolumeSimd[2]; // must be aligned or NEON may crash
166      resample_ABP_t mResampleFunc;     // called function for resampling
167             int32_t mFilterSampleRate; // designed filter sample rate.
168         src_quality mFilterQuality;    // designed filter quality.
169               void* mCoefBuffer;       // if a filter is created, this is not null
170 
171     // Property selected design parameters.
172               // This will enable fixed high quality resampling.
173 
174               // 32 char PROP_NAME_MAX limit enforced before Android O
175 
176               // Use for sample rates greater than or equal to this value.
177               // Set to non-negative to enable, negative to disable.
178               int32_t mPropertyEnableAtSampleRate = 48000;
179                       // "ro.audio.resampler.psd.enable_at_samplerate"
180 
181               // Specify HALF the resampling filter length.
182               // Set to a value which is a multiple of 4.
183               int32_t mPropertyHalfFilterLength = 32;
184                       // "ro.audio.resampler.psd.halflength"
185 
186               // Specify the stopband attenuation in positive dB.
187               // Set to a value greater or equal to 20.
188               int32_t mPropertyStopbandAttenuation = 90;
189                       // "ro.audio.resampler.psd.stopband"
190 
191               // Specify the cutoff frequency as a percentage of Nyquist.
192               // Set to a value between 50 and 100.
193               int32_t mPropertyCutoffPercent = 100;
194                       // "ro.audio.resampler.psd.cutoff_percent"
195 
196               // Specify the transition bandwidth extension beyond Nyquist.
197               // If this is nonzero then mPropertyCutoffPercent is ignored.
198               // A value of 100 or greater is typically used, where 100 means the
199               // stopband is at Nyquist (this is a typical design).
200               int32_t mPropertyTransitionBandwidthCheat = 0;
201                       // "ro.audio.resampler.psd.tbwcheat"
202 
203     // Filter creation design parameters, see setSampleRate()
204              double mStopbandAttenuationDb = 0.;
205              double mPassbandRippleDb = 0.;
206              double mNormalizedTransitionBandwidth = 0.;
207              double mFilterAttenuation = 0.;
208              double mNormalizedCutoffFrequency = 0.;
209 };
210 
211 } // namespace android
212 
213 #endif /*ANDROID_AUDIO_RESAMPLER_DYN_H*/
214