From a1ab7cc8611c83427b57f6d4d4ce7aad9d1c0330 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Mon, 24 Feb 2014 19:26:52 -0800 Subject: Add Track Sink Format to AudioMixer Track Sink Format now allows both AUDIO_FORMAT_PCM_FLOAT and AUDIO_FORMAT_PCM_16_BIT (default). The float case is not enabled now. Change-Id: Ibee70cab4725c8bc9905e49f1f9a9c2448f76e00 Signed-off-by: Andy Hung --- services/audioflinger/AudioMixer.cpp | 90 +++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 22 deletions(-) (limited to 'services/audioflinger/AudioMixer.cpp') diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp index 67d83b1..f00b82a 100644 --- a/services/audioflinger/AudioMixer.cpp +++ b/services/audioflinger/AudioMixer.cpp @@ -193,6 +193,7 @@ int AudioMixer::getTrackName(audio_channel_mask_t channelMask, int sessionId) t->mainBuffer = NULL; t->auxBuffer = NULL; t->downmixerBufferProvider = NULL; + t->mSinkFormat = AUDIO_FORMAT_PCM_16_BIT; status_t status = initTrackDownmix(&mState.tracks[n], n, channelMask); if (status == OK) { @@ -440,6 +441,13 @@ void AudioMixer::setParameter(int name, int target, int param, void *value) // for a specific track? or per mixer? /* case DOWNMIX_TYPE: break */ + case SINK_FORMAT: { + audio_format_t format = static_cast(valueInt); + if (track.mSinkFormat != format) { + track.mSinkFormat = format; + ALOGV("setParameter(TRACK, SINK_FORMAT, %#x)", format); + } + } break; default: LOG_FATAL("bad param"); } @@ -1043,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 @@ -1062,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.mSinkFormat)); } while (e1) { @@ -1170,8 +1179,18 @@ void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts) } } } - ditherAndClamp(out, outTemp, BLOCKSIZE); - out += BLOCKSIZE; + switch (t1.mSinkFormat) { + case AUDIO_FORMAT_PCM_FLOAT: + memcpy_to_float_from_q19_12(reinterpret_cast(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 sink format: %d", t1.mSinkFormat); + } numFrames += BLOCKSIZE; } while (numFrames < state->frameCount); } @@ -1253,7 +1272,16 @@ void AudioMixer::process__genericResampling(state_t* state, int64_t pts) } } } - ditherAndClamp(out, outTemp, numFrames); + switch (t1.mSinkFormat) { + case AUDIO_FORMAT_PCM_FLOAT: + memcpy_to_float_from_q19_12(reinterpret_cast(out), outTemp, numFrames*2); + break; + case AUDIO_FORMAT_PCM_16_BIT: + ditherAndClamp(out, outTemp, numFrames); + break; + default: + LOG_ALWAYS_FATAL("bad sink format: %d", t1.mSinkFormat); + } } } @@ -1294,27 +1322,45 @@ 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. + switch (t.mSinkFormat) { + case AUDIO_FORMAT_PCM_FLOAT: { + float *fout = reinterpret_cast(out); + static float scale = 1. / (32768. * 4096.); // exact when inverted do { uint32_t rl = *reinterpret_cast(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(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++ = static_cast(l) * scale; + *fout++ = static_cast(r) * scale; } 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(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(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 sink format: %d", t.mSinkFormat); } numFrames -= b.frameCount; t.bufferProvider->releaseBuffer(&b); -- cgit v1.1