diff --git a/media/libaudioclient/include/media/AudioMixer.h b/media/libaudioclient/include/media/AudioMixer.h index dcd4a5dd01..d4ce417fc9 100644 --- a/media/libaudioclient/include/media/AudioMixer.h +++ b/media/libaudioclient/include/media/AudioMixer.h @@ -33,6 +33,9 @@ // 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 +// This must match frameworks/av/services/audioflinger/Configuration.h +#define FLOAT_AUX + namespace android { // ---------------------------------------------------------------------------- diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp index 43b97a58b2..f8e05e7cbb 100644 --- a/media/libaudioprocessing/AudioMixer.cpp +++ b/media/libaudioprocessing/AudioMixer.cpp @@ -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 // 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. // If kUseNewMixer is false, this is ignored or may be overridden internally // 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. 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 (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) || - ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) { +#ifdef FLOAT_AUX + 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; prevAuxLevel = auxLevel << 16; - mAuxInc = 0.; + mAuxInc = 0.f; 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) * TO: int32_t (Q4.27) 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 @@ -1738,7 +1755,7 @@ static void volumeRampMulti(uint32_t channels, TO* out, size_t frameCount, /* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration) * TO: int32_t (Q4.27) 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 @@ -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) * TO: int32_t (Q4.27) 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 @@ -1788,13 +1805,25 @@ void AudioMixer::volumeMix(TO *out, size_t outFrames, if (USEFLOATVOL) { if (ramp) { volumeRampMulti(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) { t->adjustVolumeRamp(aux != NULL, true); } } else { volumeMulti(t->mMixerChannelCount, out, outFrames, in, aux, - t->mVolume, t->auxLevel); + t->mVolume, +#ifdef FLOAT_AUX + t->mAuxLevel +#else + t->auxLevel +#endif + ); } } else { if (ramp) { @@ -1851,7 +1880,7 @@ void AudioMixer::process_NoResampleOneTrack(state_t* state) } const size_t outFrames = b.frameCount; - volumeMix::value, false> ( + volumeMix::value /* USEFLOATVOL */, false /* ADJUSTVOL */> ( out, outFrames, in, aux, ramp, t); out += outFrames * channels; @@ -1874,7 +1903,7 @@ void AudioMixer::process_NoResampleOneTrack(state_t* state) * MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration) * TO: int32_t (Q4.27) 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 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)); t->resampler->resample((int32_t*)temp, outFrameCount, t->bufferProvider); - volumeMix::value, true>( + volumeMix::value /* USEFLOATVOL */, true /* ADJUSTVOL */>( out, outFrameCount, temp, aux, ramp, t); } 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) * TO: int32_t (Q4.27) 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 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"); const TI *in = static_cast(t->in); - volumeMix::value, true>( + volumeMix::value /* USEFLOATVOL */, true /* ADJUSTVOL */>( out, frameCount, in, aux, t->needsRamp(), t); // 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: switch (mixerInFormat) { case AUDIO_FORMAT_PCM_FLOAT: - return (AudioMixer::hook_t) - track__Resample; + return (AudioMixer::hook_t)track__Resample< + MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>; case AUDIO_FORMAT_PCM_16_BIT: - return (AudioMixer::hook_t)\ - track__Resample; + return (AudioMixer::hook_t)track__Resample< + MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>; default: LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); break; @@ -2003,11 +2032,11 @@ AudioMixer::hook_t AudioMixer::getTrackHook(int trackType, uint32_t channelCount case TRACKTYPE_NORESAMPLEMONO: switch (mixerInFormat) { case AUDIO_FORMAT_PCM_FLOAT: - return (AudioMixer::hook_t) - track__NoResample; + return (AudioMixer::hook_t)track__NoResample< + MIXTYPE_MONOEXPAND, float /*TO*/, float /*TI*/, TYPE_AUX>; case AUDIO_FORMAT_PCM_16_BIT: - return (AudioMixer::hook_t) - track__NoResample; + return (AudioMixer::hook_t)track__NoResample< + MIXTYPE_MONOEXPAND, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>; default: LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); break; @@ -2016,11 +2045,11 @@ AudioMixer::hook_t AudioMixer::getTrackHook(int trackType, uint32_t channelCount case TRACKTYPE_NORESAMPLE: switch (mixerInFormat) { case AUDIO_FORMAT_PCM_FLOAT: - return (AudioMixer::hook_t) - track__NoResample; + return (AudioMixer::hook_t)track__NoResample< + MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>; case AUDIO_FORMAT_PCM_16_BIT: - return (AudioMixer::hook_t) - track__NoResample; + return (AudioMixer::hook_t)track__NoResample< + MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>; default: LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); break; @@ -2055,11 +2084,11 @@ AudioMixer::process_hook_t AudioMixer::getProcessHook(int processType, uint32_t case AUDIO_FORMAT_PCM_FLOAT: switch (mixerOutFormat) { case AUDIO_FORMAT_PCM_FLOAT: - return process_NoResampleOneTrack; + return process_NoResampleOneTrack< + MIXTYPE_MULTI_SAVEONLY, float /*TO*/, float /*TI*/, TYPE_AUX>; case AUDIO_FORMAT_PCM_16_BIT: - return process_NoResampleOneTrack; + return process_NoResampleOneTrack< + MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, float /*TI*/, TYPE_AUX>; default: LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat); break; @@ -2068,11 +2097,11 @@ AudioMixer::process_hook_t AudioMixer::getProcessHook(int processType, uint32_t case AUDIO_FORMAT_PCM_16_BIT: switch (mixerOutFormat) { case AUDIO_FORMAT_PCM_FLOAT: - return process_NoResampleOneTrack; + return process_NoResampleOneTrack< + MIXTYPE_MULTI_SAVEONLY, float /*TO*/, int16_t /*TI*/, TYPE_AUX>; case AUDIO_FORMAT_PCM_16_BIT: - return process_NoResampleOneTrack; + return process_NoResampleOneTrack< + MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, int16_t /*TI*/, TYPE_AUX>; default: LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat); break; diff --git a/media/libaudioprocessing/AudioMixerOps.h b/media/libaudioprocessing/AudioMixerOps.h index 8d74024d50..f33e36169f 100644 --- a/media/libaudioprocessing/AudioMixerOps.h +++ b/media/libaudioprocessing/AudioMixerOps.h @@ -188,13 +188,13 @@ inline void MixAccum(TO *auxaccum, TI value) { template<> inline void MixAccum(float *auxaccum, int16_t value) { - static const float norm = 1. / (1 << 15); + static constexpr float norm = 1. / (1 << 15); *auxaccum += norm * value; } template<> inline void MixAccum(float *auxaccum, int32_t value) { - static const float norm = 1. / (1 << 27); + static constexpr float norm = 1. / (1 << 27); *auxaccum += norm * value; } @@ -238,6 +238,7 @@ enum { * NCHAN represents number of input and output channels. * TO: int32_t (Q4.27) 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 * vol: represents a volume array. * @@ -247,7 +248,8 @@ enum { * Single input channel. NCHAN represents number of output channels. * TO: int32_t (Q4.27) 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. * vol: represents volume array. * @@ -257,7 +259,8 @@ enum { * NCHAN represents number of input and output channels. * TO: int16_t (Q.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. * * MIXTYPE_MULTI_SAVEONLY does not accumulate into the out pointer. diff --git a/services/audioflinger/Configuration.h b/services/audioflinger/Configuration.h index bad46dc2ac..6e0f2b6e8a 100644 --- a/services/audioflinger/Configuration.h +++ b/services/audioflinger/Configuration.h @@ -44,4 +44,9 @@ // define FLOAT_EFFECT_CHAIN to request float effects (falls back to int16_t if unavailable) #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 diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index bfb0fe22fd..eb4f34c543 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -338,9 +338,9 @@ void AudioFlinger::EffectModule::process() if (isProcessImplemented()) { if (auxType) { // We overwrite the aux input buffer here and clear after processing. - // Note that aux input buffers are format q4_27. #ifdef FLOAT_EFFECT_CHAIN if (mSupportsFloat) { +#ifndef FLOAT_AUX // Do in-place float conversion for auxiliary effect input buffer. static_assert(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.s32, mConfig.inputCfg.buffer.frameCount); +#endif // !FLOAT_AUX } 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( mConfig.inputCfg.buffer.s16, mConfig.inputCfg.buffer.s32, mConfig.inputCfg.buffer.frameCount); +#endif } } #ifdef FLOAT_EFFECT_CHAIN @@ -415,9 +423,13 @@ void AudioFlinger::EffectModule::process() // clear auxiliary effect input buffer for next accumulation 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 = mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(int32_t); +#endif memset(mConfig.inputCfg.buffer.raw, 0, size); } } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&