Integrate DigiRadioFinale DSP program: exclusive source mux, real
Bass Boost1/SPhat1 enhancement blocks Replaces the 74-parameter ADAU1701 program with the new 224-parameter SigmaStudio export. The new netlist has no mixer -- MX1 is an exclusive selector (DC1) passing through exactly one of three stereo pairs (radio/bluetooth/beep) instead of blending them with independent gains. core::MixSource/MixerState are gone; core::ActiveSource plus IDsp::selectSource() replace applyMixer()/setInputVolume() throughout the driver/service/API stack. AudioProfile.mixer -> activeSource; the HTTP "mixer" JSON object -> a single "active_source" string. DC1 turned out to need a raw 32-bit integer (0/1/2), not the 5.23 fixpoint its compiled TYPE_DC1 macro implies -- confirmed live by writing both encodings and listening for which one actually switched sources. Documented in Adau1701Driver::selectSource() and adau1701::paramSourceIndex(). Bass Boost1 and SPhat1 are real ADI algorithm blocks in this revision, so core::applyEnhancementsToEq() (the old EQ-band-overwrite hack for bass/stereo enhancement) is deleted; IDsp::setBassBoostLevel()/ setStereoSpreadLevel() scale each block's compiled coefficients toward identity/unity instead. Confirmed live: Bass Boost audible on real program content (not a static test tone -- the algorithm is dynamics- based), Stereo Spread audible but subtle. The EQ "locked" flag from 2026-08-24 (enhancements silently overwriting manually-set bands) no longer applies to bands 1-5. A full sweep of all 223 non-DC1 named parameters (writing each back to its own compiled default) completed with zero failures, confirming the whole new address space is reachable. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,16 +12,15 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "core/ActiveSource.hpp"
|
||||
#include "core/AudioProfile.hpp"
|
||||
#include "core/DspError.hpp"
|
||||
#include "core/EnhanceLevel.hpp"
|
||||
#include "core/EnhancementsDesign.hpp"
|
||||
#include "core/EqBandIndex.hpp"
|
||||
#include "core/FrequencyHz.hpp"
|
||||
#include "core/GainDb.hpp"
|
||||
#include "core/IAudioProfileStore.hpp"
|
||||
#include "core/IDsp.hpp"
|
||||
#include "core/MixSource.hpp"
|
||||
#include "core/StoreError.hpp"
|
||||
|
||||
#include <expected>
|
||||
@@ -106,22 +105,19 @@ public:
|
||||
const core::AudioProfile& profile, bool persist);
|
||||
|
||||
/**
|
||||
* @brief setInputVolume — update one input path and apply live.
|
||||
* @brief selectSource — switch MX1's active input pair and apply live.
|
||||
*
|
||||
* @dname setInputVolume
|
||||
* @param source Si4684 or ESP32 path.
|
||||
* @param left Left gain.
|
||||
* @param right Right gain.
|
||||
* @dname selectSource
|
||||
* @param source Which stereo pair MX1 should pass through.
|
||||
* @param persist When true and store is set, write NVS.
|
||||
* @return Ok on success, or StoreError wrapping DspError/IoFailed.
|
||||
* @pubstate updates profile_.mixer and safeloads.
|
||||
* @pubstate updates profile_.activeSource and safeloads.
|
||||
*
|
||||
* @author Michele Bigi
|
||||
* @date 2026-07-06
|
||||
* @date 2026-08-25
|
||||
*/
|
||||
[[nodiscard]] std::expected<void, core::StoreError> setInputVolume(
|
||||
core::MixSource source, core::GainDb left, core::GainDb right,
|
||||
bool persist);
|
||||
[[nodiscard]] std::expected<void, core::StoreError> selectSource(
|
||||
core::ActiveSource source, bool persist);
|
||||
|
||||
/**
|
||||
* @brief setMasterVolume — update master output and apply live.
|
||||
@@ -239,9 +235,6 @@ private:
|
||||
[[nodiscard]] std::expected<void, core::StoreError> applyProfileToDsp(
|
||||
const core::AudioProfile& profile);
|
||||
|
||||
[[nodiscard]] std::expected<void, core::StoreError> applyEffectiveEq(
|
||||
bool persist);
|
||||
|
||||
core::IDsp& dsp_;
|
||||
core::IAudioProfileStore* store_;
|
||||
core::AudioProfile profile_;
|
||||
|
||||
@@ -21,15 +21,6 @@ namespace {
|
||||
|
||||
constexpr char kTag[] = "AudioService";
|
||||
|
||||
[[nodiscard]] core::AudioProfile profileForHardware(
|
||||
const core::AudioProfile& profile) noexcept
|
||||
{
|
||||
core::AudioProfile hardware = profile;
|
||||
hardware.eq =
|
||||
core::applyEnhancementsToEq(profile.eq, profile.enhancements);
|
||||
return hardware;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AudioService::AudioService(core::IDsp& dsp, core::IAudioProfileStore* store)
|
||||
@@ -81,28 +72,13 @@ std::expected<void, core::StoreError> AudioService::persistProfile() const
|
||||
std::expected<void, core::StoreError> AudioService::applyProfileToDsp(
|
||||
const core::AudioProfile& profile)
|
||||
{
|
||||
const core::AudioProfile hardware = profileForHardware(profile);
|
||||
if (auto applied = dsp_.applyProfile(hardware); !applied) {
|
||||
if (auto applied = dsp_.applyProfile(profile); !applied) {
|
||||
ESP_LOGW(kTag, "applyProfileToDsp: DSP safeload failed");
|
||||
return std::unexpected(core::StoreError::IoFailed);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::expected<void, core::StoreError> AudioService::applyEffectiveEq(
|
||||
bool persist)
|
||||
{
|
||||
const core::EqProfile effective = core::applyEnhancementsToEq(
|
||||
profile_.eq, profile_.enhancements);
|
||||
if (auto applied = dsp_.applyEq(effective); !applied) {
|
||||
return std::unexpected(core::StoreError::IoFailed);
|
||||
}
|
||||
if (persist) {
|
||||
return persistProfile();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::expected<void, core::StoreError> AudioService::applyProfile(
|
||||
const core::AudioProfile& profile, bool persist)
|
||||
{
|
||||
@@ -116,21 +92,13 @@ std::expected<void, core::StoreError> AudioService::applyProfile(
|
||||
return {};
|
||||
}
|
||||
|
||||
std::expected<void, core::StoreError> AudioService::setInputVolume(
|
||||
core::MixSource source, core::GainDb left, core::GainDb right, bool persist)
|
||||
std::expected<void, core::StoreError> AudioService::selectSource(
|
||||
core::ActiveSource source, bool persist)
|
||||
{
|
||||
if (auto applied = dsp_.setInputVolume(source, left, right); !applied) {
|
||||
if (auto applied = dsp_.selectSource(source); !applied) {
|
||||
return std::unexpected(core::StoreError::IoFailed);
|
||||
}
|
||||
|
||||
if (source == core::MixSource::Si4684) {
|
||||
profile_.mixer.si4684Left = left;
|
||||
profile_.mixer.si4684Right = right;
|
||||
} else {
|
||||
profile_.mixer.esp32Left = left;
|
||||
profile_.mixer.esp32Right = right;
|
||||
}
|
||||
|
||||
profile_.activeSource = source;
|
||||
if (persist) {
|
||||
return persistProfile();
|
||||
}
|
||||
@@ -155,10 +123,10 @@ std::expected<void, core::StoreError> AudioService::applyRadioFirstMix(
|
||||
bool persist)
|
||||
{
|
||||
const core::GainDb unity = core::GainDb::zero();
|
||||
profile_.mixer = core::MixerState::radioFirst();
|
||||
profile_.activeSource = core::ActiveSource::Radio;
|
||||
profile_.masterLeft = unity;
|
||||
profile_.masterRight = unity;
|
||||
if (auto applied = dsp_.applyMixer(profile_.mixer); !applied) {
|
||||
if (auto applied = dsp_.selectSource(profile_.activeSource); !applied) {
|
||||
return std::unexpected(core::StoreError::IoFailed);
|
||||
}
|
||||
if (auto master = dsp_.setMasterVolume(unity, unity); !master) {
|
||||
@@ -179,21 +147,39 @@ std::expected<void, core::StoreError> AudioService::setEqBand(
|
||||
.center = center,
|
||||
.q = q,
|
||||
});
|
||||
return applyEffectiveEq(persist);
|
||||
if (auto applied = dsp_.applyEq(profile_.eq); !applied) {
|
||||
return std::unexpected(core::StoreError::IoFailed);
|
||||
}
|
||||
if (persist) {
|
||||
return persistProfile();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::expected<void, core::StoreError> AudioService::setStereoEnhance(
|
||||
core::EnhanceLevel level, bool persist)
|
||||
{
|
||||
if (auto applied = dsp_.setStereoSpreadLevel(level); !applied) {
|
||||
return std::unexpected(core::StoreError::IoFailed);
|
||||
}
|
||||
profile_.enhancements.stereo = level;
|
||||
return applyEffectiveEq(persist);
|
||||
if (persist) {
|
||||
return persistProfile();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::expected<void, core::StoreError> AudioService::setBassEnhance(
|
||||
core::EnhanceLevel level, bool persist)
|
||||
{
|
||||
if (auto applied = dsp_.setBassBoostLevel(level); !applied) {
|
||||
return std::unexpected(core::StoreError::IoFailed);
|
||||
}
|
||||
profile_.enhancements.bass = level;
|
||||
return applyEffectiveEq(persist);
|
||||
if (persist) {
|
||||
return persistProfile();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::expected<void, core::DspError> AudioService::setBeepEnabled(bool enabled)
|
||||
|
||||
Reference in New Issue
Block a user