mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-24 23:09:26 -05:00
Resolve Soundboard tone key issue (#1806)
* Resolve Soundboard tone key issue
This commit is contained in:
parent
03b13f8ab0
commit
2d98c5d311
@ -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);
|
||||||
|
|
||||||
|
@ -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},
|
||||||
|
@ -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() {
|
||||||
|
@ -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();
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user