AudioEffect: Convert aux buffer format from q4.27 to float

Test: Solo Tester aux reverb
Bug: 69853407
Change-Id: I72ca2377036e5ccfd5f4631ac6cc5e86d2e40433
gugelfrei
Andy Hung 7 years ago
parent fa69ca3012
commit 116a49881b

@ -33,6 +33,9 @@
// FIXME This is actually unity gain, which might not be max in future, expressed in U.12 // FIXME This is actually unity gain, which might not be max in future, expressed in U.12
#define MAX_GAIN_INT AudioMixer::UNITY_GAIN_INT #define MAX_GAIN_INT AudioMixer::UNITY_GAIN_INT
// This must match frameworks/av/services/audioflinger/Configuration.h
#define FLOAT_AUX
namespace android { namespace android {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

@ -71,12 +71,20 @@ T max(const T& x, const T& y) {
// Set kUseNewMixer to true to use the new mixer engine always. Otherwise the // Set kUseNewMixer to true to use the new mixer engine always. Otherwise the
// original code will be used for stereo sinks, the new mixer for multichannel. // original code will be used for stereo sinks, the new mixer for multichannel.
static const bool kUseNewMixer = true; static constexpr bool kUseNewMixer = true;
// Set kUseFloat to true to allow floating input into the mixer engine. // Set kUseFloat to true to allow floating input into the mixer engine.
// If kUseNewMixer is false, this is ignored or may be overridden internally // If kUseNewMixer is false, this is ignored or may be overridden internally
// because of downmix/upmix support. // because of downmix/upmix support.
static const bool kUseFloat = true; static constexpr bool kUseFloat = true;
#ifdef FLOAT_AUX
using TYPE_AUX = float;
static_assert(kUseNewMixer && kUseFloat,
"kUseNewMixer and kUseFloat must be true for FLOAT_AUX option");
#else
using TYPE_AUX = int32_t; // q4.27
#endif
// Set to default copy buffer size in frames for input processing. // Set to default copy buffer size in frames for input processing.
static const size_t kCopyBufferFrameCount = 256; static const size_t kCopyBufferFrameCount = 256;
@ -861,16 +869,25 @@ inline void AudioMixer::track_t::adjustVolumeRamp(bool aux, bool useFloat)
} }
} }
} }
/* TODO: aux is always integer regardless of output buffer type */
if (aux) { if (aux) {
if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) || #ifdef FLOAT_AUX
((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) { if (useFloat) {
if ((mAuxInc > 0.f && mPrevAuxLevel + mAuxInc >= mAuxLevel) ||
(mAuxInc < 0.f && mPrevAuxLevel + mAuxInc <= mAuxLevel)) {
auxInc = 0;
prevAuxLevel = auxLevel << 16;
mAuxInc = 0.f;
mPrevAuxLevel = mAuxLevel;
}
} else
#endif
if ((auxInc > 0 && ((prevAuxLevel + auxInc) >> 16) >= auxLevel) ||
(auxInc < 0 && ((prevAuxLevel + auxInc) >> 16) <= auxLevel)) {
auxInc = 0; auxInc = 0;
prevAuxLevel = auxLevel << 16; prevAuxLevel = auxLevel << 16;
mAuxInc = 0.; mAuxInc = 0.f;
mPrevAuxLevel = mAuxLevel; mPrevAuxLevel = mAuxLevel;
} else {
//ALOGV("aux ramp: %d %d %d", auxLevel << 16, prevAuxLevel, auxInc);
} }
} }
} }
@ -1694,7 +1711,7 @@ void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
/* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration) /* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
* TO: int32_t (Q4.27) or float * TO: int32_t (Q4.27) or float
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
* TA: int32_t (Q4.27) * TA: int32_t (Q4.27) or float
*/ */
template <int MIXTYPE, template <int MIXTYPE,
typename TO, typename TI, typename TV, typename TA, typename TAV> typename TO, typename TI, typename TV, typename TA, typename TAV>
@ -1738,7 +1755,7 @@ static void volumeRampMulti(uint32_t channels, TO* out, size_t frameCount,
/* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration) /* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
* TO: int32_t (Q4.27) or float * TO: int32_t (Q4.27) or float
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
* TA: int32_t (Q4.27) * TA: int32_t (Q4.27) or float
*/ */
template <int MIXTYPE, template <int MIXTYPE,
typename TO, typename TI, typename TV, typename TA, typename TAV> typename TO, typename TI, typename TV, typename TA, typename TAV>
@ -1778,7 +1795,7 @@ static void volumeMulti(uint32_t channels, TO* out, size_t frameCount,
* ADJUSTVOL (set to true if volume ramp parameters needs adjustment afterwards) * ADJUSTVOL (set to true if volume ramp parameters needs adjustment afterwards)
* TO: int32_t (Q4.27) or float * TO: int32_t (Q4.27) or float
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
* TA: int32_t (Q4.27) * TA: int32_t (Q4.27) or float
*/ */
template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL, template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
typename TO, typename TI, typename TA> typename TO, typename TI, typename TA>
@ -1788,13 +1805,25 @@ void AudioMixer::volumeMix(TO *out, size_t outFrames,
if (USEFLOATVOL) { if (USEFLOATVOL) {
if (ramp) { if (ramp) {
volumeRampMulti<MIXTYPE>(t->mMixerChannelCount, out, outFrames, in, aux, volumeRampMulti<MIXTYPE>(t->mMixerChannelCount, out, outFrames, in, aux,
t->mPrevVolume, t->mVolumeInc, &t->prevAuxLevel, t->auxInc); t->mPrevVolume, t->mVolumeInc,
#ifdef FLOAT_AUX
&t->mPrevAuxLevel, t->mAuxInc
#else
&t->prevAuxLevel, t->auxInc
#endif
);
if (ADJUSTVOL) { if (ADJUSTVOL) {
t->adjustVolumeRamp(aux != NULL, true); t->adjustVolumeRamp(aux != NULL, true);
} }
} else { } else {
volumeMulti<MIXTYPE>(t->mMixerChannelCount, out, outFrames, in, aux, volumeMulti<MIXTYPE>(t->mMixerChannelCount, out, outFrames, in, aux,
t->mVolume, t->auxLevel); t->mVolume,
#ifdef FLOAT_AUX
t->mAuxLevel
#else
t->auxLevel
#endif
);
} }
} else { } else {
if (ramp) { if (ramp) {
@ -1851,7 +1880,7 @@ void AudioMixer::process_NoResampleOneTrack(state_t* state)
} }
const size_t outFrames = b.frameCount; const size_t outFrames = b.frameCount;
volumeMix<MIXTYPE, is_same<TI, float>::value, false> ( volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, false /* ADJUSTVOL */> (
out, outFrames, in, aux, ramp, t); out, outFrames, in, aux, ramp, t);
out += outFrames * channels; out += outFrames * channels;
@ -1874,7 +1903,7 @@ void AudioMixer::process_NoResampleOneTrack(state_t* state)
* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration) * MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
* TO: int32_t (Q4.27) or float * TO: int32_t (Q4.27) or float
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
* TA: int32_t (Q4.27) * TA: int32_t (Q4.27) or float
*/ */
template <int MIXTYPE, typename TO, typename TI, typename TA> template <int MIXTYPE, typename TO, typename TI, typename TA>
void AudioMixer::track__Resample(track_t* t, TO* out, size_t outFrameCount, TO* temp, TA* aux) void AudioMixer::track__Resample(track_t* t, TO* out, size_t outFrameCount, TO* temp, TA* aux)
@ -1890,7 +1919,7 @@ void AudioMixer::track__Resample(track_t* t, TO* out, size_t outFrameCount, TO*
memset(temp, 0, outFrameCount * t->mMixerChannelCount * sizeof(TO)); memset(temp, 0, outFrameCount * t->mMixerChannelCount * sizeof(TO));
t->resampler->resample((int32_t*)temp, outFrameCount, t->bufferProvider); t->resampler->resample((int32_t*)temp, outFrameCount, t->bufferProvider);
volumeMix<MIXTYPE, is_same<TI, float>::value, true>( volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>(
out, outFrameCount, temp, aux, ramp, t); out, outFrameCount, temp, aux, ramp, t);
} else { // constant volume gain } else { // constant volume gain
@ -1905,7 +1934,7 @@ void AudioMixer::track__Resample(track_t* t, TO* out, size_t outFrameCount, TO*
* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration) * MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
* TO: int32_t (Q4.27) or float * TO: int32_t (Q4.27) or float
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
* TA: int32_t (Q4.27) * TA: int32_t (Q4.27) or float
*/ */
template <int MIXTYPE, typename TO, typename TI, typename TA> template <int MIXTYPE, typename TO, typename TI, typename TA>
void AudioMixer::track__NoResample(track_t* t, TO* out, size_t frameCount, void AudioMixer::track__NoResample(track_t* t, TO* out, size_t frameCount,
@ -1914,7 +1943,7 @@ void AudioMixer::track__NoResample(track_t* t, TO* out, size_t frameCount,
ALOGVV("track__NoResample\n"); ALOGVV("track__NoResample\n");
const TI *in = static_cast<const TI *>(t->in); const TI *in = static_cast<const TI *>(t->in);
volumeMix<MIXTYPE, is_same<TI, float>::value, true>( volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>(
out, frameCount, in, aux, t->needsRamp(), t); out, frameCount, in, aux, t->needsRamp(), t);
// MIXTYPE_MONOEXPAND reads a single input channel and expands to NCHAN output channels. // MIXTYPE_MONOEXPAND reads a single input channel and expands to NCHAN output channels.
@ -1990,11 +2019,11 @@ AudioMixer::hook_t AudioMixer::getTrackHook(int trackType, uint32_t channelCount
case TRACKTYPE_RESAMPLE: case TRACKTYPE_RESAMPLE:
switch (mixerInFormat) { switch (mixerInFormat) {
case AUDIO_FORMAT_PCM_FLOAT: case AUDIO_FORMAT_PCM_FLOAT:
return (AudioMixer::hook_t) return (AudioMixer::hook_t)track__Resample<
track__Resample<MIXTYPE_MULTI, float /*TO*/, float /*TI*/, int32_t /*TA*/>; MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
case AUDIO_FORMAT_PCM_16_BIT: case AUDIO_FORMAT_PCM_16_BIT:
return (AudioMixer::hook_t)\ return (AudioMixer::hook_t)track__Resample<
track__Resample<MIXTYPE_MULTI, int32_t, int16_t, int32_t>; MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
default: default:
LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
break; break;
@ -2003,11 +2032,11 @@ AudioMixer::hook_t AudioMixer::getTrackHook(int trackType, uint32_t channelCount
case TRACKTYPE_NORESAMPLEMONO: case TRACKTYPE_NORESAMPLEMONO:
switch (mixerInFormat) { switch (mixerInFormat) {
case AUDIO_FORMAT_PCM_FLOAT: case AUDIO_FORMAT_PCM_FLOAT:
return (AudioMixer::hook_t) return (AudioMixer::hook_t)track__NoResample<
track__NoResample<MIXTYPE_MONOEXPAND, float, float, int32_t>; MIXTYPE_MONOEXPAND, float /*TO*/, float /*TI*/, TYPE_AUX>;
case AUDIO_FORMAT_PCM_16_BIT: case AUDIO_FORMAT_PCM_16_BIT:
return (AudioMixer::hook_t) return (AudioMixer::hook_t)track__NoResample<
track__NoResample<MIXTYPE_MONOEXPAND, int32_t, int16_t, int32_t>; MIXTYPE_MONOEXPAND, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
default: default:
LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
break; break;
@ -2016,11 +2045,11 @@ AudioMixer::hook_t AudioMixer::getTrackHook(int trackType, uint32_t channelCount
case TRACKTYPE_NORESAMPLE: case TRACKTYPE_NORESAMPLE:
switch (mixerInFormat) { switch (mixerInFormat) {
case AUDIO_FORMAT_PCM_FLOAT: case AUDIO_FORMAT_PCM_FLOAT:
return (AudioMixer::hook_t) return (AudioMixer::hook_t)track__NoResample<
track__NoResample<MIXTYPE_MULTI, float, float, int32_t>; MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
case AUDIO_FORMAT_PCM_16_BIT: case AUDIO_FORMAT_PCM_16_BIT:
return (AudioMixer::hook_t) return (AudioMixer::hook_t)track__NoResample<
track__NoResample<MIXTYPE_MULTI, int32_t, int16_t, int32_t>; MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
default: default:
LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
break; break;
@ -2055,11 +2084,11 @@ AudioMixer::process_hook_t AudioMixer::getProcessHook(int processType, uint32_t
case AUDIO_FORMAT_PCM_FLOAT: case AUDIO_FORMAT_PCM_FLOAT:
switch (mixerOutFormat) { switch (mixerOutFormat) {
case AUDIO_FORMAT_PCM_FLOAT: case AUDIO_FORMAT_PCM_FLOAT:
return process_NoResampleOneTrack<MIXTYPE_MULTI_SAVEONLY, return process_NoResampleOneTrack<
float /*TO*/, float /*TI*/, int32_t /*TA*/>; MIXTYPE_MULTI_SAVEONLY, float /*TO*/, float /*TI*/, TYPE_AUX>;
case AUDIO_FORMAT_PCM_16_BIT: case AUDIO_FORMAT_PCM_16_BIT:
return process_NoResampleOneTrack<MIXTYPE_MULTI_SAVEONLY, return process_NoResampleOneTrack<
int16_t, float, int32_t>; MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, float /*TI*/, TYPE_AUX>;
default: default:
LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat); LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
break; break;
@ -2068,11 +2097,11 @@ AudioMixer::process_hook_t AudioMixer::getProcessHook(int processType, uint32_t
case AUDIO_FORMAT_PCM_16_BIT: case AUDIO_FORMAT_PCM_16_BIT:
switch (mixerOutFormat) { switch (mixerOutFormat) {
case AUDIO_FORMAT_PCM_FLOAT: case AUDIO_FORMAT_PCM_FLOAT:
return process_NoResampleOneTrack<MIXTYPE_MULTI_SAVEONLY, return process_NoResampleOneTrack<
float, int16_t, int32_t>; MIXTYPE_MULTI_SAVEONLY, float /*TO*/, int16_t /*TI*/, TYPE_AUX>;
case AUDIO_FORMAT_PCM_16_BIT: case AUDIO_FORMAT_PCM_16_BIT:
return process_NoResampleOneTrack<MIXTYPE_MULTI_SAVEONLY, return process_NoResampleOneTrack<
int16_t, int16_t, int32_t>; MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
default: default:
LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat); LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
break; break;

@ -188,13 +188,13 @@ inline void MixAccum(TO *auxaccum, TI value) {
template<> template<>
inline void MixAccum<float, int16_t>(float *auxaccum, int16_t value) { inline void MixAccum<float, int16_t>(float *auxaccum, int16_t value) {
static const float norm = 1. / (1 << 15); static constexpr float norm = 1. / (1 << 15);
*auxaccum += norm * value; *auxaccum += norm * value;
} }
template<> template<>
inline void MixAccum<float, int32_t>(float *auxaccum, int32_t value) { inline void MixAccum<float, int32_t>(float *auxaccum, int32_t value) {
static const float norm = 1. / (1 << 27); static constexpr float norm = 1. / (1 << 27);
*auxaccum += norm * value; *auxaccum += norm * value;
} }
@ -238,6 +238,7 @@ enum {
* NCHAN represents number of input and output channels. * NCHAN represents number of input and output channels.
* TO: int32_t (Q4.27) or float * TO: int32_t (Q4.27) or float
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
* TA: int32_t (Q4.27) or float
* TV: int32_t (U4.28) or int16_t (U4.12) or float * TV: int32_t (U4.28) or int16_t (U4.12) or float
* vol: represents a volume array. * vol: represents a volume array.
* *
@ -247,7 +248,8 @@ enum {
* Single input channel. NCHAN represents number of output channels. * Single input channel. NCHAN represents number of output channels.
* TO: int32_t (Q4.27) or float * TO: int32_t (Q4.27) or float
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
* TV: int32_t (U4.28) or int16_t (U4.12) or float * TA: int32_t (Q4.27) or float
* TV/TAV: int32_t (U4.28) or int16_t (U4.12) or float
* Input channel count is 1. * Input channel count is 1.
* vol: represents volume array. * vol: represents volume array.
* *
@ -257,7 +259,8 @@ enum {
* NCHAN represents number of input and output channels. * NCHAN represents number of input and output channels.
* TO: int16_t (Q.15) or float * TO: int16_t (Q.15) or float
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
* TV: int32_t (U4.28) or int16_t (U4.12) or float * TA: int32_t (Q4.27) or float
* TV/TAV: int32_t (U4.28) or int16_t (U4.12) or float
* vol: represents a volume array. * vol: represents a volume array.
* *
* MIXTYPE_MULTI_SAVEONLY does not accumulate into the out pointer. * MIXTYPE_MULTI_SAVEONLY does not accumulate into the out pointer.

@ -44,4 +44,9 @@
// define FLOAT_EFFECT_CHAIN to request float effects (falls back to int16_t if unavailable) // define FLOAT_EFFECT_CHAIN to request float effects (falls back to int16_t if unavailable)
#define FLOAT_EFFECT_CHAIN #define FLOAT_EFFECT_CHAIN
#ifdef FLOAT_EFFECT_CHAIN
// define FLOAT_AUX to process aux effect buffers in float (FLOAT_EFFECT_CHAIN must be defined)
#define FLOAT_AUX
#endif
#endif // ANDROID_AUDIOFLINGER_CONFIGURATION_H #endif // ANDROID_AUDIOFLINGER_CONFIGURATION_H

@ -338,9 +338,9 @@ void AudioFlinger::EffectModule::process()
if (isProcessImplemented()) { if (isProcessImplemented()) {
if (auxType) { if (auxType) {
// We overwrite the aux input buffer here and clear after processing. // We overwrite the aux input buffer here and clear after processing.
// Note that aux input buffers are format q4_27.
#ifdef FLOAT_EFFECT_CHAIN #ifdef FLOAT_EFFECT_CHAIN
if (mSupportsFloat) { if (mSupportsFloat) {
#ifndef FLOAT_AUX
// Do in-place float conversion for auxiliary effect input buffer. // Do in-place float conversion for auxiliary effect input buffer.
static_assert(sizeof(float) <= sizeof(int32_t), static_assert(sizeof(float) <= sizeof(int32_t),
"in-place conversion requires sizeof(float) <= sizeof(int32_t)"); "in-place conversion requires sizeof(float) <= sizeof(int32_t)");
@ -349,13 +349,21 @@ void AudioFlinger::EffectModule::process()
mConfig.inputCfg.buffer.f32, mConfig.inputCfg.buffer.f32,
mConfig.inputCfg.buffer.s32, mConfig.inputCfg.buffer.s32,
mConfig.inputCfg.buffer.frameCount); mConfig.inputCfg.buffer.frameCount);
#endif // !FLOAT_AUX
} else } else
#endif #endif // FLOAT_EFFECT_CHAIN
{ {
#ifdef FLOAT_AUX
memcpy_to_i16_from_float(
mConfig.inputCfg.buffer.s16,
mConfig.inputCfg.buffer.f32,
mConfig.inputCfg.buffer.frameCount);
#else
memcpy_to_i16_from_q4_27( memcpy_to_i16_from_q4_27(
mConfig.inputCfg.buffer.s16, mConfig.inputCfg.buffer.s16,
mConfig.inputCfg.buffer.s32, mConfig.inputCfg.buffer.s32,
mConfig.inputCfg.buffer.frameCount); mConfig.inputCfg.buffer.frameCount);
#endif
} }
} }
#ifdef FLOAT_EFFECT_CHAIN #ifdef FLOAT_EFFECT_CHAIN
@ -415,9 +423,13 @@ void AudioFlinger::EffectModule::process()
// clear auxiliary effect input buffer for next accumulation // clear auxiliary effect input buffer for next accumulation
if (auxType) { if (auxType) {
// input always q4_27 regardless of FLOAT_EFFECT_CHAIN. #ifdef FLOAT_AUX
const size_t size =
mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(float);
#else
const size_t size = const size_t size =
mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(int32_t); mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(int32_t);
#endif
memset(mConfig.inputCfg.buffer.raw, 0, size); memset(mConfig.inputCfg.buffer.raw, 0, size);
} }
} else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT && } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&

Loading…
Cancel
Save