mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-07-26 00:06:00 -04:00
Added Audio Out to Soundboard app (#1748)
This commit is contained in:
parent
0e6f303eec
commit
485f57d86b
6 changed files with 38 additions and 7 deletions
|
@ -26,6 +26,7 @@
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
#include "tonesets.hpp"
|
#include "tonesets.hpp"
|
||||||
#include "ui_tone_key.hpp"
|
#include "ui_tone_key.hpp"
|
||||||
|
#include "audio.hpp"
|
||||||
|
|
||||||
using namespace tonekey;
|
using namespace tonekey;
|
||||||
using namespace portapack;
|
using namespace portapack;
|
||||||
|
@ -40,6 +41,7 @@ void SoundBoardView::stop() {
|
||||||
if (is_active())
|
if (is_active())
|
||||||
replay_thread.reset();
|
replay_thread.reset();
|
||||||
|
|
||||||
|
audio::output::stop();
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
tx_view.set_transmitting(false);
|
tx_view.set_transmitting(false);
|
||||||
|
|
||||||
|
@ -123,6 +125,8 @@ void SoundBoardView::start_tx(const uint32_t id) {
|
||||||
transmitter_model.enable();
|
transmitter_model.enable();
|
||||||
|
|
||||||
tx_view.set_transmitting(true);
|
tx_view.set_transmitting(true);
|
||||||
|
|
||||||
|
audio::output::start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void SoundBoardView::show_infos() {
|
/*void SoundBoardView::show_infos() {
|
||||||
|
@ -227,6 +231,7 @@ SoundBoardView::SoundBoardView(
|
||||||
//&text_title,
|
//&text_title,
|
||||||
//&text_duration,
|
//&text_duration,
|
||||||
//&progressbar,
|
//&progressbar,
|
||||||
|
&field_volume,
|
||||||
&page_info,
|
&page_info,
|
||||||
&check_loop,
|
&check_loop,
|
||||||
&check_random,
|
&check_random,
|
||||||
|
@ -274,7 +279,6 @@ SoundBoardView::SoundBoardView(
|
||||||
|
|
||||||
SoundBoardView::~SoundBoardView() {
|
SoundBoardView::~SoundBoardView() {
|
||||||
stop();
|
stop();
|
||||||
transmitter_model.disable();
|
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ class SoundBoardView : public View {
|
||||||
void on_select_entry();
|
void on_select_entry();
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
//{ { 0, 20 * 8 + 4 }, "Title:", Color::light_grey() },
|
{{24 * 8, 180}, "Vol:", Color::light_grey()},
|
||||||
{{0, 180}, "Key:", Color::light_grey()}};
|
{{0, 180}, "Key:", Color::light_grey()}};
|
||||||
|
|
||||||
Button button_next_page{
|
Button button_next_page{
|
||||||
|
@ -122,10 +122,13 @@ class SoundBoardView : public View {
|
||||||
};*/
|
};*/
|
||||||
|
|
||||||
OptionsField options_tone_key{
|
OptionsField options_tone_key{
|
||||||
{32, 180},
|
{4 * 8, 180},
|
||||||
18,
|
18,
|
||||||
{}};
|
{}};
|
||||||
|
|
||||||
|
AudioVolumeField field_volume{
|
||||||
|
{28 * 8, 180}};
|
||||||
|
|
||||||
Checkbox check_loop{
|
Checkbox check_loop{
|
||||||
{0, 25 * 8 + 4},
|
{0, 25 * 8 + 4},
|
||||||
4,
|
4,
|
||||||
|
|
|
@ -123,10 +123,10 @@ constexpr gpdma::channel::Config config_rx() {
|
||||||
/* TODO: Clean up terminology around "buffer", "transfer", "samples" */
|
/* TODO: Clean up terminology around "buffer", "transfer", "samples" */
|
||||||
|
|
||||||
constexpr size_t buffer_samples_log2n = 7;
|
constexpr size_t buffer_samples_log2n = 7;
|
||||||
constexpr size_t buffer_samples = (1 << buffer_samples_log2n);
|
constexpr size_t buffer_samples = (1 << buffer_samples_log2n); // 2^7 = 128 byte circular DMA buffer
|
||||||
constexpr size_t transfers_per_buffer_log2n = 2;
|
constexpr size_t transfers_per_buffer_log2n = 2;
|
||||||
constexpr size_t transfers_per_buffer = (1 << transfers_per_buffer_log2n);
|
constexpr size_t transfers_per_buffer = (1 << transfers_per_buffer_log2n); // 2^2 = 4 transfer buffers in the circular buffer
|
||||||
constexpr size_t transfer_samples = buffer_samples / transfers_per_buffer;
|
constexpr size_t transfer_samples = buffer_samples / transfers_per_buffer; // 128/4 = 32 samples in each transfer buffer
|
||||||
constexpr size_t transfers_mask = transfers_per_buffer - 1;
|
constexpr size_t transfers_mask = transfers_per_buffer - 1;
|
||||||
|
|
||||||
constexpr size_t buffer_bytes = buffer_samples * sizeof(sample_t);
|
constexpr size_t buffer_bytes = buffer_samples * sizeof(sample_t);
|
||||||
|
@ -144,6 +144,8 @@ static constexpr auto& gpdma_channel_i2s0_rx = gpdma::channels[portapack::i2s0_r
|
||||||
static volatile const gpdma::channel::LLI* tx_next_lli = nullptr;
|
static volatile const gpdma::channel::LLI* tx_next_lli = nullptr;
|
||||||
static volatile const gpdma::channel::LLI* rx_next_lli = nullptr;
|
static volatile const gpdma::channel::LLI* rx_next_lli = nullptr;
|
||||||
|
|
||||||
|
static bool single_tx_buffer = false;
|
||||||
|
|
||||||
static void tx_transfer_complete() {
|
static void tx_transfer_complete() {
|
||||||
tx_next_lli = gpdma_channel_i2s0_tx.next_lli();
|
tx_next_lli = gpdma_channel_i2s0_tx.next_lli();
|
||||||
}
|
}
|
||||||
|
@ -213,11 +215,16 @@ void disable() {
|
||||||
gpdma_channel_i2s0_rx.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]);
|
||||||
|
}
|
||||||
|
|
||||||
buffer_t tx_empty_buffer() {
|
buffer_t tx_empty_buffer() {
|
||||||
const auto next_lli = tx_next_lli;
|
const auto next_lli = tx_next_lli;
|
||||||
if (next_lli) {
|
if (next_lli) {
|
||||||
const size_t next_index = next_lli - &lli_tx_loop[0];
|
const size_t next_index = next_lli - &lli_tx_loop[0];
|
||||||
const size_t free_index = (next_index + transfers_per_buffer - 2) & transfers_mask;
|
const size_t free_index = (single_tx_buffer) ? 0 : (next_index + transfers_per_buffer - 2) & transfers_mask;
|
||||||
return {reinterpret_cast<sample_t*>(lli_tx_loop[free_index].srcaddr), transfer_samples};
|
return {reinterpret_cast<sample_t*>(lli_tx_loop[free_index].srcaddr), transfer_samples};
|
||||||
} else {
|
} else {
|
||||||
return {nullptr, 0};
|
return {nullptr, 0};
|
||||||
|
|
|
@ -47,6 +47,7 @@ void init();
|
||||||
void configure();
|
void configure();
|
||||||
void enable();
|
void enable();
|
||||||
void disable();
|
void disable();
|
||||||
|
void shrink_tx_buffer();
|
||||||
|
|
||||||
audio::buffer_t tx_empty_buffer();
|
audio::buffer_t tx_empty_buffer();
|
||||||
audio::buffer_t rx_empty_buffer();
|
audio::buffer_t rx_empty_buffer();
|
||||||
|
|
|
@ -41,6 +41,12 @@ 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 = tone_gen.process(audio_sample - 0x80);
|
sample = tone_gen.process(audio_sample - 0x80);
|
||||||
|
|
||||||
// FM
|
// FM
|
||||||
|
@ -95,6 +101,8 @@ void AudioTXProcessor::audio_config(const AudioTXConfigMessage& message) {
|
||||||
tone_gen.configure(message.tone_key_delta, message.tone_key_mix_weight);
|
tone_gen.configure(message.tone_key_delta, message.tone_key_mix_weight);
|
||||||
progress_interval_samples = message.divider;
|
progress_interval_samples = message.divider;
|
||||||
resample_acc = 0;
|
resample_acc = 0;
|
||||||
|
audio_output.configure(false);
|
||||||
|
audio::dma::shrink_tx_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioTXProcessor::replay_config(const ReplayConfigMessage& message) {
|
void AudioTXProcessor::replay_config(const ReplayConfigMessage& message) {
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
#include "baseband_thread.hpp"
|
#include "baseband_thread.hpp"
|
||||||
#include "tone_gen.hpp"
|
#include "tone_gen.hpp"
|
||||||
#include "stream_output.hpp"
|
#include "stream_output.hpp"
|
||||||
|
#include "audio_output.hpp"
|
||||||
|
#include "audio_dma.hpp"
|
||||||
|
|
||||||
|
#define AUDIO_OUTPUT_BUFFER_SIZE 32
|
||||||
|
|
||||||
class AudioTXProcessor : public BasebandProcessor {
|
class AudioTXProcessor : public BasebandProcessor {
|
||||||
public:
|
public:
|
||||||
|
@ -48,6 +52,10 @@ 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];
|
||||||
|
buffer_f32_t audio_buffer{audio_data, AUDIO_OUTPUT_BUFFER_SIZE, 48000};
|
||||||
|
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};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue