Loading media/libaaudio/src/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -214,6 +214,7 @@ cc_library { "flowgraph/MonoBlend.cpp", "flowgraph/MonoToMultiConverter.cpp", "flowgraph/MultiToMonoConverter.cpp", "flowgraph/MultiToManyConverter.cpp", "flowgraph/RampLinear.cpp", "flowgraph/SampleRateConverter.cpp", "flowgraph/SinkFloat.cpp", Loading media/libaaudio/src/client/AAudioFlowGraph.cpp +55 −15 Original line number Diff line number Diff line Loading @@ -21,8 +21,10 @@ #include "AAudioFlowGraph.h" #include <flowgraph/ClipToRange.h> #include <flowgraph/ManyToMultiConverter.h> #include <flowgraph/MonoBlend.h> #include <flowgraph/MonoToMultiConverter.h> #include <flowgraph/MultiToManyConverter.h> #include <flowgraph/RampLinear.h> #include <flowgraph/SinkFloat.h> #include <flowgraph/SinkI16.h> Loading @@ -39,12 +41,15 @@ aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat, int32_t sourceChannelCount, audio_format_t sinkFormat, int32_t sinkChannelCount, bool useMonoBlend) { bool useMonoBlend, float audioBalance) { FlowGraphPortFloatOutput *lastOutput = nullptr; // TODO change back to ALOGD ALOGI("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d", __func__, sourceFormat, sourceChannelCount, sinkFormat, sinkChannelCount); ALOGI("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d, " "useMonoBlend = %d, audioBalance = %f", __func__, sourceFormat, sourceChannelCount, sinkFormat, sinkChannelCount, useMonoBlend, audioBalance); switch (sourceFormat) { case AUDIO_FORMAT_PCM_FLOAT: Loading @@ -65,10 +70,11 @@ aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat, } lastOutput = &mSource->output; // Apply volume as a ramp to avoid pops. mVolumeRamp = std::make_unique<RampLinear>(sourceChannelCount); lastOutput->connect(&mVolumeRamp->input); lastOutput = &mVolumeRamp->output; if (useMonoBlend) { mMonoBlend = std::make_unique<MonoBlend>(sourceChannelCount); lastOutput->connect(&mMonoBlend->input); lastOutput = &mMonoBlend->output; } // For a pure float graph, there is chance that the data range may be very large. // So we should clip to a reasonable value that allows a little headroom. Loading @@ -78,12 +84,6 @@ aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat, lastOutput = &mClipper->output; } if (useMonoBlend) { mMonoBlend = std::make_unique<MonoBlend>(sourceChannelCount); lastOutput->connect(&mMonoBlend->input); lastOutput = &mMonoBlend->output; } // Expand the number of channels if required. if (sourceChannelCount == 1 && sinkChannelCount > 1) { mChannelConverter = std::make_unique<MonoToMultiConverter>(sinkChannelCount); Loading @@ -94,6 +94,23 @@ aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat, return AAUDIO_ERROR_UNIMPLEMENTED; } // Apply volume ramps to set the left/right audio balance and target volumes. // The signals will be decoupled, volume ramps will be applied, before the signals are // combined again. mMultiToManyConverter = std::make_unique<MultiToManyConverter>(sinkChannelCount); mManyToMultiConverter = std::make_unique<ManyToMultiConverter>(sinkChannelCount); lastOutput->connect(&mMultiToManyConverter->input); for (int i = 0; i < sinkChannelCount; i++) { mVolumeRamps.emplace_back(std::make_unique<RampLinear>(1)); mPanningVolumes.emplace_back(1.0f); lastOutput = mMultiToManyConverter->outputs[i].get(); lastOutput->connect(&(mVolumeRamps[i].get()->input)); lastOutput = &(mVolumeRamps[i].get()->output); lastOutput->connect(mManyToMultiConverter->inputs[i].get()); } lastOutput = &mManyToMultiConverter->output; setAudioBalance(audioBalance); switch (sinkFormat) { case AUDIO_FORMAT_PCM_FLOAT: mSink = std::make_unique<SinkFloat>(sinkChannelCount); Loading Loading @@ -125,9 +142,32 @@ void AAudioFlowGraph::process(const void *source, void *destination, int32_t num * @param volume between 0.0 and 1.0 */ void AAudioFlowGraph::setTargetVolume(float volume) { mVolumeRamp->setTarget(volume); for (int i = 0; i < mVolumeRamps.size(); i++) { mVolumeRamps[i]->setTarget(volume * mPanningVolumes[i]); } mTargetVolume = volume; } /** * @param audioBalance between -1.0 and 1.0 */ void AAudioFlowGraph::setAudioBalance(float audioBalance) { if (mPanningVolumes.size() >= 2) { float leftMultiplier = 0; float rightMultiplier = 0; mBalance.computeStereoBalance(audioBalance, &leftMultiplier, &rightMultiplier); mPanningVolumes[0] = leftMultiplier; mPanningVolumes[1] = rightMultiplier; mVolumeRamps[0]->setTarget(mTargetVolume * leftMultiplier); mVolumeRamps[1]->setTarget(mTargetVolume * rightMultiplier); } } /** * @param numFrames to slowly adjust for volume changes */ void AAudioFlowGraph::setRampLengthInFrames(int32_t numFrames) { mVolumeRamp->setLengthInFrames(numFrames); for (auto& ramp : mVolumeRamps) { ramp->setLengthInFrames(numFrames); } } media/libaaudio/src/client/AAudioFlowGraph.h +22 −2 Original line number Diff line number Diff line Loading @@ -23,9 +23,12 @@ #include <system/audio.h> #include <aaudio/AAudio.h> #include <audio_utils/Balance.h> #include <flowgraph/ClipToRange.h> #include <flowgraph/ManyToMultiConverter.h> #include <flowgraph/MonoBlend.h> #include <flowgraph/MonoToMultiConverter.h> #include <flowgraph/MultiToManyConverter.h> #include <flowgraph/RampLinear.h> class AAudioFlowGraph { Loading @@ -37,13 +40,17 @@ public: * @param sourceChannelCount * @param sinkFormat * @param sinkChannelCount * @param useMonoBlend * @param audioBalance * @param channelMask * @return */ aaudio_result_t configure(audio_format_t sourceFormat, int32_t sourceChannelCount, audio_format_t sinkFormat, int32_t sinkChannelCount, bool useMonoBlend); bool useMonoBlend, float audioBalance); void process(const void *source, void *destination, int32_t numFrames); Loading @@ -52,14 +59,27 @@ public: */ void setTargetVolume(float volume); /** * @param audioBalance between -1.0 and 1.0 */ void setAudioBalance(float audioBalance); /** * @param numFrames to slowly adjust for volume changes */ void setRampLengthInFrames(int32_t numFrames); private: std::unique_ptr<flowgraph::FlowGraphSourceBuffered> mSource; std::unique_ptr<flowgraph::MonoBlend> mMonoBlend; std::unique_ptr<flowgraph::RampLinear> mVolumeRamp; std::unique_ptr<flowgraph::ClipToRange> mClipper; std::unique_ptr<flowgraph::MonoToMultiConverter> mChannelConverter; std::unique_ptr<flowgraph::ManyToMultiConverter> mManyToMultiConverter; std::unique_ptr<flowgraph::MultiToManyConverter> mMultiToManyConverter; std::vector<std::unique_ptr<flowgraph::RampLinear>> mVolumeRamps; std::vector<float> mPanningVolumes; float mTargetVolume = 1.0f; android::audio_utils::Balance mBalance; std::unique_ptr<flowgraph::FlowGraphSink> mSink; }; Loading media/libaaudio/src/client/AudioStreamInternal.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -272,12 +272,15 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { } // Exclusive output streams should combine channels when mono audio adjustment // is enabled. // is enabled. They should also adjust for audio balance. if ((getDirection() == AAUDIO_DIRECTION_OUTPUT) && (getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE)) { bool isMasterMono = false; android::AudioSystem::getMasterMono(&isMasterMono); setRequireMonoBlend(isMasterMono); float audioBalance = 0; android::AudioSystem::getMasterBalance(&audioBalance); setAudioBalance(audioBalance); } // For debugging and analyzing the distribution of MMAP timestamps. Loading media/libaaudio/src/client/AudioStreamInternalPlay.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,8 @@ aaudio_result_t AudioStreamInternalPlay::open(const AudioStreamBuilder &builder) getSamplesPerFrame(), getDeviceFormat(), getDeviceChannelCount(), getRequireMonoBlend()); getRequireMonoBlend(), getAudioBalance()); if (result != AAUDIO_OK) { safeReleaseClose(); Loading Loading
media/libaaudio/src/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -214,6 +214,7 @@ cc_library { "flowgraph/MonoBlend.cpp", "flowgraph/MonoToMultiConverter.cpp", "flowgraph/MultiToMonoConverter.cpp", "flowgraph/MultiToManyConverter.cpp", "flowgraph/RampLinear.cpp", "flowgraph/SampleRateConverter.cpp", "flowgraph/SinkFloat.cpp", Loading
media/libaaudio/src/client/AAudioFlowGraph.cpp +55 −15 Original line number Diff line number Diff line Loading @@ -21,8 +21,10 @@ #include "AAudioFlowGraph.h" #include <flowgraph/ClipToRange.h> #include <flowgraph/ManyToMultiConverter.h> #include <flowgraph/MonoBlend.h> #include <flowgraph/MonoToMultiConverter.h> #include <flowgraph/MultiToManyConverter.h> #include <flowgraph/RampLinear.h> #include <flowgraph/SinkFloat.h> #include <flowgraph/SinkI16.h> Loading @@ -39,12 +41,15 @@ aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat, int32_t sourceChannelCount, audio_format_t sinkFormat, int32_t sinkChannelCount, bool useMonoBlend) { bool useMonoBlend, float audioBalance) { FlowGraphPortFloatOutput *lastOutput = nullptr; // TODO change back to ALOGD ALOGI("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d", __func__, sourceFormat, sourceChannelCount, sinkFormat, sinkChannelCount); ALOGI("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d, " "useMonoBlend = %d, audioBalance = %f", __func__, sourceFormat, sourceChannelCount, sinkFormat, sinkChannelCount, useMonoBlend, audioBalance); switch (sourceFormat) { case AUDIO_FORMAT_PCM_FLOAT: Loading @@ -65,10 +70,11 @@ aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat, } lastOutput = &mSource->output; // Apply volume as a ramp to avoid pops. mVolumeRamp = std::make_unique<RampLinear>(sourceChannelCount); lastOutput->connect(&mVolumeRamp->input); lastOutput = &mVolumeRamp->output; if (useMonoBlend) { mMonoBlend = std::make_unique<MonoBlend>(sourceChannelCount); lastOutput->connect(&mMonoBlend->input); lastOutput = &mMonoBlend->output; } // For a pure float graph, there is chance that the data range may be very large. // So we should clip to a reasonable value that allows a little headroom. Loading @@ -78,12 +84,6 @@ aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat, lastOutput = &mClipper->output; } if (useMonoBlend) { mMonoBlend = std::make_unique<MonoBlend>(sourceChannelCount); lastOutput->connect(&mMonoBlend->input); lastOutput = &mMonoBlend->output; } // Expand the number of channels if required. if (sourceChannelCount == 1 && sinkChannelCount > 1) { mChannelConverter = std::make_unique<MonoToMultiConverter>(sinkChannelCount); Loading @@ -94,6 +94,23 @@ aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat, return AAUDIO_ERROR_UNIMPLEMENTED; } // Apply volume ramps to set the left/right audio balance and target volumes. // The signals will be decoupled, volume ramps will be applied, before the signals are // combined again. mMultiToManyConverter = std::make_unique<MultiToManyConverter>(sinkChannelCount); mManyToMultiConverter = std::make_unique<ManyToMultiConverter>(sinkChannelCount); lastOutput->connect(&mMultiToManyConverter->input); for (int i = 0; i < sinkChannelCount; i++) { mVolumeRamps.emplace_back(std::make_unique<RampLinear>(1)); mPanningVolumes.emplace_back(1.0f); lastOutput = mMultiToManyConverter->outputs[i].get(); lastOutput->connect(&(mVolumeRamps[i].get()->input)); lastOutput = &(mVolumeRamps[i].get()->output); lastOutput->connect(mManyToMultiConverter->inputs[i].get()); } lastOutput = &mManyToMultiConverter->output; setAudioBalance(audioBalance); switch (sinkFormat) { case AUDIO_FORMAT_PCM_FLOAT: mSink = std::make_unique<SinkFloat>(sinkChannelCount); Loading Loading @@ -125,9 +142,32 @@ void AAudioFlowGraph::process(const void *source, void *destination, int32_t num * @param volume between 0.0 and 1.0 */ void AAudioFlowGraph::setTargetVolume(float volume) { mVolumeRamp->setTarget(volume); for (int i = 0; i < mVolumeRamps.size(); i++) { mVolumeRamps[i]->setTarget(volume * mPanningVolumes[i]); } mTargetVolume = volume; } /** * @param audioBalance between -1.0 and 1.0 */ void AAudioFlowGraph::setAudioBalance(float audioBalance) { if (mPanningVolumes.size() >= 2) { float leftMultiplier = 0; float rightMultiplier = 0; mBalance.computeStereoBalance(audioBalance, &leftMultiplier, &rightMultiplier); mPanningVolumes[0] = leftMultiplier; mPanningVolumes[1] = rightMultiplier; mVolumeRamps[0]->setTarget(mTargetVolume * leftMultiplier); mVolumeRamps[1]->setTarget(mTargetVolume * rightMultiplier); } } /** * @param numFrames to slowly adjust for volume changes */ void AAudioFlowGraph::setRampLengthInFrames(int32_t numFrames) { mVolumeRamp->setLengthInFrames(numFrames); for (auto& ramp : mVolumeRamps) { ramp->setLengthInFrames(numFrames); } }
media/libaaudio/src/client/AAudioFlowGraph.h +22 −2 Original line number Diff line number Diff line Loading @@ -23,9 +23,12 @@ #include <system/audio.h> #include <aaudio/AAudio.h> #include <audio_utils/Balance.h> #include <flowgraph/ClipToRange.h> #include <flowgraph/ManyToMultiConverter.h> #include <flowgraph/MonoBlend.h> #include <flowgraph/MonoToMultiConverter.h> #include <flowgraph/MultiToManyConverter.h> #include <flowgraph/RampLinear.h> class AAudioFlowGraph { Loading @@ -37,13 +40,17 @@ public: * @param sourceChannelCount * @param sinkFormat * @param sinkChannelCount * @param useMonoBlend * @param audioBalance * @param channelMask * @return */ aaudio_result_t configure(audio_format_t sourceFormat, int32_t sourceChannelCount, audio_format_t sinkFormat, int32_t sinkChannelCount, bool useMonoBlend); bool useMonoBlend, float audioBalance); void process(const void *source, void *destination, int32_t numFrames); Loading @@ -52,14 +59,27 @@ public: */ void setTargetVolume(float volume); /** * @param audioBalance between -1.0 and 1.0 */ void setAudioBalance(float audioBalance); /** * @param numFrames to slowly adjust for volume changes */ void setRampLengthInFrames(int32_t numFrames); private: std::unique_ptr<flowgraph::FlowGraphSourceBuffered> mSource; std::unique_ptr<flowgraph::MonoBlend> mMonoBlend; std::unique_ptr<flowgraph::RampLinear> mVolumeRamp; std::unique_ptr<flowgraph::ClipToRange> mClipper; std::unique_ptr<flowgraph::MonoToMultiConverter> mChannelConverter; std::unique_ptr<flowgraph::ManyToMultiConverter> mManyToMultiConverter; std::unique_ptr<flowgraph::MultiToManyConverter> mMultiToManyConverter; std::vector<std::unique_ptr<flowgraph::RampLinear>> mVolumeRamps; std::vector<float> mPanningVolumes; float mTargetVolume = 1.0f; android::audio_utils::Balance mBalance; std::unique_ptr<flowgraph::FlowGraphSink> mSink; }; Loading
media/libaaudio/src/client/AudioStreamInternal.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -272,12 +272,15 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { } // Exclusive output streams should combine channels when mono audio adjustment // is enabled. // is enabled. They should also adjust for audio balance. if ((getDirection() == AAUDIO_DIRECTION_OUTPUT) && (getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE)) { bool isMasterMono = false; android::AudioSystem::getMasterMono(&isMasterMono); setRequireMonoBlend(isMasterMono); float audioBalance = 0; android::AudioSystem::getMasterBalance(&audioBalance); setAudioBalance(audioBalance); } // For debugging and analyzing the distribution of MMAP timestamps. Loading
media/libaaudio/src/client/AudioStreamInternalPlay.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,8 @@ aaudio_result_t AudioStreamInternalPlay::open(const AudioStreamBuilder &builder) getSamplesPerFrame(), getDeviceFormat(), getDeviceChannelCount(), getRequireMonoBlend()); getRequireMonoBlend(), getAudioBalance()); if (result != AAUDIO_OK) { safeReleaseClose(); Loading