~aleteoryx/muditaos

eedff11e90d25ae1ce5f40a017e5662739720b9e — Maciej Gibowicz 1 year, 5 months ago 62ae70a
[BH-2062] Fix alarm volume fade in duration

The alarm volume should gradually increase by 0.1 every 300 ms, which
gives a time of 45 seconds for a full 15-point scale
M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +13 -10
@@ 21,17 21,19 @@ namespace audio

namespace audio
{
    inline constexpr Volume defaultVolumeStep = 1;
    inline constexpr Volume defaultVolumeStep{1};

    inline constexpr Volume maxVolume = 10;
    inline constexpr Volume minVolume = 0;
    inline constexpr Volume maxVolume{10};
    inline constexpr Volume minVolume{0};

    inline constexpr Gain maxGain = 100;
    inline constexpr Gain minGain = 0;
    inline constexpr Gain maxGain{100};
    inline constexpr Gain minGain{0};

    inline constexpr auto audioDbPrefix{"audio"};
    inline constexpr auto dbPathSeparator{'/'};

    inline constexpr auto audioDbPrefix   = "audio";
    inline constexpr auto dbPathSeparator = '/';
    inline constexpr std::chrono::seconds defaultMaxFadeDuration{5};
    inline constexpr std::chrono::seconds alarmMaxFadeDuration{45};

    enum class Setting
    {


@@ 87,7 89,8 @@ namespace audio
    struct FadeParams
    {
        Fade mode;
        std::optional<std::chrono::seconds> playbackDuration = std::nullopt;
        std::chrono::seconds maxFadeDuration{defaultMaxFadeDuration};
        std::optional<std::chrono::seconds> playbackDuration{std::nullopt};
    };

    enum class VolumeUpdateType


@@ 294,8 297,8 @@ namespace audio
            return *this;
        }

        constexpr static TokenType tokenUninitialized = -1;
        constexpr static TokenType tokenBad           = -2;
        constexpr static TokenType tokenUninitialized{-1};
        constexpr static TokenType tokenBad{-2};

        TokenType t;
        friend class ::audio::AudioMux;

M products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp => products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp +2 -2
@@ 29,8 29,8 @@ namespace alarms
                                       ? audio::Fade::In
                                       : audio::Fade::Disable;

        auto msg =
            std::make_shared<service::AudioStartPlaybackRequest>(path, playbackType, audio::FadeParams{fadeInEnabled});
        auto msg = std::make_shared<service::AudioStartPlaybackRequest>(
            path, playbackType, audio::FadeParams{fadeInEnabled, audio::alarmMaxFadeDuration});
        return service.bus.sendUnicast(std::move(msg), service::audioServiceName);
    }


