From 77178548f3541541db14b9bca00944b031094b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Smoczy=C5=84ski?= Date: Thu, 25 Mar 2021 00:19:15 +0100 Subject: [PATCH] [EGD-5260] Mono to stereo software conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add workaround for Bluetooth audio to *always* convert mono PCM to stereo. Signed-off-by: Marcin SmoczyƄski --- .../Audio/Operation/PlaybackOperation.cpp | 7 +----- module-audio/Audio/decoder/Decoder.cpp | 7 +++++- module-audio/Audio/decoder/DecoderWorker.cpp | 23 +++++++++++++++---- module-audio/Audio/decoder/DecoderWorker.hpp | 9 +++++++- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/module-audio/Audio/Operation/PlaybackOperation.cpp b/module-audio/Audio/Operation/PlaybackOperation.cpp index 6f0a830703ee242592a3cf97f0867d4be98efb07..0eca39b3522b2bc4265775a344ddfbe0d87143e1 100644 --- a/module-audio/Audio/Operation/PlaybackOperation.cpp +++ b/module-audio/Audio/Operation/PlaybackOperation.cpp @@ -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(AudioDevice::Flags::OutputStereo)); - } - else { - newProfile->SetInOutFlags(static_cast(AudioDevice::Flags::OutputMono)); - } + newProfile->SetInOutFlags(static_cast(AudioDevice::Flags::OutputStereo)); // store profile currentProfile = newProfile; diff --git a/module-audio/Audio/decoder/Decoder.cpp b/module-audio/Audio/decoder/Decoder.cpp index cceaed5d3d4dfbb35b38410140b3ec1372b44873..5bae922b65a0166bc58f76961bbfa26f3b8f2481 100644 --- a/module-audio/Audio/decoder/Decoder.cpp +++ b/module-audio/Audio/decoder/Decoder.cpp @@ -126,7 +126,12 @@ namespace audio { assert(_stream != nullptr); if (!audioWorker) { - audioWorker = std::make_unique(_stream, this, endOfFileCallback); + audioWorker = + std::make_unique(_stream, + this, + endOfFileCallback, + tag->num_channel == 1 ? DecoderWorker::ChannelMode::ForceStereo + : DecoderWorker::ChannelMode::NoConversion); audioWorker->init(); audioWorker->run(); } diff --git a/module-audio/Audio/decoder/DecoderWorker.cpp b/module-audio/Audio/decoder/DecoderWorker.cpp index f8c275457c41f0965d25284939a52475966909ab..cf5c09d4db65bc6404b3d42797579f0d6d9c95db 100644 --- a/module-audio/Audio/decoder/DecoderWorker.cpp +++ b/module-audio/Audio/decoder/DecoderWorker.cpp @@ -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; } diff --git a/module-audio/Audio/decoder/DecoderWorker.hpp b/module-audio/Audio/decoder/DecoderWorker.hpp index 1b5a232f4092c3311315befd7cb53d1260124897..6008d0622e45d8803d344241f9bd2971c818a58d 100644 --- a/module-audio/Audio/decoder/DecoderWorker.hpp +++ b/module-audio/Audio/decoder/DecoderWorker.hpp @@ -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 queues = std::list()) -> bool override; @@ -52,5 +58,6 @@ namespace audio const int bufferSize; std::unique_ptr decoderBuffer; + ChannelMode channelMode = ChannelMode::NoConversion; }; } // namespace audio