blob: 82b9505b29d59d0a91bb28b5a91d7c953cc45706 [file] [log] [blame]
Andy Hung86eae0e2013-12-09 12:12:46 -08001/*
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>
Mark Salyzyn60d02072016-09-29 08:48:48 -070022#include <android/log.h>
Andy Hung86eae0e2013-12-09 12:12:46 -080023
Andy Hung068561c2017-01-03 17:09:32 -080024#include <media/AudioResampler.h>
Andy Hung86eae0e2013-12-09 12:12:46 -080025
26namespace android {
27
Andy Hung771386e2014-04-08 18:44:38 -070028/* 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
41template<typename TC, typename TI, typename TO>
Andy Hung86eae0e2013-12-09 12:12:46 -080042class AudioResamplerDyn: public AudioResampler {
43public:
Andy Hung3348e362014-07-07 10:21:44 -070044 AudioResamplerDyn(int inChannelCount,
Andy Hung771386e2014-04-08 18:44:38 -070045 int32_t sampleRate, src_quality quality);
Andy Hung86eae0e2013-12-09 12:12:46 -080046
47 virtual ~AudioResamplerDyn();
48
49 virtual void init();
50
51 virtual void setSampleRate(int32_t inSampleRate);
52
Andy Hung5e58b0a2014-06-23 19:07:29 -070053 virtual void setVolume(float left, float right);
Andy Hung86eae0e2013-12-09 12:12:46 -080054
Andy Hung6b3b7e32015-03-29 00:49:22 -070055 virtual size_t resample(int32_t* out, size_t outFrameCount,
Andy Hung86eae0e2013-12-09 12:12:46 -080056 AudioBufferProvider* provider);
57
Andy Hung19c8e3a2018-08-23 19:07:37 -070058 void reset() override {
59 AudioResampler::reset();
60 mInBuffer.reset();
61 }
62
Andy Hung6bd378f2017-10-24 19:23:52 -070063 // Make available key design criteria for testing
64 int getHalfLength() const {
65 return mConstants.mHalfNumCoefs;
66 }
67
68 const TC *getFilterCoefs() const {
69 return mConstants.mFirCoefs;
70 }
71
72 int getPhases() const {
73 return mConstants.mL;
74 }
75
76 double getStopbandAttenuationDb() const {
77 return mStopbandAttenuationDb;
78 }
79
80 double getPassbandRippleDb() const {
81 return mPassbandRippleDb;
82 }
83
84 double getNormalizedTransitionBandwidth() const {
85 return mNormalizedTransitionBandwidth;
86 }
87
88 double getFilterAttenuation() const {
89 return mFilterAttenuation;
90 }
91
92 double getNormalizedCutoffFrequency() const {
93 return mNormalizedCutoffFrequency;
94 }
95
Andy Hung86eae0e2013-12-09 12:12:46 -080096private:
97
98 class Constants { // stores the filter constants.
99 public:
100 Constants() :
Andy Hung771386e2014-04-08 18:44:38 -0700101 mL(0), mShift(0), mHalfNumCoefs(0), mFirCoefs(NULL)
Andy Hung86eae0e2013-12-09 12:12:46 -0800102 {}
103 void set(int L, int halfNumCoefs,
104 int inSampleRate, int outSampleRate);
Andy Hung86eae0e2013-12-09 12:12:46 -0800105
Andy Hung771386e2014-04-08 18:44:38 -0700106 int mL; // interpolation phases in the filter.
107 int mShift; // right shift to get polyphase index
Andy Hung86eae0e2013-12-09 12:12:46 -0800108 unsigned int mHalfNumCoefs; // filter half #coefs
Andy Hung771386e2014-04-08 18:44:38 -0700109 const TC* mFirCoefs; // polyphase filter bank
Andy Hung86eae0e2013-12-09 12:12:46 -0800110 };
111
Andy Hung771386e2014-04-08 18:44:38 -0700112 class InBuffer { // buffer management for input type TI
Andy Hung86eae0e2013-12-09 12:12:46 -0800113 public:
114 InBuffer();
115 ~InBuffer();
116 void init();
Andy Hung771386e2014-04-08 18:44:38 -0700117
Andy Hung86eae0e2013-12-09 12:12:46 -0800118 void resize(int CHANNELS, int halfNumCoefs);
119
120 // used for direct management of the mImpulse pointer
121 inline TI* getImpulse() {
122 return mImpulse;
123 }
Andy Hung771386e2014-04-08 18:44:38 -0700124
Andy Hung86eae0e2013-12-09 12:12:46 -0800125 inline void setImpulse(TI *impulse) {
126 mImpulse = impulse;
127 }
Andy Hung771386e2014-04-08 18:44:38 -0700128
Andy Hung86eae0e2013-12-09 12:12:46 -0800129 template<int CHANNELS>
130 inline void readAgain(TI*& impulse, const int halfNumCoefs,
131 const TI* const in, const size_t inputIndex);
Andy Hung771386e2014-04-08 18:44:38 -0700132
Andy Hung86eae0e2013-12-09 12:12:46 -0800133 template<int CHANNELS>
134 inline void readAdvance(TI*& impulse, const int halfNumCoefs,
135 const TI* const in, const size_t inputIndex);
136
Hochi Huangbd179d12016-03-28 13:30:46 -0700137 void reset();
138
Andy Hung86eae0e2013-12-09 12:12:46 -0800139 private:
140 // tuning parameter guidelines: 2 <= multiple <= 8
141 static const int kStateSizeMultipleOfFilterLength = 4;
142
Andy Hung86eae0e2013-12-09 12:12:46 -0800143 // in general, mRingFull = mState + mStateSize - halfNumCoefs*CHANNELS.
Andy Hung771386e2014-04-08 18:44:38 -0700144 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.
Andy Hung86eae0e2013-12-09 12:12:46 -0800148 };
149
Andy Hung86eae0e2013-12-09 12:12:46 -0800150 void createKaiserFir(Constants &c, double stopBandAtten,
151 int inSampleRate, int outSampleRate, double tbwCheat);
152
Andy Hung6bd378f2017-10-24 19:23:52 -0700153 void createKaiserFir(Constants &c, double stopBandAtten, double fcr);
154
Andy Hung771386e2014-04-08 18:44:38 -0700155 template<int CHANNELS, bool LOCKED, int STRIDE>
Andy Hung6b3b7e32015-03-29 00:49:22 -0700156 size_t resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider);
Andy Hung771386e2014-04-08 18:44:38 -0700157
Andy Hung075abae2014-04-09 19:36:43 -0700158 // define a pointer to member function type for resample
Andy Hung6b3b7e32015-03-29 00:49:22 -0700159 typedef size_t (AudioResamplerDyn<TC, TI, TO>::*resample_ABP_t)(TO* out,
Andy Hung771386e2014-04-08 18:44:38 -0700160 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
Andy Hung6bd378f2017-10-24 19:23:52 -0700170
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
Andy Hung86571a92019-04-02 15:40:54 -0700196 // 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
Andy Hung6bd378f2017-10-24 19:23:52 -0700203 // 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.;
Andy Hung86eae0e2013-12-09 12:12:46 -0800209};
210
Glenn Kasten63238ef2015-03-02 15:50:29 -0800211} // namespace android
Andy Hung86eae0e2013-12-09 12:12:46 -0800212
213#endif /*ANDROID_AUDIO_RESAMPLER_DYN_H*/