Skip to content

Commit

Permalink
Stream i2s without hiccups I think
Browse files Browse the repository at this point in the history
  • Loading branch information
bridadan committed Jun 18, 2020
1 parent 363784e commit b37929f
Showing 1 changed file with 68 additions and 40 deletions.
108 changes: 68 additions & 40 deletions main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

#define SAMPLE_RATE (44100)
#define I2S_NUM (0)
#define WAVE_FREQ_HZ (100)
#define PI (3.14159265)
#define I2S_BCK_IO (GPIO_NUM_14)
#define I2S_WS_IO (GPIO_NUM_25)
#define I2S_DO_IO (GPIO_NUM_26)
Expand All @@ -19,6 +17,7 @@
#define DMA_BUF_SIZE_MS 5
#define DMA_BUF_SIZE_BYTES (SAMPLE_RATE * SIZE_OF_SAMPLE * NUM_CHANNELS * DMA_BUF_SIZE_MS) / 1000
#define DMA_BUF_NUMBER 5
#define MAX_FRAMES_TO_READ ((DMA_BUF_SIZE_BYTES / NUM_CHANNELS) / SIZE_OF_SAMPLE)

#define DR_FLAC_NO_STDIO
#define DR_FLAC_NO_OGG
Expand All @@ -28,7 +27,8 @@



static xQueueHandle i2s_evt_queue = NULL;
static xQueueHandle i2s_event_queue = NULL;
static xQueueHandle control_event_queue = NULL;

extern const uint8_t flac_file_start[] asm("_binary_flac_sample_small_flac_start");
extern const uint8_t flac_file_end[] asm("_binary_flac_sample_small_flac_end");
Expand All @@ -51,14 +51,15 @@ void init_i2s() {
.data_out_num = I2S_DO_IO,
.data_in_num = I2S_PIN_NO_CHANGE,
};
i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
i2s_driver_install(I2S_NUM, &i2s_config, 10, &i2s_event_queue);
i2s_set_pin(I2S_NUM, &pin_config);
}

static unsigned int flac_file_index;
static unsigned int flac_file_size;
static drflac *pFlac;
static drflac_int16 i2s_buf[DMA_BUF_SIZE_BYTES];
static uint32_t i2s_buf_start, i2s_buf_end;

size_t onRead(void *pUserData, void *pBufferOut, size_t bytesToRead) {
size_t bytes_written = 0;
Expand Down Expand Up @@ -104,43 +105,44 @@ uint32_t min(uint32_t a, uint32_t b) {
return a <= b ? a : b;
}

void write_all_to_i2s(drflac_uint64 frames_read) {
uint32_t bytes_read = frames_read * NUM_CHANNELS * SIZE_OF_SAMPLE;
//printf("writing %u/%u\n", bytes_read,DMA_BUF_SIZE_BYTES);
size_t total_bytes_written = 0;
size_t bytes_written = 0;
while (total_bytes_written < bytes_read) {
void fill_i2s_buffer() {
drflac_uint64 frames_read;
size_t bytes_written = 1;

if (flac_file_index == flac_file_size) {
i2s_stop(I2S_NUM);
return;
}

while (flac_file_index != flac_file_size && bytes_written > 0) {
if (!(i2s_buf_end - i2s_buf_start)) {
i2s_buf_start = 0;
frames_read = drflac_read_pcm_frames_s16(pFlac, MAX_FRAMES_TO_READ, i2s_buf);
if (frames_read != MAX_FRAMES_TO_READ) {
// TODO handle end of stream
}
i2s_buf_end = frames_read * NUM_CHANNELS;
}

esp_err_t result = i2s_write(
I2S_NUM,
&(i2s_buf[total_bytes_written]),
bytes_read - total_bytes_written,
&(i2s_buf[i2s_buf_start]),
(i2s_buf_end - i2s_buf_start) * SIZE_OF_SAMPLE,
&bytes_written,
100
0
);
assert(result == ESP_OK);
total_bytes_written += bytes_written;
//printf("total_bytes_written: %u/%u\r\n", total_bytes_written, bytes_read);
}
}
i2s_buf_start += bytes_written / SIZE_OF_SAMPLE;

void start_flac_stream() {
flac_file_index = 0;
flac_file_size = flac_file_end - flac_file_start;
//printf("flac_file_size %u\r\n", flac_file_size);
pFlac = drflac_open(&onRead, &onSeek, NULL, NULL);
uint32_t frames_to_read = (DMA_BUF_SIZE_BYTES / NUM_CHANNELS) / SIZE_OF_SAMPLE;
drflac_uint64 frames_read = drflac_read_pcm_frames_s16(pFlac, frames_to_read, i2s_buf);
printf("frames_to_read: %u, frames_read: %llu\r\n", frames_to_read, frames_read);
while (frames_read == frames_to_read) {
write_all_to_i2s(frames_read);
frames_read = drflac_read_pcm_frames_s16(pFlac, frames_to_read, i2s_buf);
if (!bytes_written) {
break;
}
}
write_all_to_i2s(frames_read);
}

static void IRAM_ATTR toggle_button(void *args) {
int32_t num = 1;
xQueueSendFromISR(i2s_evt_queue, &num, NULL);
xQueueSendFromISR(control_event_queue, &num, NULL);
}

void init_gpio() {
Expand All @@ -154,30 +156,56 @@ void init_gpio() {
gpio_isr_handler_add(GPIO_NUM_32, toggle_button, NULL);
}

void stream() {
i2s_event_t i2s_event;
while (1) {
if (xQueueReceive(i2s_event_queue, &i2s_event, portMAX_DELAY)) {
switch (i2s_event.type) {
case I2S_EVENT_DMA_ERROR:
printf("I2S_EVENT_DMA_ERROR\n");
break;
case I2S_EVENT_TX_DONE:
fill_i2s_buffer();
break;
case I2S_EVENT_RX_DONE:
printf("I2S_EVENT_RX_DONE\n");
break;
case I2S_EVENT_MAX:
printf("I2S_EVENT_MAX\n");
break;
}
}
}
}

void app_main(void)
{
int32_t num;
bool play = true;
i2s_evt_queue = xQueueCreate(10, sizeof(uint32_t));
control_event_queue = xQueueCreate(10, sizeof(uint32_t));
flac_file_index = 0;
flac_file_size = flac_file_end - flac_file_start;

init_i2s();
//init_gpio();
init_gpio();

start_flac_stream();
printf("finished\n");
while(1) {
vTaskDelay(1000);
}
pFlac = drflac_open(&onRead, &onSeek, NULL, NULL);
i2s_stop(I2S_NUM);
fill_i2s_buffer();
i2s_start(I2S_NUM);

xTaskCreatePinnedToCore(stream, "stream", 4096, NULL, 3, NULL, tskNO_AFFINITY);

/*
while (1) {
if (xQueueReceive(i2s_evt_queue, &num, portMAX_DELAY)) {
if (xQueueReceive(control_event_queue, &num, portMAX_DELAY)) {
play = !play;
if (play) {
printf("start\n");
i2s_start(I2S_NUM);
} else {
printf("stop\n");
i2s_stop(I2S_NUM);
}
}
}
*/
}

0 comments on commit b37929f

Please sign in to comment.