summaryrefslogtreecommitdiffstats
path: root/libs/audioflinger/AudioMixer.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:43 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:43 -0800
commitf013e1afd1e68af5e3b868c26a653bbfb39538f8 (patch)
tree7ad6c8fd9c7b55f4b4017171dec1cb760bbd26bf /libs/audioflinger/AudioMixer.cpp
parente70cfafe580c6f2994c4827cd8a534aabf3eb05c (diff)
downloadframeworks_base-f013e1afd1e68af5e3b868c26a653bbfb39538f8.zip
frameworks_base-f013e1afd1e68af5e3b868c26a653bbfb39538f8.tar.gz
frameworks_base-f013e1afd1e68af5e3b868c26a653bbfb39538f8.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'libs/audioflinger/AudioMixer.cpp')
-rw-r--r--libs/audioflinger/AudioMixer.cpp278
1 files changed, 167 insertions, 111 deletions
diff --git a/libs/audioflinger/AudioMixer.cpp b/libs/audioflinger/AudioMixer.cpp
index 9f1b17f..b03467f 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;
}
}