1
0
Fork 0

audio from sd

sd2
radex 2024-05-17 19:03:59 +02:00
parent 111700b0e9
commit cd49ebf186
Signed by: radex
SSH Key Fingerprint: SHA256:hvqRXAGG1h89yqnS+cyFTLKQbzjWD4uXIqw7Y+0ws30
7 changed files with 123 additions and 16 deletions

View File

@ -13,7 +13,5 @@ platform = raspberrypi
board = pico board = pico
framework = arduino framework = arduino
lib_deps = lib_deps =
fastled/FastLED@^3.6.0
; arduino-libraries/SD@^1.2.4
khoih-prog/RP2040_SD@^1.0.1 khoih-prog/RP2040_SD@^1.0.1

View File

@ -55,3 +55,10 @@ with open("src/audio_sample.h", "w") as f:
f.write(m68code) f.write(m68code)
print("done!") print("done!")
print("writing blob...")
with open("audio/audio.bin", "wb") as f:
f.write(bytes(normalized))
print("done!")

View File

@ -3,13 +3,21 @@
#include "hardware/pwm.h" // pwm #include "hardware/pwm.h" // pwm
#include "hardware/sync.h" // wait for interrupt #include "hardware/sync.h" // wait for interrupt
#include "hardware/gpio.h" #include "hardware/gpio.h"
#include "audio.h"
#include "audio_sample.h" // #include "audio_sample.h"
// Adapted from https://github.com/rgrosset/pico-pwm-audio // Adapted from https://github.com/rgrosset/pico-pwm-audio
#define AUDIO_PIN 23 #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 * PWM Interrupt Handler which outputs PWM level and advances the
@ -21,21 +29,23 @@ int wav_position = 0;
*/ */
void pwm_interrupt_handler() { void pwm_interrupt_handler() {
pwm_clear_irq(pwm_gpio_to_slice_num(AUDIO_PIN)); 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 // set pwm level
// allow the pwm value to repeat for 8 cycles this is >>3 // allow the pwm value to repeat for 8 cycles this is >>3
pwm_set_gpio_level(AUDIO_PIN, WAV_DATA[wav_position>>3]); pwm_set_gpio_level(AUDIO_PIN, wav_buffer[pwm_position>>3]);
wav_position++; pwm_position++;
} else { } else {
// reset to start // reset to start, flip to other buffer
wav_position = 0; 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 // 11 KHz is fine for speech. Phone lines generally sample at 8 KHz
#define SYS_CLOCK 125000000.0f #define SYS_CLOCK 125000000.0f
#define AUDIO_WRAP 250.0f #define AUDIO_WRAP 250.0f
#define AUDIO_RATE 11000.0f
#define AUDIO_CLK_DIV (SYS_CLOCK / AUDIO_WRAP / 8 / AUDIO_RATE) #define AUDIO_CLK_DIV (SYS_CLOCK / AUDIO_WRAP / 8 / AUDIO_RATE)
void init_audio() { void init_audio() {
@ -49,7 +59,7 @@ void init_audio() {
// set the handle function above // set the handle function above
irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_interrupt_handler); 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 // Setup PWM for audio output
pwm_config config = pwm_get_default_config(); pwm_config config = pwm_get_default_config();
@ -60,3 +70,17 @@ void init_audio() {
pwm_set_gpio_level(AUDIO_PIN, 0); 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);
}

View File

@ -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 init_audio();
void audio_stop();
void audio_start();
#endif

View File

@ -75,6 +75,8 @@ void setup() {
setupSD(); setupSD();
sd_getAudio();
return; return;
memset(framebuffer, 0, sizeof(framebuffer)); memset(framebuffer, 0, sizeof(framebuffer));

View File

@ -1,6 +1,8 @@
#include <Arduino.h> #include <Arduino.h>
#include <RP2040_SD.h>
#include <SPI.h> #include <SPI.h>
#include <RP2040_SD.h>
#include "sd.h"
#include "audio.h"
#define SD_DET_PIN 28 #define SD_DET_PIN 28
@ -39,22 +41,23 @@ void printDirectory(File dir, int numTabs);
void setupSD() { void setupSD() {
SPI.begin(); SPI.begin();
printSDConfig(); // printSDConfig();
if (!SD.begin(PIN_SPI_SS)) { if (!SD.begin(PIN_SPI_SS)) {
Serial.println("SD Initialization failed!"); Serial.println("SD Initialization failed!");
// Serial.print("Error code: "); // Serial.print("Error code: ");
// Serial.println(SD.card.errorCode(), HEX); // Serial.println(SD.card.errorCode(), HEX);
while (true) {}
return; return;
} }
Serial.println("SD Initialization done"); Serial.println("SD Initialization done");
testSDCard(); // testSDCard();
// printSDStats(SD.volume); // printSDStats(SD.volume);
File root = SD.open("/"); // File root = SD.open("/");
printDirectory(root, 0); // printDirectory(root, 0);
} }
void printSDConfig() { void printSDConfig() {
@ -151,3 +154,54 @@ void printSDStats(RP2040_SdVolume volume) {
Serial.print("Volume size (GB): "); Serial.print("Volume size (GB): ");
Serial.println((float)volumesize / 1024.0); 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");
}
}
}

View File

@ -1,4 +1,8 @@
#pragma once
void setupSDPins(); void setupSDPins();
void setupSD(); void setupSD();
bool isSDCardInserted(); bool isSDCardInserted();
void sd_getAudio();