/* * Copyright (C) 2013 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 ANDROID_AUDIO_RESAMPLER_DYN_H #define ANDROID_AUDIO_RESAMPLER_DYN_H #include #include #include #include namespace android { /* AudioResamplerDyn * * This class template is used for floating point and integer resamplers. * * Type variables: * TC = filter coefficient type (one of int16_t, int32_t, or float) * TI = input data type (one of int16_t or float) * TO = output data type (one of int32_t or float) * * For integer input data types TI, the coefficient type TC is either int16_t or int32_t. * For float input data types TI, the coefficient type TC is float. */ template class AudioResamplerDyn: public AudioResampler { public: AudioResamplerDyn(int inChannelCount, int32_t sampleRate, src_quality quality); virtual ~AudioResamplerDyn(); virtual void init(); virtual void setSampleRate(int32_t inSampleRate); virtual void setVolume(float left, float right); virtual size_t resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); void reset() override { AudioResampler::reset(); mInBuffer.reset(); } // Make available key design criteria for testing int getHalfLength() const { return mConstants.mHalfNumCoefs; } const TC *getFilterCoefs() const { return mConstants.mFirCoefs; } int getPhases() const { return mConstants.mL; } double getStopbandAttenuationDb() const { return mStopbandAttenuationDb; } double getPassbandRippleDb() const { return mPassbandRippleDb; } double getNormalizedTransitionBandwidth() const { return mNormalizedTransitionBandwidth; } double getFilterAttenuation() const { return mFilterAttenuation; } double getNormalizedCutoffFrequency() const { return mNormalizedCutoffFrequency; } private: class Constants { // stores the filter constants. public: Constants() : mL(0), mShift(0), mHalfNumCoefs(0), mFirCoefs(NULL) {} void set(int L, int halfNumCoefs, int inSampleRate, int outSampleRate); int mL; // interpolation phases in the filter. int mShift; // right shift to get polyphase index unsigned int mHalfNumCoefs; // filter half #coefs const TC* mFirCoefs; // polyphase filter bank }; class InBuffer { // buffer management for input type TI public: InBuffer(); ~InBuffer(); void init(); void resize(int CHANNELS, int halfNumCoefs); // used for direct management of the mImpulse pointer inline TI* getImpulse() { return mImpulse; } inline void setImpulse(TI *impulse) { mImpulse = impulse; } template inline void readAgain(TI*& impulse, const int halfNumCoefs, const TI* const in, const size_t inputIndex); template inline void readAdvance(TI*& impulse, const int halfNumCoefs, const TI* const in, const size_t inputIndex); void reset(); private: // tuning parameter guidelines: 2 <= multiple <= 8 static const int kStateSizeMultipleOfFilterLength = 4; // in general, mRingFull = mState + mStateSize - halfNumCoefs*CHANNELS. TI* mState; // base pointer for the input buffer storage TI* mImpulse; // current location of the impulse response (centered) TI* mRingFull; // mState <= mImpulse < mRingFull size_t mStateCount; // size of state in units of TI. }; void createKaiserFir(Constants &c, double stopBandAtten, int inSampleRate, int outSampleRate, double tbwCheat); void createKaiserFir(Constants &c, double stopBandAtten, double fcr); template size_t resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider); // define a pointer to member function type for resample typedef size_t (AudioResamplerDyn::*resample_ABP_t)(TO* out, size_t outFrameCount, AudioBufferProvider* provider); // data - the contiguous storage and layout of these is important. InBuffer mInBuffer; Constants mConstants; // current set of coefficient parameters TO __attribute__ ((aligned (8))) mVolumeSimd[2]; // must be aligned or NEON may crash resample_ABP_t mResampleFunc; // called function for resampling int32_t mFilterSampleRate; // designed filter sample rate. src_quality mFilterQuality; // designed filter quality. void* mCoefBuffer; // if a filter is created, this is not null // Property selected design parameters. // This will enable fixed high quality resampling. // 32 char PROP_NAME_MAX limit enforced before Android O // Use for sample rates greater than or equal to this value. // Set to non-negative to enable, negative to disable. int32_t mPropertyEnableAtSampleRate = 48000; // "ro.audio.resampler.psd.enable_at_samplerate" // Specify HALF the resampling filter length. // Set to a value which is a multiple of 4. int32_t mPropertyHalfFilterLength = 32; // "ro.audio.resampler.psd.halflength" // Specify the stopband attenuation in positive dB. // Set to a value greater or equal to 20. int32_t mPropertyStopbandAttenuation = 90; // "ro.audio.resampler.psd.stopband" // Specify the cutoff frequency as a percentage of Nyquist. // Set to a value between 50 and 100. int32_t mPropertyCutoffPercent = 100; // "ro.audio.resampler.psd.cutoff_percent" // Specify the transition bandwidth extension beyond Nyquist. // If this is nonzero then mPropertyCutoffPercent is ignored. // A value of 100 or greater is typically used, where 100 means the // stopband is at Nyquist (this is a typical design). int32_t mPropertyTransitionBandwidthCheat = 0; // "ro.audio.resampler.psd.tbwcheat" // Filter creation design parameters, see setSampleRate() double mStopbandAttenuationDb = 0.; double mPassbandRippleDb = 0.; double mNormalizedTransitionBandwidth = 0.; double mFilterAttenuation = 0.; double mNormalizedCutoffFrequency = 0.; }; } // namespace android #endif /*ANDROID_AUDIO_RESAMPLER_DYN_H*/