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

/*
* 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*/