From 4a82967fecd1224f12bf5f694c4ddca1b006ad8c Mon Sep 17 00:00:00 2001 From: Karl Osterseher Date: Thu, 6 Oct 2022 14:56:00 +0200 Subject: [PATCH] - on memory allocation error insert a chunk where all samples are set to zero - disable shortMedianFilter - decrease control loop's calls to adjust_apll() - increase size of latencyMedianFilterLong Signed-off-by: Karl Osterseher --- components/lightsnapcast/include/player.h | 2 +- components/lightsnapcast/player.c | 164 ++++++++---- components/wifi_logger | 1 + main/main.c | 299 +++++++++++++++++----- sdkconfig | 29 ++- sdkconfig.old | 35 ++- 6 files changed, 396 insertions(+), 134 deletions(-) create mode 160000 components/wifi_logger diff --git a/components/lightsnapcast/include/player.h b/components/lightsnapcast/include/player.h index 140966b..614cd25 100644 --- a/components/lightsnapcast/include/player.h +++ b/components/lightsnapcast/include/player.h @@ -13,7 +13,7 @@ 3 // TODO: maybe calculate this dynamically based on chunk duration and // buffer size?! -#define LATENCY_MEDIAN_FILTER_LEN 29 // 99 +#define LATENCY_MEDIAN_FILTER_LEN 199 // 29 // 99 #define SHORT_BUFFER_LEN 9 diff --git a/components/lightsnapcast/player.c b/components/lightsnapcast/player.c index ac88813..f236fc4 100644 --- a/components/lightsnapcast/player.c +++ b/components/lightsnapcast/player.c @@ -53,8 +53,8 @@ static sMedianNode_t latencyMedianLongBuffer[LATENCY_MEDIAN_FILTER_LEN]; static int64_t latencyToServer = 0; -static sMedianFilter_t shortMedianFilter; -static sMedianNode_t shortMedianBuffer[SHORT_BUFFER_LEN]; +// static sMedianFilter_t shortMedianFilter; +// static sMedianNode_t shortMedianBuffer[SHORT_BUFFER_LEN]; static int8_t currentDir = 0; //!< current apll direction, see apll_adjust() @@ -318,9 +318,11 @@ int8_t player_latency_insert(int64_t newValue) { int64_t medianValue; medianValue = MEDIANFILTER_Insert(&latencyMedianFilterLong, newValue); - if (xSemaphoreTake(latencyBufSemaphoreHandle, pdMS_TO_TICKS(5)) == pdTRUE) { + if (xSemaphoreTake(latencyBufSemaphoreHandle, pdMS_TO_TICKS(0)) == pdTRUE) { if (MEDIANFILTER_isFull(&latencyMedianFilterLong)) { latencyBuffFull = true; + + // ESP_LOGI(TAG, "latency median: %lld", latencyToServer); } latencyToServer = medianValue; @@ -1700,7 +1702,14 @@ int8_t allocate_pcm_chunk_memory(pcm_chunk_message_t **pcmChunk, size_t bytes) { heap_caps_get_free_size(MALLOC_CAP_32BIT | MALLOC_CAP_EXEC), heap_caps_get_largest_free_block(MALLOC_CAP_32BIT | MALLOC_CAP_EXEC)); - free_pcm_chunk(*pcmChunk); + // free_pcm_chunk(*pcmChunk); + + (*pcmChunk)->fragment->payload = NULL; + (*pcmChunk)->totalSize = bytes; + (*pcmChunk)->fragment->nextFragment = NULL; + (*pcmChunk)->fragment->size = bytes; + + ret = 0; } else { // ESP_LOGI (TAG, "got memory for pcm chunk %p %p %d", *pcmChunk, // (*pcmChunk)->fragment->payload, bytes); @@ -2091,13 +2100,14 @@ static void player_task(void *pvParameters) { initialSync = 0; - shortMedianFilter.numNodes = SHORT_BUFFER_LEN; - shortMedianFilter.medianBuffer = shortMedianBuffer; - if (MEDIANFILTER_Init(&shortMedianFilter)) { - ESP_LOGE(TAG, "snapcast_sync_task: couldn't init shortMedianFilter. STOP"); - - return; - } + // shortMedianFilter.numNodes = SHORT_BUFFER_LEN; + // shortMedianFilter.medianBuffer = shortMedianBuffer; + // if (MEDIANFILTER_Init(&shortMedianFilter)) { + // ESP_LOGE(TAG, "snapcast_sync_task: couldn't init shortMedianFilter. + // STOP"); + // + // return; + // } while (1) { // ESP_LOGW( @@ -2242,13 +2252,13 @@ static void player_task(void *pvParameters) { i2s_custom_stop(I2S_NUM_0); - if (MEDIANFILTER_Init(&shortMedianFilter)) { - ESP_LOGE(TAG, - "snapcast_sync_task: couldn't init " - "shortMedianFilter. STOP"); - - return; - } + // if (MEDIANFILTER_Init(&shortMedianFilter)) { + // ESP_LOGE(TAG, + // "snapcast_sync_task: couldn't init " + // "shortMedianFilter. STOP"); + // + // return; + // } adjust_apll(0); // reset to normal playback speed @@ -2386,20 +2396,25 @@ static void player_task(void *pvParameters) { continue; } - const uint8_t enableControlLoop = 1; + const bool enableControlLoop = true; const int64_t age_expect = -chkDur_us * CHNK_CTRL_CNT; // this value is highly coupled with I2S DMA buffer // size. DMA buffer has a size of 1 chunk (e.g. 20ms) // so next chunk we get from queue will be -20ms - const int64_t maxOffset = 25; //µs, softsync 1 + const int64_t maxOffset = 250; // 25; //µs, softsync 1 const int64_t hardResyncThreshold = 10000; //µs, hard sync if (initialSync == 1) { - avg = MEDIANFILTER_Insert(&shortMedianFilter, age + (-age_expect)); - if (MEDIANFILTER_isFull(&shortMedianFilter) == 0) { + // avg = MEDIANFILTER_Insert(&shortMedianFilter, age + + // (-age_expect)); if (MEDIANFILTER_isFull(&shortMedianFilter) == + // 0) { + // avg = age + (-age_expect); + // } + // else + { avg = age + (-age_expect); - } else { + // resync hard if we are off too far // if ((avg < -hardResyncThreshold) // || (avg > hardResyncThreshold) || @@ -2451,16 +2466,28 @@ static void player_task(void *pvParameters) { } } - if (enableControlLoop == 1) { + if (enableControlLoop == true) { + // if (avg < -maxOffset) { // we are early + // dir = -1; + // } else if ((avg >= -maxOffset) && (avg <= maxOffset)) { + // dir = 0; + // } else if (avg > maxOffset) { // we are late + // dir = 1; + // } if (avg < -maxOffset) { // we are early dir = -1; - } else if ((avg >= -maxOffset) && (avg <= maxOffset)) { + } else if (((dir == -1) && (avg >= 0)) || + ((dir == 1) && (avg <= 0))) { dir = 0; } else if (avg > maxOffset) { // we are late dir = 1; } + // uint64_t start = esp_timer_get_time(); adjust_apll(dir); + // uint64_t end = esp_timer_get_time(); + + // ESP_LOGE (TAG, "adjust_apll took %lldus", end - start); } // clang-format off @@ -2505,45 +2532,72 @@ static void player_task(void *pvParameters) { // heap_caps_get_largest_free_block // (MALLOC_CAP_32BIT | MALLOC_CAP_EXEC)); -// ESP_LOGI (TAG, "%d, %lldus, %lldus %lldus", dir, age, avg, t); +// static uint32_t tmpcnt = 2500; // every 60s +// if (tmpcnt-- == 0) { +// tmpcnt = 2500; +// ESP_LOGI (TAG, "%d, %lldus, %lldus %lldus", dir, age, avg, t); +// } +// ESP_LOGI (TAG, "%d, %lldus, %lldus %lldus", dir, age, avg, t); - // ESP_LOGI (TAG, "%d %lldus, %d", dir, avg, uxQueueMessagesWaiting(pcmChkQHdl)); + ESP_LOGI (TAG, "%d, %lldus, queue: %d, latency: %lldus", dir, avg, uxQueueMessagesWaiting(pcmChkQHdl), t); // clang-format on fragment = chnk->fragment; p_payload = fragment->payload; size = fragment->size; - do { - written = 0; - if (i2s_custom_write(I2S_NUM_0, p_payload, (size_t)size, &written, - portMAX_DELAY) != ESP_OK) { - ESP_LOGE(TAG, "i2s_playback_task: I2S write error %d", size); - } - if (written < size) { - ESP_LOGE(TAG, "i2s_playback_task: I2S didn't write all data"); - } - size -= written; - p_payload += written; - - if (size == 0) { - if (fragment->nextFragment != NULL) { - fragment = fragment->nextFragment; - p_payload = fragment->payload; - size = fragment->size; - - // ESP_LOGI (TAG, - // "i2s_playback_task: - // fragmented"); - } else { - free_pcm_chunk(chnk); - chnk = NULL; - - break; + if (p_payload != NULL) { + do { + written = 0; + if (i2s_custom_write(I2S_NUM_0, p_payload, (size_t)size, &written, + portMAX_DELAY) != ESP_OK) { + ESP_LOGE(TAG, "i2s_playback_task: I2S write error %d", size); } - } - } while (1); + if (written < size) { + ESP_LOGE(TAG, "i2s_playback_task: I2S didn't write all data"); + } + size -= written; + p_payload += written; + + if (size == 0) { + if (fragment->nextFragment != NULL) { + fragment = fragment->nextFragment; + p_payload = fragment->payload; + size = fragment->size; + + // ESP_LOGI (TAG, + // "i2s_playback_task: + // fragmented"); + } else { + free_pcm_chunk(chnk); + chnk = NULL; + + break; + } + } + } while (1); + } else { + // here we have an empty fragment because of memory allocation error. + // fill DMA with zeros so we don't get out of sync + written = 0; + const size_t write_size = 4; + uint8_t tmpBuf[write_size]; + + memset(tmpBuf, 0, sizeof(tmpBuf)); + + do { + if (i2s_custom_write(I2S_NUM_0, tmpBuf, (size_t)write_size, + &written, portMAX_DELAY) != ESP_OK) { + ESP_LOGE(TAG, "i2s_playback_task: I2S write error %d", size); + } + + size -= written; + } while (size); + + free_pcm_chunk(chnk); + chnk = NULL; + } } } else { int64_t t; diff --git a/components/wifi_logger b/components/wifi_logger new file mode 160000 index 0000000..23bf246 --- /dev/null +++ b/components/wifi_logger @@ -0,0 +1 @@ +Subproject commit 23bf246c863c15d118c46cce47dd3f1657809ab7 diff --git a/main/main.c b/main/main.c index b0cd397..cb045a9 100644 --- a/main/main.c +++ b/main/main.c @@ -51,6 +51,8 @@ #include "player.h" #include "snapcast.h" +#include "wifi_logger.h" + static FLAC__StreamDecoderReadStatus read_callback( const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); @@ -69,23 +71,28 @@ static void error_callback(const FLAC__StreamDecoder *decoder, static FLAC__StreamDecoder *flacDecoder = NULL; static QueueHandle_t decoderReadQHdl = NULL; static QueueHandle_t decoderWriteQHdl = NULL; +static QueueHandle_t flacTaskQHdl = NULL; SemaphoreHandle_t decoderReadSemaphore = NULL; SemaphoreHandle_t decoderWriteSemaphore = NULL; const char *VERSION_STRING = "0.0.2"; -#define HTTP_TASK_PRIORITY 6 +#define HTTP_TASK_PRIORITY 8 #define HTTP_TASK_CORE_ID tskNO_AFFINITY // 1 // tskNO_AFFINITY #define OTA_TASK_PRIORITY 6 #define OTA_TASK_CORE_ID tskNO_AFFINITY // 1 // tskNO_AFFINITY -#define FLAC_TASK_PRIORITY 8 +#define FLAC_DECODER_TASK_PRIORITY 7 +#define FLAC_DECODER_TASK_CORE_ID tskNO_AFFINITY // 1 // tskNO_AFFINITY + +#define FLAC_TASK_PRIORITY 7 #define FLAC_TASK_CORE_ID tskNO_AFFINITY // 1 // tskNO_AFFINITY xTaskHandle t_ota_task = NULL; xTaskHandle t_http_get_task = NULL; xTaskHandle t_flac_decoder_task = NULL; +xTaskHandle t_flac_task = NULL; struct timeval tdif, tavg; static audio_board_handle_t board_handle = NULL; @@ -113,6 +120,7 @@ uint8_t dspFlow = dspfStereo; // dspfBiamp; // dspfStereo; // dspfBassBoost; typedef struct flacData_s { char *inData; + tv_t timestamp; pcm_chunk_message_t *outData; uint32_t bytes; } flacData_t; @@ -297,32 +305,34 @@ static FLAC__StreamDecoderWriteStatus write_callback( if (ret == 0) { pcm_chunk_fragment_t *fragment = flacData->outData->fragment; - fragmentCnt = 0; + if (fragment->payload != NULL) { + fragmentCnt = 0; - for (i = 0; i < frame->header.blocksize; i++) { - // write little endian - // flacData->outData[4 * i] = (uint8_t)buffer[0][i]; - // flacData->outData[4 * i + 1] = (uint8_t) (buffer[0][i] >> 8); - // flacData->outData[4 * i + 2] = (uint8_t)buffer[1][i]; - // flacData->outData[4 * i + 3] = (uint8_t)(buffer[1][i] >> 8); + for (i = 0; i < frame->header.blocksize; i++) { + // write little endian + // flacData->outData[4 * i] = (uint8_t)buffer[0][i]; + // flacData->outData[4 * i + 1] = (uint8_t) (buffer[0][i] >> 8); + // flacData->outData[4 * i + 2] = (uint8_t)buffer[1][i]; + // flacData->outData[4 * i + 3] = (uint8_t)(buffer[1][i] >> 8); - // TODO: for now fragmented payload is not supported and the whole - // chunk is expected to be in the first fragment - tmpData = ((uint32_t)((buffer[0][i] >> 8) & 0xFF) << 24) | - ((uint32_t)((buffer[0][i] >> 0) & 0xFF) << 16) | - ((uint32_t)((buffer[1][i] >> 8) & 0xFF) << 8) | - ((uint32_t)((buffer[1][i] >> 0) & 0xFF) << 0); + // TODO: for now fragmented payload is not supported and the whole + // chunk is expected to be in the first fragment + tmpData = ((uint32_t)((buffer[0][i] >> 8) & 0xFF) << 24) | + ((uint32_t)((buffer[0][i] >> 0) & 0xFF) << 16) | + ((uint32_t)((buffer[1][i] >> 8) & 0xFF) << 8) | + ((uint32_t)((buffer[1][i] >> 0) & 0xFF) << 0); - if (fragment != NULL) { - uint32_t *test = (uint32_t *)(&(fragment->payload[fragmentCnt])); - *test = tmpData; - } + if (fragment != NULL) { + uint32_t *test = (uint32_t *)(&(fragment->payload[fragmentCnt])); + *test = tmpData; + } - fragmentCnt += 4; - if (fragmentCnt >= fragment->size) { - fragmentCnt = 0; + fragmentCnt += 4; + if (fragmentCnt >= fragment->size) { + fragmentCnt = 0; - fragment = fragment->nextFragment; + fragment = fragment->nextFragment; + } } } } else { @@ -413,15 +423,102 @@ static void flac_decoder_task(void *pvParameters) { if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) { ESP_LOGE(TAG, "ERROR: initializing decoder: %s\n", FLAC__StreamDecoderInitStatusString[init_status]); + ok = false; return; } while (1) { + ESP_LOGI(TAG, "test"); + FLAC__stream_decoder_process_until_end_of_stream(flacDecoder); } } +/** + * + */ +void flac_task(void *pvParameters) { + tv_t currentTimestamp; + flacData_t *pFlacData = NULL; + snapcastSetting_t *scSet = (snapcastSetting_t *)pvParameters; + + if (flacTaskQHdl != NULL) { + vQueueDelete(flacTaskQHdl); + flacTaskQHdl = NULL; + } + + flacTaskQHdl = xQueueCreate(128, sizeof(flacData_t *)); + if (flacTaskQHdl == NULL) { + ESP_LOGE(TAG, "Failed to create flac flacTaskQHdl"); + return; + } + + while (1) { + xQueueReceive(flacTaskQHdl, &pFlacData, + portMAX_DELAY); // get data from tcp task + + if (pFlacData != NULL) { + currentTimestamp = pFlacData->timestamp; + + ESP_LOGE(TAG, "Got timestamp %lld", + (uint64_t)currentTimestamp.sec * 1000000 + + (uint64_t)currentTimestamp.usec); + + xSemaphoreTake(decoderReadSemaphore, portMAX_DELAY); + + // send data to flac decoder + xQueueSend(decoderReadQHdl, &pFlacData, portMAX_DELAY); + // and wait until data was + // processed + xSemaphoreTake(decoderReadSemaphore, portMAX_DELAY); + // need to release mutex + // afterwards for next round + xSemaphoreGive(decoderReadSemaphore); + + free(pFlacData); + } else { + pcm_chunk_message_t *pcmData = NULL; + + xSemaphoreGive(decoderWriteSemaphore); + // and wait until it is done + xQueueReceive(decoderWriteQHdl, &pFlacData, portMAX_DELAY); + + if (pFlacData->outData != NULL) { + pcmData = pFlacData->outData; + pcmData->timestamp = currentTimestamp; + + size_t decodedSize = pcmData->totalSize; // pFlacData->bytes; + scSet->chkDur_ms = (1000UL * decodedSize) / + (uint32_t)(scSet->ch * (scSet->bits / 8)) / + scSet->sr; + if (player_send_snapcast_setting(scSet) != pdPASS) { + ESP_LOGE(TAG, + "Failed to " + "notify " + "sync task " + "about " + "codec. Did you " + "init player?"); + + return; + } + +#if CONFIG_USE_DSP_PROCESSOR + dsp_setup_flow(500, scSet.sr, scSet.chkDur_ms); + dsp_processor(pcm_chunk_message.payload, pcm_chunk_message.size, + dspFlow); +#endif + + insert_pcm_chunk(pcmData); + } + } + } +} + +#define FAST_SYNC_LATENCY_BUF 10000 // in µs +#define NORMAL_SYNC_LATENCY_BUF 1000000 // in µs + /** * */ @@ -453,7 +550,7 @@ static void http_get_task(void *pvParameters) { OpusDecoder *opusDecoder = NULL; codec_type_t codec = NONE; snapcastSetting_t scSet; - flacData_t flacData = {NULL, NULL, 0}; + flacData_t flacData = {NULL, {0, 0}, NULL, 0}; flacData_t *pFlacData; pcm_chunk_message_t *pcmData = NULL; char *typedMsg = NULL; @@ -466,7 +563,7 @@ static void http_get_task(void *pvParameters) { struct netbuf *firstNetBuf = NULL; struct netbuf *newNetBuf = NULL; uint16_t len; - uint64_t timeout = 100000; + uint64_t timeout = FAST_SYNC_LATENCY_BUF; // create a timer to send time sync messages every x µs esp_timer_create(&tSyncArgs, &timeSyncMessageTimer); @@ -481,32 +578,30 @@ static void http_get_task(void *pvParameters) { #endif while (1) { + received_header = false; + if (reset_latency_buffer() < 0) { ESP_LOGE(TAG, "reset_diff_buffer: couldn't reset median filter long. STOP"); - - timeout = 100000; - - esp_timer_stop(timeSyncMessageTimer); - if (received_header == true) { - if (!esp_timer_is_active(timeSyncMessageTimer)) { - esp_timer_start_periodic(timeSyncMessageTimer, timeout); - } - - if ((latency_buffer_full() > 0) && (timeout < 1000000)) { - if (esp_timer_is_active(timeSyncMessageTimer)) { - esp_timer_stop(timeSyncMessageTimer); - } - - esp_timer_start_periodic(timeSyncMessageTimer, timeout); - } - } - return; } + timeout = FAST_SYNC_LATENCY_BUF; + esp_timer_stop(timeSyncMessageTimer); - // xSemaphoreGive(timeSyncSemaphoreHandle); + if (received_header == true) { + if (!esp_timer_is_active(timeSyncMessageTimer)) { + esp_timer_start_periodic(timeSyncMessageTimer, timeout); + } + + if ((latency_buffer_full() > 0) && (timeout < NORMAL_SYNC_LATENCY_BUF)) { + if (esp_timer_is_active(timeSyncMessageTimer)) { + esp_timer_stop(timeSyncMessageTimer); + } + + esp_timer_start_periodic(timeSyncMessageTimer, timeout); + } + } if (opusDecoder != NULL) { opus_decoder_destroy(opusDecoder); @@ -518,6 +613,11 @@ static void http_get_task(void *pvParameters) { t_flac_decoder_task = NULL; } + if (t_flac_task != NULL) { + vTaskDelete(t_flac_task); + t_flac_task = NULL; + } + if (flacDecoder != NULL) { FLAC__stream_decoder_finish(flacDecoder); FLAC__stream_decoder_delete(flacDecoder); @@ -534,6 +634,11 @@ static void http_get_task(void *pvParameters) { decoderReadQHdl = NULL; } + if (flacTaskQHdl != NULL) { + vQueueDelete(flacTaskQHdl); + flacTaskQHdl = NULL; + } + #if SNAPCAST_SERVER_USE_MDNS // Find snapcast server // Connect to first snapcast server found @@ -630,8 +735,6 @@ static void http_get_task(void *pvParameters) { return; } - received_header = false; - // init base message base_message_rx.type = SNAPCAST_MESSAGE_HELLO; base_message_rx.id = 0x0000; @@ -722,6 +825,8 @@ static void http_get_task(void *pvParameters) { firstNetBuf = NULL; +#define TEST_DECODER_TASK 0 + decoderWriteSemaphore = xSemaphoreCreateMutex(); xSemaphoreTake(decoderWriteSemaphore, portMAX_DELAY); @@ -771,13 +876,6 @@ static void http_get_task(void *pvParameters) { case BASE_MESSAGE_STATE: { switch (internalState) { case 0: - result = gettimeofday(&now, NULL); - // ESP_LOGI(TAG, "time of day: %ld %ld", - // now.tv_sec, now.tv_usec); - if (result) { - ESP_LOGW(TAG, "Failed to gettimeofday"); - } - base_message_rx.type = *start & 0xFF; internalState++; break; @@ -906,6 +1004,11 @@ static void http_get_task(void *pvParameters) { base_message_rx.size |= (*start & 0xFF) << 24; internalState = 0; + result = gettimeofday(&now, NULL); + if (result) { + ESP_LOGW(TAG, "Failed to gettimeofday"); + } + base_message_rx.received.sec = now.tv_sec; base_message_rx.received.usec = now.tv_usec; @@ -1115,10 +1218,39 @@ static void http_get_task(void *pvParameters) { tmp = len; } + // TODO: put the following part which is blocking and + // waiting for decoded data to own task + // with lower priority than this task. This way + // snapclient latency measurements won't be stalled + // and WiFi communication can keep running + if (received_header == true) { switch (codec) { case FLAC: { +#if TEST_DECODER_TASK + pFlacData = + (flacData_t *)malloc(sizeof(flacData_t)); + pFlacData->bytes = tmp; + pFlacData->timestamp = + wire_chnk.timestamp; // store timestamp for + // later use + pFlacData->inData = start; + pFlacData->outData = NULL; + + // ESP_LOGI(TAG, "send to + // queue"); + // send data to seperate task which will handle this + xQueueSend(flacTaskQHdl, &pFlacData, portMAX_DELAY); + // ESP_LOGI(TAG, "done"); +#else + + // startTime = + // esp_timer_get_time(); + flacData.bytes = tmp; + flacData.timestamp = + wire_chnk.timestamp; // store timestamp for + // later use flacData.inData = start; pFlacData = &flacData; @@ -1133,6 +1265,7 @@ static void http_get_task(void *pvParameters) { // need to release mutex // afterwards for next round xSemaphoreGive(decoderReadSemaphore); +#endif break; } @@ -1285,6 +1418,17 @@ static void http_get_task(void *pvParameters) { if (received_header == true) { switch (codec) { case FLAC: { +#if TEST_DECODER_TASK + pFlacData = NULL; // send NULL so we know to wait + // for decoded data in task + // ESP_LOGI(TAG, + // "done sending data + // to queue"); + xQueueSend(flacTaskQHdl, &pFlacData, + portMAX_DELAY); + // ESP_LOGI(TAG, + // "really done"); +#else xSemaphoreGive(decoderWriteSemaphore); // and wait until it is done xQueueReceive(decoderWriteQHdl, &pFlacData, @@ -1321,7 +1465,18 @@ static void http_get_task(void *pvParameters) { insert_pcm_chunk(pcmData); pcmData = NULL; + + // endTime = + // esp_timer_get_time(); + + // ESP_LOGW(TAG, + // "flac + // duration: + // %lldus", + // endTime - + // startTime); } +#endif break; } @@ -1609,6 +1764,11 @@ static void http_get_task(void *pvParameters) { t_flac_decoder_task = NULL; } + if (t_flac_task != NULL) { + vTaskDelete(t_flac_task); + t_flac_task = NULL; + } + if (flacDecoder != NULL) { FLAC__stream_decoder_finish(flacDecoder); FLAC__stream_decoder_delete(flacDecoder); @@ -1625,6 +1785,11 @@ static void http_get_task(void *pvParameters) { decoderReadQHdl = NULL; } + if (flacTaskQHdl != NULL) { + vQueueDelete(flacTaskQHdl); + flacTaskQHdl = NULL; + } + if (codec == OPUS) { ESP_LOGI(TAG, "OPUS not implemented yet"); @@ -1633,8 +1798,9 @@ static void http_get_task(void *pvParameters) { if (t_flac_decoder_task == NULL) { xTaskCreatePinnedToCore( &flac_decoder_task, "flac_decoder_task", - 9 * 256, &scSet, FLAC_TASK_PRIORITY, - &t_flac_decoder_task, FLAC_TASK_CORE_ID); + 9 * 256, &scSet, FLAC_DECODER_TASK_PRIORITY, + &t_flac_decoder_task, + FLAC_DECODER_TASK_CORE_ID); } if (flacData.outData != NULL) { @@ -1669,6 +1835,14 @@ static void http_get_task(void *pvParameters) { ESP_LOGI(TAG, "fLaC sampleformat: %d:%d:%d", scSet.sr, scSet.bits, scSet.ch); +#if TEST_DECODER_TASK + if (t_flac_task == NULL) { + xTaskCreatePinnedToCore( + &flac_task, "flac_task", 9 * 256, &scSet, + FLAC_TASK_PRIORITY, &t_flac_task, + FLAC_TASK_CORE_ID); + } +#endif } else if (codec == PCM) { memcpy(&channels, tmp + 22, sizeof(channels)); uint32_t rate; @@ -1720,7 +1894,7 @@ static void http_get_task(void *pvParameters) { } if ((latency_buffer_full() > 0) && - (timeout < 1000000)) { + (timeout < NORMAL_SYNC_LATENCY_BUF)) { if (esp_timer_is_active(timeSyncMessageTimer)) { esp_timer_stop(timeSyncMessageTimer); } @@ -2191,7 +2365,7 @@ static void http_get_task(void *pvParameters) { reset_latency_buffer(); - timeout = 100000; + timeout = FAST_SYNC_LATENCY_BUF; esp_timer_stop(timeSyncMessageTimer); if (received_header == true) { @@ -2201,7 +2375,7 @@ static void http_get_task(void *pvParameters) { } if ((latency_buffer_full() > 0) && - (timeout < 1000000)) { + (timeout < NORMAL_SYNC_LATENCY_BUF)) { if (esp_timer_is_active(timeSyncMessageTimer)) { esp_timer_stop(timeSyncMessageTimer); } @@ -2217,7 +2391,8 @@ static void http_get_task(void *pvParameters) { (int64_t)tmpDiffToServer.tv_usec); player_latency_insert(newValue); - // ESP_LOGE(TAG, "latency %lld", newValue); + // ESP_LOGE(TAG, "latency + // %lld", newValue); // store current time lastTimeSync.tv_sec = now.tv_sec; @@ -2268,8 +2443,8 @@ static void http_get_task(void *pvParameters) { } if ((latency_buffer_full() > 0) && - (timeout < 1000000)) { - timeout = 1000000; + (timeout < NORMAL_SYNC_LATENCY_BUF)) { + timeout = NORMAL_SYNC_LATENCY_BUF; ESP_LOGI(TAG, "latency buffer full"); @@ -2473,6 +2648,8 @@ void app_main(void) { // menu config or set up provisioning mode settable in menuconfig wifi_init(); + // start_wifi_logger(); + // Enable websocket server ESP_LOGI(TAG, "Connected to AP"); // ESP_LOGI(TAG, "Setup ws server"); diff --git a/sdkconfig b/sdkconfig index 61ae606..ef17219 100644 --- a/sdkconfig +++ b/sdkconfig @@ -50,6 +50,8 @@ CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y # CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set # CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set CONFIG_BOOTLOADER_LOG_LEVEL=3 +# CONFIG_BOOTLOADER_SPI_CUSTOM_WP_PIN is not set +CONFIG_BOOTLOADER_SPI_WP_PIN=7 CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y # CONFIG_BOOTLOADER_FACTORY_RESET is not set # CONFIG_BOOTLOADER_APP_TEST is not set @@ -78,9 +80,9 @@ CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 # CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 # CONFIG_ESPTOOLPY_NO_STUB is not set -# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y # CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set -CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DIO is not set # CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set CONFIG_ESPTOOLPY_FLASHMODE="dio" CONFIG_ESPTOOLPY_FLASHFREQ_80M=y @@ -528,14 +530,14 @@ CONFIG_ESP_TIMER_IMPL_TG0_LAC=y # Wi-Fi # CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 -CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=128 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 # CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=8 # CONFIG_ESP32_WIFI_CSI_ENABLED is not set CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y -CONFIG_ESP32_WIFI_TX_BA_WIN=16 +CONFIG_ESP32_WIFI_TX_BA_WIN=8 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP32_WIFI_RX_BA_WIN=16 CONFIG_ESP32_WIFI_NVS_ENABLED=y @@ -1181,6 +1183,19 @@ CONFIG_WEBSOCKET_SERVER_TASK_STACK_DEPTH=3000 CONFIG_WEBSOCKET_SERVER_TASK_PRIORITY=5 # CONFIG_WEBSOCKET_SERVER_PINNED is not set # end of WebSocket Server + +# +# WiFi Logger configuration +# +CONFIG_TRANSPORT_PROTOCOL_UDP=y +# CONFIG_TRANSPORT_PROTOCOL_TCP is not set +# CONFIG_TRANSPORT_PROTOCOL_WEBSOCKET is not set +CONFIG_ROUTE_ESP_IDF_API_LOGS_TO_WIFI=y +CONFIG_SERVER_IP_ADDRESS="192.168.1.56" +CONFIG_SERVER_PORT=9999 +CONFIG_MESSAGE_QUEUE_SIZE=1000 +CONFIG_BUFFER_SIZE=512 +# end of WiFi Logger configuration # end of Component config # @@ -1201,9 +1216,9 @@ CONFIG_LOG_BOOTLOADER_LEVEL=3 CONFIG_APP_ROLLBACK_ENABLE=y # CONFIG_APP_ANTI_ROLLBACK is not set # CONFIG_FLASH_ENCRYPTION_ENABLED is not set -# CONFIG_FLASHMODE_QIO is not set +CONFIG_FLASHMODE_QIO=y # CONFIG_FLASHMODE_QOUT is not set -CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DIO is not set # CONFIG_FLASHMODE_DOUT is not set # CONFIG_MONITOR_BAUD_9600B is not set # CONFIG_MONITOR_BAUD_57600B is not set diff --git a/sdkconfig.old b/sdkconfig.old index 342a236..a175976 100644 --- a/sdkconfig.old +++ b/sdkconfig.old @@ -50,6 +50,8 @@ CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y # CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set # CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set CONFIG_BOOTLOADER_LOG_LEVEL=3 +# CONFIG_BOOTLOADER_SPI_CUSTOM_WP_PIN is not set +CONFIG_BOOTLOADER_SPI_WP_PIN=7 CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y # CONFIG_BOOTLOADER_FACTORY_RESET is not set # CONFIG_BOOTLOADER_APP_TEST is not set @@ -78,9 +80,9 @@ CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 # CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 # CONFIG_ESPTOOLPY_NO_STUB is not set -# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y # CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set -CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DIO is not set # CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set CONFIG_ESPTOOLPY_FLASHMODE="dio" CONFIG_ESPTOOLPY_FLASHFREQ_80M=y @@ -529,13 +531,13 @@ CONFIG_ESP_TIMER_IMPL_TG0_LAC=y # CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=128 -# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y -CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +# CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=10 # CONFIG_ESP32_WIFI_CSI_ENABLED is not set CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y -CONFIG_ESP32_WIFI_TX_BA_WIN=16 +CONFIG_ESP32_WIFI_TX_BA_WIN=10 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP32_WIFI_RX_BA_WIN=16 CONFIG_ESP32_WIFI_NVS_ENABLED=y @@ -549,7 +551,7 @@ CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 CONFIG_WIFI_LOG_DEFAULT_LEVEL_INFO=y # CONFIG_WIFI_LOG_DEFAULT_LEVEL_DEBUG is not set # CONFIG_WIFI_LOG_DEFAULT_LEVEL_VERBOSE is not set -CONFIG_ESP32_WIFI_IRAM_OPT=y +# CONFIG_ESP32_WIFI_IRAM_OPT is not set CONFIG_ESP32_WIFI_RX_IRAM_OPT=y CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y # CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set @@ -1181,6 +1183,19 @@ CONFIG_WEBSOCKET_SERVER_TASK_STACK_DEPTH=3000 CONFIG_WEBSOCKET_SERVER_TASK_PRIORITY=5 # CONFIG_WEBSOCKET_SERVER_PINNED is not set # end of WebSocket Server + +# +# WiFi Logger configuration +# +CONFIG_TRANSPORT_PROTOCOL_UDP=y +# CONFIG_TRANSPORT_PROTOCOL_TCP is not set +# CONFIG_TRANSPORT_PROTOCOL_WEBSOCKET is not set +CONFIG_ROUTE_ESP_IDF_API_LOGS_TO_WIFI=y +CONFIG_SERVER_IP_ADDRESS="192.168.1.56" +CONFIG_SERVER_PORT=9999 +CONFIG_MESSAGE_QUEUE_SIZE=1000 +CONFIG_BUFFER_SIZE=512 +# end of WiFi Logger configuration # end of Component config # @@ -1201,9 +1216,9 @@ CONFIG_LOG_BOOTLOADER_LEVEL=3 CONFIG_APP_ROLLBACK_ENABLE=y # CONFIG_APP_ANTI_ROLLBACK is not set # CONFIG_FLASH_ENCRYPTION_ENABLED is not set -# CONFIG_FLASHMODE_QIO is not set +CONFIG_FLASHMODE_QIO=y # CONFIG_FLASHMODE_QOUT is not set -CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DIO is not set # CONFIG_FLASHMODE_DOUT is not set # CONFIG_MONITOR_BAUD_9600B is not set # CONFIG_MONITOR_BAUD_57600B is not set