~aleteoryx/muditaos

6f257d38dbd42ac6aa54258e640571b6cbe003ad — Marcin Lyda 3 years ago 8e6ee1f
[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
M image/user/data/equalizer/earspeaker_routing.json => image/user/data/equalizer/earspeaker_routing.json +2 -0
@@ 6,6 6,8 @@
  "inputGain": 0,
  "inputPath": 1,
  "outputPath": 1,
  "playbackPathGain": 2,
  "playbackPathAtten": 2,
  "filterParams": [
    {
      "filterType": "HighPass",

M image/user/data/equalizer/loudspeaker_playback.json => image/user/data/equalizer/loudspeaker_playback.json +2 -0
@@ 6,6 6,8 @@
  "inputGain": 0,
  "inputPath": 2,
  "outputPath": 2,
  "playbackPathGain": 0,
  "playbackPathAtten": 2,
  "filterParams": [
    {
      "filterType": "HighPass",

M image/user/data/equalizer/loudspeaker_routing.json => image/user/data/equalizer/loudspeaker_routing.json +2 -0
@@ 6,6 6,8 @@
  "inputGain": 0,
  "inputPath": 1,
  "outputPath": 2,
  "playbackPathGain": 0,
  "playbackPathAtten": 5,
  "filterParams": [
    {
      "filterType": "HighPass",

M module-audio/Audio/Profiles/ProfileConfigUtils.cpp => module-audio/Audio/Profiles/ProfileConfigUtils.cpp +37 -12
@@ 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<codec::InputPath>(configJson[strings::inputPath].int_value());
        config.outputPath    = utils::toEnum<codec::OutputPath>(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();

M module-audio/Audio/Profiles/ProfilePlaybackLoudspeaker.hpp => module-audio/Audio/Profiles/ProfilePlaybackLoudspeaker.hpp +9 -7
@@ 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),

M module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp => module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp +7 -4
@@ 21,10 21,13 @@ namespace audio
                      .flags =
                          static_cast<uint32_t>(audio::codec::Flags::InputLeft) | // microphone use left audio channel
                          static_cast<uint32_t>(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),

M module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp => module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp +2 -0
@@ 25,6 25,8 @@ namespace audio
                          static_cast<uint32_t>(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(

M module-audio/Audio/Profiles/README.md => module-audio/Audio/Profiles/README.md +22 -17
@@ 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:


M module-audio/Audio/codec.hpp => module-audio/Audio/codec.hpp +9 -7
@@ 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),

M module-audio/Audio/test/testfiles/testProfile.json => module-audio/Audio/test/testfiles/testProfile.json +2 -0
@@ 6,6 6,8 @@
  "inputGain": 2,
  "inputPath": 2,
  "outputPath": 3,
  "playbackPathGain": 2,
  "playbackPathAtten": 3,
  "filterParams": [
    {
      "filterType": "None",

A module-audio/Audio/test/testfiles/testProfileFallback.json => module-audio/Audio/test/testfiles/testProfileFallback.json +48 -0
@@ 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
    }
  ]
}

M module-audio/Audio/test/unittest_config_utils.cpp => module-audio/Audio/test/unittest_config_utils.cpp +10 -0
@@ 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);
    }
}

M module-audio/board/rt1051/puretx/PureTxAudioCodec.cpp => module-audio/board/rt1051/puretx/PureTxAudioCodec.cpp +2 -0
@@ 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);


M module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp => module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp +4 -10
@@ 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 &param)
            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 &param)
            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 &param)
            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;


M module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp => module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp +6 -4
@@ 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;
};