From 824d921fd0921fe25d4511279b266f37250febe8 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Tue, 7 Jun 2022 20:23:20 +0100 Subject: [PATCH 1/6] pico: adjust audio code to handle filling a buffer over multiple updates If we want to move audio to core1, VGA/DV don't give us much time for audio updates --- 32blit-pico/audio_i2s.cpp | 27 ++++++++++++++++++++------- 32blit-pico/audio_pwm.cpp | 27 ++++++++++++++++++++------- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/32blit-pico/audio_i2s.cpp b/32blit-pico/audio_i2s.cpp index 79bef69e2..2a88c2ce0 100644 --- a/32blit-pico/audio_i2s.cpp +++ b/32blit-pico/audio_i2s.cpp @@ -12,6 +12,8 @@ static audio_buffer_pool *audio_pool = nullptr; +static struct audio_buffer *cur_buffer = nullptr; + void init_audio() { static audio_format_t audio_format = { .sample_freq = AUDIO_SAMPLE_FREQ, @@ -54,18 +56,29 @@ void init_audio() { } void update_audio(uint32_t time) { - // audio - struct audio_buffer *buffer = take_audio_buffer(audio_pool, false); - if(buffer) { - auto samples = (int16_t *) buffer->buffer->bytes; + // attempt to get new buffer + if(!cur_buffer) { + cur_buffer = take_audio_buffer(audio_pool, false); + if(cur_buffer) + cur_buffer->sample_count = 0; + } + + if(cur_buffer) { + auto samples = ((int16_t *)cur_buffer->buffer->bytes) + cur_buffer->sample_count; - for(uint32_t i = 0; i < buffer->max_sample_count; i += 2) { + auto max_samples = cur_buffer->max_sample_count - cur_buffer->sample_count; + + for(uint32_t i = 0; i < max_samples; i += 2) { int val = (int)blit::get_audio_frame() - 0x8000; *samples++ = val; *samples++ = val; } - buffer->sample_count = buffer->max_sample_count; - give_audio_buffer(audio_pool, buffer); + cur_buffer->sample_count += max_samples; + + if(cur_buffer->sample_count == cur_buffer->max_sample_count) { + give_audio_buffer(audio_pool, cur_buffer); + cur_buffer = nullptr; + } } } diff --git a/32blit-pico/audio_pwm.cpp b/32blit-pico/audio_pwm.cpp index 76d8d12e9..ccc432f7d 100644 --- a/32blit-pico/audio_pwm.cpp +++ b/32blit-pico/audio_pwm.cpp @@ -14,6 +14,8 @@ static audio_buffer_pool *audio_pool = nullptr; +static struct audio_buffer *cur_buffer = nullptr; + void init_audio() { static audio_format_t audio_format = { .sample_freq = AUDIO_SAMPLE_FREQ, @@ -62,17 +64,28 @@ void init_audio() { } void update_audio(uint32_t time) { - // audio - struct audio_buffer *buffer = take_audio_buffer(audio_pool, false); - if(buffer) { - auto samples = (int16_t *) buffer->buffer->bytes; + // attempt to get new buffer + if(!cur_buffer) { + cur_buffer = take_audio_buffer(audio_pool, false); + if(cur_buffer) + cur_buffer->sample_count = 0; + } + + if(cur_buffer) { + auto samples = ((int16_t *)cur_buffer->buffer->bytes) + cur_buffer->sample_count; - for(uint32_t i = 0; i < buffer->max_sample_count; i++) { + auto max_samples = cur_buffer->max_sample_count - cur_buffer->sample_count; + + for(uint32_t i = 0; i < max_samples; i++) { int val = (int)blit::get_audio_frame() - 0x8000; *samples++ = val; } - buffer->sample_count = buffer->max_sample_count; - give_audio_buffer(audio_pool, buffer); + cur_buffer->sample_count += max_samples; + + if(cur_buffer->sample_count == cur_buffer->max_sample_count) { + give_audio_buffer(audio_pool, cur_buffer); + cur_buffer = nullptr; + } } } From 8aabda56e8c61d29cf53be89e0220ced98d7e7ea Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Tue, 26 Sep 2023 11:51:31 +0100 Subject: [PATCH 2/6] pico: add config to limit number of samples per update --- 32blit-pico/audio_i2s.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/32blit-pico/audio_i2s.cpp b/32blit-pico/audio_i2s.cpp index 2a88c2ce0..2440ccab1 100644 --- a/32blit-pico/audio_i2s.cpp +++ b/32blit-pico/audio_i2s.cpp @@ -68,6 +68,11 @@ void update_audio(uint32_t time) { auto max_samples = cur_buffer->max_sample_count - cur_buffer->sample_count; +#ifdef AUDIO_MAX_SAMPLE_UPDATE + if(max_samples > AUDIO_MAX_SAMPLE_UPDATE) + max_samples = AUDIO_MAX_SAMPLE_UPDATE; +#endif + for(uint32_t i = 0; i < max_samples; i += 2) { int val = (int)blit::get_audio_frame() - 0x8000; *samples++ = val; From 4dc72664473a93f087878ff8a821d61021ae187b Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Thu, 13 Jul 2023 16:26:11 +0100 Subject: [PATCH 3/6] pico: run audio on core1 if enabled --- 32blit-pico/main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/32blit-pico/main.cpp b/32blit-pico/main.cpp index 018ec44b4..6b9122dd1 100644 --- a/32blit-pico/main.cpp +++ b/32blit-pico/main.cpp @@ -109,9 +109,11 @@ void core1_main() { multicore_lockout_victim_init(); init_display_core1(); + init_audio(); while(true) { update_display_core1(); + update_audio(::now()); sleep_us(1); } } @@ -185,7 +187,9 @@ int main() { init_input(); init_fs(); init_usb(); +#if !defined(ENABLE_CORE1) init_audio(); +#endif #if defined(ENABLE_CORE1) multicore_launch_core1(core1_main); @@ -204,7 +208,9 @@ int main() { update_display(now); update_input(); int ms_to_next_update = tick(::now()); +#if !defined(ENABLE_CORE1) update_audio(now); +#endif update_led(); update_usb(); update_multiplayer(); From f487e3649487913f46e198f7e32f8ed946d436a3 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Tue, 26 Sep 2023 11:51:59 +0100 Subject: [PATCH 4/6] pico: limit samples per update for VGA board --- 32blit-pico/board/vgaboard/config.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/32blit-pico/board/vgaboard/config.h b/32blit-pico/board/vgaboard/config.h index d325fb669..fe227c49a 100644 --- a/32blit-pico/board/vgaboard/config.h +++ b/32blit-pico/board/vgaboard/config.h @@ -4,6 +4,8 @@ #define ALLOW_HIRES 0 // disable by default, mode switching isn't supported #endif +#define AUDIO_MAX_SAMPLE_UPDATE 64 + // spi #define SD_SCK 5 #define SD_MOSI 18 From d8b3c10ed6d264952e95607d489cbfd5693fece9 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Mon, 25 Sep 2023 17:30:55 +0100 Subject: [PATCH 5/6] pico: use a low priority alarm for audio when core1 is disabled --- 32blit-pico/main.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/32blit-pico/main.cpp b/32blit-pico/main.cpp index 6b9122dd1..7f1adb61b 100644 --- a/32blit-pico/main.cpp +++ b/32blit-pico/main.cpp @@ -2,6 +2,7 @@ #include "hardware/structs/rosc.h" #include "hardware/vreg.h" +#include "hardware/timer.h" #include "pico/binary_info.h" #include "pico/multicore.h" #include "pico/rand.h" @@ -104,6 +105,7 @@ void update(uint32_t); bool core1_started = false; +#ifdef ENABLE_CORE1 void core1_main() { core1_started = true; multicore_lockout_victim_init(); @@ -118,6 +120,15 @@ void core1_main() { } } +#else +static void alarm_callback(uint alarm_num) { + update_audio(::now()); + + timer_hw->intr = 1 << alarm_num; + hardware_alarm_set_target(alarm_num, make_timeout_time_ms(5)); +} +#endif + int main() { #if OVERCLOCK_250 // Apply a modest overvolt, default is 1.10v. @@ -193,6 +204,12 @@ int main() { #if defined(ENABLE_CORE1) multicore_launch_core1(core1_main); +#else + // fallback audio timer if core1 is unavailable / not enabled + int alarm_num = hardware_alarm_claim_unused(true); + hardware_alarm_set_callback(alarm_num, alarm_callback); + hardware_alarm_set_target(alarm_num, make_timeout_time_ms(5)); + irq_set_priority(TIMER_IRQ_0 + alarm_num, PICO_LOWEST_IRQ_PRIORITY); #endif blit::set_screen_mode(ScreenMode::lores); @@ -208,9 +225,6 @@ int main() { update_display(now); update_input(); int ms_to_next_update = tick(::now()); -#if !defined(ENABLE_CORE1) - update_audio(now); -#endif update_led(); update_usb(); update_multiplayer(); From 1b5d026becf538fe8f19a63160c608b47057211b Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Tue, 26 Sep 2023 12:07:56 +0100 Subject: [PATCH 6/6] pico: reduce i2s buffer size Save some RAM --- 32blit-pico/audio_i2s.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/32blit-pico/audio_i2s.cpp b/32blit-pico/audio_i2s.cpp index 2440ccab1..9a57c4804 100644 --- a/32blit-pico/audio_i2s.cpp +++ b/32blit-pico/audio_i2s.cpp @@ -26,7 +26,7 @@ void init_audio() { .sample_stride = 2 }; - struct audio_buffer_pool *producer_pool = audio_new_producer_pool(&producer_format, 4, 441); + struct audio_buffer_pool *producer_pool = audio_new_producer_pool(&producer_format, 4, 256); const struct audio_format *output_format; uint8_t dma_channel = dma_claim_unused_channel(true);