Add Slice 5 ADAU1701 runtime audio control (firmware 0.5.0).
Safeload mixer/EQ/master on the ADAU1701, persist AudioProfile in NVS, expose /api/audio routes and web UI controls, with host tests and manual sync. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -22,6 +22,15 @@ add_library(digiradio_core STATIC
|
||||
"${CORE_SRC_DIR}/EmbeddedBlobReader.cpp"
|
||||
"${CORE_SRC_DIR}/TunerJson.cpp"
|
||||
"${CORE_SRC_DIR}/FrequencyKHz.cpp"
|
||||
"${CORE_SRC_DIR}/GainDb.cpp"
|
||||
"${CORE_SRC_DIR}/FrequencyHz.cpp"
|
||||
"${CORE_SRC_DIR}/EqBandIndex.cpp"
|
||||
"${CORE_SRC_DIR}/BiquadCoefficients.cpp"
|
||||
"${CORE_SRC_DIR}/BiquadDesign.cpp"
|
||||
"${CORE_SRC_DIR}/MixerState.cpp"
|
||||
"${CORE_SRC_DIR}/EqProfile.cpp"
|
||||
"${CORE_SRC_DIR}/AudioProfile.cpp"
|
||||
"${CORE_SRC_DIR}/AudioProfileJson.cpp"
|
||||
)
|
||||
target_include_directories(digiradio_core PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../include"
|
||||
@@ -46,3 +55,11 @@ add_test(NAME tuner_json_test COMMAND tuner_json_test)
|
||||
add_executable(frequency_khz_test frequency_khz_test.cpp)
|
||||
target_link_libraries(frequency_khz_test PRIVATE digiradio_core)
|
||||
add_test(NAME frequency_khz_test COMMAND frequency_khz_test)
|
||||
|
||||
add_executable(biquad_design_test biquad_design_test.cpp)
|
||||
target_link_libraries(biquad_design_test PRIVATE digiradio_core)
|
||||
add_test(NAME biquad_design_test COMMAND biquad_design_test)
|
||||
|
||||
add_executable(audio_profile_json_test audio_profile_json_test.cpp)
|
||||
target_link_libraries(audio_profile_json_test PRIVATE digiradio_core)
|
||||
add_test(NAME audio_profile_json_test COMMAND audio_profile_json_test)
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @file audio_profile_json_test.cpp
|
||||
* @brief Host tests for AudioProfile JSON round-trip.
|
||||
*
|
||||
* DigiRadio firmware — https://github.com/manvalan/DigiRadio
|
||||
*
|
||||
* Copyright 2026 Michele Bigi
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @author Michele Bigi
|
||||
* @date 2026-07-06
|
||||
*/
|
||||
|
||||
#include "core/AudioProfile.hpp"
|
||||
#include "core/AudioProfileJson.hpp"
|
||||
#include "core/EqBandIndex.hpp"
|
||||
#include "core/FrequencyHz.hpp"
|
||||
#include "core/GainDb.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] int runRoundTripTest()
|
||||
{
|
||||
core::AudioProfile profile = core::AudioProfile::factoryDefault();
|
||||
const auto band = core::EqBandIndex::tryFromIndex(2U);
|
||||
const auto gain = core::GainDb::tryFromDb(3.0F);
|
||||
const auto center = core::FrequencyHz::tryFromHz(500U);
|
||||
if (!band || !gain || !center) {
|
||||
std::cerr << "test setup failed\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
profile.eq.setBand(*band,
|
||||
core::EqBandSettings{
|
||||
.gain = *gain,
|
||||
.center = *center,
|
||||
.q = 2.0F,
|
||||
});
|
||||
|
||||
const std::string json = core::serializeAudioProfileJson(profile);
|
||||
const auto parsed = core::parseAudioProfileJson(json);
|
||||
if (!parsed) {
|
||||
std::cerr << "parse failed\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const auto& b = parsed->eq.band(*band);
|
||||
if (b.gain.value() != 3.0F || b.center.value() != 500U
|
||||
|| b.q != 2.0F) {
|
||||
std::cerr << "round-trip mismatch\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
if (runRoundTripTest() != EXIT_SUCCESS) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @file biquad_design_test.cpp
|
||||
* @brief Host tests for ADAU biquad design and fixpoint conversion.
|
||||
*
|
||||
* DigiRadio firmware — https://github.com/manvalan/DigiRadio
|
||||
*
|
||||
* Copyright 2026 Michele Bigi
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @author Michele Bigi
|
||||
* @date 2026-07-06
|
||||
*/
|
||||
|
||||
#include "core/BiquadDesign.hpp"
|
||||
#include "core/FrequencyHz.hpp"
|
||||
#include "core/GainDb.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] int runUnityGainFixpointTest()
|
||||
{
|
||||
const auto gain = core::GainDb::zero();
|
||||
const std::int32_t fix = core::gainDbToLinearFixpoint(gain);
|
||||
if (fix != 0x00800000) {
|
||||
std::cerr << "expected 0 dB fixpoint 0x00800000, got 0x"
|
||||
<< std::hex << fix << std::dec << '\n';
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
[[nodiscard]] int runFlatBiquadTest()
|
||||
{
|
||||
const core::BiquadCoefficients flat = core::designFlatEq();
|
||||
if (std::fabs(flat.b0 - 1.0F) > 0.001F || std::fabs(flat.b1) > 0.001F
|
||||
|| std::fabs(flat.b2) > 0.001F || std::fabs(flat.a0) > 0.001F
|
||||
|| std::fabs(flat.a1) > 0.001F) {
|
||||
std::cerr << "flat biquad coefficients unexpected\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const auto center = core::FrequencyHz::tryFromHz(1000U);
|
||||
const auto zero = core::GainDb::zero();
|
||||
const core::BiquadCoefficients peaking =
|
||||
core::designPeakingEq(*center, zero, 1.414F);
|
||||
if (std::fabs(peaking.b0 - 1.0F) > 0.001F) {
|
||||
std::cerr << "0 dB peaking should match flat b0\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
if (runUnityGainFixpointTest() != EXIT_SUCCESS) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (runFlatBiquadTest() != EXIT_SUCCESS) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user