From 807c76346bc71c0634584c5482a3dda0e291924b Mon Sep 17 00:00:00 2001 From: Mark Thompson <129641948+NotherNgineer@users.noreply.github.com> Date: Tue, 19 Mar 2024 15:30:05 -0500 Subject: [PATCH] Improved audio beep tone (#2014) * Improved sine wave beep tone * Prevent divide-by-zero --- firmware/baseband/audio_dma.cpp | 26 ++++++++++++++++++++++++-- firmware/baseband/tone_gen.cpp | 2 ++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/audio_dma.cpp b/firmware/baseband/audio_dma.cpp index 56c70c42..990f49f7 100644 --- a/firmware/baseband/audio_dma.cpp +++ b/firmware/baseband/audio_dma.cpp @@ -239,19 +239,41 @@ void shrink_tx_buffer(bool shrink) { } void beep_start(uint32_t freq, uint32_t sample_rate, uint32_t beep_duration_ms) { - tone_gen.configure_beep(freq, sample_rate); + // Prevent divide-by-0 + if (freq == 0 || sample_rate == 0) + return; + // Fill entire buffer with sine waves + tone_gen.configure_beep(freq, sample_rate); for (size_t i = 0; i < buffer_samples; i++) buffer_tx[i].left = buffer_tx[i].right = tone_gen.process_beep(); - uint32_t beep_interrupt_count = beep_duration_ms * sample_rate / (1000 * transfer_samples); + // Try to adjust DMA transfer count to align with full sine waves for a better tone + float samples_per_sine_wave = float(sample_rate) / freq; + uint32_t sine_waves_per_buffer = buffer_samples / samples_per_sine_wave; + size_t sample_count = (sine_waves_per_buffer == 0) ? buffer_samples : sine_waves_per_buffer * samples_per_sine_wave + 0.5; + + // Use single larger transfer buffer with sample count determined above + lli_tx_loop[0].lli = lli_pointer(&lli_tx_loop[0]); + lli_tx_loop[0].control = control_tx(sample_count * sizeof(sample_t)); + + // Convert duration ms to number of buffers to send before stopping + // NB: beep_duration_ms==0 means beep continuously until stopped + uint32_t beep_interrupt_count = beep_duration_ms * sample_rate / (1000 * sample_count); if ((beep_duration_ms != 0) && (beep_interrupt_count == 0)) beep_interrupt_count = 1; beep_duration_downcounter = beep_interrupt_count; } void beep_stop() { + // Clear audio DMA buffer memset(&buffer_tx, 0, buffer_bytes); + + // Restore DMA linked list to use multiple smaller buffers + lli_tx_loop[0].control = control_tx(transfer_bytes); + if (!single_tx_buffer && (transfers_per_buffer > 1)) { + lli_tx_loop[0].lli = lli_pointer(&lli_tx_loop[1]); + } } buffer_t tx_empty_buffer() { diff --git a/firmware/baseband/tone_gen.cpp b/firmware/baseband/tone_gen.cpp index f1b7565d..efe74c66 100644 --- a/firmware/baseband/tone_gen.cpp +++ b/firmware/baseband/tone_gen.cpp @@ -27,6 +27,7 @@ // Functions for audio beep (used by Sonde RSSI) void ToneGen::configure_beep(const uint32_t freq, const uint32_t sample_rate) { f_delta_ = (float)(freq * sizeof(sine_table_i8)) / sample_rate; + f_tone_phase_ = 0.0; } int16_t ToneGen::process_beep() { @@ -44,6 +45,7 @@ int16_t ToneGen::process_beep() { void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) { delta_ = delta; + tone_phase_ = 0; tone_mix_weight_ = tone_mix_weight; input_mix_weight_ = 1.0 - tone_mix_weight; }