From 917aa7ab260a122c23412fecc5434b9545830da8 Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 3 May 2021 06:39:30 +0200 Subject: [PATCH] - change buffer sizes of medians - change syncing to be more predictable using I2S_EVENT_TX_DONE o also increase DMA length so i2s won't eat up so much processing time o ensure at least one chunk is in DMA buffer --- components/lightsnapcast/include/snapcast.h | 2 +- main/main.c | 462 +++++++++++++------- 2 files changed, 306 insertions(+), 158 deletions(-) diff --git a/components/lightsnapcast/include/snapcast.h b/components/lightsnapcast/include/snapcast.h index 8acc293..387fe5c 100644 --- a/components/lightsnapcast/include/snapcast.h +++ b/components/lightsnapcast/include/snapcast.h @@ -87,7 +87,7 @@ void codec_header_message_free(codec_header_message_t *msg); typedef struct wire_chunk_message { tv_t timestamp; - uint32_t size; + size_t size; char *payload; } wire_chunk_message_t; diff --git a/main/main.c b/main/main.c index a100c93..e94f7dc 100644 --- a/main/main.c +++ b/main/main.c @@ -50,7 +50,7 @@ #include -#define CONFIG_USE_WIFI_PROVISIONING 1 +#define CONFIG_USE_WIFI_PROVISIONING 0 #define COLLECT_RUNTIME_STATS 0 // @ 48kHz, 2ch, 16bit audio data and 24ms wirechunks (hardcoded for now) we expect 0.024 * 2 * 16/8 * 48000 = 4608 Bytes @@ -100,7 +100,8 @@ TaskHandle_t syncTaskHandle = NULL; #define CONFIG_USE_SNTP 0 -#define DAC_OUT_BUFFER_TIME_US 0 +#define DAC_OUT_BUFFER_TIME_US 0//3500 // determined this by comparing a 180bpm metronome signal on a scope which is played by esp32 and ubuntu client + // not sure why I need this though... And why it is so high. I'd expect something in the µs range??! static const char *TAG = "SC"; @@ -111,7 +112,7 @@ char *codecString = NULL; // configMAX_PRIORITIES - 1 // TODO: what are the best values here? -#define SYNC_TASK_PRIORITY 8//configMAX_PRIORITIES - 2 +#define SYNC_TASK_PRIORITY 7//configMAX_PRIORITIES - 2 #define SYNC_TASK_CORE_ID tskNO_AFFINITY//1//tskNO_AFFINITY #define TIMESTAMP_TASK_PRIORITY 6 @@ -154,8 +155,8 @@ SemaphoreHandle_t timer0_syncSampleSemaphoreHandle = NULL; SemaphoreHandle_t latencyBufSemaphoreHandle = NULL; -#define MEDIAN_FILTER_LONG_BUF_LEN 599 -#define MEDIAN_FILTER_MINI_BUF_LEN 199 +#define MEDIAN_FILTER_LONG_BUF_LEN 199//299 +#define MEDIAN_FILTER_MINI_BUF_LEN 59//199 #define MEDIAN_FILTER_SHORT_BUF_LEN 19 uint8_t latencyBufCnt = 0; @@ -176,17 +177,13 @@ static int64_t latencyToServer = 0; // shortBuffer_.setSize(100); // miniBuffer_.setSize(20); -#define SHORT_BUFFER_LEN 99 +#define SHORT_BUFFER_LEN 59//99 int64_t short_buffer[SHORT_BUFFER_LEN]; int64_t short_buffer_median[SHORT_BUFFER_LEN]; -int short_buffer_cnt = 0; -int short_buffer_full = 0; #define MINI_BUFFER_LEN 19 int64_t mini_buffer[MINI_BUFFER_LEN]; int64_t mini_buffer_median[MINI_BUFFER_LEN]; -int mini_buffer_cnt = 0; -int mini_buffer_full = 0; static sMedianFilter_t shortMedianFilter; static sMedianNode_t shortMedianBuffer[SHORT_BUFFER_LEN]; @@ -201,7 +198,7 @@ uint8_t muteCH[4] = {0}; audio_board_handle_t board_handle; /* Constants that aren't configurable in menuconfig */ -#define HOST "192.168.1.6" +#define HOST "192.168.8.1" #define PORT 1704 #define BUFF_LEN 10000 unsigned int addr; @@ -218,8 +215,8 @@ static char buff[BUFF_LEN]; //static audio_element_handle_t snapcast_stream; static char mac_address[18]; -#define MY_SSID "..." -#define MY_WPA2_PSK "..." +#define MY_SSID "OpenWrt" +#define MY_WPA2_PSK "" static EventGroupHandle_t s_wifi_event_group; @@ -293,7 +290,7 @@ static void get_device_service_name(char *service_name, size_t max) * */ static void wifi_init_sta(void) { - /* Start Wi-Fi in station mode */ + // Start Wi-Fi in station mode ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_start()); @@ -423,11 +420,23 @@ void wifi_init(void) { * */ void wifi_init(void) { + // Register our event handler for Wi-Fi, IP and Provisioning related events + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL)); + + // Initialize Wi-Fi including netif with default config + esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL)); + + +// wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); +// ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + +// ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); +// ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL)); wifi_config_t wifi_config = { .sta = { @@ -590,7 +599,7 @@ int8_t latency_buffer_full(void) { } if (xSemaphoreTake( latencyBufSemaphoreHandle, 0) == pdFALSE) { - //ESP_LOGW(TAG, "latency_buffer_full: can't take semaphore"); + ESP_LOGW(TAG, "latency_buffer_full: can't take semaphore"); return -1; } @@ -931,6 +940,8 @@ static void snapcast_sync_task(void *pvParameters) { int64_t avg = 0; int64_t latencyInitialSync = 0; int dir = 0; + i2s_event_t i2sEvent; + uint32_t i2sDmaBufferCnt = 0; ESP_LOGI(TAG, "started sync task"); @@ -940,8 +951,6 @@ static void snapcast_sync_task(void *pvParameters) { adjust_apll(0); - mini_buffer_cnt = 0; - mini_buffer_full = 0; miniMedianFilter.numNodes = MINI_BUFFER_LEN; miniMedianFilter.medianBuffer = miniMedianBuffer; if (MEDIANFILTER_Init(&miniMedianFilter) ) { @@ -950,8 +959,6 @@ static void snapcast_sync_task(void *pvParameters) { return; } - short_buffer_cnt = 0; - short_buffer_full = 0; shortMedianFilter.numNodes = SHORT_BUFFER_LEN; shortMedianFilter.medianBuffer = shortMedianBuffer; if (MEDIANFILTER_Init(&shortMedianFilter) ) { @@ -964,37 +971,63 @@ static void snapcast_sync_task(void *pvParameters) { if (chnk == NULL) { // ESP_LOGE(TAG, "msg waiting pcm %d ts %d", uxQueueMessagesWaiting(pcmChunkQueueHandle), uxQueueMessagesWaiting(timestampQueueHandle)); - ret = xQueueReceive(pcmChunkQueueHandle, &chnk, pdMS_TO_TICKS(2000) ); - if( ret == pdPASS ) { - //ESP_LOGW(TAG, "pcm chunks waiting %d", uxQueueMessagesWaiting(pcmChunkQueueHandle)); + if ((initialSync == 0) && (i2sDmaBufferCnt == 0)) { + ret = xQueueReceive(pcmChunkQueueHandle, &chnk, pdMS_TO_TICKS(2000) ); + if( ret != pdFAIL ) { +// ESP_LOGW(TAG, "got first pcm chunk"); + } + } + else { + ret = xQueueReceive(i2s_event_queue, &i2sEvent, pdMS_TO_TICKS(24) ); + if( ret != pdFAIL ) { + if (i2sEvent.type == I2S_EVENT_TX_DONE) { +// ESP_LOGI(TAG, "I2S_EVENT_TX_DONE, %u", i2sDmaBufferCnt); + if (i2sDmaBufferCnt > 0) { + i2sDmaBufferCnt--; + if ((initialSync == 0) && (i2sDmaBufferCnt == 0)) { + i2s_stop(i2s_cfg.i2s_port); + + continue; + } + } + + if ((i2sDmaBufferCnt % 2) == 0) { + ret = xQueueReceive(pcmChunkQueueHandle, &chnk, pdMS_TO_TICKS(10) ); + if( ret != pdFAIL ) { +// ESP_LOGW(TAG, "got next pcm chunk"); + } + else { + ESP_LOGW(TAG, "couldn't get pcm chunk %d %d", uxQueueMessagesWaiting(pcmChunkQueueHandle), uxQueueMessagesWaiting(timestampQueueHandle)); + + continue; + } + } + else { +// ESP_LOGW(TAG, "continue"); + + continue; + } + } + else { + ESP_LOGW(TAG, "i2s unexpected event"); + + continue; + } + } + else { + ESP_LOGW(TAG, "no i2s events"); + + continue; + } } } else { +// ESP_LOGW(TAG, "already retrieved chunk needs service"); + ret = pdPASS; } - if( ret == pdPASS ) { -//// // wait for early time syncs to be ready -// int tmp = latency_buffer_full(); -// if ( tmp <= 0 ) { -// if (tmp < 0) { -// vTaskDelay(1); -// -// continue; -// } -// -// // free chunk so we can get next one -// free(chnk->payload); -// free(chnk); -// chnk = NULL; -// -//// ESP_LOGW(TAG, "diff buffer not full"); -// -// vTaskDelay( pdMS_TO_TICKS(100) ); -// -// continue; -// } - + if( ret != pdFAIL ) { // if (initialSync == 0) // using this, latency on initial sync is stored and serverNow calculation is based solely on this value until next hard sync if (1) // always use newest, median filtered serverNow { @@ -1007,9 +1040,11 @@ static void snapcast_sync_task(void *pvParameters) { else { ESP_LOGW(TAG, "couldn't get server now"); - free(chnk->payload); - free(chnk); - chnk = NULL; + if (chnk != NULL) { + free(chnk->payload); + free(chnk); + chnk = NULL; + } vTaskDelay( pdMS_TO_TICKS(100) ); @@ -1027,6 +1062,46 @@ static void snapcast_sync_task(void *pvParameters) { (int64_t)taskCfg->outputBufferDacTime_us; } + // wait for early time syncs to be ready + int tmp = latency_buffer_full(); + if ( tmp <= 0 ) { + if (tmp < 0) { + vTaskDelay(1); + + continue; + } + + if (age >= 0) { + // free chunk so we can get next one + free(chnk->payload); + free(chnk); + chnk = NULL; + } + +// ESP_LOGW(TAG, "diff buffer not full"); + + vTaskDelay( pdMS_TO_TICKS(10) ); + + continue; + } + + if (chnk != NULL) { + p_payload = chnk->payload; + size = chnk->size; + } + + if ((initialSync == 0) && (i2sDmaBufferCnt > 0)) { + ESP_LOGW(TAG, "waiting for i2s to empty %u", i2sDmaBufferCnt); + + if (chnk != NULL) { + free(chnk->payload); + free(chnk); + chnk = NULL; + } + + continue; + } + if (age < 0) { // get initial sync using hardware timer if (initialSync == 0) { if (MEDIANFILTER_Init(&shortMedianFilter) ) { @@ -1037,17 +1112,72 @@ static void snapcast_sync_task(void *pvParameters) { adjust_apll(0); // reset to normal playback speed - p_payload = chnk->payload; - size = chnk->size; +// i2s_stop(i2s_cfg.i2s_port); +// i2s_zero_dma_buffer(i2s_cfg.i2s_port); + + +// p_payload = chnk->payload; +// size = chnk->size; i2s_stop(i2s_cfg.i2s_port); +// i2s_zero_dma_buffer(i2s_cfg.i2s_port); + + i2sDmaBufferCnt = 0; + size_t writtenBytes; - int err = i2s_write(i2s_cfg.i2s_port, p_payload, size, &writtenBytes, 0); + int err = i2s_write(i2s_cfg.i2s_port, p_payload, size, &writtenBytes, pdMS_TO_TICKS(2000)); if (err != ESP_OK) { ESP_LOGE(TAG, "I2S write error"); } + + i2sDmaBufferCnt += 2; + +// ESP_LOGE(TAG, "I2S written 1 %u / %u", writtenBytes, size); + size -= writtenBytes; //p_payload += writtenBytes; // TODO: produces heap error??? + if (size == 0) { +// ESP_LOGI(TAG, "I2S can take more"); + + if (chnk != NULL) { + free(chnk->payload); + free(chnk); + chnk = NULL; + } + + ret = xQueueReceive(pcmChunkQueueHandle, &chnk, portMAX_DELAY); + if( ret != pdFAIL ) { + p_payload = chnk->payload; + size = chnk->size; + err = i2s_write(i2s_cfg.i2s_port, p_payload, size, &writtenBytes, pdMS_TO_TICKS(2000)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "I2S write error"); + } + +// ESP_LOGE(TAG, "I2S written 2 %u / %u", writtenBytes, size); + + i2sDmaBufferCnt += 2; + + size -= writtenBytes; + if (size != 0) { + ESP_LOGE(TAG, "I2S check DMA buffer sizes, 1 chunk should fit in two DMA buffers! %u, %u", size, writtenBytes); + } + + if (chnk != NULL) { + free(chnk->payload); + free(chnk); + chnk = NULL; + } + + //p_payload += writtenBytes; // TODO: produces heap error??? + } + else { + ESP_LOGW(TAG, "I2S writing more not possible, couldn't get pcm chunk"); + + continue; + } + } + //tg0_timer1_start((-age * 10) - alarmValSub)); // alarm a little earlier to account for context switch duration from freeRTOS, timer with 100ns ticks tg0_timer1_start(-age - alarmValSub); // alarm a little earlier to account for context switch duration from freeRTOS, timer with 1µs ticks @@ -1070,50 +1200,56 @@ static void snapcast_sync_task(void *pvParameters) { // TODO: try to get better initial sync using alarmValSub to alarm early, // doesn't work with current style of loading i2s buffer early. -// if (((age < -11LL) || (age > 0)) && (initialSync == 0)) { -// if (age < -11LL) { -// alarmValSub--; -// } -// else { -// alarmValSub++; -// } +// if (((age < -11LL) || (age > 0)) && (initialSync == 0)) { +// if (age < -11LL) { +// alarmValSub--; +// } +// else { +// alarmValSub++; +// } // -// // free chunk so we can get next one +// // free chunk so we can get next one +// if (chnk != NULL) { // free(chnk->payload); // free(chnk); // chnk = NULL; -// -// struct timeval t; -// get_diff_to_server(&t); -// ESP_LOGI(TAG, "no hard sync, age %lldus, %lldus", age, ((int64_t)t.tv_sec * 1000000LL + (int64_t)t.tv_usec)); -// -// continue; -// } -// else if (initialSync == 0) { -// // i2s_start(i2s_cfg.i2s_port); -// -// ESP_LOGW(TAG, "start"); // } // - get_diff_to_server(&latencyInitialSync); // store current latency for later use +// int64_t t; +// get_diff_to_server(&t); +// ESP_LOGI(TAG, "no hard sync, age %lldus, %lldus", age, t); +// +// vTaskDelay(pdMS_TO_TICKS((writtenBytes / 4) / 48) + 1); // wait until i2s dma is empty +// +// continue; +// } +// else if (initialSync == 0) { +//// i2s_start(i2s_cfg.i2s_port); +// +// ESP_LOGW(TAG, "start"); +// } + +// get_diff_to_server(&latencyInitialSync); // store current latency for later use initialSync = 1; + + ESP_LOGI(TAG, "initial sync %lldus", age); +// ESP_LOGW(TAG, "chunk %d %d", uxQueueMessagesWaiting(pcmChunkQueueHandle), uxQueueMessagesWaiting(timestampQueueHandle)); + + continue; } } else if ((age > 0) && (initialSync == 0)) { - free(chnk->payload); - free(chnk); - chnk = NULL; + if (chnk != NULL) { + free(chnk->payload); + free(chnk); + chnk = NULL; + } int64_t t; get_diff_to_server(&t); ESP_LOGW(TAG, "RESYNCING HARD 1 %lldus, %lldus", age, t); - if (short_buffer_full) { - short_buffer_cnt = 0; - short_buffer_full = 0; - } - dir = 0; initialSync = 0; @@ -1123,95 +1259,98 @@ static void snapcast_sync_task(void *pvParameters) { } if (initialSync == 1) { - p_payload = chnk->payload; - size = chnk->size; + const uint8_t enableControlLoop = 1; + const int64_t age_expect = 48000; + const int64_t maxOffset = 100; + const int64_t maxOffset_dropSample = 1000; - size_t writtenBytes; - int err = i2s_write(I2S_NUM_0, p_payload, size, &writtenBytes, portMAX_DELAY); - if (err != ESP_OK) { - ESP_LOGE(TAG, "I2S write error"); - } - - - short_buffer_full = 1; -// short_buffer_cnt++; -// if (short_buffer_cnt >= SHORT_BUFFER_LEN ) { -// short_buffer_full = 1; -// } - - avg = MEDIANFILTER_Insert(&shortMedianFilter, age); + avg = MEDIANFILTER_Insert(&shortMedianFilter, age + age_expect); + //avg = age + age_expect; // resync hard if we are off too far - if ((avg < -1 * chunkDuration_us / 8) || (avg > 1 * chunkDuration_us / 8) || (initialSync == 0)) { - free(chnk->payload); - free(chnk); - chnk = NULL; + if ((avg < -1 * chunkDuration_us / 4) || (avg > 1 * chunkDuration_us / 4) || (initialSync == 0)) { + if (chnk != NULL) { + free(chnk->payload); + free(chnk); + chnk = NULL; + } int64_t t; get_diff_to_server(&t); - ESP_LOGW(TAG, "RESYNCING HARD 2 %lldus, %lldus", age, t); - - short_buffer_cnt = 0; - short_buffer_full = 0; + ESP_LOGW(TAG, "RESYNCING HARD 2 %lldus, %lldus, %lldus", age, avg, t); initialSync = 0; alarmValSub = 0; continue; } - } + size_t writtenBytes; + int err = i2s_write(I2S_NUM_0, p_payload, size, &writtenBytes, pdMS_TO_TICKS(100)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "I2S write error"); + } - const int64_t age_expect = 0; - const int64_t maxOffset = 300; - const int64_t maxOffset_dropSample = 1000; - // NOT 100% SURE ABOUT THE FOLLOWING CONTROL LOOP, PROBABLY BETTER WAYS TO DO IT, STILL TESTING - if (initialSync == 1) - { // got initial sync, decrease / increase playback speed if abs(age) > maxOffset + if (writtenBytes != size) { + ESP_LOGE(TAG, "written too less %u %u", size, writtenBytes); + } + + i2sDmaBufferCnt += 2; + + // NOT 100% SURE ABOUT THE FOLLOWING CONTROL LOOP, PROBABLY BETTER WAYS TO DO IT, STILL TESTING int samples = 1; int sampleSize = 4; int ageDiff = 0; - if (short_buffer_full) { - if (avg < (age_expect - maxOffset)) { + // TODO: not sure how to do frame correction with current implementation + // which relies heavily on putting full chunks into I2S DMA buffer + // and tracking the buffer's fill state by counting events. Adding + // or deleting samples will confuse the algorithm... + if (enableControlLoop == 1) { + if (avg < -maxOffset) { dir = -1; - if (avg < (age_expect - maxOffset_dropSample) ) { - ageDiff = (int)(age_expect - avg); - samples = ageDiff / (sampleDuration_ns / 1000); - if (samples > 4) { - samples = 4; - } - - // too young add samples - size_t writtenBytes; - int err = i2s_write(I2S_NUM_0, p_payload, samples * sampleSize, &writtenBytes, portMAX_DELAY); - if (err != ESP_OK) { - ESP_LOGE(TAG, "I2S write error"); - } - - ESP_LOGI(TAG, "insert %d samples", samples); - } +// //if (avg < (age_expect - maxOffset_dropSample) ) { +// if (avg < -maxOffset_dropSample) { +// //ageDiff = (int)(age_expect - avg); +// ageDiff = (int)avg; +// samples = ageDiff / (sampleDuration_ns / 1000); +// if (samples > 4) { +// samples = 4; +// } +// +// // too young add samples +// size_t writtenBytes; +// +// int err = i2s_write(I2S_NUM_0, p_payload, samples * sampleSize, &writtenBytes, portMAX_DELAY); +// if (err != ESP_OK) { +// ESP_LOGE(TAG, "I2S write error"); +// } +// +// ESP_LOGI(TAG, "insert %d samples", samples); +// } } - else if ((avg >= (age_expect - maxOffset)) && (avg <= (age_expect + maxOffset))) { + else if ((avg >= -maxOffset) && (avg <= maxOffset)) { dir = 0; } - else if (avg > (age_expect + maxOffset)) { + else if (avg > maxOffset) { dir = 1; - if (avg > (age_expect + maxOffset_dropSample)) { - ageDiff = (int)(avg - age_expect); - samples = ageDiff / (sampleDuration_ns / 1000); - if (samples > 4) { - samples = 4; - } - - // drop samples - p_payload += samples * sampleSize; - size -= samples * sampleSize; - - ESP_LOGI(TAG, "drop %d samples", samples); - } +// //if (avg > (age_expect + maxOffset_dropSample)) { +// if (avg > maxOffset_dropSample) { +// //ageDiff = (int)(avg - age_expect); +// ageDiff = (int)avg; +// samples = ageDiff / (sampleDuration_ns / 1000); +// if (samples > 4) { +// samples = 4; +// } +// +// // drop samples +// p_payload += samples * sampleSize; +// size -= samples * sampleSize; +// +// ESP_LOGI(TAG, "drop %d samples", samples); +// } } adjust_apll(dir); @@ -1220,11 +1359,14 @@ static void snapcast_sync_task(void *pvParameters) { int64_t t; get_diff_to_server(&t); - ESP_LOGI(TAG, "%d: %lldus, %lldus %lldus %lldus", dir, age, avg, t, latencyInitialSync); + ESP_LOGI(TAG, "%d: %lldus, %lldus %lldus", dir, age, avg, t); +// ESP_LOGW(TAG, "chunk %d %d", uxQueueMessagesWaiting(pcmChunkQueueHandle), uxQueueMessagesWaiting(timestampQueueHandle)); - free(chnk->payload); - free(chnk); - chnk = NULL; + if (chnk != NULL) { + free(chnk->payload); + free(chnk); + chnk = NULL; + } } else { int64_t t; @@ -1236,9 +1378,6 @@ static void snapcast_sync_task(void *pvParameters) { reset_latency_buffer(); // ensure correct latencies, if there is no stream received from server. // latency will be shorter if no wirechunks have to be serviced and decoded - short_buffer_cnt = 0; - short_buffer_full = 0; - dir = 0; initialSync = 0; @@ -1747,16 +1886,19 @@ static void http_get_task(void *pvParameters) { else { // if mini latency buffer is full, we stop initial flooding with time messages if (latencyBuffFull == false) { - if (xSemaphoreTake( latencyBufSemaphoreHandle, portMAX_DELAY ) == pdTRUE) { + if (xSemaphoreTake( latencyBufSemaphoreHandle, pdMS_TO_TICKS(1) ) == pdTRUE) { latencyBuffFull = true; xSemaphoreGive( latencyBufSemaphoreHandle ); } + else { + ESP_LOGW(TAG, "Couldn't set latencyBuffFull = true"); + } } } } - if (xSemaphoreTake( latencyBufSemaphoreHandle, portMAX_DELAY ) == pdTRUE) { + if (xSemaphoreTake( latencyBufSemaphoreHandle, pdMS_TO_TICKS(1) ) == pdTRUE) { // TODO: find better way to check if Median Filter is full // Count how much latencies we have stored so far // latencyBufCnt++; @@ -1774,7 +1916,7 @@ static void http_get_task(void *pvParameters) { xSemaphoreGive( latencyBufSemaphoreHandle ); } else { - ESP_LOGW(TAG, "can't take latencyBufSemaphoreHandle"); + ESP_LOGW(TAG, "couldn't set latencyToServer = medianValue"); } // store current time @@ -1944,6 +2086,7 @@ int flac_decoder_write_cb(audio_element_handle_t el, char *buf, int len, TickTyp // receivedByteCnt += len; // ESP_LOGI(TAG, "flac_decoder_write_cb: len %d, cnt %lld, received total: %lld", len, flacCnt, receivedByteCnt); // ESP_LOGI(TAG, "flac_decoder_write_cb: flac cnt %lld",flacCnt); +// ESP_LOGI(TAG, "flac_decoder_write_cb: len %d", len); if (xQueueReceive( timestampQueueHandle, ×tamp, wait_time ) == pdPASS) { pcm_chunk_message = (wire_chunk_message_t *)heap_caps_malloc(sizeof(wire_chunk_message_t), MALLOC_CAP_SPIRAM); @@ -1965,6 +2108,9 @@ int flac_decoder_write_cb(audio_element_handle_t el, char *buf, int len, TickTyp if (xQueueSendToBack( pcmChunkQueueHandle, &pcm_chunk_message, pdMS_TO_TICKS(1000)) != pdTRUE) { ESP_LOGW(TAG, "wirechunk_to_pcm_timestamp_task: send: pcmChunkQueue full, messages waiting %d", uxQueueMessagesWaiting(pcmChunkQueueHandle)); } + else { + //ESP_LOGI(TAG, "flac_decoder_write_cb: pcm_chunk_message->size %u", pcm_chunk_message->size); + } } } } @@ -2001,8 +2147,8 @@ void setup_dsp_i2s(uint32_t sample_rate, i2s_port_t i2sNum) .bits_per_sample = BITS_PER_SAMPLE, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels .communication_format = I2S_COMM_FORMAT_STAND_I2S, - .dma_buf_count = 34, - .dma_buf_len = 16, + .dma_buf_count = 5,//32 + 0,//34, + .dma_buf_len = 576,//16,//16, .intr_alloc_flags = 1, //Default interrupt priority .use_apll = true, .fixed_mclk = 0, @@ -2028,6 +2174,8 @@ void app_main(void) { esp_err_t ret; uint8_t base_mac[6]; + //ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { /* NVS partition was truncated @@ -2110,7 +2258,7 @@ void app_main(void) { ESP_LOGI(TAG, "Start audio_pipelines"); audio_pipeline_run(flacDecodePipeline); - i2s_start(i2s_cfg.i2s_port); +// i2s_start(i2s_cfg.i2s_port); // i2s_stop(i2s_cfg.i2s_port); // i2s_zero_dma_buffer(i2s_cfg.i2s_port);