diff options
Diffstat (limited to 'services/audioflinger/AudioMixer.cpp')
-rw-r--r-- | services/audioflinger/AudioMixer.cpp | 1155 |
1 files changed, 0 insertions, 1155 deletions
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp deleted file mode 100644 index 3f4c19a..0000000 --- a/services/audioflinger/AudioMixer.cpp +++ /dev/null @@ -1,1155 +0,0 @@ -/* -** -** 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 -** -** 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 -** limitations under the License. -*/ - -#define LOG_TAG "AudioMixer" -//#define LOG_NDEBUG 0 - -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> - -#include <cutils/bitops.h> -#include <cutils/compiler.h> -#include <utils/Debug.h> - -#include <system/audio.h> - -#include <audio_utils/primitives.h> -#include <common_time/local_clock.h> -#include <common_time/cc_helper.h> - -#include "AudioMixer.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate, uint32_t maxNumTracks) - : mTrackNames(0), mConfiguredNames((1 << maxNumTracks) - 1), mSampleRate(sampleRate) -{ - // AudioMixer is not yet capable of multi-channel beyond stereo - COMPILE_TIME_ASSERT_FUNCTION_SCOPE(2 == MAX_NUM_CHANNELS); - - ALOG_ASSERT(maxNumTracks <= MAX_NUM_TRACKS, "maxNumTracks %u > MAX_NUM_TRACKS %u", - maxNumTracks, MAX_NUM_TRACKS); - - LocalClock lc; - - mState.enabledTracks= 0; - mState.needsChanged = 0; - mState.frameCount = frameCount; - mState.hook = process__nop; - mState.outputTemp = NULL; - mState.resampleTemp = NULL; - // mState.reserved - - // FIXME Most of the following initialization is probably redundant since - // tracks[i] should only be referenced if (mTrackNames & (1 << i)) != 0 - // and mTrackNames is initially 0. However, leave it here until that's verified. - track_t* t = mState.tracks; - for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) { - t->needs = 0; - t->volume[0] = UNITY_GAIN; - t->volume[1] = UNITY_GAIN; - // no initialization needed - // t->prevVolume[0] - // t->prevVolume[1] - t->volumeInc[0] = 0; - t->volumeInc[1] = 0; - t->auxLevel = 0; - t->auxInc = 0; - // no initialization needed - // t->prevAuxLevel - // t->frameCount - t->channelCount = 2; - t->enabled = false; - t->format = 16; - t->channelMask = AUDIO_CHANNEL_OUT_STEREO; - t->bufferProvider = NULL; - t->buffer.raw = NULL; - // t->buffer.frameCount - t->hook = NULL; - t->in = NULL; - t->resampler = NULL; - t->sampleRate = mSampleRate; - t->mainBuffer = NULL; - t->auxBuffer = NULL; - t->localTimeFreq = lc.getLocalFreq(); - t++; - } -} - -AudioMixer::~AudioMixer() -{ - track_t* t = mState.tracks; - for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) { - delete t->resampler; - t++; - } - delete [] mState.outputTemp; - delete [] mState.resampleTemp; -} - -int AudioMixer::getTrackName() -{ - uint32_t names = (~mTrackNames) & mConfiguredNames; - if (names != 0) { - int n = __builtin_ctz(names); - ALOGV("add track (%d)", n); - mTrackNames |= 1 << n; - return TRACK0 + n; - } - return -1; -} - -void AudioMixer::invalidateState(uint32_t mask) -{ - if (mask) { - mState.needsChanged |= mask; - mState.hook = process__validate; - } - } - -void AudioMixer::deleteTrackName(int name) -{ - name -= TRACK0; - ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name); - ALOGV("deleteTrackName(%d)", name); - track_t& track(mState.tracks[ name ]); - if (track.enabled) { - track.enabled = false; - invalidateState(1<<name); - } - if (track.resampler != NULL) { - // delete the resampler - delete track.resampler; - track.resampler = NULL; - track.sampleRate = mSampleRate; - invalidateState(1<<name); - } - track.volumeInc[0] = 0; - track.volumeInc[1] = 0; - mTrackNames &= ~(1<<name); -} - -void AudioMixer::enable(int name) -{ - name -= TRACK0; - ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name); - track_t& track = mState.tracks[name]; - - if (!track.enabled) { - track.enabled = true; - ALOGV("enable(%d)", name); - invalidateState(1 << name); - } -} - -void AudioMixer::disable(int name) -{ - name -= TRACK0; - ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name); - track_t& track = mState.tracks[name]; - - if (track.enabled) { - track.enabled = false; - ALOGV("disable(%d)", name); - invalidateState(1 << name); - } -} - -void AudioMixer::setParameter(int name, int target, int param, void *value) -{ - name -= TRACK0; - ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name); - track_t& track = mState.tracks[name]; - - int valueInt = (int)value; - int32_t *valueBuf = (int32_t *)value; - - switch (target) { - - case TRACK: - switch (param) { - case CHANNEL_MASK: { - uint32_t mask = (uint32_t)value; - if (track.channelMask != mask) { - uint32_t channelCount = popcount(mask); - ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS) && (channelCount), - "bad channel count %u", channelCount); - track.channelMask = mask; - track.channelCount = channelCount; - ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask); - invalidateState(1 << name); - } - } break; - case MAIN_BUFFER: - if (track.mainBuffer != valueBuf) { - track.mainBuffer = valueBuf; - ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf); - invalidateState(1 << name); - } - break; - case AUX_BUFFER: - if (track.auxBuffer != valueBuf) { - track.auxBuffer = valueBuf; - ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf); - invalidateState(1 << name); - } - break; - default: - LOG_FATAL("bad param"); - } - break; - - case RESAMPLE: - switch (param) { - case SAMPLE_RATE: - ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt); - if (track.setResampler(uint32_t(valueInt), mSampleRate)) { - ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)", - uint32_t(valueInt)); - invalidateState(1 << name); - } - break; - case RESET: - track.resetResampler(); - invalidateState(1 << name); - break; - default: - LOG_FATAL("bad param"); - } - break; - - case RAMP_VOLUME: - case VOLUME: - switch (param) { - case VOLUME0: - case VOLUME1: - if (track.volume[param-VOLUME0] != valueInt) { - ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt); - track.prevVolume[param-VOLUME0] = track.volume[param-VOLUME0] << 16; - track.volume[param-VOLUME0] = valueInt; - if (target == VOLUME) { - track.prevVolume[param-VOLUME0] = valueInt << 16; - track.volumeInc[param-VOLUME0] = 0; - } else { - int32_t d = (valueInt<<16) - track.prevVolume[param-VOLUME0]; - int32_t volInc = d / int32_t(mState.frameCount); - track.volumeInc[param-VOLUME0] = volInc; - if (volInc == 0) { - track.prevVolume[param-VOLUME0] = valueInt << 16; - } - } - invalidateState(1 << name); - } - break; - case AUXLEVEL: - //ALOG_ASSERT(0 <= valueInt && valueInt <= MAX_GAIN_INT, "bad aux level %d", valueInt); - if (track.auxLevel != valueInt) { - ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt); - track.prevAuxLevel = track.auxLevel << 16; - track.auxLevel = valueInt; - if (target == VOLUME) { - track.prevAuxLevel = valueInt << 16; - track.auxInc = 0; - } else { - int32_t d = (valueInt<<16) - track.prevAuxLevel; - int32_t volInc = d / int32_t(mState.frameCount); - track.auxInc = volInc; - if (volInc == 0) { - track.prevAuxLevel = valueInt << 16; - } - } - invalidateState(1 << name); - } - break; - default: - LOG_FATAL("bad param"); - } - break; - - default: - LOG_FATAL("bad target"); - } -} - -bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate) -{ - if (value!=devSampleRate || resampler) { - if (sampleRate != value) { - sampleRate = value; - if (resampler == NULL) { - resampler = AudioResampler::create( - format, channelCount, devSampleRate); - resampler->setLocalTimeFreq(localTimeFreq); - } - return true; - } - } - return false; -} - -inline -void AudioMixer::track_t::adjustVolumeRamp(bool aux) -{ - for (uint32_t i=0 ; i<MAX_NUM_CHANNELS ; 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; - } - } - if (aux) { - if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) || - ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) { - auxInc = 0; - prevAuxLevel = auxLevel<<16; - } - } -} - -size_t AudioMixer::getUnreleasedFrames(int name) const -{ - name -= TRACK0; - if (uint32_t(name) < MAX_NUM_TRACKS) { - return mState.tracks[name].getUnreleasedFrames(); - } - return 0; -} - -void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider) -{ - name -= TRACK0; - ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name); - mState.tracks[name].bufferProvider = bufferProvider; -} - - - -void AudioMixer::process(int64_t pts) -{ - mState.hook(&mState, pts); -} - - -void AudioMixer::process__validate(state_t* state, int64_t pts) -{ - ALOGW_IF(!state->needsChanged, - "in process__validate() but nothing's invalid"); - - uint32_t changed = state->needsChanged; - state->needsChanged = 0; // clear the validation flag - - // recompute which tracks are enabled / disabled - uint32_t enabled = 0; - uint32_t disabled = 0; - while (changed) { - const int i = 31 - __builtin_clz(changed); - const uint32_t mask = 1<<i; - changed &= ~mask; - track_t& t = state->tracks[i]; - (t.enabled ? enabled : disabled) |= mask; - } - state->enabledTracks &= ~disabled; - state->enabledTracks |= enabled; - - // compute everything we need... - int countActiveTracks = 0; - bool all16BitsStereoNoResample = true; - bool resampling = false; - bool volumeRamp = false; - uint32_t en = state->enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - - countActiveTracks++; - track_t& t = state->tracks[i]; - uint32_t n = 0; - n |= NEEDS_CHANNEL_1 + t.channelCount - 1; - n |= NEEDS_FORMAT_16; - n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED; - if (t.auxLevel != 0 && t.auxBuffer != NULL) { - n |= NEEDS_AUX_ENABLED; - } - - if (t.volumeInc[0]|t.volumeInc[1]) { - volumeRamp = true; - } else if (!t.doesResample() && t.volumeRL == 0) { - n |= NEEDS_MUTE_ENABLED; - } - t.needs = n; - - if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) { - t.hook = track__nop; - } else { - if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) { - all16BitsStereoNoResample = false; - } - if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) { - all16BitsStereoNoResample = false; - resampling = true; - t.hook = track__genericResample; - } else { - if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){ - t.hook = track__16BitsMono; - all16BitsStereoNoResample = false; - } - if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){ - t.hook = track__16BitsStereo; - } - } - } - } - - // select the processing hooks - state->hook = process__nop; - if (countActiveTracks) { - if (resampling) { - if (!state->outputTemp) { - state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount]; - } - if (!state->resampleTemp) { - state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount]; - } - state->hook = process__genericResampling; - } else { - if (state->outputTemp) { - delete [] state->outputTemp; - state->outputTemp = NULL; - } - if (state->resampleTemp) { - delete [] state->resampleTemp; - state->resampleTemp = NULL; - } - state->hook = process__genericNoResampling; - if (all16BitsStereoNoResample && !volumeRamp) { - if (countActiveTracks == 1) { - state->hook = process__OneTrack16BitsStereoNoResampling; - } - } - } - } - - ALOGV("mixer configuration change: %d activeTracks (%08x) " - "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d", - countActiveTracks, state->enabledTracks, - all16BitsStereoNoResample, resampling, volumeRamp); - - state->hook(state, pts); - - // Now that the volume ramp has been done, set optimal state and - // track hooks for subsequent mixer process - if (countActiveTracks) { - bool allMuted = true; - uint32_t en = state->enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - if (!t.doesResample() && t.volumeRL == 0) - { - t.needs |= NEEDS_MUTE_ENABLED; - t.hook = track__nop; - } else { - allMuted = false; - } - } - if (allMuted) { - state->hook = process__nop; - } else if (all16BitsStereoNoResample) { - if (countActiveTracks == 1) { - state->hook = process__OneTrack16BitsStereoNoResampling; - } - } - } -} - - -void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux) -{ - t->resampler->setSampleRate(t->sampleRate); - - // ramp gain - resample to temp buffer and scale/mix in 2nd step - if (aux != NULL) { - // always resample with unity gain when sending to auxiliary buffer to be able - // to apply send level after resampling - // TODO: modify each resampler to support aux channel? - t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN); - memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t)); - t->resampler->resample(temp, outFrameCount, t->bufferProvider); - if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) { - volumeRampStereo(t, out, outFrameCount, temp, aux); - } else { - volumeStereo(t, out, outFrameCount, temp, aux); - } - } else { - if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) { - t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN); - memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t)); - t->resampler->resample(temp, outFrameCount, t->bufferProvider); - volumeRampStereo(t, out, outFrameCount, temp, aux); - } - - // constant gain - else { - t->resampler->setVolume(t->volume[0], t->volume[1]); - t->resampler->resample(out, outFrameCount, t->bufferProvider); - } - } -} - -void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux) -{ -} - -void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux) -{ - int32_t vl = t->prevVolume[0]; - int32_t vr = t->prevVolume[1]; - const int32_t vlInc = t->volumeInc[0]; - const int32_t vrInc = t->volumeInc[1]; - - //ALOGD("[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 - if (CC_UNLIKELY(aux != NULL)) { - int32_t va = t->prevAuxLevel; - const int32_t vaInc = t->auxInc; - int32_t l; - int32_t r; - - do { - l = (*temp++ >> 12); - r = (*temp++ >> 12); - *out++ += (vl >> 16) * l; - *out++ += (vr >> 16) * r; - *aux++ += (va >> 17) * (l + r); - vl += vlInc; - vr += vrInc; - va += vaInc; - } while (--frameCount); - t->prevAuxLevel = va; - } else { - do { - *out++ += (vl >> 16) * (*temp++ >> 12); - *out++ += (vr >> 16) * (*temp++ >> 12); - vl += vlInc; - vr += vrInc; - } while (--frameCount); - } - t->prevVolume[0] = vl; - t->prevVolume[1] = vr; - t->adjustVolumeRamp(aux != NULL); -} - -void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux) -{ - const int16_t vl = t->volume[0]; - const int16_t vr = t->volume[1]; - - if (CC_UNLIKELY(aux != NULL)) { - const int16_t va = t->auxLevel; - do { - int16_t l = (int16_t)(*temp++ >> 12); - int16_t r = (int16_t)(*temp++ >> 12); - out[0] = mulAdd(l, vl, out[0]); - int16_t a = (int16_t)(((int32_t)l + r) >> 1); - out[1] = mulAdd(r, vr, out[1]); - out += 2; - aux[0] = mulAdd(a, va, aux[0]); - aux++; - } while (--frameCount); - } else { - do { - int16_t l = (int16_t)(*temp++ >> 12); - int16_t r = (int16_t)(*temp++ >> 12); - out[0] = mulAdd(l, vl, out[0]); - out[1] = mulAdd(r, vr, out[1]); - out += 2; - } while (--frameCount); - } -} - -void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux) -{ - const int16_t *in = static_cast<const int16_t *>(t->in); - - if (CC_UNLIKELY(aux != NULL)) { - int32_t l; - int32_t r; - // ramp gain - if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) { - int32_t vl = t->prevVolume[0]; - int32_t vr = t->prevVolume[1]; - int32_t va = t->prevAuxLevel; - const int32_t vlInc = t->volumeInc[0]; - const int32_t vrInc = t->volumeInc[1]; - const int32_t vaInc = t->auxInc; - // ALOGD("[1] %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); - - do { - l = (int32_t)*in++; - r = (int32_t)*in++; - *out++ += (vl >> 16) * l; - *out++ += (vr >> 16) * r; - *aux++ += (va >> 17) * (l + r); - vl += vlInc; - vr += vrInc; - va += vaInc; - } while (--frameCount); - - t->prevVolume[0] = vl; - t->prevVolume[1] = vr; - t->prevAuxLevel = va; - t->adjustVolumeRamp(true); - } - - // constant gain - else { - const uint32_t vrl = t->volumeRL; - const int16_t va = (int16_t)t->auxLevel; - do { - uint32_t rl = *reinterpret_cast<const uint32_t *>(in); - int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1); - in += 2; - out[0] = mulAddRL(1, rl, vrl, out[0]); - out[1] = mulAddRL(0, rl, vrl, out[1]); - out += 2; - aux[0] = mulAdd(a, va, aux[0]); - aux++; - } while (--frameCount); - } - } else { - // ramp gain - if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) { - int32_t vl = t->prevVolume[0]; - int32_t vr = t->prevVolume[1]; - const int32_t vlInc = t->volumeInc[0]; - const int32_t vrInc = t->volumeInc[1]; - - // ALOGD("[1] %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); - - do { - *out++ += (vl >> 16) * (int32_t) *in++; - *out++ += (vr >> 16) * (int32_t) *in++; - vl += vlInc; - vr += vrInc; - } while (--frameCount); - - t->prevVolume[0] = vl; - t->prevVolume[1] = vr; - t->adjustVolumeRamp(false); - } - - // constant gain - else { - const uint32_t vrl = t->volumeRL; - do { - uint32_t rl = *reinterpret_cast<const uint32_t *>(in); - in += 2; - out[0] = mulAddRL(1, rl, vrl, out[0]); - out[1] = mulAddRL(0, rl, vrl, out[1]); - out += 2; - } while (--frameCount); - } - } - t->in = in; -} - -void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux) -{ - const int16_t *in = static_cast<int16_t const *>(t->in); - - if (CC_UNLIKELY(aux != NULL)) { - // ramp gain - if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) { - int32_t vl = t->prevVolume[0]; - int32_t vr = t->prevVolume[1]; - int32_t va = t->prevAuxLevel; - const int32_t vlInc = t->volumeInc[0]; - const int32_t vrInc = t->volumeInc[1]; - const int32_t vaInc = t->auxInc; - - // ALOGD("[2] %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); - - do { - int32_t l = *in++; - *out++ += (vl >> 16) * l; - *out++ += (vr >> 16) * l; - *aux++ += (va >> 16) * l; - vl += vlInc; - vr += vrInc; - va += vaInc; - } while (--frameCount); - - t->prevVolume[0] = vl; - t->prevVolume[1] = vr; - t->prevAuxLevel = va; - t->adjustVolumeRamp(true); - } - // constant gain - else { - const int16_t vl = t->volume[0]; - const int16_t vr = t->volume[1]; - const int16_t va = (int16_t)t->auxLevel; - do { - int16_t l = *in++; - out[0] = mulAdd(l, vl, out[0]); - out[1] = mulAdd(l, vr, out[1]); - out += 2; - aux[0] = mulAdd(l, va, aux[0]); - aux++; - } while (--frameCount); - } - } else { - // ramp gain - if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) { - int32_t vl = t->prevVolume[0]; - int32_t vr = t->prevVolume[1]; - const int32_t vlInc = t->volumeInc[0]; - const int32_t vrInc = t->volumeInc[1]; - - // ALOGD("[2] %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); - - do { - int32_t l = *in++; - *out++ += (vl >> 16) * l; - *out++ += (vr >> 16) * l; - vl += vlInc; - vr += vrInc; - } while (--frameCount); - - t->prevVolume[0] = vl; - t->prevVolume[1] = vr; - t->adjustVolumeRamp(false); - } - // constant gain - else { - const int16_t vl = t->volume[0]; - const int16_t vr = t->volume[1]; - do { - int16_t l = *in++; - out[0] = mulAdd(l, vl, out[0]); - out[1] = mulAdd(l, vr, out[1]); - out += 2; - } while (--frameCount); - } - } - t->in = in; -} - -// no-op case -void AudioMixer::process__nop(state_t* state, int64_t pts) -{ - uint32_t e0 = state->enabledTracks; - size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS; - while (e0) { - // process by group of tracks with same output buffer to - // avoid multiple memset() on same buffer - uint32_t e1 = e0, e2 = e0; - int i = 31 - __builtin_clz(e1); - track_t& t1 = state->tracks[i]; - e2 &= ~(1<<i); - while (e2) { - i = 31 - __builtin_clz(e2); - e2 &= ~(1<<i); - track_t& t2 = state->tracks[i]; - if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) { - e1 &= ~(1<<i); - } - } - e0 &= ~(e1); - - memset(t1.mainBuffer, 0, bufSize); - - while (e1) { - i = 31 - __builtin_clz(e1); - e1 &= ~(1<<i); - t1 = state->tracks[i]; - size_t outFrames = state->frameCount; - while (outFrames) { - t1.buffer.frameCount = outFrames; - int64_t outputPTS = calculateOutputPTS( - t1, pts, state->frameCount - outFrames); - t1.bufferProvider->getNextBuffer(&t1.buffer, outputPTS); - if (t1.buffer.raw == NULL) break; - outFrames -= t1.buffer.frameCount; - t1.bufferProvider->releaseBuffer(&t1.buffer); - } - } - } -} - -// generic code without resampling -void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts) -{ - int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32))); - - // acquire each track's buffer - uint32_t enabledTracks = state->enabledTracks; - uint32_t e0 = enabledTracks; - while (e0) { - const int i = 31 - __builtin_clz(e0); - e0 &= ~(1<<i); - track_t& t = state->tracks[i]; - t.buffer.frameCount = state->frameCount; - t.bufferProvider->getNextBuffer(&t.buffer, pts); - 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); - } - - e0 = enabledTracks; - while (e0) { - // process by group of tracks with same output buffer to - // optimize cache use - uint32_t e1 = e0, e2 = e0; - int j = 31 - __builtin_clz(e1); - track_t& t1 = state->tracks[j]; - e2 &= ~(1<<j); - while (e2) { - j = 31 - __builtin_clz(e2); - e2 &= ~(1<<j); - track_t& t2 = state->tracks[j]; - if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) { - e1 &= ~(1<<j); - } - } - e0 &= ~(e1); - // this assumes output 16 bits stereo, no resampling - int32_t *out = t1.mainBuffer; - size_t numFrames = 0; - do { - memset(outTemp, 0, sizeof(outTemp)); - e2 = e1; - while (e2) { - const int i = 31 - __builtin_clz(e2); - e2 &= ~(1<<i); - track_t& t = state->tracks[i]; - size_t outFrames = BLOCKSIZE; - int32_t *aux = NULL; - if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) { - aux = t.auxBuffer + numFrames; - } - 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, aux); - t.frameCount -= inFrames; - outFrames -= inFrames; - if (CC_UNLIKELY(aux != NULL)) { - aux += inFrames; - } - } - if (t.frameCount == 0 && outFrames) { - t.bufferProvider->releaseBuffer(&t.buffer); - t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames); - int64_t outputPTS = calculateOutputPTS( - t, pts, numFrames + (BLOCKSIZE - outFrames)); - t.bufferProvider->getNextBuffer(&t.buffer, outputPTS); - t.in = t.buffer.raw; - if (t.in == NULL) { - enabledTracks &= ~(1<<i); - e1 &= ~(1<<i); - break; - } - t.frameCount = t.buffer.frameCount; - } - } - } - ditherAndClamp(out, outTemp, BLOCKSIZE); - out += BLOCKSIZE; - numFrames += BLOCKSIZE; - } while (numFrames < state->frameCount); - } - - // release each track's buffer - e0 = enabledTracks; - while (e0) { - const int i = 31 - __builtin_clz(e0); - e0 &= ~(1<<i); - track_t& t = state->tracks[i]; - t.bufferProvider->releaseBuffer(&t.buffer); - } -} - - -// generic code with resampling -void AudioMixer::process__genericResampling(state_t* state, int64_t pts) -{ - // this const just means that local variable outTemp doesn't change - int32_t* const outTemp = state->outputTemp; - const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount; - - size_t numFrames = state->frameCount; - - uint32_t e0 = state->enabledTracks; - while (e0) { - // process by group of tracks with same output buffer - // to optimize cache use - uint32_t e1 = e0, e2 = e0; - int j = 31 - __builtin_clz(e1); - track_t& t1 = state->tracks[j]; - e2 &= ~(1<<j); - while (e2) { - j = 31 - __builtin_clz(e2); - e2 &= ~(1<<j); - track_t& t2 = state->tracks[j]; - if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) { - e1 &= ~(1<<j); - } - } - e0 &= ~(e1); - int32_t *out = t1.mainBuffer; - memset(outTemp, 0, size); - while (e1) { - const int i = 31 - __builtin_clz(e1); - e1 &= ~(1<<i); - track_t& t = state->tracks[i]; - int32_t *aux = NULL; - if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) { - aux = t.auxBuffer; - } - - // this is a little goofy, on the resampling case we don't - // acquire/release the buffers because it's done by - // the resampler. - if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) { - t.resampler->setPTS(pts); - t.hook(&t, outTemp, numFrames, state->resampleTemp, aux); - } else { - - size_t outFrames = 0; - - while (outFrames < numFrames) { - t.buffer.frameCount = numFrames - outFrames; - int64_t outputPTS = calculateOutputPTS(t, pts, outFrames); - t.bufferProvider->getNextBuffer(&t.buffer, outputPTS); - 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; - - if (CC_UNLIKELY(aux != NULL)) { - aux += outFrames; - } - t.hook(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux); - outFrames += t.buffer.frameCount; - t.bufferProvider->releaseBuffer(&t.buffer); - } - } - } - ditherAndClamp(out, outTemp, numFrames); - } -} - -// one track, 16 bits stereo without resampling is the most common case -void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state, - int64_t pts) -{ - // This method is only called when state->enabledTracks has exactly - // one bit set. The asserts below would verify this, but are commented out - // since the whole point of this method is to optimize performance. - //ALOG_ASSERT(0 != state->enabledTracks, "no tracks enabled"); - const int i = 31 - __builtin_clz(state->enabledTracks); - //ALOG_ASSERT((1 << i) == state->enabledTracks, "more than 1 track enabled"); - const track_t& t = state->tracks[i]; - - AudioBufferProvider::Buffer& b(t.buffer); - - int32_t* out = t.mainBuffer; - 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; - while (numFrames) { - b.frameCount = numFrames; - int64_t outputPTS = calculateOutputPTS(t, pts, out - t.mainBuffer); - t.bufferProvider->getNextBuffer(&b, outputPTS); - const int16_t *in = b.i16; - - // in == NULL can happen if the track was flushed just after having - // been enabled for mixing. - if (in == NULL || ((unsigned long)in & 3)) { - memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t)); - ALOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x", - in, i, t.channelCount, t.needs); - return; - } - size_t outFrames = b.frameCount; - - if (CC_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<const uint32_t *>(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<const uint32_t *>(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); - } -} - -#if 0 -// 2 tracks is also a common case -// NEVER used in current implementation of process__validate() -// only use if the 2 tracks have the same output buffer -void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state, - int64_t pts) -{ - int i; - uint32_t en = state->enabledTracks; - - i = 31 - __builtin_clz(en); - const track_t& t0 = state->tracks[i]; - AudioBufferProvider::Buffer& b0(t0.buffer); - - en &= ~(1<<i); - i = 31 - __builtin_clz(en); - const track_t& t1 = state->tracks[i]; - AudioBufferProvider::Buffer& b1(t1.buffer); - - const int16_t *in0; - const int16_t vl0 = t0.volume[0]; - const int16_t vr0 = t0.volume[1]; - size_t frameCount0 = 0; - - const int16_t *in1; - const int16_t vl1 = t1.volume[0]; - const int16_t vr1 = t1.volume[1]; - size_t frameCount1 = 0; - - //FIXME: only works if two tracks use same buffer - int32_t* out = t0.mainBuffer; - size_t numFrames = state->frameCount; - const int16_t *buff = NULL; - - - while (numFrames) { - - if (frameCount0 == 0) { - b0.frameCount = numFrames; - int64_t outputPTS = calculateOutputPTS(t0, pts, - out - t0.mainBuffer); - t0.bufferProvider->getNextBuffer(&b0, outputPTS); - 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; - } - if (frameCount1 == 0) { - b1.frameCount = numFrames; - int64_t outputPTS = calculateOutputPTS(t1, pts, - out - t0.mainBuffer); - t1.bufferProvider->getNextBuffer(&b1, outputPTS); - 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; - } - - size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1; - - 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); - } - if (frameCount1 == 0) { - t1.bufferProvider->releaseBuffer(&b1); - } - } - - delete [] buff; -} -#endif - -int64_t AudioMixer::calculateOutputPTS(const track_t& t, int64_t basePTS, - int outputFrameIndex) -{ - if (AudioBufferProvider::kInvalidPTS == basePTS) - return AudioBufferProvider::kInvalidPTS; - - return basePTS + ((outputFrameIndex * t.localTimeFreq) / t.sampleRate); -} - -// ---------------------------------------------------------------------------- -}; // namespace android |