From 6b3b7e304e0f8f167241b2c75f1eb04a9ef192ec Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Sun, 29 Mar 2015 00:49:22 -0700 Subject: Return number of frames output from resample method Change-Id: Ic297e2ed59839f1788c83e099ef1a9e4af29591f --- services/audioflinger/AudioResampler.cpp | 23 +++++++++++++---------- services/audioflinger/AudioResampler.h | 12 +++++++++--- services/audioflinger/AudioResamplerCubic.cpp | 23 +++++++++++++---------- services/audioflinger/AudioResamplerCubic.h | 6 +++--- services/audioflinger/AudioResamplerDyn.cpp | 7 ++++--- services/audioflinger/AudioResamplerDyn.h | 6 +++--- services/audioflinger/AudioResamplerSinc.cpp | 14 ++++++++------ services/audioflinger/AudioResamplerSinc.h | 4 ++-- services/audioflinger/tests/resampler_tests.cpp | 5 ++++- 9 files changed, 59 insertions(+), 41 deletions(-) (limited to 'services') diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp index 46e3d6c..e49b7b1 100644 --- a/services/audioflinger/AudioResampler.cpp +++ b/services/audioflinger/AudioResampler.cpp @@ -41,7 +41,7 @@ public: AudioResamplerOrder1(int inChannelCount, int32_t sampleRate) : AudioResampler(inChannelCount, sampleRate, LOW_QUALITY), mX0L(0), mX0R(0) { } - virtual void resample(int32_t* out, size_t outFrameCount, + virtual size_t resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); private: // number of bits used in interpolation multiply - 15 bits avoids overflow @@ -51,9 +51,9 @@ private: static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits; void init() {} - void resampleMono16(int32_t* out, size_t outFrameCount, + size_t resampleMono16(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); - void resampleStereo16(int32_t* out, size_t outFrameCount, + size_t resampleStereo16(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); #ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1 void AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, @@ -329,7 +329,7 @@ void AudioResampler::reset() { // ---------------------------------------------------------------------------- -void AudioResamplerOrder1::resample(int32_t* out, size_t outFrameCount, +size_t AudioResamplerOrder1::resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) { // should never happen, but we overflow if it does @@ -338,15 +338,16 @@ void AudioResamplerOrder1::resample(int32_t* out, size_t outFrameCount, // select the appropriate resampler switch (mChannelCount) { case 1: - resampleMono16(out, outFrameCount, provider); - break; + return resampleMono16(out, outFrameCount, provider); case 2: - resampleStereo16(out, outFrameCount, provider); - break; + return resampleStereo16(out, outFrameCount, provider); + default: + LOG_ALWAYS_FATAL("invalid channel count: %d", mChannelCount); + return 0; } } -void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount, +size_t AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) { int32_t vl = mVolume[0]; @@ -442,9 +443,10 @@ resampleStereo16_exit: // save state mInputIndex = inputIndex; mPhaseFraction = phaseFraction; + return outputIndex / 2 /* channels for stereo */; } -void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount, +size_t AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) { int32_t vl = mVolume[0]; @@ -538,6 +540,7 @@ resampleMono16_exit: // save state mInputIndex = inputIndex; mPhaseFraction = phaseFraction; + return outputIndex; } #ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1 diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h index 863614a..a8e3e6f 100644 --- a/services/audioflinger/AudioResampler.h +++ b/services/audioflinger/AudioResampler.h @@ -67,12 +67,18 @@ public: // Resample int16_t samples from provider and accumulate into 'out'. // A mono provider delivers a sequence of samples. // A stereo provider delivers a sequence of interleaved pairs of samples. - // Multi-channel providers are not supported. + // // In either case, 'out' holds interleaved pairs of fixed-point Q4.27. // That is, for a mono provider, there is an implicit up-channeling. // Since this method accumulates, the caller is responsible for clearing 'out' initially. - // FIXME assumes provider is always successful; it should return the actual frame count. - virtual void resample(int32_t* out, size_t outFrameCount, + // + // For a float resampler, 'out' holds interleaved pairs of float samples. + // + // Multichannel interleaved frames for n > 2 is supported for quality DYN_LOW_QUALITY, + // DYN_MED_QUALITY, and DYN_HIGH_QUALITY. + // + // Returns the number of frames resampled into the out buffer. + virtual size_t resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) = 0; virtual void reset(); diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp index d3cbd1c..172c2a5 100644 --- a/services/audioflinger/AudioResamplerCubic.cpp +++ b/services/audioflinger/AudioResamplerCubic.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "AudioSRC" +#define LOG_TAG "AudioResamplerCubic" #include #include @@ -32,7 +32,7 @@ void AudioResamplerCubic::init() { memset(&right, 0, sizeof(state)); } -void AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount, +size_t AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) { // should never happen, but we overflow if it does @@ -41,15 +41,16 @@ void AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount, // select the appropriate resampler switch (mChannelCount) { case 1: - resampleMono16(out, outFrameCount, provider); - break; + return resampleMono16(out, outFrameCount, provider); case 2: - resampleStereo16(out, outFrameCount, provider); - break; + return resampleStereo16(out, outFrameCount, provider); + default: + LOG_ALWAYS_FATAL("invalid channel count: %d", mChannelCount); + return 0; } } -void AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount, +size_t AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) { int32_t vl = mVolume[0]; @@ -67,7 +68,7 @@ void AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount, mBuffer.frameCount = inFrameCount; provider->getNextBuffer(&mBuffer, mPTS); if (mBuffer.raw == NULL) { - return; + return 0; } // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount); } @@ -115,9 +116,10 @@ save_state: // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); mInputIndex = inputIndex; mPhaseFraction = phaseFraction; + return outputIndex / 2 /* channels for stereo */; } -void AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount, +size_t AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) { int32_t vl = mVolume[0]; @@ -135,7 +137,7 @@ void AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount, mBuffer.frameCount = inFrameCount; provider->getNextBuffer(&mBuffer, mPTS); if (mBuffer.raw == NULL) { - return; + return 0; } // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount); } @@ -182,6 +184,7 @@ save_state: // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); mInputIndex = inputIndex; mPhaseFraction = phaseFraction; + return outputIndex; } // ---------------------------------------------------------------------------- diff --git a/services/audioflinger/AudioResamplerCubic.h b/services/audioflinger/AudioResamplerCubic.h index 1ddc5f9..4b45b0b 100644 --- a/services/audioflinger/AudioResamplerCubic.h +++ b/services/audioflinger/AudioResamplerCubic.h @@ -31,7 +31,7 @@ public: AudioResamplerCubic(int inChannelCount, int32_t sampleRate) : AudioResampler(inChannelCount, sampleRate, MED_QUALITY) { } - virtual void resample(int32_t* out, size_t outFrameCount, + virtual size_t resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); private: // number of bits used in interpolation multiply - 14 bits avoids overflow @@ -43,9 +43,9 @@ private: int32_t a, b, c, y0, y1, y2, y3; } state; void init(); - void resampleMono16(int32_t* out, size_t outFrameCount, + size_t resampleMono16(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); - void resampleStereo16(int32_t* out, size_t outFrameCount, + size_t resampleStereo16(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); static inline int32_t interp(state* p, int32_t x) { return (((((p->a * x >> 14) + p->b) * x >> 14) + p->c) * x >> 14) + p->y1; diff --git a/services/audioflinger/AudioResamplerDyn.cpp b/services/audioflinger/AudioResamplerDyn.cpp index c21d4ca..6481b85 100644 --- a/services/audioflinger/AudioResamplerDyn.cpp +++ b/services/audioflinger/AudioResamplerDyn.cpp @@ -477,15 +477,15 @@ void AudioResamplerDyn::setSampleRate(int32_t inSampleRate) } template -void AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount, +size_t AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) { - (this->*mResampleFunc)(reinterpret_cast(out), outFrameCount, provider); + return (this->*mResampleFunc)(reinterpret_cast(out), outFrameCount, provider); } template template -void AudioResamplerDyn::resample(TO* out, size_t outFrameCount, +size_t AudioResamplerDyn::resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider) { // TODO Mono -> Mono is not supported. OUTPUT_CHANNELS reflects minimum of stereo out. @@ -610,6 +610,7 @@ resample_exit: ALOG_ASSERT(mBuffer.frameCount == 0); // there must be no frames in the buffer mInBuffer.setImpulse(impulse); mPhaseFraction = phaseFraction; + return outputIndex / OUTPUT_CHANNELS; } /* instantiate templates used by AudioResampler::create */ diff --git a/services/audioflinger/AudioResamplerDyn.h b/services/audioflinger/AudioResamplerDyn.h index 238b163..3b1c381 100644 --- a/services/audioflinger/AudioResamplerDyn.h +++ b/services/audioflinger/AudioResamplerDyn.h @@ -52,7 +52,7 @@ public: virtual void setVolume(float left, float right); - virtual void resample(int32_t* out, size_t outFrameCount, + virtual size_t resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); private: @@ -111,10 +111,10 @@ private: int inSampleRate, int outSampleRate, double tbwCheat); template - void resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider); + size_t resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider); // define a pointer to member function type for resample - typedef void (AudioResamplerDyn::*resample_ABP_t)(TO* out, + typedef size_t (AudioResamplerDyn::*resample_ABP_t)(TO* out, size_t outFrameCount, AudioBufferProvider* provider); // data - the contiguous storage and layout of these is important. diff --git a/services/audioflinger/AudioResamplerSinc.cpp b/services/audioflinger/AudioResamplerSinc.cpp index ba9a356..41730ee 100644 --- a/services/audioflinger/AudioResamplerSinc.cpp +++ b/services/audioflinger/AudioResamplerSinc.cpp @@ -256,7 +256,7 @@ void AudioResamplerSinc::setVolume(float left, float right) { mVolumeSIMD[1] = u4_28_from_float(clampFloatVol(right)); } -void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, +size_t AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) { // FIXME store current state (up or down sample) and only load the coefs when the state @@ -272,17 +272,18 @@ void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, // select the appropriate resampler switch (mChannelCount) { case 1: - resample<1>(out, outFrameCount, provider); - break; + return resample<1>(out, outFrameCount, provider); case 2: - resample<2>(out, outFrameCount, provider); - break; + return resample<2>(out, outFrameCount, provider); + default: + LOG_ALWAYS_FATAL("invalid channel count: %d", mChannelCount); + return 0; } } template -void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, +size_t AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) { const Constants& c(*mConstants); @@ -357,6 +358,7 @@ resample_exit: mImpulse = impulse; mInputIndex = inputIndex; mPhaseFraction = phaseFraction; + return outputIndex / CHANNELS; } template diff --git a/services/audioflinger/AudioResamplerSinc.h b/services/audioflinger/AudioResamplerSinc.h index 6d8e85d..0fbeac8 100644 --- a/services/audioflinger/AudioResamplerSinc.h +++ b/services/audioflinger/AudioResamplerSinc.h @@ -39,7 +39,7 @@ public: virtual ~AudioResamplerSinc(); - virtual void resample(int32_t* out, size_t outFrameCount, + virtual size_t resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); private: void init(); @@ -47,7 +47,7 @@ private: virtual void setVolume(float left, float right); template - void resample(int32_t* out, size_t outFrameCount, + size_t resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); template diff --git a/services/audioflinger/tests/resampler_tests.cpp b/services/audioflinger/tests/resampler_tests.cpp index d6217ba..9e375db 100644 --- a/services/audioflinger/tests/resampler_tests.cpp +++ b/services/audioflinger/tests/resampler_tests.cpp @@ -48,7 +48,10 @@ void resample(int channels, void *output, if (thisFrames == 0 || thisFrames > outputFrames - i) { thisFrames = outputFrames - i; } - resampler->resample((int32_t*) output + channels*i, thisFrames, provider); + size_t framesResampled = resampler->resample( + (int32_t*) output + channels*i, thisFrames, provider); + // we should have enough buffer space, so there is no short count. + ASSERT_EQ(thisFrames, framesResampled); i += thisFrames; } } -- cgit v1.1