diff options
Diffstat (limited to 'services/audioflinger/AudioResamplerSinc.cpp')
-rw-r--r-- | services/audioflinger/AudioResamplerSinc.cpp | 177 |
1 files changed, 95 insertions, 82 deletions
diff --git a/services/audioflinger/AudioResamplerSinc.cpp b/services/audioflinger/AudioResamplerSinc.cpp index 0ae4b64..90651f1 100644 --- a/services/audioflinger/AudioResamplerSinc.cpp +++ b/services/audioflinger/AudioResamplerSinc.cpp @@ -64,13 +64,65 @@ const int32_t AudioResamplerSinc::mFirCoefsDown[] = { 0x00000000 // this one is needed for lerping the last coefficient }; -//Define the static variables -int AudioResamplerSinc::coefsBits; -int AudioResamplerSinc::cShift; -uint32_t AudioResamplerSinc::cMask; -int AudioResamplerSinc::pShift; -uint32_t AudioResamplerSinc::pMask; -unsigned int AudioResamplerSinc::halfNumCoefs; +// we use 15 bits to interpolate between these samples +// this cannot change because the mul below rely on it. +static const int pLerpBits = 15; + +static pthread_once_t once_control = PTHREAD_ONCE_INIT; +static readCoefficientsFn readResampleCoefficients = NULL; + +/*static*/ AudioResamplerSinc::Constants AudioResamplerSinc::highQualityConstants; +/*static*/ AudioResamplerSinc::Constants AudioResamplerSinc::veryHighQualityConstants; + +void AudioResamplerSinc::init_routine() +{ + // for high quality resampler, the parameters for coefficients are compile-time constants + Constants *c = &highQualityConstants; + c->coefsBits = RESAMPLE_FIR_LERP_INT_BITS; + c->cShift = kNumPhaseBits - c->coefsBits; + c->cMask = ((1<< c->coefsBits)-1) << c->cShift; + c->pShift = kNumPhaseBits - c->coefsBits - pLerpBits; + c->pMask = ((1<< pLerpBits)-1) << c->pShift; + c->halfNumCoefs = RESAMPLE_FIR_NUM_COEF; + + // for very high quality resampler, the parameters are load-time constants + veryHighQualityConstants = highQualityConstants; + + // Open the dll to get the coefficients for VERY_HIGH_QUALITY + void *resampleCoeffLib = dlopen("libaudio-resampler.so", RTLD_NOW); + ALOGV("Open libaudio-resampler library = %p", resampleCoeffLib); + if (resampleCoeffLib == NULL) { + ALOGE("Could not open audio-resampler library: %s", dlerror()); + return; + } + + readResampleCoefficients = (readCoefficientsFn) dlsym(resampleCoeffLib, + "readResamplerCoefficients"); + readResampleFirNumCoeffFn readResampleFirNumCoeff = (readResampleFirNumCoeffFn) + dlsym(resampleCoeffLib, "readResampleFirNumCoeff"); + readResampleFirLerpIntBitsFn readResampleFirLerpIntBits = (readResampleFirLerpIntBitsFn) + dlsym(resampleCoeffLib, "readResampleFirLerpIntBits"); + if (!readResampleCoefficients || !readResampleFirNumCoeff || !readResampleFirLerpIntBits) { + readResampleCoefficients = NULL; + dlclose(resampleCoeffLib); + resampleCoeffLib = NULL; + ALOGE("Could not find symbol: %s", dlerror()); + return; + } + + c = &veryHighQualityConstants; + // we have 16 coefs samples per zero-crossing + c->coefsBits = readResampleFirLerpIntBits(); + ALOGV("coefsBits = %d", c->coefsBits); + c->cShift = kNumPhaseBits - c->coefsBits; + c->cMask = ((1<<c->coefsBits)-1) << c->cShift; + c->pShift = kNumPhaseBits - c->coefsBits - pLerpBits; + c->pMask = ((1<<pLerpBits)-1) << c->pShift; + // number of zero-crossing on each side + c->halfNumCoefs = readResampleFirNumCoeff(); + ALOGV("halfNumCoefs = %d", c->halfNumCoefs); + // note that we "leak" resampleCoeffLib until the process exits +} // ---------------------------------------------------------------------------- @@ -148,8 +200,8 @@ int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a) // ---------------------------------------------------------------------------- AudioResamplerSinc::AudioResamplerSinc(int bitDepth, - int inChannelCount, int32_t sampleRate, int32_t quality) - : AudioResampler(bitDepth, inChannelCount, sampleRate), + int inChannelCount, int32_t sampleRate, src_quality quality) + : AudioResampler(bitDepth, inChannelCount, sampleRate, quality), mState(0) { /* @@ -168,74 +220,28 @@ AudioResamplerSinc::AudioResamplerSinc(int bitDepth, * */ - mResampleCoeffLib = NULL; - //Intialize the parameters for resampler coefficients - //for high quality - coefsBits = RESAMPLE_FIR_LERP_INT_BITS; - cShift = kNumPhaseBits - coefsBits; - cMask = ((1<< coefsBits)-1) << cShift; - - pShift = kNumPhaseBits - coefsBits - pLerpBits; - pMask = ((1<< pLerpBits)-1) << pShift; - - halfNumCoefs = RESAMPLE_FIR_NUM_COEF; - - //Check if qcom highest quality can be used - char value[PROPERTY_VALUE_MAX]; - //Open the dll to get the coefficients for VERY_HIGH_QUALITY - if (quality == VERY_HIGH_QUALITY ) { - mResampleCoeffLib = dlopen("libaudio-resampler.so", RTLD_NOW); - ALOGV("Open libaudio-resampler library = %p",mResampleCoeffLib); - if (mResampleCoeffLib == NULL) { - ALOGE("Could not open audio-resampler library: %s", dlerror()); - return; - } - mReadResampleCoefficients = (readCoefficientsFn)dlsym(mResampleCoeffLib, "readResamplerCoefficients"); - mReadResampleFirNumCoeff = (readResampleFirNumCoeffFn)dlsym(mResampleCoeffLib, "readResampleFirNumCoeff"); - mReadResampleFirLerpIntBits = (readResampleFirLerpIntBitsFn)dlsym(mResampleCoeffLib,"readResampleFirLerpIntBits"); - if (!mReadResampleCoefficients || !mReadResampleFirNumCoeff || !mReadResampleFirLerpIntBits) { - mReadResampleCoefficients = NULL; - mReadResampleFirNumCoeff = NULL; - mReadResampleFirLerpIntBits = NULL; - dlclose(mResampleCoeffLib); - mResampleCoeffLib = NULL; - ALOGE("Could not find convert symbol: %s", dlerror()); - return; - } - // we have 16 coefs samples per zero-crossing - coefsBits = mReadResampleFirLerpIntBits(); - ALOGV("coefsBits = %d",coefsBits); - cShift = kNumPhaseBits - coefsBits; - cMask = ((1<<coefsBits)-1) << cShift; - pShift = kNumPhaseBits - coefsBits - pLerpBits; - pMask = ((1<<pLerpBits)-1) << pShift; - // number of zero-crossing on each side - halfNumCoefs = mReadResampleFirNumCoeff(); - ALOGV("halfNumCoefs = %d",halfNumCoefs); + // Load the constants for coefficients + int ok = pthread_once(&once_control, init_routine); + if (ok != 0) { + ALOGE("%s pthread_once failed: %d", __func__, ok); } + mConstants = (quality == VERY_HIGH_QUALITY) ? &veryHighQualityConstants : &highQualityConstants; } AudioResamplerSinc::~AudioResamplerSinc() { - if(mResampleCoeffLib) { - ALOGV("close the libaudio-resampler library"); - dlclose(mResampleCoeffLib); - mResampleCoeffLib = NULL; - mReadResampleCoefficients = NULL; - mReadResampleFirNumCoeff = NULL; - mReadResampleFirLerpIntBits = NULL; - } - delete [] mState; + delete[] mState; } void AudioResamplerSinc::init() { + const Constants *c = mConstants; - const size_t numCoefs = 2*halfNumCoefs; + const size_t numCoefs = 2*c->halfNumCoefs; const size_t stateSize = numCoefs * mChannelCount * 2; mState = new int16_t[stateSize]; memset(mState, 0, sizeof(int16_t)*stateSize); - mImpulse = mState + (halfNumCoefs-1)*mChannelCount; + mImpulse = mState + (c->halfNumCoefs-1)*mChannelCount; mRingFull = mImpulse + (numCoefs+1)*mChannelCount; } @@ -243,11 +249,14 @@ void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) { - if(mResampleCoeffLib){ + // FIXME store current state (up or down sample) and only load the coefs when the state + // changes. Or load two pointers one for up and one for down in the init function. + // Not critical now since the read functions are fast, but would be important if read was slow. + if (readResampleCoefficients) { ALOGV("get coefficient from libmm-audio resampler library"); - mFirCoefs = (mInSampleRate <= mSampleRate) ? mReadResampleCoefficients(true) : mReadResampleCoefficients(false); - } - else { + mFirCoefs = (mInSampleRate <= mSampleRate) ? readResampleCoefficients(true) : + readResampleCoefficients(false); + } else { ALOGV("Use default coefficients"); mFirCoefs = (mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown; } @@ -269,6 +278,7 @@ template<int CHANNELS> void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) { + const Constants *c = mConstants; int16_t* impulse = mImpulse; uint32_t vRL = mVolumeRL; size_t inputIndex = mInputIndex; @@ -307,7 +317,7 @@ void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, const size_t frameCount = mBuffer.frameCount; // Always read-in the first samples from the input buffer - int16_t* head = impulse + halfNumCoefs*CHANNELS; + int16_t* head = impulse + c->halfNumCoefs*CHANNELS; head[0] = in[inputIndex*CHANNELS + 0]; if (CHANNELS == 2) head[1] = in[inputIndex*CHANNELS + 1]; @@ -365,15 +375,16 @@ void AudioResamplerSinc::read( int16_t*& impulse, uint32_t& phaseFraction, const int16_t* in, size_t inputIndex) { + const Constants *c = mConstants; const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; impulse += CHANNELS; phaseFraction -= 1LU<<kNumPhaseBits; if (impulse >= mRingFull) { - const size_t stateSize = (halfNumCoefs*2)*CHANNELS; + const size_t stateSize = (c->halfNumCoefs*2)*CHANNELS; memcpy(mState, mState+stateSize, sizeof(int16_t)*stateSize); impulse -= stateSize; } - int16_t* head = impulse + halfNumCoefs*CHANNELS; + int16_t* head = impulse + c->halfNumCoefs*CHANNELS; head[0] = in[inputIndex*CHANNELS + 0]; if (CHANNELS == 2) head[1] = in[inputIndex*CHANNELS + 1]; @@ -383,15 +394,17 @@ template<int CHANNELS> void AudioResamplerSinc::filterCoefficient( int32_t& l, int32_t& r, uint32_t phase, const int16_t *samples) { + const Constants *c = mConstants; + // compute the index of the coefficient on the positive side and // negative side - uint32_t indexP = (phase & cMask) >> cShift; - uint16_t lerpP = (phase & pMask) >> pShift; - uint32_t indexN = (-phase & cMask) >> cShift; - uint16_t lerpN = (-phase & pMask) >> pShift; + uint32_t indexP = (phase & c->cMask) >> c->cShift; + uint16_t lerpP = (phase & c->pMask) >> c->pShift; + uint32_t indexN = (-phase & c->cMask) >> c->cShift; + uint16_t lerpN = (-phase & c->pMask) >> c->pShift; if ((indexP == 0) && (lerpP == 0)) { - indexN = cMask >> cShift; - lerpN = pMask >> pShift; + indexN = c->cMask >> c->cShift; + lerpN = c->pMask >> c->pShift; } l = 0; @@ -399,19 +412,19 @@ void AudioResamplerSinc::filterCoefficient( const int32_t* coefs = mFirCoefs; const int16_t *sP = samples; const int16_t *sN = samples+CHANNELS; - for (unsigned int i=0 ; i<halfNumCoefs/4 ; i++) { + for (unsigned int i=0 ; i < c->halfNumCoefs/4 ; i++) { interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; + sP -= CHANNELS; sN += CHANNELS; coefs += 1 << c->coefsBits; interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; + sP -= CHANNELS; sN += CHANNELS; coefs += 1 << c->coefsBits; interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; + sP -= CHANNELS; sN += CHANNELS; coefs += 1 << c->coefsBits; interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; + sP -= CHANNELS; sN += CHANNELS; coefs += 1 << c->coefsBits; } } |