You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
7.3 KiB
214 lines
7.3 KiB
4 months ago
|
/*
|
||
|
* 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 <stdint.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <android/log.h>
|
||
|
|
||
|
#include <media/AudioResampler.h>
|
||
|
|
||
|
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<typename TC, typename TI, typename TO>
|
||
|
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<int CHANNELS>
|
||
|
inline void readAgain(TI*& impulse, const int halfNumCoefs,
|
||
|
const TI* const in, const size_t inputIndex);
|
||
|
|
||
|
template<int CHANNELS>
|
||
|
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<int CHANNELS, bool LOCKED, int STRIDE>
|
||
|
size_t resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider);
|
||
|
|
||
|
// define a pointer to member function type for resample
|
||
|
typedef size_t (AudioResamplerDyn<TC, TI, TO>::*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*/
|