diff --git a/32blit-pico/audio_i2s.cpp b/32blit-pico/audio_i2s.cpp index 79bef69e2..9a57c4804 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, @@ -24,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); @@ -54,18 +56,34 @@ 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; + + auto max_samples = cur_buffer->max_sample_count - cur_buffer->sample_count; - for(uint32_t i = 0; i < buffer->max_sample_count; i += 2) { +#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; *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; + } } } 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 diff --git a/32blit-pico/main.cpp b/32blit-pico/main.cpp index 018ec44b4..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,18 +105,30 @@ void update(uint32_t); bool core1_started = false; +#ifdef ENABLE_CORE1 void core1_main() { core1_started = true; multicore_lockout_victim_init(); init_display_core1(); + init_audio(); while(true) { update_display_core1(); + update_audio(::now()); sleep_us(1); } } +#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. @@ -185,10 +198,18 @@ int main() { init_input(); init_fs(); init_usb(); +#if !defined(ENABLE_CORE1) init_audio(); +#endif #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); @@ -204,7 +225,6 @@ int main() { update_display(now); update_input(); int ms_to_next_update = tick(::now()); - update_audio(now); update_led(); update_usb(); update_multiplayer();