|
|
@ -17,6 +17,7 @@ |
|
|
|
#include "driver/i2s.h" |
|
|
|
//#include <soc/i2s_reg.h>
|
|
|
|
#include <math.h> |
|
|
|
#include "freertos/semphr.h" |
|
|
|
|
|
|
|
|
|
|
|
#define SAMPLE_RATE (11025) |
|
|
@ -28,9 +29,10 @@ |
|
|
|
|
|
|
|
using namespace std; |
|
|
|
|
|
|
|
volatile bool Sound::playing = false; |
|
|
|
SemaphoreHandle_t xPlayingSemaphore = NULL; |
|
|
|
|
|
|
|
Sound::Sound() { |
|
|
|
xPlayingSemaphore = xSemaphoreCreateMutex(); |
|
|
|
} |
|
|
|
|
|
|
|
void Sound::init() { |
|
|
@ -78,60 +80,67 @@ void Sound::init() { |
|
|
|
i2s_push_sample(i2s_num, (char *)&sample_val, portMAX_DELAY); |
|
|
|
} |
|
|
|
|
|
|
|
stop(); |
|
|
|
i2s_stop(i2s_num); |
|
|
|
} |
|
|
|
|
|
|
|
void Sound::play() { |
|
|
|
Serial.println("Sound::play()"); |
|
|
|
i2s_start(i2s_num); |
|
|
|
Sound::playing = true; |
|
|
|
} |
|
|
|
|
|
|
|
void Sound::stop() { |
|
|
|
Serial.println("Sound::stop()"); |
|
|
|
i2s_stop(i2s_num); |
|
|
|
Sound::playing = false; |
|
|
|
} |
|
|
|
|
|
|
|
void Sound::end() { |
|
|
|
i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
|
|
|
|
} |
|
|
|
|
|
|
|
void Sound::buffer_refill_task(void *pvParameter) { |
|
|
|
void Sound::play_task(void *pvParameter) { |
|
|
|
// Serial.print("initial free stack: "); Serial.println(uxTaskGetStackHighWaterMark( NULL ), DEC); // DEBUG
|
|
|
|
char *path = (char *) pvParameter; |
|
|
|
Serial.println("sdcard: opening File"); |
|
|
|
SDCard::open(path); |
|
|
|
Serial.println("sound task: playing"); |
|
|
|
if ( xPlayingSemaphore == NULL || xSemaphoreTake( xPlayingSemaphore, (TickType_t) 10) != pdTRUE ) { |
|
|
|
Serial.println("Sound task: could not obtain semaphore"); |
|
|
|
vTaskDelete( NULL ); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
Sound::play(); |
|
|
|
while (SDCard::available()) { |
|
|
|
File file = SDCard::open(path); |
|
|
|
if (!file) { |
|
|
|
Serial.print("Failed to open file: "); Serial.println(path); |
|
|
|
vTaskDelete( NULL ); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
unsigned char* buf = new unsigned char[BUF_LENGTH]; |
|
|
|
unsigned int buf_pos; |
|
|
|
Serial.print("Allocated buffer at: "); Serial.println((int)buf,HEX); |
|
|
|
|
|
|
|
i2s_start(i2s_num); |
|
|
|
|
|
|
|
while (SDCard::available(file)) { |
|
|
|
// Serial.print("chunk free stack: "); Serial.println(uxTaskGetStackHighWaterMark( NULL ), DEC); // DEBUG
|
|
|
|
// get chunk of data
|
|
|
|
SDCard::read(); // overwrite buffer
|
|
|
|
DataSource::buf_pos = 0; |
|
|
|
SDCard::read(file, buf, BUF_LENGTH); // overwrite buffer
|
|
|
|
buf_pos = 0; |
|
|
|
|
|
|
|
while (DataSource::buf_pos < BUF_LENGTH) { |
|
|
|
while (buf_pos < BUF_LENGTH) { |
|
|
|
// Serial.print("i2s_push free stack: "); Serial.println(uxTaskGetStackHighWaterMark( NULL ), DEC); // DEBUG
|
|
|
|
uint16_t *buf = (uint16_t *) DataSource::buffer; |
|
|
|
int buf_pos = (DataSource::buf_pos)/4; |
|
|
|
uint16_t *buf16 = (uint16_t *) buf; |
|
|
|
int buf16_pos = buf_pos/4; // ToDo: why not 2?
|
|
|
|
// 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) buf[buf_pos]); |
|
|
|
unsigned int sample = ((unsigned short) buf16[buf16_pos] << 16 & 0xffff0000) | ((unsigned short) buf16[buf16_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; |
|
|
|
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(); |
|
|
|
SDCard::close(file); |
|
|
|
i2s_stop(i2s_num); |
|
|
|
delete[] buf; |
|
|
|
xSemaphoreGive( xPlayingSemaphore ); |
|
|
|
Serial.println("task exiting"); |
|
|
|
vTaskDelete( NULL ); |
|
|
|
} |
|
|
|