Resolve Soundboard tone key issue (#1806)

* Resolve Soundboard tone key issue
This commit is contained in:
Mark Thompson 2024-01-23 13:53:04 -06:00 committed by GitHub
parent 03b13f8ab0
commit 2d98c5d311
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 108 additions and 32 deletions

View File

@ -116,11 +116,11 @@ void SoundBoardView::start_tx(const uint32_t id) {
// TODO: Delete all this and use tx model. // TODO: Delete all this and use tx model.
baseband::set_audiotx_config( baseband::set_audiotx_config(
1536000 / 20, // Update vu-meter at 20Hz TONES_SAMPLERATE / 20, // Update vu-meter at 20Hz
transmitter_model.channel_bandwidth(), transmitter_model.channel_bandwidth(),
0, // Gain is unused 0, // Gain is unused
8, // shift_bits_s16, default 8 bits, but also unused 8, // shift_bits_s16, default 8 bits, but also unused
TONES_F2D(tone_key_frequency(tone_key_index), 1536000), TONES_F2D(tone_key_frequency(tone_key_index), TONES_SAMPLERATE),
0, // AM 0, // AM
0, // DSB 0, // DSB
0, // USB 0, // USB
@ -132,7 +132,8 @@ void SoundBoardView::start_tx(const uint32_t id) {
tx_view.set_transmitting(true); tx_view.set_transmitting(true);
audio::output::start(); if (tone_key_index == 0)
audio::output::start();
} }
/*void SoundBoardView::show_infos() { /*void SoundBoardView::show_infos() {
@ -238,6 +239,7 @@ SoundBoardView::SoundBoardView(
//&text_duration, //&text_duration,
//&progressbar, //&progressbar,
&field_volume, &field_volume,
&text_volume_disabled,
&page_info, &page_info,
&check_loop, &check_loop,
&check_random, &check_random,
@ -263,6 +265,13 @@ SoundBoardView::SoundBoardView(
tone_keys_populate(options_tone_key); tone_keys_populate(options_tone_key);
options_tone_key.set_selected_index(0); options_tone_key.set_selected_index(0);
text_volume_disabled.hidden(true);
options_tone_key.on_change = [this](size_t index, OptionsField::value_t) {
bool tone_key_enabled = (index != 0);
text_volume_disabled.hidden(!tone_key_enabled);
field_volume.hidden(tone_key_enabled);
};
check_loop.set_value(false); check_loop.set_value(false);
check_random.set_value(false); check_random.set_value(false);

View File

@ -128,6 +128,9 @@ class SoundBoardView : public View {
AudioVolumeField field_volume{ AudioVolumeField field_volume{
{28 * 8, 180}}; {28 * 8, 180}};
Text text_volume_disabled{
{28 * 8, 180, 3 * 8, 16},
"--"};
Checkbox check_loop{ Checkbox check_loop{
{0, 25 * 8 + 4}, {0, 25 * 8 + 4},

View File

@ -215,9 +215,12 @@ void disable() {
gpdma_channel_i2s0_rx.disable(); gpdma_channel_i2s0_rx.disable();
} }
void shrink_tx_buffer() { void shrink_tx_buffer(bool shrink) {
single_tx_buffer = true; single_tx_buffer = shrink;
lli_tx_loop[0].lli = lli_pointer(&lli_tx_loop[0]); if (single_tx_buffer)
lli_tx_loop[0].lli = lli_pointer(&lli_tx_loop[0]);
else
lli_tx_loop[0].lli = lli_pointer(&lli_tx_loop[1]);
} }
buffer_t tx_empty_buffer() { buffer_t tx_empty_buffer() {

View File

@ -47,7 +47,7 @@ void init();
void configure(); void configure();
void enable(); void enable();
void disable(); void disable();
void shrink_tx_buffer(); void shrink_tx_buffer(bool shrink);
audio::buffer_t tx_empty_buffer(); audio::buffer_t tx_empty_buffer();
audio::buffer_t rx_empty_buffer(); audio::buffer_t rx_empty_buffer();

View File

@ -32,34 +32,34 @@
#include <cstddef> #include <cstddef>
#include <array> #include <array>
void AudioOutput::configure( void AudioOutput::configure(const bool do_proc) {
const bool do_proc) {
do_processing = do_proc; do_processing = do_proc;
} }
void AudioOutput::configure( void AudioOutput::configure(const iir_biquad_config_t& hpf_config, const iir_biquad_config_t& deemph_config, const float squelch_threshold) {
const iir_biquad_config_t& hpf_config,
const iir_biquad_config_t& deemph_config,
const float squelch_threshold) {
hpf.configure(hpf_config); hpf.configure(hpf_config);
deemph.configure(deemph_config); deemph.configure(deemph_config);
squelch.set_threshold(squelch_threshold); squelch.set_threshold(squelch_threshold);
} }
void AudioOutput::write( void AudioOutput::write_unprocessed(const buffer_s16_t& audio) {
const buffer_s16_t& audio) { block_buffer_s16.feed(
audio,
[this](const buffer_s16_t& buffer) {
audio_present = true;
fill_audio_buffer(buffer, audio_present);
});
}
void AudioOutput::write(const buffer_s16_t& audio) {
std::array<float, 32> audio_f; std::array<float, 32> audio_f;
for (size_t i = 0; i < audio.count; i++) { for (size_t i = 0; i < audio.count; i++) {
audio_f[i] = audio.p[i] * ki; audio_f[i] = audio.p[i] * ki;
} }
write(buffer_f32_t{ write(buffer_f32_t{audio_f.data(), audio.count, audio.sampling_rate});
audio_f.data(),
audio.count,
audio.sampling_rate});
} }
void AudioOutput::write( void AudioOutput::write(const buffer_f32_t& audio) {
const buffer_f32_t& audio) {
block_buffer.feed( block_buffer.feed(
audio, audio,
[this](const buffer_f32_t& buffer) { [this](const buffer_f32_t& buffer) {
@ -67,8 +67,7 @@ void AudioOutput::write(
}); });
} }
void AudioOutput::on_block( void AudioOutput::on_block(const buffer_f32_t& audio) {
const buffer_f32_t& audio) {
if (do_processing) { if (do_processing) {
const auto audio_present_now = squelch.execute(audio); const auto audio_present_now = squelch.execute(audio);
@ -93,6 +92,18 @@ bool AudioOutput::is_squelched() {
return !audio_present; return !audio_present;
} }
void AudioOutput::fill_audio_buffer(const buffer_s16_t& audio, const bool send_to_fifo) {
auto audio_buffer = audio::dma::tx_empty_buffer();
for (size_t i = 0; i < audio_buffer.count; i++) {
audio_buffer.p[i].left = audio_buffer.p[i].right = audio.p[i];
}
if (stream && send_to_fifo) {
stream->write(audio.p, audio_buffer.count * sizeof(int16_t));
}
feed_audio_stats(audio);
}
void AudioOutput::fill_audio_buffer(const buffer_f32_t& audio, const bool send_to_fifo) { void AudioOutput::fill_audio_buffer(const buffer_f32_t& audio, const bool send_to_fifo) {
std::array<int16_t, 32> audio_int; std::array<int16_t, 32> audio_int;
@ -110,6 +121,15 @@ void AudioOutput::fill_audio_buffer(const buffer_f32_t& audio, const bool send_t
feed_audio_stats(audio); feed_audio_stats(audio);
} }
void AudioOutput::feed_audio_stats(const buffer_s16_t& audio) {
audio_stats.feed(
audio,
[](const AudioStatistics& statistics) {
const AudioStatisticsMessage audio_stats_message{statistics};
shared_memory.application_queue.push(audio_stats_message);
});
}
void AudioOutput::feed_audio_stats(const buffer_f32_t& audio) { void AudioOutput::feed_audio_stats(const buffer_f32_t& audio) {
audio_stats.feed( audio_stats.feed(
audio, audio,

View File

@ -44,6 +44,7 @@ class AudioOutput {
const iir_biquad_config_t& deemph_config = iir_config_passthrough, const iir_biquad_config_t& deemph_config = iir_config_passthrough,
const float squelch_threshold = 0.0f); const float squelch_threshold = 0.0f);
void write_unprocessed(const buffer_s16_t& audio);
void write(const buffer_s16_t& audio); void write(const buffer_s16_t& audio);
void write(const buffer_f32_t& audio); void write(const buffer_f32_t& audio);
@ -57,6 +58,7 @@ class AudioOutput {
static constexpr float k = 32768.0f; static constexpr float k = 32768.0f;
static constexpr float ki = 1.0f / k; static constexpr float ki = 1.0f / k;
BlockDecimator<int16_t, 32> block_buffer_s16{1};
BlockDecimator<float, 32> block_buffer{1}; BlockDecimator<float, 32> block_buffer{1};
IIRBiquadFilter hpf{}; IIRBiquadFilter hpf{};
@ -73,7 +75,11 @@ class AudioOutput {
bool do_processing = true; bool do_processing = true;
void on_block(const buffer_f32_t& audio); void on_block(const buffer_f32_t& audio);
void fill_audio_buffer(const buffer_s16_t& audio, const bool send_to_fifo);
void fill_audio_buffer(const buffer_f32_t& audio, const bool send_to_fifo); void fill_audio_buffer(const buffer_f32_t& audio, const bool send_to_fifo);
void feed_audio_stats(const buffer_s16_t& audio);
void feed_audio_stats(const buffer_f32_t& audio); void feed_audio_stats(const buffer_f32_t& audio);
}; };

View File

@ -23,6 +23,19 @@
#include "utility.hpp" #include "utility.hpp"
void AudioStatsCollector::consume_audio_buffer(const buffer_s16_t& src) {
auto src_p = src.p;
const auto src_end = &src.p[src.count];
while (src_p < src_end) {
const auto sample = *(src_p++);
const auto sample_squared = sample * sample;
squared_sum += sample_squared;
if (sample_squared > max_squared) {
max_squared = sample_squared;
}
}
}
void AudioStatsCollector::consume_audio_buffer(const buffer_f32_t& src) { void AudioStatsCollector::consume_audio_buffer(const buffer_f32_t& src) {
auto src_p = src.p; auto src_p = src.p;
const auto src_end = &src.p[src.count]; const auto src_end = &src.p[src.count];
@ -56,6 +69,12 @@ bool AudioStatsCollector::update_stats(const size_t sample_count, const size_t s
} }
} }
bool AudioStatsCollector::feed(const buffer_s16_t& src) {
consume_audio_buffer(src);
return update_stats(src.count, src.sampling_rate);
}
bool AudioStatsCollector::feed(const buffer_f32_t& src) { bool AudioStatsCollector::feed(const buffer_f32_t& src) {
consume_audio_buffer(src); consume_audio_buffer(src);

View File

@ -30,6 +30,13 @@
class AudioStatsCollector { class AudioStatsCollector {
public: public:
template <typename Callback>
void feed(const buffer_s16_t& src, Callback callback) {
if (feed(src)) {
callback(statistics);
}
}
template <typename Callback> template <typename Callback>
void feed(const buffer_f32_t& src, Callback callback) { void feed(const buffer_f32_t& src, Callback callback) {
if (feed(src)) { if (feed(src)) {
@ -52,10 +59,12 @@ class AudioStatsCollector {
AudioStatistics statistics{}; AudioStatistics statistics{};
void consume_audio_buffer(const buffer_s16_t& src);
void consume_audio_buffer(const buffer_f32_t& src); void consume_audio_buffer(const buffer_f32_t& src);
bool update_stats(const size_t sample_count, const size_t sampling_rate); bool update_stats(const size_t sample_count, const size_t sampling_rate);
bool feed(const buffer_s16_t& src);
bool feed(const buffer_f32_t& src); bool feed(const buffer_f32_t& src);
bool mute(const size_t sample_count, const size_t sampling_rate); bool mute(const size_t sample_count, const size_t sampling_rate);
}; };

View File

@ -41,13 +41,17 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer) {
} }
} }
// Output to speaker too sample = audio_sample - 0x80;
uint32_t imod32 = i & (AUDIO_OUTPUT_BUFFER_SIZE - 1);
audio_data[imod32] = ((int16_t)audio_sample - 0x80) * (1.0f / 128.0f);
if (imod32 == (AUDIO_OUTPUT_BUFFER_SIZE - 1))
audio_output.write(audio_buffer);
sample = tone_gen.process(audio_sample - 0x80); // Output to speaker too
if (!tone_key_enabled) {
uint32_t imod32 = i & (AUDIO_OUTPUT_BUFFER_SIZE - 1);
audio_data[imod32] = sample * 256;
if (imod32 == (AUDIO_OUTPUT_BUFFER_SIZE - 1))
audio_output.write_unprocessed(audio_buffer);
}
sample = tone_gen.process(sample);
// FM // FM
delta = sample * fm_delta; delta = sample * fm_delta;
@ -102,7 +106,9 @@ void AudioTXProcessor::audio_config(const AudioTXConfigMessage& message) {
progress_interval_samples = message.divider; progress_interval_samples = message.divider;
resample_acc = 0; resample_acc = 0;
audio_output.configure(false); audio_output.configure(false);
audio::dma::shrink_tx_buffer();
tone_key_enabled = (message.tone_key_delta != 0);
audio::dma::shrink_tx_buffer(!tone_key_enabled);
} }
void AudioTXProcessor::replay_config(const ReplayConfigMessage& message) { void AudioTXProcessor::replay_config(const ReplayConfigMessage& message) {

View File

@ -52,14 +52,15 @@ class AudioTXProcessor : public BasebandProcessor {
int32_t sample{0}, delta{}; int32_t sample{0}, delta{};
int8_t re{0}, im{0}; int8_t re{0}, im{0};
float audio_data[AUDIO_OUTPUT_BUFFER_SIZE]; int16_t audio_data[AUDIO_OUTPUT_BUFFER_SIZE];
buffer_f32_t audio_buffer{audio_data, AUDIO_OUTPUT_BUFFER_SIZE, 48000}; buffer_s16_t audio_buffer{audio_data, AUDIO_OUTPUT_BUFFER_SIZE, 48000};
AudioOutput audio_output{}; AudioOutput audio_output{};
size_t progress_interval_samples = 0, progress_samples = 0; size_t progress_interval_samples = 0, progress_samples = 0;
bool configured{false}; bool configured{false};
uint32_t bytes_read{0}; uint32_t bytes_read{0};
bool tone_key_enabled{false};
void sample_rate_config(const SampleRateConfigMessage& message); void sample_rate_config(const SampleRateConfigMessage& message);
void audio_config(const AudioTXConfigMessage& message); void audio_config(const AudioTXConfigMessage& message);