diff options
Diffstat (limited to 'libs/audioflinger/AudioMixer.cpp')
| -rw-r--r-- | libs/audioflinger/AudioMixer.cpp | 278 | 
1 files changed, 167 insertions, 111 deletions
| diff --git a/libs/audioflinger/AudioMixer.cpp b/libs/audioflinger/AudioMixer.cpp index 9f1b17f082..b03467f6ce 100644 --- a/libs/audioflinger/AudioMixer.cpp +++ b/libs/audioflinger/AudioMixer.cpp @@ -2,16 +2,16 @@  **  ** Copyright 2007, 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  +** 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  +**     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  +** 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.  */ @@ -247,8 +247,8 @@ inline  void AudioMixer::track_t::adjustVolumeRamp()  {      for (int i=0 ; i<2 ; i++) { -        if (((volumeInc[i]>0) && ((prevVolume[i]>>16) >= volume[i])) || -            ((volumeInc[i]<0) && ((prevVolume[i]>>16) <= volume[i]))) { +        if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) || +            ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {              volumeInc[i] = 0;              prevVolume[i] = volume[i]<<16;          } @@ -307,7 +307,7 @@ void AudioMixer::process__validate(state_t* state, void* output)          n |= NEEDS_CHANNEL_1 + t.channelCount - 1;          n |= NEEDS_FORMAT_16;          n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED; -         +                 if (t.volumeInc[0]|t.volumeInc[1]) {              volumeRamp = 1;          } else if (!t.doesResample() && t.volumeRL == 0) { @@ -370,7 +370,7 @@ void AudioMixer::process__validate(state_t* state, void* output)     state->hook(state, output); -   // Now that the volume ramp has been done, set optimal state and  +   // Now that the volume ramp has been done, set optimal state and     // track hooks for subsequent mixer process     if (countActiveTracks) {         int allMuted = 1; @@ -397,7 +397,7 @@ void AudioMixer::process__validate(state_t* state, void* output)     }  } -static inline  +static inline  int32_t mulAdd(int16_t in, int16_t v, int32_t a)  {  #if defined(__arm__) && !defined(__thumb__) @@ -412,7 +412,7 @@ int32_t mulAdd(int16_t in, int16_t v, int32_t a)  #endif  } -static inline  +static inline  int32_t mul(int16_t in, int16_t v)  {  #if defined(__arm__) && !defined(__thumb__) @@ -427,7 +427,7 @@ int32_t mul(int16_t in, int16_t v)  #endif  } -static inline  +static inline  int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)  {  #if defined(__arm__) && !defined(__thumb__) @@ -453,7 +453,7 @@ int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)  #endif  } -static inline  +static inline  int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)  {  #if defined(__arm__) && !defined(__thumb__) @@ -513,7 +513,7 @@ void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, i      //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",      //        t, vlInc/65536.0f, vl/65536.0f, t->volume[0],      //       (vl + vlInc*frameCount)/65536.0f, frameCount); -     +         // ramp volume      do {          *out++ += (vl >> 16) * (*temp++ >> 12); @@ -548,7 +548,7 @@ void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount              vl += vlInc;              vr += vrInc;          } while (--frameCount); -         +                 t->prevVolume[0] = vl;          t->prevVolume[1] = vr;          t->adjustVolumeRamp(); @@ -590,7 +590,7 @@ void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount,              vl += vlInc;              vr += vrInc;          } while (--frameCount); -         +                 t->prevVolume[0] = vl;          t->prevVolume[1] = vr;          t->adjustVolumeRamp(); @@ -609,7 +609,7 @@ void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount,      t->in = in;  } -inline  +inline  void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c)  {      for (size_t i=0 ; i<c ; i++) { @@ -633,8 +633,12 @@ void AudioMixer::process__nop(state_t* state, void* output)          const int i = 31 - __builtin_clz(en);          en &= ~(1<<i);          track_t& t = state->tracks[i]; -        t.bufferProvider->getNextBuffer(&t.buffer); -        if (t.buffer.raw) { +        size_t outFrames = state->frameCount; +        while (outFrames) { +            t.buffer.frameCount = outFrames; +            t.bufferProvider->getNextBuffer(&t.buffer); +            if (!t.buffer.raw) break; +            outFrames -= t.buffer.frameCount;              t.bufferProvider->releaseBuffer(&t.buffer);          }      } @@ -652,12 +656,14 @@ void AudioMixer::process__genericNoResampling(state_t* state, void* output)          const int i = 31 - __builtin_clz(en);          en &= ~(1<<i);          track_t& t = state->tracks[i]; +        t.buffer.frameCount = state->frameCount;          t.bufferProvider->getNextBuffer(&t.buffer); +        t.frameCount = t.buffer.frameCount;          t.in = t.buffer.raw;          // t.in == NULL can happen if the track was flushed just after having          // been enabled for mixing.          if (t.in == NULL) -            enabledTracks &= ~(1<<i);  +            enabledTracks &= ~(1<<i);      }      // this assumes output 16 bits stereo, no resampling @@ -671,12 +677,31 @@ void AudioMixer::process__genericNoResampling(state_t* state, void* output)              const int i = 31 - __builtin_clz(en);              en &= ~(1<<i);              track_t& t = state->tracks[i]; -            (t.hook)(&t, outTemp, BLOCKSIZE, state->resampleTemp); +            size_t outFrames = BLOCKSIZE; +            +            while (outFrames) { +                size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount; +                if (inFrames) { +                    (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp); +                    t.frameCount -= inFrames; +                    outFrames -= inFrames; +                } +                if (t.frameCount == 0 && outFrames) { +                    t.bufferProvider->releaseBuffer(&t.buffer); +                    t.buffer.frameCount = numFrames - (BLOCKSIZE - outFrames); +                    t.bufferProvider->getNextBuffer(&t.buffer); +                    t.in = t.buffer.raw; +                    if (t.in == NULL) { +                        enabledTracks &= ~(1<<i); +                        break; +                    } +                    t.frameCount = t.buffer.frameCount; +                 } +            }          }          ditherAndClamp(out, outTemp, BLOCKSIZE);          out += BLOCKSIZE; -          numFrames -= BLOCKSIZE;      } while (numFrames); @@ -713,12 +738,19 @@ void AudioMixer::process__genericResampling(state_t* state, void* output)          if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {              (t.hook)(&t, outTemp, numFrames, state->resampleTemp);          } else { -            t.bufferProvider->getNextBuffer(&t.buffer); -            t.in = t.buffer.raw; -            // t.in == NULL can happen if the track was flushed just after having -            // been enabled for mixing. -            if (t.in) { -                (t.hook)(&t, outTemp, numFrames, state->resampleTemp); + +            size_t outFrames = numFrames; +            +            while (outFrames) { +                t.buffer.frameCount = outFrames; +                t.bufferProvider->getNextBuffer(&t.buffer); +                t.in = t.buffer.raw; +                // t.in == NULL can happen if the track was flushed just after having +                // been enabled for mixing. +                if (t.in == NULL) break; + +                (t.hook)(&t, outTemp + (numFrames-outFrames)*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp); +                outFrames -= t.buffer.frameCount;                  t.bufferProvider->releaseBuffer(&t.buffer);              }          } @@ -734,45 +766,51 @@ void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state, void*      const track_t& t = state->tracks[i];      AudioBufferProvider::Buffer& b(t.buffer); -    t.bufferProvider->getNextBuffer(&b); -    int16_t const *in = t.buffer.i16; - -    // in == NULL can happen if the track was flushed just after having -    // been enabled for mixing. -    if (in == NULL) { -        memset(output, 0, state->frameCount*MAX_NUM_CHANNELS*sizeof(int16_t)); -        return; -    } -     +         int32_t* out = static_cast<int32_t*>(output);      size_t numFrames = state->frameCount; +        const int16_t vl = t.volume[0];      const int16_t vr = t.volume[1];      const uint32_t vrl = t.volumeRL; -    if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) { -        // volume is boosted, so we might need to clamp even though -        // we process only one track. -        do { -            uint32_t rl = *reinterpret_cast<uint32_t const *>(in); -            in += 2; -            int32_t l = mulRL(1, rl, vrl) >> 12; -            int32_t r = mulRL(0, rl, vrl) >> 12; -            // clamping... -            l = clamp16(l); -            r = clamp16(r); -            *out++ = (r<<16) | (l & 0xFFFF); -        } while (--numFrames); -    } else { -        do { -            uint32_t rl = *reinterpret_cast<uint32_t const *>(in); -            in += 2; -            int32_t l = mulRL(1, rl, vrl) >> 12; -            int32_t r = mulRL(0, rl, vrl) >> 12; -            *out++ = (r<<16) | (l & 0xFFFF); -        } while (--numFrames); -    } +    while (numFrames) { +        b.frameCount = numFrames; +        t.bufferProvider->getNextBuffer(&b); +        int16_t const *in = b.i16; -    t.bufferProvider->releaseBuffer(&b); +        // in == NULL can happen if the track was flushed just after having +        // been enabled for mixing. +        if (in == NULL) { +            memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t)); +            return; +        } +        size_t outFrames = b.frameCount; +        +        if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) { +            // volume is boosted, so we might need to clamp even though +            // we process only one track. +            do { +                uint32_t rl = *reinterpret_cast<uint32_t const *>(in); +                in += 2; +                int32_t l = mulRL(1, rl, vrl) >> 12; +                int32_t r = mulRL(0, rl, vrl) >> 12; +                // clamping... +                l = clamp16(l); +                r = clamp16(r); +                *out++ = (r<<16) | (l & 0xFFFF); +            } while (--outFrames); +        } else { +            do { +                uint32_t rl = *reinterpret_cast<uint32_t const *>(in); +                in += 2; +                int32_t l = mulRL(1, rl, vrl) >> 12; +                int32_t r = mulRL(0, rl, vrl) >> 12; +                *out++ = (r<<16) | (l & 0xFFFF); +            } while (--outFrames); +        } +        numFrames -= b.frameCount; +        t.bufferProvider->releaseBuffer(&b); +    }  }  // 2 tracks is also a common case @@ -784,71 +822,89 @@ void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state, void      i = 31 - __builtin_clz(en);      const track_t& t0 = state->tracks[i];      AudioBufferProvider::Buffer& b0(t0.buffer); -    t0.bufferProvider->getNextBuffer(&b0);      en &= ~(1<<i);      i = 31 - __builtin_clz(en);      const track_t& t1 = state->tracks[i];      AudioBufferProvider::Buffer& b1(t1.buffer); -    t1.bufferProvider->getNextBuffer(&b1); - +         int16_t const *in0;      const int16_t vl0 = t0.volume[0];      const int16_t vr0 = t0.volume[1]; +    size_t frameCount0 = 0; +        int16_t const *in1;      const int16_t vl1 = t1.volume[0];      const int16_t vr1 = t1.volume[1]; -    size_t numFrames = state->frameCount; +    size_t frameCount1 = 0; +         int32_t* out = static_cast<int32_t*>(output); - -    // t0/1.buffer.i16 == NULL can happen if the track was flushed just after having -    // been enabled for mixing. -    if (t0.buffer.i16 != NULL) { -        in0 = t0.buffer.i16; -        if (t1.buffer.i16 != NULL) { -            in1 = t1.buffer.i16; -        } else { -            in1 = new int16_t[MAX_NUM_CHANNELS * state->frameCount]; -            memset((void *)in1, 0, state->frameCount*MAX_NUM_CHANNELS*sizeof(int16_t)); +    size_t numFrames = state->frameCount; +    int16_t const *buff = NULL; + +   +    while (numFrames) { +    +        if (frameCount0 == 0) { +            b0.frameCount = numFrames; +            t0.bufferProvider->getNextBuffer(&b0); +            if (b0.i16 == NULL) { +                if (buff == NULL) { +                    buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount]; +                } +                in0 = buff; +                b0.frameCount = numFrames; +            } else { +                in0 = b0.i16; +            } +            frameCount0 = b0.frameCount;          } -    } else { -        in0 = new int16_t[MAX_NUM_CHANNELS * state->frameCount]; -        memset((void *)in0, 0, state->frameCount*MAX_NUM_CHANNELS*sizeof(int16_t)); -        if (t1.buffer.i16 != NULL) { -            in1 = t1.buffer.i16; -        } else { -            in1 = in0; +        if (frameCount1 == 0) { +            b1.frameCount = numFrames; +            t1.bufferProvider->getNextBuffer(&b1); +            if (b1.i16 == NULL) { +                if (buff == NULL) { +                    buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount]; +                } +                in1 = buff; +                b1.frameCount = numFrames; +               } else { +                in1 = b1.i16; +            } +            frameCount1 = b1.frameCount;          } -    } -     -    do { -        int32_t l0 = *in0++; -        int32_t r0 = *in0++; -        l0 = mul(l0, vl0); -        r0 = mul(r0, vr0); -        int32_t l = *in1++; -        int32_t r = *in1++; -        l = mulAdd(l, vl1, l0) >> 12; -        r = mulAdd(r, vr1, r0) >> 12; -        // clamping... -        l = clamp16(l); -        r = clamp16(r); -        *out++ = (r<<16) | (l & 0xFFFF); -    } while (--numFrames); +        +        size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1; -     -    if (t0.buffer.i16 != NULL) { -        t0.bufferProvider->releaseBuffer(&b0); -        if (t1.buffer.i16 != NULL) { -            t1.bufferProvider->releaseBuffer(&b1); -        } else { -            delete [] in1; +        numFrames -= outFrames; +        frameCount0 -= outFrames; +        frameCount1 -= outFrames; +        +        do { +            int32_t l0 = *in0++; +            int32_t r0 = *in0++; +            l0 = mul(l0, vl0); +            r0 = mul(r0, vr0); +            int32_t l = *in1++; +            int32_t r = *in1++; +            l = mulAdd(l, vl1, l0) >> 12; +            r = mulAdd(r, vr1, r0) >> 12; +            // clamping... +            l = clamp16(l); +            r = clamp16(r); +            *out++ = (r<<16) | (l & 0xFFFF); +        } while (--outFrames); +        +        if (frameCount0 == 0) { +            t0.bufferProvider->releaseBuffer(&b0);          } -    } else { -        delete [] in0; -        if (t1.buffer.i16 != NULL) { +        if (frameCount1 == 0) {              t1.bufferProvider->releaseBuffer(&b1);          } +    }    +        +    if (buff != NULL) { +        delete [] buff;             }  } |