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

Commit ea8fa7a5 authored by jiabin's avatar jiabin
Browse files

Refactor adjust channels buffer provider.

Combine adjust channels buffer provider and adjust channels non-destructive
buffer provider.
When contracting mono + haptic channels to mono, do not use
adjust_channels to avoid mixing haptic channel into audio channel.

Bug: 125915810
Test: play audio-haptic coupled files
Change-Id: I39916a3e0628a44ed4a148c265564af7135a2176
parent bb08e4d9
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -273,7 +273,7 @@ private:
            mPostDownmixReformatBufferProvider.reset(nullptr);
            mDownmixerBufferProvider.reset(nullptr);
            mReformatBufferProvider.reset(nullptr);
            mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr);
            mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
            mAdjustChannelsBufferProvider.reset(nullptr);
        }

@@ -347,8 +347,12 @@ private:
         * all pre-mixer track buffer conversions outside the AudioMixer class.
         *
         * 1) mInputBufferProvider: The AudioTrack buffer provider.
         * 2) mAdjustChannelsBufferProvider: Expend or contracts data
         * 3) mAdjustChannelsNonDestructiveBufferProvider: Non-destructively adjust sample data
         * 2) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved
         *    channel format to another. Expanded channels are filled with zeros and put at the end
         *    of each audio frame. Contracted channels are copied to the end of the buffer.
         * 3) mContractChannelsNonDestructiveBufferProvider: Non-destructively contract sample data.
         *    This is currently using at audio-haptic coupled playback to separate audio and haptic
         *    data. Contracted channels could be written to given buffer.
         * 4) mReformatBufferProvider: If not NULL, performs the audio reformat to
         *    match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer
         *    requires reformat. For example, it may convert floating point input to
@@ -360,9 +364,10 @@ private:
         * 7) mTimestretchBufferProvider: Adds timestretching for playback rate
         */
        AudioBufferProvider*     mInputBufferProvider;    // externally provided buffer provider.
        // TODO: combine AdjustChannelsBufferProvider and AdjustChannelsNonDestructiveBufferProvider
        // TODO: combine mAdjustChannelsBufferProvider and
        // mContractChannelsNonDestructiveBufferProvider
        std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
        std::unique_ptr<PassthruBufferProvider> mAdjustChannelsNonDestructiveBufferProvider;
        std::unique_ptr<PassthruBufferProvider> mContractChannelsNonDestructiveBufferProvider;
        std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider;
        std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider;
        std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider;
+13 −13
Original line number Diff line number Diff line
@@ -408,8 +408,8 @@ status_t AudioMixer::Track::prepareForAdjustChannels()
void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive()
{
    ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive");
    if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
        mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr);
    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
        mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
        reconfigureBufferProviders();
    }
}
@@ -426,13 +426,13 @@ status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames
                ? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame(
                        mMixerChannelCount, mMixerFormat)
                : NULL;
        mAdjustChannelsNonDestructiveBufferProvider.reset(
                new AdjustChannelsNonDestructiveBufferProvider(
        mContractChannelsNonDestructiveBufferProvider.reset(
                new AdjustChannelsBufferProvider(
                        mFormat,
                        mAdjustNonDestructiveInChannelCount,
                        mAdjustNonDestructiveOutChannelCount,
                        mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
                        frames,
                        mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
                        buffer));
        reconfigureBufferProviders();
    }
@@ -441,9 +441,9 @@ status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames

void AudioMixer::Track::clearContractedBuffer()
{
    if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
        static_cast<AdjustChannelsNonDestructiveBufferProvider*>(
                mAdjustChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
        static_cast<AdjustChannelsBufferProvider*>(
                mContractChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
    }
}

@@ -455,9 +455,9 @@ void AudioMixer::Track::reconfigureBufferProviders()
        mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider);
        bufferProvider = mAdjustChannelsBufferProvider.get();
    }
    if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
        mAdjustChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
        bufferProvider = mAdjustChannelsNonDestructiveBufferProvider.get();
    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
        mContractChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
        bufferProvider = mContractChannelsNonDestructiveBufferProvider.get();
    }
    if (mReformatBufferProvider.get() != nullptr) {
        mReformatBufferProvider->setBufferProvider(bufferProvider);
@@ -966,8 +966,8 @@ void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider
        track->mDownmixerBufferProvider->reset();
    } else if (track->mReformatBufferProvider.get() != nullptr) {
        track->mReformatBufferProvider->reset();
    } else if (track->mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
        track->mAdjustChannelsNonDestructiveBufferProvider->reset();
    } else if (track->mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
        track->mContractChannelsNonDestructiveBufferProvider->reset();
    } else if (track->mAdjustChannelsBufferProvider.get() != nullptr) {
        track->mAdjustChannelsBufferProvider->reset();
    }
