~aleteoryx/muditaos

77178548f3541541db14b9bca00944b031094b16 — Marcin Smoczyński 4 years ago b890bcd
[EGD-5260] Mono to stereo software conversion

Add workaround for Bluetooth audio to *always* convert mono PCM to
stereo.

Signed-off-by: Marcin Smoczyński <smoczynski.marcin@gmail.com>
M module-audio/Audio/Operation/PlaybackOperation.cpp => module-audio/Audio/Operation/PlaybackOperation.cpp +1 -6
@@ 169,12 169,7 @@ namespace audio

        // adjust new profile with information from file's tags
        newProfile->SetSampleRate(tags->sample_rate);
        if (tags->num_channel == channel::stereoSound) {
            newProfile->SetInOutFlags(static_cast<uint32_t>(AudioDevice::Flags::OutputStereo));
        }
        else {
            newProfile->SetInOutFlags(static_cast<uint32_t>(AudioDevice::Flags::OutputMono));
        }
        newProfile->SetInOutFlags(static_cast<uint32_t>(AudioDevice::Flags::OutputStereo));

        // store profile
        currentProfile = newProfile;

M module-audio/Audio/decoder/Decoder.cpp => module-audio/Audio/decoder/Decoder.cpp +6 -1
@@ 126,7 126,12 @@ namespace audio
    {
        assert(_stream != nullptr);
        if (!audioWorker) {
            audioWorker = std::make_unique<DecoderWorker>(_stream, this, endOfFileCallback);
            audioWorker =
                std::make_unique<DecoderWorker>(_stream,
                                                this,
                                                endOfFileCallback,
                                                tag->num_channel == 1 ? DecoderWorker::ChannelMode::ForceStereo
                                                                      : DecoderWorker::ChannelMode::NoConversion);
            audioWorker->init();
            audioWorker->run();
        }

M module-audio/Audio/decoder/DecoderWorker.cpp => module-audio/Audio/decoder/DecoderWorker.cpp +18 -5
@@ 4,10 4,13 @@
#include "DecoderWorker.hpp"
#include "Audio/decoder/Decoder.hpp"

audio::DecoderWorker::DecoderWorker(Stream *audioStreamOut, Decoder *decoder, EndOfFileCallback endOfFileCallback)
audio::DecoderWorker::DecoderWorker(Stream *audioStreamOut,
                                    Decoder *decoder,
                                    EndOfFileCallback endOfFileCallback,
                                    ChannelMode mode)
    : sys::Worker(DecoderWorker::workerName, DecoderWorker::workerPriority, stackDepth), audioStreamOut(audioStreamOut),
      decoder(decoder), endOfFileCallback(endOfFileCallback),
      bufferSize(audioStreamOut->getBlockSize() / sizeof(BufferInternalType))
      bufferSize(audioStreamOut->getBlockSize() / sizeof(BufferInternalType)), channelMode(mode)
{}

audio::DecoderWorker::~DecoderWorker()


@@ 84,17 87,27 @@ bool audio::DecoderWorker::handleMessage(uint32_t queueID)

void audio::DecoderWorker::pushAudioData()
{
    auto samplesRead = 0;
    auto samplesRead             = 0;
    const unsigned int readScale = channelMode == ChannelMode::ForceStereo ? 2 : 1;

    while (!audioStreamOut->isFull() && playbackEnabled) {
        samplesRead = decoder->decode(bufferSize, decoderBuffer.get());
        auto buffer = decoderBuffer.get();

        samplesRead = decoder->decode(bufferSize / readScale, buffer);

        if (samplesRead == 0) {
            endOfFileCallback();
            break;
        }

        if (!audioStreamOut->push(decoderBuffer.get(), samplesRead * sizeof(BufferInternalType))) {
        // pcm mono to stereo force conversion
        if (channelMode == ChannelMode::ForceStereo) {
            for (unsigned int i = bufferSize / 2; i > 0; i--) {
                buffer[i * 2 - 1] = buffer[i * 2 - 2] = buffer[i - 1];
            }
        }

        if (!audioStreamOut->push(decoderBuffer.get(), samplesRead * sizeof(BufferInternalType) * readScale)) {
            LOG_FATAL("Decoder failed to push to stream.");
            break;
        }

M module-audio/Audio/decoder/DecoderWorker.hpp => module-audio/Audio/decoder/DecoderWorker.hpp +8 -1
@@ 21,7 21,13 @@ namespace audio
            DisablePlayback,
        };

        DecoderWorker(Stream *audioStreamOut, Decoder *decoder, EndOfFileCallback endOfFileCallback);
        enum class ChannelMode
        {
            NoConversion,
            ForceStereo
        };

        DecoderWorker(Stream *audioStreamOut, Decoder *decoder, EndOfFileCallback endOfFileCallback, ChannelMode mode);
        ~DecoderWorker() override;

        virtual auto init(std::list<sys::WorkerQueueInfo> queues = std::list<sys::WorkerQueueInfo>()) -> bool override;


@@ 52,5 58,6 @@ namespace audio

        const int bufferSize;
        std::unique_ptr<BufferInternalType[]> decoderBuffer;
        ChannelMode channelMode = ChannelMode::NoConversion;
    };
} // namespace audio