diff --git a/firmware/application/apps/soundboard_app.cpp b/firmware/application/apps/soundboard_app.cpp index 56933134..5d23dff8 100644 --- a/firmware/application/apps/soundboard_app.cpp +++ b/firmware/application/apps/soundboard_app.cpp @@ -116,11 +116,11 @@ void SoundBoardView::start_tx(const uint32_t id) { // TODO: Delete all this and use tx model. baseband::set_audiotx_config( - 1536000 / 20, // Update vu-meter at 20Hz + TONES_SAMPLERATE / 20, // Update vu-meter at 20Hz transmitter_model.channel_bandwidth(), 0, // Gain is 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, // DSB 0, // USB @@ -132,7 +132,8 @@ void SoundBoardView::start_tx(const uint32_t id) { tx_view.set_transmitting(true); - audio::output::start(); + if (tone_key_index == 0) + audio::output::start(); } /*void SoundBoardView::show_infos() { @@ -238,6 +239,7 @@ SoundBoardView::SoundBoardView( //&text_duration, //&progressbar, &field_volume, + &text_volume_disabled, &page_info, &check_loop, &check_random, @@ -263,6 +265,13 @@ SoundBoardView::SoundBoardView( tone_keys_populate(options_tone_key); 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_random.set_value(false); diff --git a/firmware/application/apps/soundboard_app.hpp b/firmware/application/apps/soundboard_app.hpp index 88dc3c20..52b1c96f 100644 --- a/firmware/application/apps/soundboard_app.hpp +++ b/firmware/application/apps/soundboard_app.hpp @@ -128,6 +128,9 @@ class SoundBoardView : public View { AudioVolumeField field_volume{ {28 * 8, 180}}; + Text text_volume_disabled{ + {28 * 8, 180, 3 * 8, 16}, + "--"}; Checkbox check_loop{ {0, 25 * 8 + 4}, diff --git a/firmware/baseband/audio_dma.cpp b/firmware/baseband/audio_dma.cpp index df12ccfe..f493fd93 100644 --- a/firmware/baseband/audio_dma.cpp +++ b/firmware/baseband/audio_dma.cpp @@ -215,9 +215,12 @@ void disable() { gpdma_channel_i2s0_rx.disable(); } -void shrink_tx_buffer() { - single_tx_buffer = true; - lli_tx_loop[0].lli = lli_pointer(&lli_tx_loop[0]); +void shrink_tx_buffer(bool shrink) { + single_tx_buffer = shrink; + 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() { diff --git a/firmware/baseband/audio_dma.hpp b/firmware/baseband/audio_dma.hpp index 2416b6cf..8634de82 100644 --- a/firmware/baseband/audio_dma.hpp +++ b/firmware/baseband/audio_dma.hpp @@ -47,7 +47,7 @@ void init(); void configure(); void enable(); void disable(); -void shrink_tx_buffer(); +void shrink_tx_buffer(bool shrink); audio::buffer_t tx_empty_buffer(); audio::buffer_t rx_empty_buffer(); diff --git a/firmware/baseband/audio_output.cpp b/firmware/baseband/audio_output.cpp index 8a895a87..81cd2b3e 100644 --- a/firmware/baseband/audio_output.cpp +++ b/firmware/baseband/audio_output.cpp @@ -32,34 +32,34 @@ #include #include -void AudioOutput::configure( - const bool do_proc) { +void AudioOutput::configure(const bool do_proc) { do_processing = do_proc; } -void AudioOutput::configure( - const iir_biquad_config_t& hpf_config, - const iir_biquad_config_t& deemph_config, - const float squelch_threshold) { +void AudioOutput::configure(const iir_biquad_config_t& hpf_config, const iir_biquad_config_t& deemph_config, const float squelch_threshold) { hpf.configure(hpf_config); deemph.configure(deemph_config); squelch.set_threshold(squelch_threshold); } -void AudioOutput::write( - const buffer_s16_t& audio) { +void AudioOutput::write_unprocessed(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 audio_f; for (size_t i = 0; i < audio.count; i++) { audio_f[i] = audio.p[i] * ki; } - write(buffer_f32_t{ - audio_f.data(), - audio.count, - audio.sampling_rate}); + write(buffer_f32_t{audio_f.data(), audio.count, audio.sampling_rate}); } -void AudioOutput::write( - const buffer_f32_t& audio) { +void AudioOutput::write(const buffer_f32_t& audio) { block_buffer.feed( audio, [this](const buffer_f32_t& buffer) { @@ -67,8 +67,7 @@ void AudioOutput::write( }); } -void AudioOutput::on_block( - const buffer_f32_t& audio) { +void AudioOutput::on_block(const buffer_f32_t& audio) { if (do_processing) { const auto audio_present_now = squelch.execute(audio); @@ -93,6 +92,18 @@ bool AudioOutput::is_squelched() { 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) { std::array audio_int; @@ -110,6 +121,15 @@ void AudioOutput::fill_audio_buffer(const buffer_f32_t& audio, const bool send_t 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) { audio_stats.feed( audio, diff --git a/firmware/baseband/audio_output.hpp b/firmware/baseband/audio_output.hpp index 84104920..1b00a016 100644 --- a/firmware/baseband/audio_output.hpp +++ b/firmware/baseband/audio_output.hpp @@ -44,6 +44,7 @@ class AudioOutput { const iir_biquad_config_t& deemph_config = iir_config_passthrough, 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_f32_t& audio); @@ -57,6 +58,7 @@ class AudioOutput { static constexpr float k = 32768.0f; static constexpr float ki = 1.0f / k; + BlockDecimator block_buffer_s16{1}; BlockDecimator block_buffer{1}; IIRBiquadFilter hpf{}; @@ -73,7 +75,11 @@ class AudioOutput { bool do_processing = true; 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 feed_audio_stats(const buffer_s16_t& audio); void feed_audio_stats(const buffer_f32_t& audio); }; diff --git a/firmware/baseband/audio_stats_collector.cpp b/firmware/baseband/audio_stats_collector.cpp index 5ed98391..4a5af3a2 100644 --- a/firmware/baseband/audio_stats_collector.cpp +++ b/firmware/baseband/audio_stats_collector.cpp @@ -23,6 +23,19 @@ #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) { auto src_p = src.p; 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) { consume_audio_buffer(src); diff --git a/firmware/baseband/audio_stats_collector.hpp b/firmware/baseband/audio_stats_collector.hpp index 527323d3..3a46b6b6 100644 --- a/firmware/baseband/audio_stats_collector.hpp +++ b/firmware/baseband/audio_stats_collector.hpp @@ -30,6 +30,13 @@ class AudioStatsCollector { public: + template + void feed(const buffer_s16_t& src, Callback callback) { + if (feed(src)) { + callback(statistics); + } + } + template void feed(const buffer_f32_t& src, Callback callback) { if (feed(src)) { @@ -52,10 +59,12 @@ class AudioStatsCollector { AudioStatistics statistics{}; + void consume_audio_buffer(const buffer_s16_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 feed(const buffer_s16_t& src); bool feed(const buffer_f32_t& src); bool mute(const size_t sample_count, const size_t sampling_rate); }; diff --git a/firmware/baseband/proc_audiotx.cpp b/firmware/baseband/proc_audiotx.cpp index 0965aef7..4e84977a 100644 --- a/firmware/baseband/proc_audiotx.cpp +++ b/firmware/baseband/proc_audiotx.cpp @@ -41,13 +41,17 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer) { } } - // Output to speaker too - 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 = audio_sample - 0x80; - 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 delta = sample * fm_delta; @@ -102,7 +106,9 @@ void AudioTXProcessor::audio_config(const AudioTXConfigMessage& message) { progress_interval_samples = message.divider; resample_acc = 0; 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) { diff --git a/firmware/baseband/proc_audiotx.hpp b/firmware/baseband/proc_audiotx.hpp index d11be3cb..0791cd41 100644 --- a/firmware/baseband/proc_audiotx.hpp +++ b/firmware/baseband/proc_audiotx.hpp @@ -52,14 +52,15 @@ class AudioTXProcessor : public BasebandProcessor { int32_t sample{0}, delta{}; int8_t re{0}, im{0}; - float audio_data[AUDIO_OUTPUT_BUFFER_SIZE]; - buffer_f32_t audio_buffer{audio_data, AUDIO_OUTPUT_BUFFER_SIZE, 48000}; + int16_t audio_data[AUDIO_OUTPUT_BUFFER_SIZE]; + buffer_s16_t audio_buffer{audio_data, AUDIO_OUTPUT_BUFFER_SIZE, 48000}; AudioOutput audio_output{}; size_t progress_interval_samples = 0, progress_samples = 0; bool configured{false}; uint32_t bytes_read{0}; + bool tone_key_enabled{false}; void sample_rate_config(const SampleRateConfigMessage& message); void audio_config(const AudioTXConfigMessage& message);