diff --git a/README.md b/README.md index 01a382f..c9d34e1 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ platformio run -t upload && platformio device monitor -b 115200 * internal DAC? * Add-ons? * dynamic keypad thresholds +* wav file headers +* stack size in play task ## References diff --git a/src/datasource.h b/src/datasource.h new file mode 100644 index 0000000..d2698e6 --- /dev/null +++ b/src/datasource.h @@ -0,0 +1,16 @@ +#ifndef _DATASOURCE_H +#define _DATASOURCE_H + +class DataSource { + protected: + public: + static void open(const char *uri); + static size_t read(); + static void close(); + static bool available(); + static unsigned char *buffer; + static unsigned int buf_pos; + private: +}; + +#endif /* _DATASOURCE_H */ diff --git a/src/main.cpp b/src/main.cpp index fe01ebd..c0c21b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,7 +11,6 @@ #include "keyboard.h" #include "sdcard.h" #include "sound.h" -#include "ringbuf.h" #define VERSION "0.0" @@ -21,66 +20,14 @@ Keyboard keyboard; SDCard sdcard; Sound sound; -Ringbuf ringbuf = Ringbuf((size_t) BUF_LENGTH); -TaskHandle_t xTaskRead = NULL; -TaskHandle_t xTaskWrite = NULL; +TaskHandle_t xTaskSound = NULL; bool playing = false; static const char *soundFile[3][3] = {{"/T0.wav", "/T1.wav", "/T2.wav"}, {"/T3.wav", "/T4.wav", "/T5.wav"}, {"/T6.wav", "/T7.wav", "/T8.wav"}}; -void i2s_write_task(void *pvParameter) { - sound.play(); - for ( ;; ) { - //TickType_t delay = 10 / portTICK_PERIOD_MS; // max delay: 10ms instead of portMAX_DELAY - uint16_t *start_ptr = ringbuf.getRead(); - size_t size_avail = ringbuf.getReadAvail(); - int num_samples = 0; - for (int i=0; i 0) { - num_samples = sdcard.read(start_ptr, size_avail); - ringbuf.setWrite(num_samples); - } - Serial.print(num_samples,DEC); - Serial.println(" read samples from sdcard"); - - if (!sdcard.available()) break; // EOF - vTaskDelay(20 / portTICK_PERIOD_MS); // 20ms - } - ringbuf.active = false; - Serial.println("sdcard: EOF"); - sdcard.close(); - vTaskDelete( NULL ); -} - - - void setup() { // initialize LED digital pin as an output. @@ -98,7 +45,7 @@ void setup() static const char *bootSound = "/boot.wav"; - xTaskCreate(&sd_read_task, "read_task", 2048, (void*)bootSound, 5, &xTaskRead); + xTaskCreate(&(Sound::buffer_refill_task), "buffer_refill_task", 4096, (void*)bootSound, 5, &xTaskSound); } void loop() @@ -110,7 +57,7 @@ void loop() Serial.println("touch"); if (sound.playing == false) { Serial.println("new task"); - xTaskCreate(&sd_read_task, "read_task", 2048, (void*)soundFile[i/3][i%3], 5, &xTaskRead); + xTaskCreate(&(Sound::buffer_refill_task), "buffer_refill_task", 4096, (void*)soundFile[i/3][i%3], 5, &xTaskSound); } } } diff --git a/src/ringbuf.cpp b/src/ringbuf.cpp deleted file mode 100644 index ffdf321..0000000 --- a/src/ringbuf.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "Arduino.h" - -#include "ringbuf.h" - -using namespace std; - -Ringbuf::Ringbuf(size_t buf_length) { - this->buf = (uint16_t *)malloc(buf_length); - Serial.print("Allocated buffer at: "); - Serial.println((int)this->buf,HEX); - this->buf_length = buf_length; - this->read_pos = 0; - this->write_pos = 0; - this->full = false; - this->active = false; -} - -Ringbuf::~Ringbuf() { - free(this->buf); -} - -uint16_t *Ringbuf::getWrite() { - return this->buf + write_pos; -} - -size_t Ringbuf::getWriteAvail() { - if (full) return 0; // full - else if (read_pos<=write_pos) return buf_length - write_pos; // to the end - else return read_pos - write_pos; // between -} - -uint16_t *Ringbuf::getRead() { - return this->buf + read_pos; -} - -size_t Ringbuf::getReadAvail() { - if (read_pos==write_pos && !full) return 0; // empty - else if (read_pos>=write_pos) return buf_length - read_pos; // read til end - else return write_pos - read_pos; -} - -void Ringbuf::setWrite(size_t bytes){ - write_pos = (write_pos+bytes)%buf_length; - if(read_pos==write_pos) full = true; -} - -void Ringbuf::setRead(size_t bytes){ - read_pos = (read_pos+bytes)%buf_length; - if(read_pos==write_pos) full = false; -} diff --git a/src/ringbuf.h b/src/ringbuf.h deleted file mode 100644 index 4409376..0000000 --- a/src/ringbuf.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _RINGBUF_H -#define _RINGBUF_H - - -class Ringbuf { - public: - Ringbuf(size_t buf_length); - ~Ringbuf(); - uint16_t *buf; - unsigned int buf_length; - unsigned int read_pos; - unsigned int write_pos; - uint16_t *getWrite(); - size_t getWriteAvail(); - uint16_t *getRead(); - size_t getReadAvail(); - void setWrite(size_t bytes); - void setRead(size_t bytes); - bool full; - bool active = false; - private: -}; - -#endif /* _RINGBUF_H */ diff --git a/src/sdcard.cpp b/src/sdcard.cpp index 8b2f6ea..6672e93 100644 --- a/src/sdcard.cpp +++ b/src/sdcard.cpp @@ -13,11 +13,16 @@ #include "hardware.h" #include "sdcard.h" #include "sound.h" +#include "datasource.h" using namespace std; static const char* TAG = "SDCard"; +unsigned char *DataSource::buffer = NULL; +unsigned int DataSource::buf_pos = 0; +File SDCard::file; + SDCard::SDCard() { } @@ -57,21 +62,24 @@ void SDCard::umount() { } void SDCard::open(const char *path) { - file = fs.open(path); - if(!file){ + DataSource::buffer = (unsigned char *)malloc(BUF_LENGTH); + Serial.print("Allocated buffer at: "); Serial.println((int)(DataSource::buffer),HEX); + SDCard::file = (SDCard::fs).open(path); + if(!SDCard::file){ Serial.println("Failed to open file for reading"); return; } } void SDCard::close() { - file.close(); + free(DataSource::buffer); + SDCard::file.close(); } bool SDCard::available() { - return file.available(); + return SDCard::file.available(); } -size_t SDCard::read(uint16_t *buffer, size_t len){ - return file.read((uint8_t *)buffer, len*sizeof(uint16_t))/sizeof(uint16_t); +size_t SDCard::read(){ + return SDCard::file.read((uint8_t *)DataSource::buffer, BUF_LENGTH); } diff --git a/src/sdcard.h b/src/sdcard.h index 8a80fda..074eb46 100644 --- a/src/sdcard.h +++ b/src/sdcard.h @@ -5,21 +5,23 @@ #include "FS.h" #include "SD.h" #include "SPI.h" +#include "datasource.h" -class SDCard { +class SDCard: public DataSource { public: SDCard(); void mount(); void umount(); - void open(const char *path); - void close(); - size_t read(uint16_t *buffer, size_t len); - bool available(); + static void open(const char *path); + static void close(); + static size_t read(); + static bool available(); + static File file; + static constexpr fs::FS &fs = SD; private: - fs::FS &fs = SD; uint8_t cardType; uint64_t cardSize; - File file; + }; #endif /* _SDCARD_H */ diff --git a/src/sound.cpp b/src/sound.cpp index 0845ebb..f1efbea 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -7,6 +7,8 @@ */ #include "sound.h" +#include "datasource.h" +#include "sdcard.h" #include "Arduino.h" #include @@ -26,6 +28,8 @@ using namespace std; +bool Sound::playing = false; + Sound::Sound() { } @@ -88,6 +92,41 @@ void Sound::end() { i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver } +void Sound::buffer_refill_task(void *pvParameter) { + char *path = (char *) pvParameter; + Serial.println("sdcard: opening File"); + SDCard::open(path); + + Sound::play(); + while (SDCard::available()) { + // get chunk of data + SDCard::read(); // overwrite buffer + DataSource::buf_pos = 0; + + while (DataSource::buf_pos < BUF_LENGTH) { + uint16_t *buf = (uint16_t *) DataSource::buffer; + int buf_pos = (DataSource::buf_pos)/4; + // convert data + //unsigned int sample = ((unsigned short) DataSource::buffer[DataSource::buf_pos] << 16 & 0xffff0000) | ((unsigned short) DataSource::buffer[DataSource::buf_pos]); + unsigned int sample = ((unsigned short) buf[buf_pos] << 16 & 0xffff0000) | ((unsigned short) DataSource::buffer[buf_pos]); + // push samples + int num_pushed_bytes = i2s_push_sample(Sound::i2s_num, (char *)&sample, 0); + if (num_pushed_bytes == 0) { + Serial.println("i2s buf filled"); + vTaskDelay(20 / portTICK_PERIOD_MS); + } + DataSource::buf_pos += num_pushed_bytes; + } + // Buffer now empty + //TickType_t delay = 10 / portTICK_PERIOD_MS; // max delay: 10ms instead of portMAX_DELAY + vTaskDelay(20 / portTICK_PERIOD_MS); + } + Serial.println("sdcard: EOF"); + SDCard::close(); + Sound::stop(); + vTaskDelete( NULL ); +} + /* callback(?) for new audio data */ int Sound::render_sample_block(uint16_t *sample_buf_left, uint16_t *sample_buf_right, int num_samples) { TickType_t delay = 10 / portTICK_PERIOD_MS; // max delay: 10ms instead of portMAX_DELAY diff --git a/src/sound.h b/src/sound.h index 108f7ad..56b2237 100644 --- a/src/sound.h +++ b/src/sound.h @@ -7,29 +7,21 @@ #include "hardware.h" -typedef struct { - int16_t buf[512]; - int len; - int index; - int playing; -} i2sbuffer_t; - class Sound { public: Sound(); void init(); void end(); - void loop(); // void close(); - void play(); + static void play(); // void pause(); - void stop(); + static void stop(); int render_sample_block(uint16_t *sample_buf_left, uint16_t *sample_buf_right, int num_samples); - const i2s_port_t i2s_num = (i2s_port_t)I2S_NUM; - bool playing; + static const i2s_port_t i2s_num = (i2s_port_t)I2S_NUM; + static bool playing; + static void buffer_refill_task(void *pvParameter); private: - i2sbuffer_t buffer; - + TaskHandle_t xTaskRefillBuffer; }; #endif /* _SOUND_H */