Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8393bed8 authored by Robert Wu's avatar Robert Wu
Browse files

Add MMAP Audio Balance

Similar to adding Mono audio, this cl adds the audio balance settings
to MMAP Audio.

Bug:209521805
Test: Settings -> Accessibility -> Audio Adjustment -> Audio Balance
Use OboeTester and play outputs with various settings on the slider

Change-Id: I3269f6fe39b5f720da69739c49eb787e57f93b0a
parent d7400830
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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",
+55 −15
Original line number Diff line number Diff line
@@ -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>
@@ -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:
@@ -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.
@@ -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);
@@ -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);
@@ -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);
    }
}
+22 −2
Original line number Diff line number Diff line
@@ -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 {
@@ -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);

@@ -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;
};

+4 −1
Original line number Diff line number Diff line
@@ -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.
+2 −1
Original line number Diff line number Diff line
@@ -53,7 +53,8 @@ aaudio_result_t AudioStreamInternalPlay::open(const AudioStreamBuilder &builder)
                             getSamplesPerFrame(),
                             getDeviceFormat(),
                             getDeviceChannelCount(),
                             getRequireMonoBlend());
                             getRequireMonoBlend(),
                             getAudioBalance());

        if (result != AAUDIO_OK) {
            safeReleaseClose();
Loading