summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/AudioMixer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/audioflinger/AudioMixer.cpp')
-rw-r--r--services/audioflinger/AudioMixer.cpp212
1 files changed, 130 insertions, 82 deletions
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index f92421e..2d67efb 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -58,7 +58,7 @@ AudioMixer::DownmixerBufferProvider::~DownmixerBufferProvider()
status_t AudioMixer::DownmixerBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer,
int64_t pts) {
//ALOGV("DownmixerBufferProvider::getNextBuffer()");
- if (this->mTrackBufferProvider != NULL) {
+ if (mTrackBufferProvider != NULL) {
status_t res = mTrackBufferProvider->getNextBuffer(pBuffer, pts);
if (res == OK) {
mDownmixConfig.inputCfg.buffer.frameCount = pBuffer->frameCount;
@@ -81,7 +81,7 @@ status_t AudioMixer::DownmixerBufferProvider::getNextBuffer(AudioBufferProvider:
void AudioMixer::DownmixerBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) {
//ALOGV("DownmixerBufferProvider::releaseBuffer()");
- if (this->mTrackBufferProvider != NULL) {
+ if (mTrackBufferProvider != NULL) {
mTrackBufferProvider->releaseBuffer(pBuffer);
} else {
ALOGE("DownmixerBufferProvider::releaseBuffer() error: NULL track buffer provider");
@@ -90,9 +90,9 @@ void AudioMixer::DownmixerBufferProvider::releaseBuffer(AudioBufferProvider::Buf
// ----------------------------------------------------------------------------
-bool AudioMixer::isMultichannelCapable = false;
+bool AudioMixer::sIsMultichannelCapable = false;
-effect_descriptor_t AudioMixer::dwnmFxDesc;
+effect_descriptor_t AudioMixer::sDwnmFxDesc;
// Ensure mConfiguredNames bitmask is initialized properly on all architectures.
// The value of 1 << x is undefined in C when x >= 32.
@@ -113,8 +113,6 @@ AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate, uint32_t maxNumTr
// AudioMixer is not yet capable of multi-channel output beyond stereo
ALOG_ASSERT(2 == MAX_NUM_CHANNELS, "bad MAX_NUM_CHANNELS %d", MAX_NUM_CHANNELS);
- LocalClock lc;
-
pthread_once(&sOnceControl, &sInitRoutine);
mState.enabledTracks= 0;
@@ -136,27 +134,6 @@ AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate, uint32_t maxNumTr
t++;
}
- // find multichannel downmix effect if we have to play multichannel content
- uint32_t numEffects = 0;
- int ret = EffectQueryNumberEffects(&numEffects);
- if (ret != 0) {
- ALOGE("AudioMixer() error %d querying number of effects", ret);
- return;
- }
- ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
-
- for (uint32_t i = 0 ; i < numEffects ; i++) {
- if (EffectQueryEffect(i, &dwnmFxDesc) == 0) {
- ALOGV("effect %d is called %s", i, dwnmFxDesc.name);
- if (memcmp(&dwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
- ALOGI("found effect \"%s\" from %s",
- dwnmFxDesc.name, dwnmFxDesc.implementor);
- isMultichannelCapable = true;
- break;
- }
- }
- }
- ALOGE_IF(!isMultichannelCapable, "unable to find downmix effect");
}
AudioMixer::~AudioMixer()
@@ -216,6 +193,7 @@ int AudioMixer::getTrackName(audio_channel_mask_t channelMask, int sessionId)
t->mainBuffer = NULL;
t->auxBuffer = NULL;
t->downmixerBufferProvider = NULL;
+ t->mMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
status_t status = initTrackDownmix(&mState.tracks[n], n, channelMask);
if (status == OK) {
@@ -229,7 +207,7 @@ int AudioMixer::getTrackName(audio_channel_mask_t channelMask, int sessionId)
void AudioMixer::invalidateState(uint32_t mask)
{
- if (mask) {
+ if (mask != 0) {
mState.needsChanged |= mask;
mState.hook = process__validate;
}
@@ -252,7 +230,7 @@ status_t AudioMixer::initTrackDownmix(track_t* pTrack, int trackNum, audio_chann
return status;
}
-void AudioMixer::unprepareTrackForDownmix(track_t* pTrack, int trackName) {
+void AudioMixer::unprepareTrackForDownmix(track_t* pTrack, int trackName __unused) {
ALOGV("AudioMixer::unprepareTrackForDownmix(%d)", trackName);
if (pTrack->downmixerBufferProvider != NULL) {
@@ -276,13 +254,13 @@ status_t AudioMixer::prepareTrackForDownmix(track_t* pTrack, int trackName)
DownmixerBufferProvider* pDbp = new DownmixerBufferProvider();
int32_t status;
- if (!isMultichannelCapable) {
+ if (!sIsMultichannelCapable) {
ALOGE("prepareTrackForDownmix(%d) fails: mixer doesn't support multichannel content",
trackName);
goto noDownmixForActiveTrack;
}
- if (EffectCreate(&dwnmFxDesc.uuid,
+ if (EffectCreate(&sDwnmFxDesc.uuid,
pTrack->sessionId /*sessionId*/, -2 /*ioId not relevant here, using random value*/,
&pDbp->mDownmixHandle/*pHandle*/) != 0) {
ALOGE("prepareTrackForDownmix(%d) fails: error creating downmixer effect", trackName);
@@ -463,8 +441,15 @@ void AudioMixer::setParameter(int name, int target, int param, void *value)
// for a specific track? or per mixer?
/* case DOWNMIX_TYPE:
break */
+ case MIXER_FORMAT: {
+ audio_format_t format = static_cast<audio_format_t>(valueInt);
+ if (track.mMixerFormat != format) {
+ track.mMixerFormat = format;
+ ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format);
+ }
+ } break;
default:
- LOG_FATAL("bad param");
+ LOG_ALWAYS_FATAL("setParameter track: bad param %d", param);
}
break;
@@ -489,7 +474,7 @@ void AudioMixer::setParameter(int name, int target, int param, void *value)
invalidateState(1 << name);
break;
default:
- LOG_FATAL("bad param");
+ LOG_ALWAYS_FATAL("setParameter resample: bad param %d", param);
}
break;
@@ -537,12 +522,12 @@ void AudioMixer::setParameter(int name, int target, int param, void *value)
}
break;
default:
- LOG_FATAL("bad param");
+ LOG_ALWAYS_FATAL("setParameter volume: bad param %d", param);
}
break;
default:
- LOG_FATAL("bad target");
+ LOG_ALWAYS_FATAL("setParameter: bad target %d", target);
}
}
@@ -560,14 +545,14 @@ bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
// Should have a way to distinguish tracks with static ratios vs. dynamic ratios.
if (!((value == 44100 && devSampleRate == 48000) ||
(value == 48000 && devSampleRate == 44100))) {
- quality = AudioResampler::LOW_QUALITY;
+ quality = AudioResampler::DYN_LOW_QUALITY;
} else {
quality = AudioResampler::DEFAULT_QUALITY;
}
resampler = AudioResampler::create(
format,
// the resampler sees the number of channels after the downmixer, if any
- downmixerBufferProvider != NULL ? MAX_NUM_CHANNELS : channelCount,
+ (int) (downmixerBufferProvider != NULL ? MAX_NUM_CHANNELS : channelCount),
devSampleRate, quality);
resampler->setLocalTimeFreq(sLocalTimeFreq);
}
@@ -668,27 +653,29 @@ void AudioMixer::process__validate(state_t* state, int64_t pts)
countActiveTracks++;
track_t& t = state->tracks[i];
uint32_t n = 0;
+ // FIXME can overflow (mask is only 3 bits)
n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
- n |= NEEDS_FORMAT_16;
- n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
+ if (t.doesResample()) {
+ n |= NEEDS_RESAMPLE;
+ }
if (t.auxLevel != 0 && t.auxBuffer != NULL) {
- n |= NEEDS_AUX_ENABLED;
+ n |= NEEDS_AUX;
}
if (t.volumeInc[0]|t.volumeInc[1]) {
volumeRamp = true;
} else if (!t.doesResample() && t.volumeRL == 0) {
- n |= NEEDS_MUTE_ENABLED;
+ n |= NEEDS_MUTE;
}
t.needs = n;
- if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
+ if (n & NEEDS_MUTE) {
t.hook = track__nop;
} else {
- if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
+ if (n & NEEDS_AUX) {
all16BitsStereoNoResample = false;
}
- if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
+ if (n & NEEDS_RESAMPLE) {
all16BitsStereoNoResample = false;
resampling = true;
t.hook = track__genericResample;
@@ -710,7 +697,7 @@ void AudioMixer::process__validate(state_t* state, int64_t pts)
// select the processing hooks
state->hook = process__nop;
- if (countActiveTracks) {
+ if (countActiveTracks > 0) {
if (resampling) {
if (!state->outputTemp) {
state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
@@ -746,16 +733,15 @@ void AudioMixer::process__validate(state_t* state, int64_t pts)
// Now that the volume ramp has been done, set optimal state and
// track hooks for subsequent mixer process
- if (countActiveTracks) {
+ if (countActiveTracks > 0) {
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;
+ if (!t.doesResample() && t.volumeRL == 0) {
+ t.needs |= NEEDS_MUTE;
t.hook = track__nop;
} else {
allMuted = false;
@@ -806,8 +792,8 @@ void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFram
}
}
-void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp,
- int32_t* aux)
+void AudioMixer::track__nop(track_t* t __unused, int32_t* out __unused,
+ size_t outFrameCount __unused, int32_t* temp __unused, int32_t* aux __unused)
{
}
@@ -883,8 +869,8 @@ void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32
}
}
-void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp,
- int32_t* aux)
+void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount,
+ int32_t* temp __unused, int32_t* aux)
{
const int16_t *in = static_cast<const int16_t *>(t->in);
@@ -974,8 +960,8 @@ void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount
t->in = in;
}
-void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp,
- int32_t* aux)
+void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount,
+ int32_t* temp __unused, int32_t* aux)
{
const int16_t *in = static_cast<int16_t const *>(t->in);
@@ -1065,7 +1051,7 @@ void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount,
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;
+ size_t sampleCount = state->frameCount * MAX_NUM_CHANNELS;
while (e0) {
// process by group of tracks with same output buffer to
// avoid multiple memset() on same buffer
@@ -1084,7 +1070,8 @@ void AudioMixer::process__nop(state_t* state, int64_t pts)
}
e0 &= ~(e1);
- memset(t1.mainBuffer, 0, bufSize);
+ memset(t1.mainBuffer, 0, sampleCount
+ * audio_bytes_per_sample(t1.mMixerFormat));
}
while (e1) {
@@ -1154,7 +1141,7 @@ void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
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)) {
+ if (CC_UNLIKELY(t.needs & NEEDS_AUX)) {
aux = t.auxBuffer + numFrames;
}
while (outFrames) {
@@ -1166,7 +1153,7 @@ void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
break;
}
size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
- if (inFrames) {
+ if (inFrames > 0) {
t.hook(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames,
state->resampleTemp, aux);
t.frameCount -= inFrames;
@@ -1192,8 +1179,18 @@ void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
}
}
}
- ditherAndClamp(out, outTemp, BLOCKSIZE);
- out += BLOCKSIZE;
+ switch (t1.mMixerFormat) {
+ case AUDIO_FORMAT_PCM_FLOAT:
+ memcpy_to_float_from_q4_27(reinterpret_cast<float *>(out), outTemp, BLOCKSIZE * 2);
+ out += BLOCKSIZE * 2; // output is 2 floats/frame.
+ break;
+ case AUDIO_FORMAT_PCM_16_BIT:
+ ditherAndClamp(out, outTemp, BLOCKSIZE);
+ out += BLOCKSIZE; // output is 1 int32_t (2 int16_t samples)/frame
+ break;
+ default:
+ LOG_ALWAYS_FATAL("bad mixer format: %d", t1.mMixerFormat);
+ }
numFrames += BLOCKSIZE;
} while (numFrames < state->frameCount);
}
@@ -1242,14 +1239,14 @@ void AudioMixer::process__genericResampling(state_t* state, int64_t pts)
e1 &= ~(1<<i);
track_t& t = state->tracks[i];
int32_t *aux = NULL;
- if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
+ if (CC_UNLIKELY(t.needs & NEEDS_AUX)) {
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) {
+ if (t.needs & NEEDS_RESAMPLE) {
t.resampler->setPTS(pts);
t.hook(&t, outTemp, numFrames, state->resampleTemp, aux);
} else {
@@ -1275,7 +1272,16 @@ void AudioMixer::process__genericResampling(state_t* state, int64_t pts)
}
}
}
- ditherAndClamp(out, outTemp, numFrames);
+ switch (t1.mMixerFormat) {
+ case AUDIO_FORMAT_PCM_FLOAT:
+ memcpy_to_float_from_q4_27(reinterpret_cast<float*>(out), outTemp, numFrames*2);
+ break;
+ case AUDIO_FORMAT_PCM_16_BIT:
+ ditherAndClamp(out, outTemp, numFrames);
+ break;
+ default:
+ LOG_ALWAYS_FATAL("bad mixer format: %d", t1.mMixerFormat);
+ }
}
}
@@ -1316,27 +1322,46 @@ void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state,
}
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 {
+ switch (t.mMixerFormat) {
+ case AUDIO_FORMAT_PCM_FLOAT: {
+ float *fout = reinterpret_cast<float*>(out);
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);
+ int32_t l = mulRL(1, rl, vrl);
+ int32_t r = mulRL(0, rl, vrl);
+ *fout++ = float_from_q4_27(l);
+ *fout++ = float_from_q4_27(r);
+ // Note: In case of later int16_t sink output,
+ // conversion and clamping is done by memcpy_to_i16_from_float().
} while (--outFrames);
+ } break;
+ case AUDIO_FORMAT_PCM_16_BIT:
+ 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);
+ }
+ break;
+ default:
+ LOG_ALWAYS_FATAL("bad mixer format: %d", t.mMixerFormat);
}
numFrames -= b.frameCount;
t.bufferProvider->releaseBuffer(&b);
@@ -1449,8 +1474,9 @@ void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state,
int64_t AudioMixer::calculateOutputPTS(const track_t& t, int64_t basePTS,
int outputFrameIndex)
{
- if (AudioBufferProvider::kInvalidPTS == basePTS)
+ if (AudioBufferProvider::kInvalidPTS == basePTS) {
return AudioBufferProvider::kInvalidPTS;
+ }
return basePTS + ((outputFrameIndex * sLocalTimeFreq) / t.sampleRate);
}
@@ -1462,6 +1488,28 @@ int64_t AudioMixer::calculateOutputPTS(const track_t& t, int64_t basePTS,
{
LocalClock lc;
sLocalTimeFreq = lc.getLocalFreq();
+
+ // find multichannel downmix effect if we have to play multichannel content
+ uint32_t numEffects = 0;
+ int ret = EffectQueryNumberEffects(&numEffects);
+ if (ret != 0) {
+ ALOGE("AudioMixer() error %d querying number of effects", ret);
+ return;
+ }
+ ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
+
+ for (uint32_t i = 0 ; i < numEffects ; i++) {
+ if (EffectQueryEffect(i, &sDwnmFxDesc) == 0) {
+ ALOGV("effect %d is called %s", i, sDwnmFxDesc.name);
+ if (memcmp(&sDwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
+ ALOGI("found effect \"%s\" from %s",
+ sDwnmFxDesc.name, sDwnmFxDesc.implementor);
+ sIsMultichannelCapable = true;
+ break;
+ }
+ }
+ }
+ ALOGW_IF(!sIsMultichannelCapable, "unable to find downmix effect");
}
// ----------------------------------------------------------------------------