diff options
| author | 2008-12-19 08:31:54 -0800 | |
|---|---|---|
| committer | 2008-12-19 08:31:54 -0800 | |
| commit | 772a89695f179b51d16b26c1b0d946aa3e850e70 (patch) | |
| tree | 9a9fdadd1301625f875a3c126c986c79e3363ac4 /libs/audioflinger/AudioResampler.cpp | |
| parent | d34e59679f6a98e9e67ef4bd18da6e5a86d386bc (diff) | |
| parent | e09fd9e819c23dc90bca68375645e15544861330 (diff) | |
Merge commit 'remotes/korg/cupcake'
Conflicts:
	core/java/com/android/internal/app/AlertController.java
	core/res/res/values/strings.xml
	media/java/android/media/AudioSystem.java
	services/java/com/android/server/LocationManagerService.java
Diffstat (limited to 'libs/audioflinger/AudioResampler.cpp')
| -rw-r--r-- | libs/audioflinger/AudioResampler.cpp | 350 | 
1 files changed, 324 insertions, 26 deletions
| diff --git a/libs/audioflinger/AudioResampler.cpp b/libs/audioflinger/AudioResampler.cpp index c93ead37d9..5dabacbb70 100644 --- a/libs/audioflinger/AudioResampler.cpp +++ b/libs/audioflinger/AudioResampler.cpp @@ -14,17 +14,23 @@   * limitations under the License.   */ +#define LOG_TAG "AudioResampler" +//#define LOG_NDEBUG 0 +  #include <stdint.h>  #include <stdlib.h>  #include <sys/types.h>  #include <cutils/log.h>  #include <cutils/properties.h> -  #include "AudioResampler.h"  #include "AudioResamplerSinc.h"  #include "AudioResamplerCubic.h"  namespace android { + +#ifdef __ARM_ARCH_5E__  // optimized asm option +    #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1 +#endif // __ARM_ARCH_5E__  // ----------------------------------------------------------------------------  class AudioResamplerOrder1 : public AudioResampler { @@ -46,6 +52,15 @@ private:              AudioBufferProvider* provider);      void 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, +            size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, +            uint32_t &phaseFraction, uint32_t phaseIncrement); +    void AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, +            size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, +            uint32_t &phaseFraction, uint32_t phaseIncrement); +#endif  // ASM_ARM_RESAMP1 +      static inline int32_t Interp(int32_t x0, int32_t x1, uint32_t f) {          return x0 + (((x1 - x0) * (int32_t)(f >> kPreInterpShift)) >> kNumInterpBits);      } @@ -73,20 +88,23 @@ AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,      if (quality == DEFAULT)          quality = LOW_QUALITY; -     +      switch (quality) {      default:      case LOW_QUALITY: +        LOGV("Create linear Resampler");          resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate);          break;      case MED_QUALITY: +        LOGV("Create cubic Resampler");          resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate);          break;      case HIGH_QUALITY: +        LOGV("Create sinc Resampler");          resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate);          break;      } -     +      // initialize resampler      resampler->init();      return resampler; @@ -103,10 +121,10 @@ AudioResampler::AudioResampler(int bitDepth, int inChannelCount,                  inChannelCount);          // LOG_ASSERT(0);      } -     +      // initialize common members      mVolume[0] = mVolume[1] = 0; -    mBuffer.raw = NULL; +    mBuffer.frameCount = 0;      // save format for quick lookup      if (inChannelCount == 1) { @@ -160,19 +178,31 @@ void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount,      uint32_t phaseIncrement = mPhaseIncrement;      size_t outputIndex = 0;      size_t outputSampleCount = outFrameCount * 2; +    size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;      // LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n", -    //		outFrameCount, inputIndex, phaseFraction, phaseIncrement); +    //      outFrameCount, inputIndex, phaseFraction, phaseIncrement);      while (outputIndex < outputSampleCount) {          // buffer is empty, fetch a new one -        if (mBuffer.raw == NULL) { +        while (mBuffer.frameCount == 0) { +            mBuffer.frameCount = inFrameCount;              provider->getNextBuffer(&mBuffer); -            if (mBuffer.raw == NULL) -                break; +            if (mBuffer.raw == NULL) { +                goto resampleStereo16_exit; +            } +              // LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount); +            if (mBuffer.frameCount > inputIndex) break; + +            inputIndex -= mBuffer.frameCount; +            mX0L = mBuffer.i16[mBuffer.frameCount*2-2]; +            mX0R = mBuffer.i16[mBuffer.frameCount*2-1]; +            provider->releaseBuffer(&mBuffer); +             // mBuffer.frameCount == 0 now so we reload a new buffer          } +          int16_t *in = mBuffer.i16;          // handle boundary case @@ -187,34 +217,47 @@ void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount,          // process input samples          // LOGE("general case\n"); -        while (outputIndex < outputSampleCount) { + +#ifdef ASM_ARM_RESAMP1  // asm optimisation for ResamplerOrder1 +        if (inputIndex + 2 < mBuffer.frameCount) { +            int32_t* maxOutPt; +            int32_t maxInIdx; + +            maxOutPt = out + (outputSampleCount - 2);   // 2 because 2 frames per loop +            maxInIdx = mBuffer.frameCount - 2; +            AsmStereo16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr, +                    phaseFraction, phaseIncrement); +        } +#endif  // ASM_ARM_RESAMP1 + +        while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {              out[outputIndex++] += vl * Interp(in[inputIndex*2-2],                      in[inputIndex*2], phaseFraction);              out[outputIndex++] += vr * Interp(in[inputIndex*2-1],                      in[inputIndex*2+1], phaseFraction);              Advance(&inputIndex, &phaseFraction, phaseIncrement); -            if (inputIndex >= mBuffer.frameCount) -                break;          } +          // LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);          // if done with buffer, save samples          if (inputIndex >= mBuffer.frameCount) {              inputIndex -= mBuffer.frameCount; -            // LOGE("buffer done, new input index", inputIndex); +            // LOGE("buffer done, new input index %d", inputIndex);              mX0L = mBuffer.i16[mBuffer.frameCount*2-2];              mX0R = mBuffer.i16[mBuffer.frameCount*2-1];              provider->releaseBuffer(&mBuffer); -            // verify that the releaseBuffer NULLS the buffer pointer  -            // LOG_ASSERT(mBuffer.raw == NULL); +            // verify that the releaseBuffer resets the buffer frameCount +            // LOG_ASSERT(mBuffer.frameCount == 0);          }      }      // LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex); +resampleStereo16_exit:      // save state      mInputIndex = inputIndex;      mPhaseFraction = phaseFraction; @@ -231,18 +274,27 @@ void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount,      uint32_t phaseIncrement = mPhaseIncrement;      size_t outputIndex = 0;      size_t outputSampleCount = outFrameCount * 2; +    size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;      // LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n",      //      outFrameCount, inputIndex, phaseFraction, phaseIncrement); -      while (outputIndex < outputSampleCount) { -          // buffer is empty, fetch a new one -        if (mBuffer.raw == NULL) { +        while (mBuffer.frameCount == 0) { +            mBuffer.frameCount = inFrameCount;              provider->getNextBuffer(&mBuffer); -            if (mBuffer.raw == NULL) -                break; +            if (mBuffer.raw == NULL) { +                mInputIndex = inputIndex; +                mPhaseFraction = phaseFraction; +                goto resampleMono16_exit; +            }              // LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount); +            if (mBuffer.frameCount >  inputIndex) break; + +            inputIndex -= mBuffer.frameCount; +            mX0L = mBuffer.i16[mBuffer.frameCount-1]; +            provider->releaseBuffer(&mBuffer); +            // mBuffer.frameCount == 0 now so we reload a new buffer          }          int16_t *in = mBuffer.i16; @@ -259,38 +311,284 @@ void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount,          // process input samples          // LOGE("general case\n"); -        while (outputIndex < outputSampleCount) { + +#ifdef ASM_ARM_RESAMP1  // asm optimisation for ResamplerOrder1 +        if (inputIndex + 2 < mBuffer.frameCount) { +            int32_t* maxOutPt; +            int32_t maxInIdx; + +            maxOutPt = out + (outputSampleCount - 2); +            maxInIdx = (int32_t)mBuffer.frameCount - 2; +                AsmMono16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr, +                        phaseFraction, phaseIncrement); +        } +#endif  // ASM_ARM_RESAMP1 + +        while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {              int32_t sample = Interp(in[inputIndex-1], in[inputIndex],                      phaseFraction);              out[outputIndex++] += vl * sample;              out[outputIndex++] += vr * sample;              Advance(&inputIndex, &phaseFraction, phaseIncrement); -            if (inputIndex >= mBuffer.frameCount) -                break;          } + +          // LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);          // if done with buffer, save samples          if (inputIndex >= mBuffer.frameCount) {              inputIndex -= mBuffer.frameCount; -            // LOGE("buffer done, new input index", inputIndex); +            // LOGE("buffer done, new input index %d", inputIndex);              mX0L = mBuffer.i16[mBuffer.frameCount-1];              provider->releaseBuffer(&mBuffer); -            // verify that the releaseBuffer NULLS the buffer pointer  -            // LOG_ASSERT(mBuffer.raw == NULL); +            // verify that the releaseBuffer resets the buffer frameCount +            // LOG_ASSERT(mBuffer.frameCount == 0);          }      }      // LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex); +resampleMono16_exit:      // save state      mInputIndex = inputIndex;      mPhaseFraction = phaseFraction;  } +#ifdef ASM_ARM_RESAMP1  // asm optimisation for ResamplerOrder1 + +/******************************************************************* +* +*   AsmMono16Loop +*   asm optimized monotonic loop version; one loop is 2 frames +*   Input: +*       in : pointer on input samples +*       maxOutPt : pointer on first not filled +*       maxInIdx : index on first not used +*       outputIndex : pointer on current output index +*       out : pointer on output buffer +*       inputIndex : pointer on current input index +*       vl, vr : left and right gain +*       phaseFraction : pointer on current phase fraction +*       phaseIncrement +*   Ouput: +*       outputIndex : +*       out : updated buffer +*       inputIndex : index of next to use +*       phaseFraction : phase fraction for next interpolation +* +*******************************************************************/ +void AudioResamplerOrder1::AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, +            size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, +            uint32_t &phaseFraction, uint32_t phaseIncrement) +{ +#define MO_PARAM5   "36"        // offset of parameter 5 (outputIndex) + +    asm( +        "stmfd  sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" +        // get parameters +        "   ldr r6, [sp, #" MO_PARAM5 " + 20]\n"    // &phaseFraction +        "   ldr r6, [r6]\n"                         // phaseFraction +        "   ldr r7, [sp, #" MO_PARAM5 " + 8]\n"     // &inputIndex +        "   ldr r7, [r7]\n"                         // inputIndex +        "   ldr r8, [sp, #" MO_PARAM5 " + 4]\n"     // out +        "   ldr r0, [sp, #" MO_PARAM5 " + 0]\n"     // &outputIndex +        "   ldr r0, [r0]\n"                         // outputIndex +        "   add r8, r0, asl #2\n"                   // curOut +        "   ldr r9, [sp, #" MO_PARAM5 " + 24]\n"    // phaseIncrement +        "   ldr r10, [sp, #" MO_PARAM5 " + 12]\n"   // vl +        "   ldr r11, [sp, #" MO_PARAM5 " + 16]\n"   // vr + +        // r0 pin, x0, Samp + +        // r1 in +        // r2 maxOutPt +        // r3 maxInIdx + +        // r4 x1, i1, i3, Out1 +        // r5 out0 + +        // r6 frac +        // r7 inputIndex +        // r8 curOut + +        // r9 inc +        // r10 vl +        // r11 vr + +        // r12 +        // r13 sp +        // r14 + +        // the following loop works on 2 frames + +        ".Y4L01:\n" +        "   cmp r8, r2\n"                   // curOut - maxCurOut +        "   bcs .Y4L02\n" + +#define MO_ONE_FRAME \ +    "   add r0, r1, r7, asl #1\n"       /* in + inputIndex */\ +    "   ldrsh r4, [r0]\n"               /* in[inputIndex] */\ +    "   ldr r5, [r8]\n"                 /* out[outputIndex] */\ +    "   ldrsh r0, [r0, #-2]\n"          /* in[inputIndex-1] */\ +    "   bic r6, r6, #0xC0000000\n"      /* phaseFraction & ... */\ +    "   sub r4, r4, r0\n"               /* in[inputIndex] - in[inputIndex-1] */\ +    "   mov r4, r4, lsl #2\n"           /* <<2 */\ +    "   smulwt r4, r4, r6\n"            /* (x1-x0)*.. */\ +    "   add r6, r6, r9\n"               /* phaseFraction + phaseIncrement */\ +    "   add r0, r0, r4\n"               /* x0 - (..) */\ +    "   mla r5, r0, r10, r5\n"          /* vl*interp + out[] */\ +    "   ldr r4, [r8, #4]\n"             /* out[outputIndex+1] */\ +    "   str r5, [r8], #4\n"             /* out[outputIndex++] = ... */\ +    "   mla r4, r0, r11, r4\n"          /* vr*interp + out[] */\ +    "   add r7, r7, r6, lsr #30\n"      /* inputIndex + phaseFraction>>30 */\ +    "   str r4, [r8], #4\n"             /* out[outputIndex++] = ... */ + +        MO_ONE_FRAME    // frame 1 +        MO_ONE_FRAME    // frame 2 + +        "   cmp r7, r3\n"                   // inputIndex - maxInIdx +        "   bcc .Y4L01\n" +        ".Y4L02:\n" + +        "   bic r6, r6, #0xC0000000\n"             // phaseFraction & ... +        // save modified values +        "   ldr r0, [sp, #" MO_PARAM5 " + 20]\n"    // &phaseFraction +        "   str r6, [r0]\n"                         // phaseFraction +        "   ldr r0, [sp, #" MO_PARAM5 " + 8]\n"     // &inputIndex +        "   str r7, [r0]\n"                         // inputIndex +        "   ldr r0, [sp, #" MO_PARAM5 " + 4]\n"     // out +        "   sub r8, r0\n"                           // curOut - out +        "   asr r8, #2\n"                           // new outputIndex +        "   ldr r0, [sp, #" MO_PARAM5 " + 0]\n"     // &outputIndex +        "   str r8, [r0]\n"                         // save outputIndex + +        "   ldmfd   sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}\n" +    ); +} + +/******************************************************************* +* +*   AsmStereo16Loop +*   asm optimized stereo loop version; one loop is 2 frames +*   Input: +*       in : pointer on input samples +*       maxOutPt : pointer on first not filled +*       maxInIdx : index on first not used +*       outputIndex : pointer on current output index +*       out : pointer on output buffer +*       inputIndex : pointer on current input index +*       vl, vr : left and right gain +*       phaseFraction : pointer on current phase fraction +*       phaseIncrement +*   Ouput: +*       outputIndex : +*       out : updated buffer +*       inputIndex : index of next to use +*       phaseFraction : phase fraction for next interpolation +* +*******************************************************************/ +void AudioResamplerOrder1::AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, +            size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, +            uint32_t &phaseFraction, uint32_t phaseIncrement) +{ +#define ST_PARAM5    "40"     // offset of parameter 5 (outputIndex) +    asm( +        "stmfd  sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n" +        // get parameters +        "   ldr r6, [sp, #" ST_PARAM5 " + 20]\n"    // &phaseFraction +        "   ldr r6, [r6]\n"                         // phaseFraction +        "   ldr r7, [sp, #" ST_PARAM5 " + 8]\n"     // &inputIndex +        "   ldr r7, [r7]\n"                         // inputIndex +        "   ldr r8, [sp, #" ST_PARAM5 " + 4]\n"     // out +        "   ldr r0, [sp, #" ST_PARAM5 " + 0]\n"     // &outputIndex +        "   ldr r0, [r0]\n"                         // outputIndex +        "   add r8, r0, asl #2\n"                   // curOut +        "   ldr r9, [sp, #" ST_PARAM5 " + 24]\n"    // phaseIncrement +        "   ldr r10, [sp, #" ST_PARAM5 " + 12]\n"   // vl +        "   ldr r11, [sp, #" ST_PARAM5 " + 16]\n"   // vr + +        // r0 pin, x0, Samp + +        // r1 in +        // r2 maxOutPt +        // r3 maxInIdx + +        // r4 x1, i1, i3, out1 +        // r5 out0 + +        // r6 frac +        // r7 inputIndex +        // r8 curOut + +        // r9 inc +        // r10 vl +        // r11 vr + +        // r12 temporary +        // r13 sp +        // r14 + +        ".Y5L01:\n" +        "   cmp r8, r2\n"                   // curOut - maxCurOut +        "   bcs .Y5L02\n" + +#define ST_ONE_FRAME \ +    "   bic r6, r6, #0xC0000000\n"      /* phaseFraction & ... */\ +\ +    "   add r0, r1, r7, asl #2\n"       /* in + 2*inputIndex */\ +\ +    "   ldrsh r4, [r0]\n"               /* in[2*inputIndex] */\ +    "   ldr r5, [r8]\n"                 /* out[outputIndex] */\ +    "   ldrsh r12, [r0, #-4]\n"         /* in[2*inputIndex-2] */\ +    "   sub r4, r4, r12\n"              /* in[2*InputIndex] - in[2*InputIndex-2] */\ +    "   mov r4, r4, lsl #2\n"           /* <<2 */\ +    "   smulwt r4, r4, r6\n"            /* (x1-x0)*.. */\ +    "   add r12, r12, r4\n"             /* x0 - (..) */\ +    "   mla r5, r12, r10, r5\n"         /* vl*interp + out[] */\ +    "   ldr r4, [r8, #4]\n"             /* out[outputIndex+1] */\ +    "   str r5, [r8], #4\n"             /* out[outputIndex++] = ... */\ +\ +    "   ldrsh r12, [r0, #+2]\n"         /* in[2*inputIndex+1] */\ +    "   ldrsh r0, [r0, #-2]\n"          /* in[2*inputIndex-1] */\ +    "   sub r12, r12, r0\n"             /* in[2*InputIndex] - in[2*InputIndex-2] */\ +    "   mov r12, r12, lsl #2\n"         /* <<2 */\ +    "   smulwt r12, r12, r6\n"          /* (x1-x0)*.. */\ +    "   add r12, r0, r12\n"             /* x0 - (..) */\ +    "   mla r4, r12, r11, r4\n"         /* vr*interp + out[] */\ +    "   str r4, [r8], #4\n"             /* out[outputIndex++] = ... */\ +\ +    "   add r6, r6, r9\n"               /* phaseFraction + phaseIncrement */\ +    "   add r7, r7, r6, lsr #30\n"      /* inputIndex + phaseFraction>>30 */ + +    ST_ONE_FRAME    // frame 1 +    ST_ONE_FRAME    // frame 1 + +        "   cmp r7, r3\n"                       // inputIndex - maxInIdx +        "   bcc .Y5L01\n" +        ".Y5L02:\n" + +        "   bic r6, r6, #0xC0000000\n"              // phaseFraction & ... +        // save modified values +        "   ldr r0, [sp, #" ST_PARAM5 " + 20]\n"    // &phaseFraction +        "   str r6, [r0]\n"                         // phaseFraction +        "   ldr r0, [sp, #" ST_PARAM5 " + 8]\n"     // &inputIndex +        "   str r7, [r0]\n"                         // inputIndex +        "   ldr r0, [sp, #" ST_PARAM5 " + 4]\n"     // out +        "   sub r8, r0\n"                           // curOut - out +        "   asr r8, #2\n"                           // new outputIndex +        "   ldr r0, [sp, #" ST_PARAM5 " + 0]\n"     // &outputIndex +        "   str r8, [r0]\n"                         // save outputIndex + +        "   ldmfd   sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, pc}\n" +    ); +} + +#endif  // ASM_ARM_RESAMP1 + +  // ----------------------------------------------------------------------------  }  ; // namespace android |