From 6f257d38dbd42ac6aa54258e640571b6cbe003ad Mon Sep 17 00:00:00 2001 From: Marcin Lyda Date: Mon, 21 Mar 2022 11:28:04 +0100 Subject: [PATCH] [MOS-303] Add playback path gain params to json Additional pair of parameters has been added to current implementation of equalizer to enable changing playback path gain during audio path fine-tuning --- .../data/equalizer/earspeaker_routing.json | 2 + .../data/equalizer/loudspeaker_playback.json | 2 + .../data/equalizer/loudspeaker_routing.json | 2 + .../Audio/Profiles/ProfileConfigUtils.cpp | 49 ++++++++++++++----- .../Profiles/ProfilePlaybackLoudspeaker.hpp | 16 +++--- .../Profiles/ProfileRoutingEarspeaker.hpp | 11 +++-- .../Profiles/ProfileRoutingLoudspeaker.hpp | 2 + module-audio/Audio/Profiles/README.md | 39 ++++++++------- module-audio/Audio/codec.hpp | 16 +++--- .../Audio/test/testfiles/testProfile.json | 2 + .../test/testfiles/testProfileFallback.json | 48 ++++++++++++++++++ .../Audio/test/unittest_config_utils.cpp | 10 ++++ .../board/rt1051/puretx/PureTxAudioCodec.cpp | 2 + .../board/rt1051/bsp/audio/CodecMAX98090.cpp | 14 ++---- .../board/rt1051/bsp/audio/CodecMAX98090.hpp | 10 ++-- 15 files changed, 164 insertions(+), 61 deletions(-) create mode 100644 module-audio/Audio/test/testfiles/testProfileFallback.json diff --git a/image/user/data/equalizer/earspeaker_routing.json b/image/user/data/equalizer/earspeaker_routing.json index 9acd11053adfd2ff2363bb2696e98caa5ff5244c..28d7a5790d976db66c38f5b9397d3f912516a25d 100644 --- a/image/user/data/equalizer/earspeaker_routing.json +++ b/image/user/data/equalizer/earspeaker_routing.json @@ -6,6 +6,8 @@ "inputGain": 0, "inputPath": 1, "outputPath": 1, + "playbackPathGain": 2, + "playbackPathAtten": 2, "filterParams": [ { "filterType": "HighPass", diff --git a/image/user/data/equalizer/loudspeaker_playback.json b/image/user/data/equalizer/loudspeaker_playback.json index 6a1d84cb4aea84a1c372939cc6b2a8b93b4978d8..aedc9765d65b847b5af04d73a734ab55b0f8532b 100644 --- a/image/user/data/equalizer/loudspeaker_playback.json +++ b/image/user/data/equalizer/loudspeaker_playback.json @@ -6,6 +6,8 @@ "inputGain": 0, "inputPath": 2, "outputPath": 2, + "playbackPathGain": 0, + "playbackPathAtten": 2, "filterParams": [ { "filterType": "HighPass", diff --git a/image/user/data/equalizer/loudspeaker_routing.json b/image/user/data/equalizer/loudspeaker_routing.json index c7c1eb845b3b7de401bbf711777c72aae3bfdb2e..77dba0ee1a8f40b58ee3adc6f54164bd15639641 100644 --- a/image/user/data/equalizer/loudspeaker_routing.json +++ b/image/user/data/equalizer/loudspeaker_routing.json @@ -6,6 +6,8 @@ "inputGain": 0, "inputPath": 1, "outputPath": 2, + "playbackPathGain": 0, + "playbackPathAtten": 5, "filterParams": [ { "filterType": "HighPass", diff --git a/module-audio/Audio/Profiles/ProfileConfigUtils.cpp b/module-audio/Audio/Profiles/ProfileConfigUtils.cpp index c9f3fb70db8f3df7eea00e78aa979768e08be51d..269f2e1e5c25d82eb6889e8fdb7e2e28939913dc 100644 --- a/module-audio/Audio/Profiles/ProfileConfigUtils.cpp +++ b/module-audio/Audio/Profiles/ProfileConfigUtils.cpp @@ -10,18 +10,20 @@ namespace audio { namespace strings { - constexpr inline auto samplerate = "samplerate"; - constexpr inline auto bitWidth = "bitWidth"; - constexpr inline auto flags = "flags"; - constexpr inline auto outputVolume = "outputVolume"; - constexpr inline auto outputPath = "outputPath"; - constexpr inline auto inputGain = "inputGain"; - constexpr inline auto inputPath = "inputPath"; - constexpr inline auto filterParams = "filterParams"; - constexpr inline auto filterType = "filterType"; - constexpr inline auto frequency = "frequency"; - constexpr inline auto Q = "Q"; - constexpr inline auto gain = "gain"; + constexpr inline auto samplerate = "samplerate"; + constexpr inline auto bitWidth = "bitWidth"; + constexpr inline auto flags = "flags"; + constexpr inline auto outputVolume = "outputVolume"; + constexpr inline auto outputPath = "outputPath"; + constexpr inline auto inputGain = "inputGain"; + constexpr inline auto inputPath = "inputPath"; + constexpr inline auto filterParams = "filterParams"; + constexpr inline auto filterType = "filterType"; + constexpr inline auto frequency = "frequency"; + constexpr inline auto Q = "Q"; + constexpr inline auto gain = "gain"; + constexpr inline auto playbackPathGain = "playbackPathGain"; + constexpr inline auto playbackPathAtten = "playbackPathAtten"; } // namespace strings namespace utils @@ -87,6 +89,29 @@ namespace audio config.inputPath = utils::toEnum(configJson[strings::inputPath].int_value()); config.outputPath = utils::toEnum(configJson[strings::outputPath].int_value()); + std::uint8_t playbackPathGain = configJson[strings::playbackPathGain].int_value(); + std::uint8_t playbackPathAtten = configJson[strings::playbackPathAtten].int_value(); + + constexpr std::uint8_t playbackPathGainMax = 3; + if (playbackPathGain <= playbackPathGainMax) { + config.playbackPathGain = playbackPathGain; + } + else { + LOG_WARN("playbackPathGain value out of range (%u), using fallback value %u!", + playbackPathGain, + config.playbackPathGain); + } + + constexpr std::uint8_t playbackPathAttenMax = 15; + if (playbackPathAtten <= playbackPathAttenMax) { + config.playbackPathAtten = playbackPathAtten; + } + else { + LOG_WARN("playbackPathAtten value out of range (%u), using fallback value %u!", + playbackPathAtten, + config.playbackPathAtten); + } + json11::Json::array paramsArray; audio::equalizer::Equalizer filterParams; paramsArray = configJson[strings::filterParams].array_items(); diff --git a/module-audio/Audio/Profiles/ProfilePlaybackLoudspeaker.hpp b/module-audio/Audio/Profiles/ProfilePlaybackLoudspeaker.hpp index 99309fb057c591cb23c90e90ce640cb8bfbd99d3..4312406c853cde3821f70533c7cef6a75273d60f 100644 --- a/module-audio/Audio/Profiles/ProfilePlaybackLoudspeaker.hpp +++ b/module-audio/Audio/Profiles/ProfilePlaybackLoudspeaker.hpp @@ -17,13 +17,15 @@ namespace audio Type::PlaybackLoudspeaker, purefs::dir::getUserDiskPath() / "data/equalizer/loudspeaker_playback.json", audio::codec::Configuration{ - .sampleRate_Hz = 0, - .bitWidth = 16, - .flags = 0, - .outputVolume = 0, - .inputGain = 0, - .inputPath = audio::codec::InputPath::None, - .outputPath = audio::codec::OutputPath::Loudspeaker, + .sampleRate_Hz = 0, + .bitWidth = 16, + .flags = 0, + .outputVolume = 0, + .inputGain = 0, + .playbackPathGain = 0, + .playbackPathAtten = 2, + .inputPath = audio::codec::InputPath::None, + .outputPath = audio::codec::OutputPath::Loudspeaker, .filterCoefficients = {qfilter_CalculateCoeffs(audio::equalizer::FilterType::HighPass, 501.8f, 44100, 0.701f, 0), qfilter_CalculateCoeffs(audio::equalizer::FilterType::LowPass, 14999.5f, 44100, 0.701f, 0), diff --git a/module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp b/module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp index 8814c3ef3a8a59a40adbaa5c015930dc4c5286bb..f41734c05224b42cfb75c29847a1ccb251d7dd90 100644 --- a/module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp +++ b/module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp @@ -21,10 +21,13 @@ namespace audio .flags = static_cast(audio::codec::Flags::InputLeft) | // microphone use left audio channel static_cast(audio::codec::Flags::OutputMono), - .outputVolume = 0, - .inputGain = 0, - .inputPath = audio::codec::InputPath::Microphone, - .outputPath = audio::codec::OutputPath::Earspeaker, + .outputVolume = 0, + .inputGain = 0, + .playbackPathGain = 0, + .playbackPathAtten = 5, + .inputPath = audio::codec::InputPath::Microphone, + .outputPath = audio::codec::OutputPath::Earspeaker, + .filterCoefficients = {qfilter_CalculateCoeffs(audio::equalizer::FilterType::HighPass, 700.f, 44100, 0.701f, 10), qfilter_CalculateCoeffs(audio::equalizer::FilterType::LowPass, 4993.7f, 44100, 0.701f, -5), diff --git a/module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp b/module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp index ff98c636dec0d13c7c388725d59634661476b91a..ef8ec50af7670caddfd8b3a395a14193e2f4dbac 100644 --- a/module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp +++ b/module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp @@ -25,6 +25,8 @@ namespace audio static_cast(audio::codec::Flags::OutputMono), .outputVolume = 0, .inputGain = 0, + .playbackPathGain = 0, + .playbackPathAtten = 5, .inputPath = audio::codec::InputPath::Microphone, .outputPath = audio::codec::OutputPath::Loudspeaker, .filterCoefficients = {qfilter_CalculateCoeffs( diff --git a/module-audio/Audio/Profiles/README.md b/module-audio/Audio/Profiles/README.md index 17e44065be440426d9eedc58d2032bf245fd76f0..e2030afae48d657797280a8cbfa2d6222ad2648f 100644 --- a/module-audio/Audio/Profiles/README.md +++ b/module-audio/Audio/Profiles/README.md @@ -11,16 +11,21 @@ In order to prevent audio issues, when no file is present or the JSON structure ##File structure -| Field | Value type | Description | -|--------------|------------|-------------------------------------------------------------| -| samplerate | integer | Defines the sample rate of the profile | -| bitWidth | integer | Defines the bit width of the audio stream | -| flags | integer | Defines the input/output channels (see codec.hpp) | -| outputVolume | float | Defines the output volume for the particular profile | -| inputGain | float | Defines the input gain for the particular profile | -| inputPath | integer | Defines the audio path for profile's input (see codec.hpp) | -| outputPath | integer | Defines the audio path for profile's output (see codec.hpp) | -| filterParams | array | Array of filter parameters (one per band) | +| Field | Value type | Description | Valid range | +|-------------------|------------|-------------------------------------------------------------|-----------------------| +| samplerate | integer | Defines the sample rate of the profile | 8000 - 96000 Hz | +| bitWidth | integer | Defines the bit width of the audio stream | 8 b - 32 b | +| flags | integer | Defines the input/output channels (see codec.hpp) | 0 - 4 | +| outputVolume | float | Defines the output volume for the particular profile | 0 - 10 | +| inputGain | float | Defines the input gain for the particular profile | 0 - 10 | +| playbackPathGain | integer | Defines the gain of MAX98090 playback path | 0 - 3 (0 dB - 18 dB) | +| playbackPathAtten | integer | Defines the attenuation of MAX98090 playback path | 0 - 15 (0 dB - 15 dB) | +| inputPath | integer | Defines the audio path for profile's input (see codec.hpp) | 0 - 2 | +| outputPath | integer | Defines the audio path for profile's output (see codec.hpp) | 0 - 3 | +| filterParams | array | Array of filter parameters (one per band) | See table below | + +Parameter _playbackPathGain_ is adjusted in 6dB increments; _playbackPathAtten_ is adjusted in 1dB increments, as described +in Table 49 (p. 120) in MAX98090 datasheet. ### Filter parameters array @@ -30,13 +35,13 @@ appropriate filter type - `None`. ### Array element structure -| Field | Value type | Description | -|------------|------------|------------------------------------------------------------| -| filterType | string | Defines the type of the filter | -| frequency | float | Defines the cutoff frequency for the filter | -| samplerate | integer | Defines the samplerate used to calculate the filter coeffs | -| Q | float | Defines Q-factor for the filter | -| gain | float | Defines gain for shelf-like filters | +| Field | Value type | Description | Valid range | +|------------|------------|------------------------------------------------------------|----------------| +| filterType | string | Defines the type of the filter | See list below | +| frequency | float | Defines the cutoff frequency for the filter | \> 0 Hz | +| samplerate | integer | Defines the samplerate used to calculate the filter coeffs | \> 0 Hz | +| Q | float | Defines Q factor for the filter | 0.1 - 10 | +| gain | float | Defines gain for shelf-like filters | \> 0 | Filter type can be selected from following types: diff --git a/module-audio/Audio/codec.hpp b/module-audio/Audio/codec.hpp index 21c7b82c6915342e9c4529d3a9a433678313293e..ce9ac6359da2bb3060d06cf0a8d0fb661b45e5b7 100644 --- a/module-audio/Audio/codec.hpp +++ b/module-audio/Audio/codec.hpp @@ -34,13 +34,15 @@ namespace audio::codec struct Configuration { - std::uint32_t sampleRate_Hz = 0; /*!< Sample rate of audio data */ - std::uint32_t bitWidth = 0; /*!< Data length of audio data, usually 8/16/24/32 bits */ - std::uint32_t flags = 0; /*!< In/Out configuration flags */ - float outputVolume = 0.0f; - float inputGain = 0.0f; - InputPath inputPath = InputPath::None; - OutputPath outputPath = OutputPath::None; + std::uint32_t sampleRate_Hz = 0; /*!< Sample rate of audio data */ + std::uint32_t bitWidth = 0; /*!< Data length of audio data, usually 8/16/24/32 bits */ + std::uint32_t flags = 0; /*!< In/Out configuration flags */ + float outputVolume = 0.0f; + float inputGain = 0.0f; + std::uint8_t playbackPathGain = 0; + std::uint8_t playbackPathAtten = 5; + InputPath inputPath = InputPath::None; + OutputPath outputPath = OutputPath::None; audio::equalizer::Equalizer filterCoefficients = { qfilter_CalculateCoeffs(audio::equalizer::FilterType::None, 100.2f, 44100, 0.701f, 0), qfilter_CalculateCoeffs(audio::equalizer::FilterType::None, 17996.2f, 44100, 0.701f, 0), diff --git a/module-audio/Audio/test/testfiles/testProfile.json b/module-audio/Audio/test/testfiles/testProfile.json index 0897e77b20b2ec870b2f234184274b1b6596b5eb..a3ab06776f2e5576fd506ec70513ab6a83da5f08 100644 --- a/module-audio/Audio/test/testfiles/testProfile.json +++ b/module-audio/Audio/test/testfiles/testProfile.json @@ -6,6 +6,8 @@ "inputGain": 2, "inputPath": 2, "outputPath": 3, + "playbackPathGain": 2, + "playbackPathAtten": 3, "filterParams": [ { "filterType": "None", diff --git a/module-audio/Audio/test/testfiles/testProfileFallback.json b/module-audio/Audio/test/testfiles/testProfileFallback.json new file mode 100644 index 0000000000000000000000000000000000000000..0fe0d585b41a7e17231e632e78bbed57cbef3092 --- /dev/null +++ b/module-audio/Audio/test/testfiles/testProfileFallback.json @@ -0,0 +1,48 @@ +{ + "samplerate": 44100, + "bitWidth": 8, + "flags": 1, + "outputVolume": 1, + "inputGain": 2, + "inputPath": 2, + "outputPath": 3, + "playbackPathGain": 30, + "playbackPathAtten": -17, + "filterParams": [ + { + "filterType": "None", + "frequency": 1000.2, + "samplerate": 44100, + "Q": 0.7, + "gain": 10 + }, + { + "filterType": "HighPass", + "frequency": 2000.0, + "samplerate": 8000, + "Q": 1.7, + "gain": -10 + }, + { + "filterType": "LowPass", + "frequency": 10000, + "samplerate": 44100, + "Q": 0.75, + "gain": 2.5 + }, + { + "filterType": "Notch", + "frequency": 2500, + "samplerate": 44100, + "Q": 4.4, + "gain": 5.3 + }, + { + "filterType": "BandPass", + "frequency": 1000, + "samplerate": 44100, + "Q": 0.7, + "gain": 10 + } + ] +} diff --git a/module-audio/Audio/test/unittest_config_utils.cpp b/module-audio/Audio/test/unittest_config_utils.cpp index 61a7287b7533f129cb24dbaa8293269498f5c45a..429677c434110d5e28f44462536b6dfccb1f3a8e 100644 --- a/module-audio/Audio/test/unittest_config_utils.cpp +++ b/module-audio/Audio/test/unittest_config_utils.cpp @@ -60,6 +60,8 @@ TEST_CASE("Audio profile config utils") REQUIRE(config.outputVolume == 1.0); REQUIRE(config.inputPath == audio::codec::InputPath::None); REQUIRE(config.outputPath == audio::codec::OutputPath::None); + REQUIRE(config.playbackPathGain == 2); + REQUIRE(config.playbackPathAtten == 3); audio::equalizer::Equalizer filterCoefficients = { qfilter_CalculateCoeffs(audio::equalizer::FilterType::None, 1000.2f, 44100, 0.7f, 10), @@ -72,4 +74,12 @@ TEST_CASE("Audio profile config utils") REQUIRE(config.filterCoefficients.at(i) == filterCoefficients.at(i)); } } + + SECTION("Checking if fallback values are loaded when playback path parameters are out of range") + { + auto config = audio::loadConfigurationFromFile("testfiles/testProfileFallback.json"); + + REQUIRE(config.playbackPathGain == 0); + REQUIRE(config.playbackPathAtten == 5); + } } diff --git a/module-audio/board/rt1051/puretx/PureTxAudioCodec.cpp b/module-audio/board/rt1051/puretx/PureTxAudioCodec.cpp index bdd5d34e423e230ae23dba5e614e77403bfc0a1a..24bcebb8d184a844677f0b832592720055a0284c 100644 --- a/module-audio/board/rt1051/puretx/PureTxAudioCodec.cpp +++ b/module-audio/board/rt1051/puretx/PureTxAudioCodec.cpp @@ -108,6 +108,8 @@ namespace audio codecParams.outputPath = getCodecOutputPath(currentFormat); codecParams.outVolume = currentFormat.outputVolume; codecParams.inGain = currentFormat.inputGain; + codecParams.playbackPathGain = currentFormat.playbackPathGain; + codecParams.playbackPathAtten = currentFormat.playbackPathAtten; SetupEQ(); codec.Start(codecParams); diff --git a/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp b/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp index acb5c182ad795f33a82f4484c0d9863c4bdfb59e..edd900c22e154f4dcf66eaba78dc5e793d3e524d 100644 --- a/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp +++ b/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "CodecMAX98090.hpp" @@ -134,9 +134,7 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m) i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP; i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1); - constexpr uint8_t coarse = 2; - constexpr uint8_t fine = 2; - SetPlaybackPath(coarse, fine); + SetPlaybackPath(params.playbackPathGain, params.playbackPathAtten); SetFilterMode(FilterMode::Voice); } break; @@ -157,9 +155,7 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m) i2cAddr.subAddress = MAX98090_REG_OUTPUT_ENABLE; i2c->Write(i2cAddr, (uint8_t *)&outputenable, 1); - constexpr uint8_t coarse = 0; - constexpr uint8_t fine = 2; - SetPlaybackPath(coarse, fine); + SetPlaybackPath(params.playbackPathGain, params.playbackPathAtten); } break; case CodecParamsMAX98090::OutputPath::LoudspeakerMono: { @@ -175,9 +171,7 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m) i2cAddr.subAddress = MAX98090_REG_OUTPUT_ENABLE; i2c->Write(i2cAddr, (uint8_t *)&outputenable, 1); - constexpr uint8_t coarse = 0; - constexpr uint8_t fine = 5; - SetPlaybackPath(coarse, fine); + SetPlaybackPath(params.playbackPathGain, params.playbackPathAtten); SetFilterMode(FilterMode::Voice); } break; diff --git a/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp b/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp index 8e5ee3198bbb3dd4138c9036cc44e0836597e7cd..680e64f38c560fbc81432d7bd9c74f68de9a56a5 100644 --- a/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp +++ b/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #ifndef PUREPHONE_CODECMAX98090_HPP @@ -60,9 +60,11 @@ class CodecParamsMAX98090 : public CodecParams None }; - bool muteEnable = false; - bool resetEnable = false; - bool micBiasEnable = false; + bool muteEnable = false; + bool resetEnable = false; + bool micBiasEnable = false; + std::uint8_t playbackPathGain = 0; + std::uint8_t playbackPathAtten = 0; InputPath inputPath = InputPath::None; OutputPath outputPath = OutputPath::None; };