M products/BellHybrid/services/audio/VolumeFade.cpp => products/BellHybrid/services/audio/VolumeFade.cpp +32 -18
@@ 10,24 10,14 @@ namespace audio
    {
        using namespace std::chrono_literals;
        constexpr auto timerName{"volumeFadeTimer"};
        constexpr auto fadeInterval{33ms};
        constexpr auto minFadeInterval{33ms};
        constexpr auto fadeStep{0.1f};

        std::chrono::milliseconds calculateTimerPeriod(std::chrono::seconds elapsed,
                                                       std::chrono::seconds duration,
                                                       float currentVolume)
        {
            using floatToMs         = std::chrono::duration<float, std::chrono::milliseconds::period>;
            const auto timeRequired = floatToMs(currentVolume / fadeStep) * fadeInterval.count();
            const auto calculatedTime =
                std::chrono::duration_cast<std::chrono::milliseconds>(duration - elapsed - timeRequired);
            return std::max(calculatedTime, fadeInterval);
        }
    } // namespace

    VolumeFade::VolumeFade(sys::Service *parent, SetCallback callback) : setVolumeCallback(std::move(callback))
    {
        timerHandle = sys::TimerFactory::createPeriodicTimer(
        fadeInterval = minFadeInterval;
        timerHandle  = sys::TimerFactory::createPeriodicTimer(
            parent, timerName, fadeInterval, [this]([[maybe_unused]] sys::Timer &timer) { PerformNextFadeStep(); });
    }



@@ 52,8 42,9 @@ namespace audio
        currentVolume      = minVolume + fadeStep;
        phase              = Phase::FadeIn;
        timestamp          = std::chrono::system_clock::now();
        fadeInterval       = calculateFadeInterval(fadeParams.maxFadeDuration);

        if (this->fadeParams.playbackDuration.has_value()) {
        if (this->fadeParams.mode == audio::Fade::InOut && this->fadeParams.playbackDuration.has_value()) {
            // If the song is shorter than the fade in and out durations, we reduce the target volume value so that both
            // phases have time to complete
            const auto maxFadePeriod =


@@ 91,7 82,7 @@ namespace audio
            if (setVolumeCallback != nullptr) {
                setVolumeCallback(currentVolume);
            }
            RestartTimer();
            RestartWaitingTimer();
        }
    }



@@ 125,7 116,7 @@ namespace audio
            }
            else if (fadeParams.mode == audio::Fade::InOut && fadeParams.playbackDuration.has_value()) {
                phase = Phase::Wait;
                RestartTimer();
                RestartWaitingTimer();
            }
            else {
                Stop();


@@ 164,11 155,34 @@ namespace audio
        }
    }

    void VolumeFade::RestartTimer()
    void VolumeFade::RestartWaitingTimer()
    {
        const auto now         = std::chrono::system_clock::now();
        const auto timeElapsed = std::chrono::duration_cast<std::chrono::seconds>(now - timestamp);
        timerHandle.restart(calculateTimerPeriod(timeElapsed, fadeParams.playbackDuration.value(), currentVolume));
        timerHandle.restart(calculateWaitingTimerPeriod(timeElapsed));
    }

    std::chrono::milliseconds VolumeFade::calculateFadeInterval(std::chrono::seconds maxDuration)
    {
        const auto volumeDifference = maxVolume - minVolume;
        if (volumeDifference <= 0) {
            return minFadeInterval;
        }
        const auto calculatedTime =
            std::chrono::duration_cast<std::chrono::milliseconds>(maxDuration / (volumeDifference / fadeStep));
        return std::max(calculatedTime, minFadeInterval);
    }

    std::chrono::milliseconds VolumeFade::calculateWaitingTimerPeriod(std::chrono::seconds timeElapsed)
    {
        using floatToMs = std::chrono::duration<float, std::chrono::milliseconds::period>;
        if (!fadeParams.playbackDuration.has_value()) {
            return minFadeInterval;
        }
        const auto timeRequired   = floatToMs(currentVolume / fadeStep) * fadeInterval.count();
        const auto calculatedTime = std::chrono::duration_cast<std::chrono::milliseconds>(
            fadeParams.playbackDuration.value() - timeElapsed - timeRequired);
        return std::max(calculatedTime, minFadeInterval);
    }

} // namespace audio

M products/BellHybrid/services/audio/include/audio/VolumeFade.hpp => products/BellHybrid/services/audio/include/audio/VolumeFade.hpp +4 -1
@@ 37,15 37,18 @@ namespace audio
        float minVolume;
        float maxVolume;
        float currentVolume;
        std::chrono::milliseconds fadeInterval;
        SetCallback setVolumeCallback;
        Phase phase{Phase::Idle};
        std::chrono::time_point<std::chrono::system_clock> timestamp;

        void PerformNextFadeStep();
        void RestartTimer();
        void RestartWaitingTimer();
        void TurnUpVolume();
        void TurnDownVolume();
        void SetTargetVolume(float volume);
        bool IsFadePhaseActive();
        std::chrono::milliseconds calculateFadeInterval(std::chrono::seconds maxDuration);
        std::chrono::milliseconds calculateWaitingTimerPeriod(std::chrono::seconds timeElapsed);
    };
} // namespace audio