From cd49ebf186770cc3974893e7ff999ab41d59d98a Mon Sep 17 00:00:00 2001 From: radex Date: Fri, 17 May 2024 19:03:59 +0200 Subject: [PATCH] audio from sd --- firmware/platformio.ini | 2 - firmware/scripts/audio_convert.py | 7 ++++ firmware/src/audio.cpp | 42 +++++++++++++++----- firmware/src/audio.h | 18 +++++++++ firmware/src/main.cpp | 2 + firmware/src/sd.cpp | 64 ++++++++++++++++++++++++++++--- firmware/src/sd.h | 4 ++ 7 files changed, 123 insertions(+), 16 deletions(-) diff --git a/firmware/platformio.ini b/firmware/platformio.ini index aa0bbc0..864bc9d 100644 --- a/firmware/platformio.ini +++ b/firmware/platformio.ini @@ -13,7 +13,5 @@ platform = raspberrypi board = pico framework = arduino lib_deps = - fastled/FastLED@^3.6.0 - ; arduino-libraries/SD@^1.2.4 khoih-prog/RP2040_SD@^1.0.1 diff --git a/firmware/scripts/audio_convert.py b/firmware/scripts/audio_convert.py index e6d1bee..f905200 100644 --- a/firmware/scripts/audio_convert.py +++ b/firmware/scripts/audio_convert.py @@ -55,3 +55,10 @@ with open("src/audio_sample.h", "w") as f: f.write(m68code) print("done!") + +print("writing blob...") + +with open("audio/audio.bin", "wb") as f: + f.write(bytes(normalized)) + +print("done!") diff --git a/firmware/src/audio.cpp b/firmware/src/audio.cpp index a7dec04..85ecf86 100644 --- a/firmware/src/audio.cpp +++ b/firmware/src/audio.cpp @@ -3,13 +3,21 @@ #include "hardware/pwm.h" // pwm #include "hardware/sync.h" // wait for interrupt #include "hardware/gpio.h" +#include "audio.h" -#include "audio_sample.h" +// #include "audio_sample.h" // Adapted from https://github.com/rgrosset/pico-pwm-audio #define AUDIO_PIN 23 -int wav_position = 0; + +#define MAX_PWM_POS (BUFFER_LEN << 3) + +uint8_t wav_buffer_0[BUFFER_LEN] = {0}; +uint8_t wav_buffer_1[BUFFER_LEN] = {0}; +bool wav_buffer1_active = false; +volatile bool next_buffer_requested = false; // horrible, use some interrupt-based solution or at least locks or whatever +uint32_t pwm_position = 0; /* * PWM Interrupt Handler which outputs PWM level and advances the @@ -21,21 +29,23 @@ int wav_position = 0; */ void pwm_interrupt_handler() { pwm_clear_irq(pwm_gpio_to_slice_num(AUDIO_PIN)); - if (wav_position < (WAV_DATA_LENGTH<<3) - 1) { + if (pwm_position < MAX_PWM_POS - 1) { + auto wav_buffer = wav_buffer1_active ? wav_buffer_1 : wav_buffer_0; // set pwm level // allow the pwm value to repeat for 8 cycles this is >>3 - pwm_set_gpio_level(AUDIO_PIN, WAV_DATA[wav_position>>3]); - wav_position++; + pwm_set_gpio_level(AUDIO_PIN, wav_buffer[pwm_position>>3]); + pwm_position++; } else { - // reset to start - wav_position = 0; + // reset to start, flip to other buffer + pwm_position = 0; + next_buffer_requested = true; + wav_buffer1_active = !wav_buffer1_active; } } // 11 KHz is fine for speech. Phone lines generally sample at 8 KHz #define SYS_CLOCK 125000000.0f #define AUDIO_WRAP 250.0f -#define AUDIO_RATE 11000.0f #define AUDIO_CLK_DIV (SYS_CLOCK / AUDIO_WRAP / 8 / AUDIO_RATE) void init_audio() { @@ -49,7 +59,7 @@ void init_audio() { // set the handle function above irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_interrupt_handler); - irq_set_enabled(PWM_IRQ_WRAP, true); + // irq_set_enabled(PWM_IRQ_WRAP, true); // Setup PWM for audio output pwm_config config = pwm_get_default_config(); @@ -60,3 +70,17 @@ void init_audio() { pwm_set_gpio_level(AUDIO_PIN, 0); } + +void audio_stop() { + Serial.println("audio_stop"); + irq_set_enabled(PWM_IRQ_WRAP, false); + pwm_set_gpio_level(AUDIO_PIN, 0); +} + +void audio_start() { + Serial.println("audio_start"); + audio_stop(); + pwm_position = 0; + wav_buffer1_active = false; + irq_set_enabled(PWM_IRQ_WRAP, true); +} diff --git a/firmware/src/audio.h b/firmware/src/audio.h index f73f774..36d7d30 100644 --- a/firmware/src/audio.h +++ b/firmware/src/audio.h @@ -1 +1,19 @@ +#pragma once + +#ifndef _audio_h +#define _audio_h + +#define AUDIO_RATE 11000.0f +#define BUFFER_LEN 8192 +#define BUFFER_LEN_MS (BUFFER_LEN / AUDIO_RATE) * 1000.0f + +extern uint8_t wav_buffer_0[BUFFER_LEN]; +extern uint8_t wav_buffer_1[BUFFER_LEN]; +extern bool wav_buffer1_active; +extern volatile bool next_buffer_requested; + void init_audio(); +void audio_stop(); +void audio_start(); + +#endif diff --git a/firmware/src/main.cpp b/firmware/src/main.cpp index 1027c82..0db7bab 100644 --- a/firmware/src/main.cpp +++ b/firmware/src/main.cpp @@ -75,6 +75,8 @@ void setup() { setupSD(); + sd_getAudio(); + return; memset(framebuffer, 0, sizeof(framebuffer)); diff --git a/firmware/src/sd.cpp b/firmware/src/sd.cpp index 1ea8487..289efc8 100644 --- a/firmware/src/sd.cpp +++ b/firmware/src/sd.cpp @@ -1,6 +1,8 @@ #include -#include #include +#include +#include "sd.h" +#include "audio.h" #define SD_DET_PIN 28 @@ -39,22 +41,23 @@ void printDirectory(File dir, int numTabs); void setupSD() { SPI.begin(); - printSDConfig(); + // printSDConfig(); if (!SD.begin(PIN_SPI_SS)) { Serial.println("SD Initialization failed!"); // Serial.print("Error code: "); // Serial.println(SD.card.errorCode(), HEX); + while (true) {} return; } Serial.println("SD Initialization done"); - testSDCard(); + // testSDCard(); // printSDStats(SD.volume); - File root = SD.open("/"); - printDirectory(root, 0); + // File root = SD.open("/"); + // printDirectory(root, 0); } void printSDConfig() { @@ -151,3 +154,54 @@ void printSDStats(RP2040_SdVolume volume) { Serial.print("Volume size (GB): "); Serial.println((float)volumesize / 1024.0); } + +File file; + +void sd_getAudio() { + if (!SD.exists("/badapple/audio.bin")) { + Serial.println("Audio not found :("); + return; + } + + if (file) { + file.close(); + } + + file = SD.open("/badapple/audio.bin", FILE_READ); + Serial.println("Audio file opened"); + + audio_stop(); + + // load two buffers' worth of audio + if (file.read(&wav_buffer_0, BUFFER_LEN) < BUFFER_LEN) { + Serial.println("Could not read first sample"); + return; + } + + if (file.read(&wav_buffer_1, BUFFER_LEN) < BUFFER_LEN) { + Serial.println("Could not read second sample"); + return; + } + + audio_start(); + + while (true) { + if (!next_buffer_requested) { + delay(50); + continue; + } + next_buffer_requested = false; + + auto next_buffer = wav_buffer1_active ? &wav_buffer_0 : &wav_buffer_1; + auto bytesRead = file.read(next_buffer, BUFFER_LEN); + + if (bytesRead < BUFFER_LEN) { + Serial.println("End of audio file"); + file.seek(0); + } else { + Serial.print("Read "); + Serial.print(bytesRead); + Serial.println(" bytes from audio file"); + } + } +} diff --git a/firmware/src/sd.h b/firmware/src/sd.h index 888fad2..862f3eb 100644 --- a/firmware/src/sd.h +++ b/firmware/src/sd.h @@ -1,4 +1,8 @@ +#pragma once + void setupSDPins(); void setupSD(); bool isSDCardInserted(); + +void sd_getAudio();