+36 −47
Original line number Diff line number Diff line
@@ -627,69 +627,53 @@ void TimestretchBufferProvider::processFrames(void *dstBuffer, size_t *dstFrames
    }
}

AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(audio_format_t format,
        size_t inChannelCount, size_t outChannelCount, size_t frameCount) :
        CopyBufferProvider(
                audio_bytes_per_frame(inChannelCount, format),
                audio_bytes_per_frame(outChannelCount, format),
                frameCount),
        mFormat(format),
        mInChannelCount(inChannelCount),
        mOutChannelCount(outChannelCount),
        mSampleSizeInBytes(audio_bytes_per_sample(format))
{
    ALOGV("AdjustBufferProvider(%p)(%#x, %zu, %zu, %zu)",
            this, format, inChannelCount, outChannelCount, frameCount);
}

void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
{
    adjust_channels(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
            frames * mInChannelCount * mSampleSizeInBytes);
}

AdjustChannelsNonDestructiveBufferProvider::AdjustChannelsNonDestructiveBufferProvider(
AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(
        audio_format_t format, size_t inChannelCount, size_t outChannelCount,
        audio_format_t contractedFormat, size_t contractedFrameCount, void* contractedBuffer) :
        size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer) :
        CopyBufferProvider(
                audio_bytes_per_frame(inChannelCount, format),
                audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
                audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
                contractedFrameCount),
                frameCount),
        mFormat(format),
        mInChannelCount(inChannelCount),
        mOutChannelCount(outChannelCount),
        mSampleSizeInBytes(audio_bytes_per_sample(format)),
        mFrameCount(frameCount),
        mContractedChannelCount(inChannelCount - outChannelCount),
        mContractedFormat(contractedFormat),
        mContractedFrameCount(contractedFrameCount),
        mContractedBuffer(contractedBuffer),
        mContractedWrittenFrames(0)
{
    ALOGV("AdjustChannelsNonDestructiveBufferProvider(%p)(%#x, %zu, %zu, %#x, %p)",
            this, format, inChannelCount, outChannelCount, contractedFormat, contractedBuffer);
    ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p)", this, format,
            inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer);
    if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
        mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat);
    }
}

status_t AdjustChannelsNonDestructiveBufferProvider::getNextBuffer(
        AudioBufferProvider::Buffer* pBuffer)
status_t AdjustChannelsBufferProvider::getNextBuffer(AudioBufferProvider::Buffer* pBuffer)
{
    const size_t outFramesLeft = mContractedFrameCount - mContractedWrittenFrames;
    if (mContractedBuffer != nullptr) {
        // Restrict frame count only when it is needed to save contracted frames.
        const size_t outFramesLeft = mFrameCount - mContractedWrittenFrames;
        if (outFramesLeft < pBuffer->frameCount) {
            // Restrict the frame count so that we don't write over the size of the output buffer.
            pBuffer->frameCount = outFramesLeft;
        }
    }
    return CopyBufferProvider::getNextBuffer(pBuffer);
}

void AdjustChannelsNonDestructiveBufferProvider::copyFrames(
        void *dst, const void *src, size_t frames)
