Loading services/audioflinger/AudioResampler.cpp +6 −5 Original line number Diff line number Diff line Loading @@ -259,13 +259,14 @@ AudioResampler::AudioResampler(int bitDepth, int inChannelCount, mPhaseFraction(0), mLocalTimeFreq(0), mPTS(AudioBufferProvider::kInvalidPTS), mQuality(quality) { // sanity check on format if ((bitDepth != 16) ||(inChannelCount < 1) || (inChannelCount > 2)) { ALOGE("Unsupported sample format, %d bits, %d channels", bitDepth, inChannelCount); // ALOG_ASSERT(0); if ((bitDepth != 16 && (quality < DYN_LOW_QUALITY || bitDepth != 32)) || inChannelCount < 1 || inChannelCount > (quality < DYN_LOW_QUALITY ? 2 : 8)) { LOG_ALWAYS_FATAL("Unsupported sample format %d quality %d bits, %d channels", quality, bitDepth, inChannelCount); } if (sampleRate <= 0) { ALOGE("Unsupported sample rate %d Hz", sampleRate); LOG_ALWAYS_FATAL("Unsupported sample rate %d Hz", sampleRate); } // initialize common members Loading services/audioflinger/AudioResamplerDyn.cpp +72 −34 Original line number Diff line number Diff line Loading @@ -38,11 +38,6 @@ namespace android { // generate a unique resample type compile-time constant (constexpr) #define RESAMPLETYPE(CHANNELS, LOCKED, STRIDE) \ ((((CHANNELS)-1)&1) | !!(LOCKED)<<1 \ | ((STRIDE)==8 ? 1 : (STRIDE)==16 ? 2 : 0)<<2) /* * InBuffer is a type agnostic input buffer. * Loading Loading @@ -403,12 +398,76 @@ void AudioResamplerDyn<TC, TI, TO>::setSampleRate(int32_t inSampleRate) // determine which resampler to use // check if locked phase (works only if mPhaseIncrement has no "fractional phase bits") int locked = (mPhaseIncrement << (sizeof(mPhaseIncrement)*8 - c.mShift)) == 0; int stride = (c.mHalfNumCoefs&7)==0 ? 16 : (c.mHalfNumCoefs&3)==0 ? 8 : 2; if (locked) { mPhaseFraction = mPhaseFraction >> c.mShift << c.mShift; // remove fractional phase } setResampler(RESAMPLETYPE(mChannelCount, locked, stride)); // stride is the minimum number of filter coefficients processed per loop iteration. // We currently only allow a stride of 16 to match with SIMD processing. // This means that the filter length must be a multiple of 16, // or half the filter length (mHalfNumCoefs) must be a multiple of 8. // // Note: A stride of 2 is achieved with non-SIMD processing. int stride = ((c.mHalfNumCoefs & 7) == 0) ? 16 : 2; LOG_ALWAYS_FATAL_IF(stride < 16, "Resampler stride must be 16 or more"); LOG_ALWAYS_FATAL_IF(mChannelCount > 8 || mChannelCount < 1, "Resampler channels(%d) must be between 1 to 8", mChannelCount); // stride 16 (falls back to stride 2 for machines that do not support NEON) if (locked) { switch (mChannelCount) { case 1: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, true, 16>; break; case 2: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, true, 16>; break; case 3: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<3, true, 16>; break; case 4: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<4, true, 16>; break; case 5: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<5, true, 16>; break; case 6: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<6, true, 16>; break; case 7: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<7, true, 16>; break; case 8: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<8, true, 16>; break; } } else { switch (mChannelCount) { case 1: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, false, 16>; break; case 2: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, false, 16>; break; case 3: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<3, false, 16>; break; case 4: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<4, false, 16>; break; case 5: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<5, false, 16>; break; case 6: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<6, false, 16>; break; case 7: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<7, false, 16>; break; case 8: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<8, false, 16>; break; } } #ifdef DEBUG_RESAMPLER printf("channels:%d %s stride:%d %s coef:%d shift:%d\n", mChannelCount, locked ? "locked" : "interpolated", Loading @@ -423,35 +482,13 @@ void AudioResamplerDyn<TC, TI, TO>::resample(int32_t* out, size_t outFrameCount, (this->*mResampleFunc)(reinterpret_cast<TO*>(out), outFrameCount, provider); } template<typename TC, typename TI, typename TO> void AudioResamplerDyn<TC, TI, TO>::setResampler(unsigned resampleType) { // stride 16 (falls back to stride 2 for machines that do not support NEON) switch (resampleType) { case RESAMPLETYPE(1, true, 16): mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, true, 16>; return; case RESAMPLETYPE(2, true, 16): mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, true, 16>; return; case RESAMPLETYPE(1, false, 16): mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, false, 16>; return; case RESAMPLETYPE(2, false, 16): mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, false, 16>; return; default: LOG_ALWAYS_FATAL("Invalid resampler type: %u", resampleType); mResampleFunc = NULL; return; } } template<typename TC, typename TI, typename TO> template<int CHANNELS, bool LOCKED, int STRIDE> void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider) { // TODO Mono -> Mono is not supported. OUTPUT_CHANNELS reflects minimum of stereo out. const int OUTPUT_CHANNELS = (CHANNELS < 2) ? 2 : CHANNELS; const Constants& c(mConstants); const TC* const coefs = mConstants.mFirCoefs; TI* impulse = mInBuffer.getImpulse(); Loading @@ -459,7 +496,7 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount, uint32_t phaseFraction = mPhaseFraction; const uint32_t phaseIncrement = mPhaseIncrement; size_t outputIndex = 0; size_t outputSampleCount = outFrameCount * 2; // stereo output size_t outputSampleCount = outFrameCount * OUTPUT_CHANNELS; const uint32_t phaseWrapLimit = c.mL << c.mShift; size_t inFrameCount = (phaseIncrement * (uint64_t)outFrameCount + phaseFraction) / phaseWrapLimit; Loading Loading @@ -490,7 +527,7 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount, while (mBuffer.frameCount == 0 && inFrameCount > 0) { mBuffer.frameCount = inFrameCount; provider->getNextBuffer(&mBuffer, calculateOutputPTS(outputIndex / 2)); calculateOutputPTS(outputIndex / OUTPUT_CHANNELS)); if (mBuffer.raw == NULL) { goto resample_exit; } Loading Loading @@ -538,7 +575,8 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount, phaseFraction, phaseWrapLimit, coefShift, halfNumCoefs, coefs, impulse, volumeSimd); outputIndex += 2; outputIndex += OUTPUT_CHANNELS; phaseFraction += phaseIncrement; while (phaseFraction >= phaseWrapLimit) { Loading services/audioflinger/AudioResamplerDyn.h +1 −3 Original line number Diff line number Diff line Loading @@ -110,12 +110,10 @@ private: void createKaiserFir(Constants &c, double stopBandAtten, int inSampleRate, int outSampleRate, double tbwCheat); void setResampler(unsigned resampleType); template<int CHANNELS, bool LOCKED, int STRIDE> void resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider); // declare a pointer to member function for resample // define a pointer to member function type for resample typedef void (AudioResamplerDyn<TC, TI, TO>::*resample_ABP_t)(TO* out, size_t outFrameCount, AudioBufferProvider* provider); Loading services/audioflinger/tests/resampler_tests.cpp +51 −14 Original line number Diff line number Diff line Loading @@ -35,7 +35,8 @@ #include "AudioResampler.h" #include "test_utils.h" void resample(void *output, size_t outputFrames, const std::vector<size_t> &outputIncr, void resample(int channels, void *output, size_t outputFrames, const std::vector<size_t> &outputIncr, android::AudioBufferProvider *provider, android::AudioResampler *resampler) { for (size_t i = 0, j = 0; i < outputFrames; ) { Loading @@ -46,7 +47,7 @@ void resample(void *output, size_t outputFrames, const std::vector<size_t> &outp if (thisFrames == 0 || thisFrames > outputFrames - i) { thisFrames = outputFrames - i; } resampler->resample((int32_t*) output + 2*i, thisFrames, provider); resampler->resample((int32_t*) output + channels*i, thisFrames, provider); i += thisFrames; } } Loading @@ -64,19 +65,26 @@ void buffercmp(const void *reference, const void *test, } } void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFreq, void testBufferIncrement(size_t channels, bool useFloat, unsigned inputFreq, unsigned outputFreq, enum android::AudioResampler::src_quality quality) { const int bits = useFloat ? 32 : 16; // create the provider std::vector<int> inputIncr; SignalProvider provider; if (useFloat) { provider.setChirp<float>(channels, 0., outputFreq/2., outputFreq, outputFreq/2000.); } else { provider.setChirp<int16_t>(channels, 0., outputFreq/2., outputFreq, outputFreq/2000.); } provider.setIncr(inputIncr); // calculate the output size size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq; size_t outputFrameSize = 2 * sizeof(int32_t); size_t outputFrameSize = channels * (useFloat ? sizeof(float) : sizeof(int32_t)); size_t outputSize = outputFrameSize * outputFrames; outputSize &= ~7; Loading @@ -84,7 +92,7 @@ void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFre const int volumePrecision = 12; /* typical unity gain */ android::AudioResampler* resampler; resampler = android::AudioResampler::create(16, channels, outputFreq, quality); resampler = android::AudioResampler::create(bits, channels, outputFreq, quality); resampler->setSampleRate(inputFreq); resampler->setVolume(1 << volumePrecision, 1 << volumePrecision); Loading @@ -92,7 +100,7 @@ void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFre std::vector<size_t> refIncr; refIncr.push_back(outputFrames); void* reference = malloc(outputSize); resample(reference, outputFrames, refIncr, &provider, resampler); resample(channels, reference, outputFrames, refIncr, &provider, resampler); provider.reset(); Loading @@ -101,7 +109,7 @@ void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFre resampler->reset(); #else delete resampler; resampler = android::AudioResampler::create(16, channels, outputFreq, quality); resampler = android::AudioResampler::create(bits, channels, outputFreq, quality); resampler->setSampleRate(inputFreq); resampler->setVolume(1 << volumePrecision, 1 << volumePrecision); #endif Loading @@ -112,7 +120,10 @@ void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFre outIncr.push_back(2); outIncr.push_back(3); void* test = malloc(outputSize); resample(test, outputFrames, outIncr, &provider, resampler); inputIncr.push_back(1); inputIncr.push_back(3); provider.setIncr(inputIncr); resample(channels, test, outputFrames, outIncr, &provider, resampler); // check buffercmp(reference, test, outputFrameSize, outputFrames); Loading Loading @@ -155,7 +166,7 @@ void testStopbandDownconversion(size_t channels, // calculate the output size size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq; size_t outputFrameSize = 2 * sizeof(int32_t); size_t outputFrameSize = channels * sizeof(int32_t); size_t outputSize = outputFrameSize * outputFrames; outputSize &= ~7; Loading @@ -171,7 +182,7 @@ void testStopbandDownconversion(size_t channels, std::vector<size_t> refIncr; refIncr.push_back(outputFrames); void* reference = malloc(outputSize); resample(reference, outputFrames, refIncr, &provider, resampler); resample(channels, reference, outputFrames, refIncr, &provider, resampler); int32_t *out = reinterpret_cast<int32_t *>(reference); Loading Loading @@ -226,7 +237,7 @@ TEST(audioflinger_resampler, bufferincrement_fixedphase) { }; for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) { testBufferIncrement(2, 48000, 32000, kQualityArray[i]); testBufferIncrement(2, false, 48000, 32000, kQualityArray[i]); } } Loading @@ -243,7 +254,33 @@ TEST(audioflinger_resampler, bufferincrement_interpolatedphase) { }; for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) { testBufferIncrement(2, 22050, 48000, kQualityArray[i]); testBufferIncrement(2, false, 22050, 48000, kQualityArray[i]); } } TEST(audioflinger_resampler, bufferincrement_fixedphase_multi) { // only dynamic quality static const enum android::AudioResampler::src_quality kQualityArray[] = { android::AudioResampler::DYN_LOW_QUALITY, android::AudioResampler::DYN_MED_QUALITY, android::AudioResampler::DYN_HIGH_QUALITY, }; for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) { testBufferIncrement(4, false, 48000, 32000, kQualityArray[i]); } } TEST(audioflinger_resampler, bufferincrement_interpolatedphase_multi_float) { // only dynamic quality static const enum android::AudioResampler::src_quality kQualityArray[] = { android::AudioResampler::DYN_LOW_QUALITY, android::AudioResampler::DYN_MED_QUALITY, android::AudioResampler::DYN_HIGH_QUALITY, }; for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) { testBufferIncrement(8, true, 22050, 48000, kQualityArray[i]); } } Loading Loading
services/audioflinger/AudioResampler.cpp +6 −5 Original line number Diff line number Diff line Loading @@ -259,13 +259,14 @@ AudioResampler::AudioResampler(int bitDepth, int inChannelCount, mPhaseFraction(0), mLocalTimeFreq(0), mPTS(AudioBufferProvider::kInvalidPTS), mQuality(quality) { // sanity check on format if ((bitDepth != 16) ||(inChannelCount < 1) || (inChannelCount > 2)) { ALOGE("Unsupported sample format, %d bits, %d channels", bitDepth, inChannelCount); // ALOG_ASSERT(0); if ((bitDepth != 16 && (quality < DYN_LOW_QUALITY || bitDepth != 32)) || inChannelCount < 1 || inChannelCount > (quality < DYN_LOW_QUALITY ? 2 : 8)) { LOG_ALWAYS_FATAL("Unsupported sample format %d quality %d bits, %d channels", quality, bitDepth, inChannelCount); } if (sampleRate <= 0) { ALOGE("Unsupported sample rate %d Hz", sampleRate); LOG_ALWAYS_FATAL("Unsupported sample rate %d Hz", sampleRate); } // initialize common members Loading
services/audioflinger/AudioResamplerDyn.cpp +72 −34 Original line number Diff line number Diff line Loading @@ -38,11 +38,6 @@ namespace android { // generate a unique resample type compile-time constant (constexpr) #define RESAMPLETYPE(CHANNELS, LOCKED, STRIDE) \ ((((CHANNELS)-1)&1) | !!(LOCKED)<<1 \ | ((STRIDE)==8 ? 1 : (STRIDE)==16 ? 2 : 0)<<2) /* * InBuffer is a type agnostic input buffer. * Loading Loading @@ -403,12 +398,76 @@ void AudioResamplerDyn<TC, TI, TO>::setSampleRate(int32_t inSampleRate) // determine which resampler to use // check if locked phase (works only if mPhaseIncrement has no "fractional phase bits") int locked = (mPhaseIncrement << (sizeof(mPhaseIncrement)*8 - c.mShift)) == 0; int stride = (c.mHalfNumCoefs&7)==0 ? 16 : (c.mHalfNumCoefs&3)==0 ? 8 : 2; if (locked) { mPhaseFraction = mPhaseFraction >> c.mShift << c.mShift; // remove fractional phase } setResampler(RESAMPLETYPE(mChannelCount, locked, stride)); // stride is the minimum number of filter coefficients processed per loop iteration. // We currently only allow a stride of 16 to match with SIMD processing. // This means that the filter length must be a multiple of 16, // or half the filter length (mHalfNumCoefs) must be a multiple of 8. // // Note: A stride of 2 is achieved with non-SIMD processing. int stride = ((c.mHalfNumCoefs & 7) == 0) ? 16 : 2; LOG_ALWAYS_FATAL_IF(stride < 16, "Resampler stride must be 16 or more"); LOG_ALWAYS_FATAL_IF(mChannelCount > 8 || mChannelCount < 1, "Resampler channels(%d) must be between 1 to 8", mChannelCount); // stride 16 (falls back to stride 2 for machines that do not support NEON) if (locked) { switch (mChannelCount) { case 1: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, true, 16>; break; case 2: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, true, 16>; break; case 3: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<3, true, 16>; break; case 4: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<4, true, 16>; break; case 5: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<5, true, 16>; break; case 6: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<6, true, 16>; break; case 7: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<7, true, 16>; break; case 8: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<8, true, 16>; break; } } else { switch (mChannelCount) { case 1: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, false, 16>; break; case 2: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, false, 16>; break; case 3: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<3, false, 16>; break; case 4: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<4, false, 16>; break; case 5: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<5, false, 16>; break; case 6: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<6, false, 16>; break; case 7: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<7, false, 16>; break; case 8: mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<8, false, 16>; break; } } #ifdef DEBUG_RESAMPLER printf("channels:%d %s stride:%d %s coef:%d shift:%d\n", mChannelCount, locked ? "locked" : "interpolated", Loading @@ -423,35 +482,13 @@ void AudioResamplerDyn<TC, TI, TO>::resample(int32_t* out, size_t outFrameCount, (this->*mResampleFunc)(reinterpret_cast<TO*>(out), outFrameCount, provider); } template<typename TC, typename TI, typename TO> void AudioResamplerDyn<TC, TI, TO>::setResampler(unsigned resampleType) { // stride 16 (falls back to stride 2 for machines that do not support NEON) switch (resampleType) { case RESAMPLETYPE(1, true, 16): mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, true, 16>; return; case RESAMPLETYPE(2, true, 16): mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, true, 16>; return; case RESAMPLETYPE(1, false, 16): mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, false, 16>; return; case RESAMPLETYPE(2, false, 16): mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, false, 16>; return; default: LOG_ALWAYS_FATAL("Invalid resampler type: %u", resampleType); mResampleFunc = NULL; return; } } template<typename TC, typename TI, typename TO> template<int CHANNELS, bool LOCKED, int STRIDE> void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider) { // TODO Mono -> Mono is not supported. OUTPUT_CHANNELS reflects minimum of stereo out. const int OUTPUT_CHANNELS = (CHANNELS < 2) ? 2 : CHANNELS; const Constants& c(mConstants); const TC* const coefs = mConstants.mFirCoefs; TI* impulse = mInBuffer.getImpulse(); Loading @@ -459,7 +496,7 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount, uint32_t phaseFraction = mPhaseFraction; const uint32_t phaseIncrement = mPhaseIncrement; size_t outputIndex = 0; size_t outputSampleCount = outFrameCount * 2; // stereo output size_t outputSampleCount = outFrameCount * OUTPUT_CHANNELS; const uint32_t phaseWrapLimit = c.mL << c.mShift; size_t inFrameCount = (phaseIncrement * (uint64_t)outFrameCount + phaseFraction) / phaseWrapLimit; Loading Loading @@ -490,7 +527,7 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount, while (mBuffer.frameCount == 0 && inFrameCount > 0) { mBuffer.frameCount = inFrameCount; provider->getNextBuffer(&mBuffer, calculateOutputPTS(outputIndex / 2)); calculateOutputPTS(outputIndex / OUTPUT_CHANNELS)); if (mBuffer.raw == NULL) { goto resample_exit; } Loading Loading @@ -538,7 +575,8 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount, phaseFraction, phaseWrapLimit, coefShift, halfNumCoefs, coefs, impulse, volumeSimd); outputIndex += 2; outputIndex += OUTPUT_CHANNELS; phaseFraction += phaseIncrement; while (phaseFraction >= phaseWrapLimit) { Loading
services/audioflinger/AudioResamplerDyn.h +1 −3 Original line number Diff line number Diff line Loading @@ -110,12 +110,10 @@ private: void createKaiserFir(Constants &c, double stopBandAtten, int inSampleRate, int outSampleRate, double tbwCheat); void setResampler(unsigned resampleType); template<int CHANNELS, bool LOCKED, int STRIDE> void resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider); // declare a pointer to member function for resample // define a pointer to member function type for resample typedef void (AudioResamplerDyn<TC, TI, TO>::*resample_ABP_t)(TO* out, size_t outFrameCount, AudioBufferProvider* provider); Loading
services/audioflinger/tests/resampler_tests.cpp +51 −14 Original line number Diff line number Diff line Loading @@ -35,7 +35,8 @@ #include "AudioResampler.h" #include "test_utils.h" void resample(void *output, size_t outputFrames, const std::vector<size_t> &outputIncr, void resample(int channels, void *output, size_t outputFrames, const std::vector<size_t> &outputIncr, android::AudioBufferProvider *provider, android::AudioResampler *resampler) { for (size_t i = 0, j = 0; i < outputFrames; ) { Loading @@ -46,7 +47,7 @@ void resample(void *output, size_t outputFrames, const std::vector<size_t> &outp if (thisFrames == 0 || thisFrames > outputFrames - i) { thisFrames = outputFrames - i; } resampler->resample((int32_t*) output + 2*i, thisFrames, provider); resampler->resample((int32_t*) output + channels*i, thisFrames, provider); i += thisFrames; } } Loading @@ -64,19 +65,26 @@ void buffercmp(const void *reference, const void *test, } } void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFreq, void testBufferIncrement(size_t channels, bool useFloat, unsigned inputFreq, unsigned outputFreq, enum android::AudioResampler::src_quality quality) { const int bits = useFloat ? 32 : 16; // create the provider std::vector<int> inputIncr; SignalProvider provider; if (useFloat) { provider.setChirp<float>(channels, 0., outputFreq/2., outputFreq, outputFreq/2000.); } else { provider.setChirp<int16_t>(channels, 0., outputFreq/2., outputFreq, outputFreq/2000.); } provider.setIncr(inputIncr); // calculate the output size size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq; size_t outputFrameSize = 2 * sizeof(int32_t); size_t outputFrameSize = channels * (useFloat ? sizeof(float) : sizeof(int32_t)); size_t outputSize = outputFrameSize * outputFrames; outputSize &= ~7; Loading @@ -84,7 +92,7 @@ void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFre const int volumePrecision = 12; /* typical unity gain */ android::AudioResampler* resampler; resampler = android::AudioResampler::create(16, channels, outputFreq, quality); resampler = android::AudioResampler::create(bits, channels, outputFreq, quality); resampler->setSampleRate(inputFreq); resampler->setVolume(1 << volumePrecision, 1 << volumePrecision); Loading @@ -92,7 +100,7 @@ void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFre std::vector<size_t> refIncr; refIncr.push_back(outputFrames); void* reference = malloc(outputSize); resample(reference, outputFrames, refIncr, &provider, resampler); resample(channels, reference, outputFrames, refIncr, &provider, resampler); provider.reset(); Loading @@ -101,7 +109,7 @@ void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFre resampler->reset(); #else delete resampler; resampler = android::AudioResampler::create(16, channels, outputFreq, quality); resampler = android::AudioResampler::create(bits, channels, outputFreq, quality); resampler->setSampleRate(inputFreq); resampler->setVolume(1 << volumePrecision, 1 << volumePrecision); #endif Loading @@ -112,7 +120,10 @@ void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFre outIncr.push_back(2); outIncr.push_back(3); void* test = malloc(outputSize); resample(test, outputFrames, outIncr, &provider, resampler); inputIncr.push_back(1); inputIncr.push_back(3); provider.setIncr(inputIncr); resample(channels, test, outputFrames, outIncr, &provider, resampler); // check buffercmp(reference, test, outputFrameSize, outputFrames); Loading Loading @@ -155,7 +166,7 @@ void testStopbandDownconversion(size_t channels, // calculate the output size size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq; size_t outputFrameSize = 2 * sizeof(int32_t); size_t outputFrameSize = channels * sizeof(int32_t); size_t outputSize = outputFrameSize * outputFrames; outputSize &= ~7; Loading @@ -171,7 +182,7 @@ void testStopbandDownconversion(size_t channels, std::vector<size_t> refIncr; refIncr.push_back(outputFrames); void* reference = malloc(outputSize); resample(reference, outputFrames, refIncr, &provider, resampler); resample(channels, reference, outputFrames, refIncr, &provider, resampler); int32_t *out = reinterpret_cast<int32_t *>(reference); Loading Loading @@ -226,7 +237,7 @@ TEST(audioflinger_resampler, bufferincrement_fixedphase) { }; for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) { testBufferIncrement(2, 48000, 32000, kQualityArray[i]); testBufferIncrement(2, false, 48000, 32000, kQualityArray[i]); } } Loading @@ -243,7 +254,33 @@ TEST(audioflinger_resampler, bufferincrement_interpolatedphase) { }; for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) { testBufferIncrement(2, 22050, 48000, kQualityArray[i]); testBufferIncrement(2, false, 22050, 48000, kQualityArray[i]); } } TEST(audioflinger_resampler, bufferincrement_fixedphase_multi) { // only dynamic quality static const enum android::AudioResampler::src_quality kQualityArray[] = { android::AudioResampler::DYN_LOW_QUALITY, android::AudioResampler::DYN_MED_QUALITY, android::AudioResampler::DYN_HIGH_QUALITY, }; for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) { testBufferIncrement(4, false, 48000, 32000, kQualityArray[i]); } } TEST(audioflinger_resampler, bufferincrement_interpolatedphase_multi_float) { // only dynamic quality static const enum android::AudioResampler::src_quality kQualityArray[] = { android::AudioResampler::DYN_LOW_QUALITY, android::AudioResampler::DYN_MED_QUALITY, android::AudioResampler::DYN_HIGH_QUALITY, }; for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) { testBufferIncrement(8, true, 22050, 48000, kQualityArray[i]); } } Loading