void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
{
    adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
            frames * mInChannelCount * mSampleSizeInBytes);
    if (mContractedFormat != AUDIO_FORMAT_INVALID && mContractedBuffer != NULL
            && mInChannelCount > mOutChannelCount) {
    if (mInChannelCount > mOutChannelCount) {
        // For case multi to mono, adjust_channels has special logic that will mix first two input
        // channels into a single output channel. In that case, use adjust_channels_non_destructive
        // to keep only one channel data even when contracting to mono.
        adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount,
                mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
        if (mContractedFormat != AUDIO_FORMAT_INVALID
            && mContractedBuffer != nullptr) {
            const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
            memcpy_by_audio_format(
                    (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
@@ -697,9 +681,14 @@ void AdjustChannelsNonDestructiveBufferProvider::copyFrames(
                    mContractedChannelCount * frames);
            mContractedWrittenFrames += frames;
        }
    } else {
        // Prefer expanding data from the end of each audio frame.
        adjust_channels(src, mInChannelCount, dst, mOutChannelCount,
                mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
    }
}

void AdjustChannelsNonDestructiveBufferProvider::reset()
void AdjustChannelsBufferProvider::reset()
{
    mContractedWrittenFrames = 0;
    CopyBufferProvider::reset();
+12 −24
Original line number Diff line number Diff line
@@ -218,33 +218,21 @@ private:
    bool                 mAudioPlaybackRateValid; // flag for current parameters validity
};

// AdjustBufferProvider derives from CopyBufferProvider to adjust sample data.
// AdjustChannelsBufferProvider derives from CopyBufferProvider to adjust sample data.
// Expands or contracts sample data from one interleaved channel format to another.
// Expanded channels are filled with zeros and put at the end of each audio frame.
// Contracted channels are omitted from the end of each audio frame.
// Extra expanded channels are filled with zeros and put at the end of each audio frame.
// Contracted channels are copied to the end of the output buffer(storage should be
// allocated appropriately).
// Contracted channels could be written to output buffer.
class AdjustChannelsBufferProvider : public CopyBufferProvider {
public:
    AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
            size_t outChannelCount, size_t frameCount);
    //Overrides
    void copyFrames(void *dst, const void *src, size_t frames) override;

protected:
    const audio_format_t mFormat;
    const size_t         mInChannelCount;
    const size_t         mOutChannelCount;
    const size_t         mSampleSizeInBytes;
};

// AdjustChannelsNonDestructiveBufferProvider derives from CopyBufferProvider to adjust sample data.
// Expands or contracts sample data from one interleaved channel format to another.
// Extra expanded channels are interleaved in from the end of the input buffer.
// Contracted channels are copied to the end of the output buffer.
// Contracted channels could be written to output buffer.
class AdjustChannelsNonDestructiveBufferProvider : public CopyBufferProvider {
public:
    AdjustChannelsNonDestructiveBufferProvider(audio_format_t format, size_t inChannelCount,
            size_t outChannelCount, audio_format_t contractedFormat, size_t contractedFrameCount,
            size_t outChannelCount, size_t frameCount) : AdjustChannelsBufferProvider(
                    format, inChannelCount, outChannelCount,
                    frameCount, AUDIO_FORMAT_INVALID, nullptr) { }
    // Contracted data is converted to contractedFormat and put into contractedBuffer.
    AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
            size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat,
            void* contractedBuffer);
    //Overrides
    status_t getNextBuffer(Buffer* pBuffer) override;
@@ -258,9 +246,9 @@ protected:
    const size_t         mInChannelCount;
    const size_t         mOutChannelCount;
    const size_t         mSampleSizeInBytes;
    const size_t         mFrameCount;
    const size_t         mContractedChannelCount;
    const audio_format_t mContractedFormat;
    const size_t         mContractedFrameCount;
    void                *mContractedBuffer;
    size_t               mContractedWrittenFrames;
    size_t               mContractedFrameSize;