- decode audio data directly from http_task()

Signed-off-by: Karl Osterseher <karli_o@gmx.at>
This commit is contained in:
Karl Osterseher
2024-03-30 06:19:10 +01:00
Unverified
parent d5f591b1bd
commit bddcaa6017
3 changed files with 524 additions and 408 deletions

View File

@@ -1484,7 +1484,7 @@ static void player_task(void *pvParameters) {
const int64_t shortOffset = SHORT_OFFSET; // µs, softsync
const int64_t miniOffset = MINI_OFFSET; // µs, softsync
const int64_t hardResyncThreshold = 1000; // µs, hard sync
const int64_t hardResyncThreshold = 2000; // µs, hard sync
if (initialSync == 1) {
avg = age;
@@ -1569,6 +1569,25 @@ static void player_task(void *pvParameters) {
usec = diff2Server - sec * 1000000;
msec = usec / 1000;
usec = usec % 1000;
ESP_LOGI(TAG, "%d, %lldus, q %d", dir, avg,
uxQueueMessagesWaiting(pcmChkQHdl));
// ESP_LOGI (TAG, "%d, %lldus, %lldus %llds,
//%lld.%lldms", dir, age, avg, sec, msec, usec);
// ESP_LOGI(TAG, "%d, %lldus, %lldus, %lldus, q:%d", dir, avg,
// shortMedian, miniMedian,
// uxQueueMessagesWaiting(pcmChkQHdl));
// ESP_LOGI( TAG, "8b f
// %d b %d", heap_caps_get_free_size(MALLOC_CAP_8BIT |
// MALLOC_CAP_INTERNAL),
// heap_caps_get_largest_free_block(MALLOC_CAP_8BIT |
// MALLOC_CAP_INTERNAL)); ESP_LOGI( TAG, "32b f %d b %d",
// heap_caps_get_free_size(MALLOC_CAP_32BIT |
// MALLOC_CAP_EXEC), heap_caps_get_largest_free_block
// (MALLOC_CAP_32BIT | MALLOC_CAP_EXEC));
}
dir = 0;

View File

@@ -147,7 +147,7 @@ typedef struct decoderData_s {
// or SNAPCAST_MESSAGE_WIRE_CHUNK
uint8_t *inData;
tv_t timestamp;
pcm_chunk_message_t *outData;
uint8_t *outData;
uint32_t bytes;
} decoderData_t;
@@ -167,6 +167,22 @@ static int id_counter = 0;
static OpusDecoder *opusDecoder = NULL;
static decoderData_t decoderChunk = {
.type = SNAPCAST_MESSAGE_INVALID,
.inData = NULL,
.timestamp = {0, 0},
.outData = NULL,
.bytes = 0,
};
static decoderData_t pcmChunk = {
.type = SNAPCAST_MESSAGE_INVALID,
.inData = NULL,
.timestamp = {0, 0},
.outData = NULL,
.bytes = 0,
};
/**
*
*/
@@ -278,34 +294,48 @@ static FLAC__StreamDecoderReadStatus read_callback(
(void)scSet;
xQueueReceive(decoderReadQHdl, &flacData, portMAX_DELAY);
// xQueueReceive(decoderReadQHdl, &flacData, portMAX_DELAY);
// if (xQueueReceive(decoderReadQHdl, &flacData, pdMS_TO_TICKS(100)))
if (decoderChunk.inData) {
// ESP_LOGI(TAG, "in flac read cb %ld %p", flacData->bytes,
// flacData->inData);
// ESP_LOGI(TAG, "in flac read cb %d %p", flacData->bytes, flacData->inData);
if (flacData->bytes <= 0) {
free_flac_data(flacData);
if (decoderChunk.bytes <= 0) {
// free_flac_data(flacData);
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
}
if (flacData->inData == NULL) {
free_flac_data(flacData);
// if (flacData->inData == NULL) {
// free_flac_data(flacData);
//
// return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
// }
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
}
if (decoderChunk.bytes <= *bytes) {
memcpy(buffer, decoderChunk.inData, decoderChunk.bytes);
*bytes = decoderChunk.bytes;
if (flacData->bytes <= *bytes) {
memcpy(buffer, flacData->inData, flacData->bytes);
*bytes = flacData->bytes;
// ESP_LOGW(TAG, "read all flac inData %d", *bytes);
free(decoderChunk.inData);
decoderChunk.inData = NULL;
decoderChunk.bytes = 0;
} else {
memcpy(buffer, flacData->inData, *bytes);
// ESP_LOGW(TAG, "dind't read all flac inData %d", *bytes);
flacData->inData += *bytes;
flacData->bytes -= *bytes;
memcpy(buffer, decoderChunk.inData, *bytes);
memmove(decoderChunk.inData, decoderChunk.inData + *bytes,
decoderChunk.bytes - *bytes);
decoderChunk.bytes -= *bytes;
decoderChunk.inData =
(uint8_t *)realloc(decoderChunk.inData, decoderChunk.bytes);
ESP_LOGW(TAG, "dind't read all flac inData %d", *bytes);
// flacData->inData += *bytes;
// flacData->bytes -= *bytes;
}
free_flac_data(flacData);
// free_flac_data(flacData);
// xQueueSend (flacReadQHdl, &flacData, portMAX_DELAY);
@@ -314,6 +344,9 @@ static FLAC__StreamDecoderReadStatus read_callback(
// ESP_LOGE(TAG, "%s: data processed", __func__);
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
} else {
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
}
}
/**
@@ -323,10 +356,12 @@ static FLAC__StreamDecoderWriteStatus write_callback(
const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,
const FLAC__int32 *const buffer[], void *client_data) {
size_t i;
decoderData_t *flacData = NULL; // = &flacOutData;
decoderData_t *flacData = NULL;
snapcastSetting_t *scSet = (snapcastSetting_t *)client_data;
int ret = 0;
uint32_t fragmentCnt = 0;
size_t bytes = frame->header.blocksize * frame->header.channels *
frame->header.bits_per_sample / 8;
(void)decoder;
@@ -334,8 +369,8 @@ static FLAC__StreamDecoderWriteStatus write_callback(
// xQueueReceive (flacReadQHdl, &flacData, portMAX_DELAY);
// ESP_LOGI(TAG, "in flac write cb %d %p", frame->header.blocksize,
// flacData);
// ESP_LOGI(TAG, "in flac write cb %ld %d, pcmChunk.bytes %ld",
// frame->header.blocksize, bytes, pcmChunk.bytes);
if (frame->header.channels != scSet->ch) {
ESP_LOGE(TAG,
@@ -352,70 +387,91 @@ static FLAC__StreamDecoderWriteStatus write_callback(
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
if (buffer[0] == NULL) {
ESP_LOGE(TAG, "ERROR: buffer [0] is NULL\n");
ESP_LOGE(TAG, "ERROR: buffer [0] is NULL");
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
if (buffer[1] == NULL) {
ESP_LOGE(TAG, "ERROR: buffer [1] is NULL\n");
ESP_LOGE(TAG, "ERROR: buffer [1] is NULL");
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
flacData = (decoderData_t *)malloc(sizeof(decoderData_t));
if (flacData == NULL) {
pcmChunk.outData =
(uint8_t *)realloc(pcmChunk.outData, pcmChunk.bytes + bytes);
if (!pcmChunk.outData) {
ESP_LOGE(TAG, "%s, failed to allocate PCM chunk payload", __func__);
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
memset(flacData, 0, sizeof(decoderData_t));
flacData->bytes = frame->header.blocksize * frame->header.channels *
(frame->header.bits_per_sample / 8);
ret = allocate_pcm_chunk_memory(&(flacData->outData), flacData->bytes);
// ESP_LOGI (TAG, "mem %p %p %d", flacData->outData,
// flacData->outData->fragment->payload, flacData->bytes);
if (ret == 0) {
pcm_chunk_fragment_t *fragment = flacData->outData->fragment;
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);
// TODO: for now fragmented payload is not supported and the whole
// chunk is expected to be in the first fragment
uint32_t tmpData;
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) {
volatile uint32_t *test =
(volatile uint32_t *)(&(fragment->payload[fragmentCnt]));
*test = (volatile uint32_t)tmpData;
pcmChunk.outData[pcmChunk.bytes + 4 * i] = (uint8_t)(buffer[0][i]);
pcmChunk.outData[pcmChunk.bytes + 4 * i + 1] = (uint8_t)(buffer[0][i] >> 8);
pcmChunk.outData[pcmChunk.bytes + 4 * i + 2] = (uint8_t)(buffer[1][i]);
pcmChunk.outData[pcmChunk.bytes + 4 * i + 3] = (uint8_t)(buffer[1][i] >> 8);
}
fragmentCnt += 4;
if (fragmentCnt >= fragment->size) {
fragmentCnt = 0;
pcmChunk.bytes += bytes;
fragment = fragment->nextFragment;
}
}
}
}
scSet->chkInFrames = frame->header.blocksize;
// flacData = (decoderData_t *)malloc(sizeof(decoderData_t));
// if (flacData == NULL) {
// return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
// }
//
// memset(flacData, 0, sizeof(decoderData_t));
//
// flacData->bytes = frame->header.blocksize * frame->header.channels *
// (frame->header.bits_per_sample / 8);
//
// ret = allocate_pcm_chunk_memory(&(flacData->outData), flacData->bytes);
//
//// ESP_LOGW (TAG, "block size: %ld", frame->header.blocksize);
//
// // ESP_LOGI (TAG, "mem %p %p %d", flacData->outData,
// // flacData->outData->fragment->payload, flacData->bytes);
//
// if (ret == 0) {
// pcm_chunk_fragment_t *fragment = flacData->outData->fragment;
//
// 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);
//
// // TODO: for now fragmented payload is not supported and the whole
// // chunk is expected to be in the first fragment
// uint32_t tmpData;
// 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) {
// volatile uint32_t *test =
// (volatile uint32_t *)(&(fragment->payload[fragmentCnt]));
// *test = (volatile uint32_t)tmpData;
// }
//
// fragmentCnt += 4;
// if (fragmentCnt >= fragment->size) {
// fragmentCnt = 0;
//
// fragment = fragment->nextFragment;
// }
// }
// }
// }
// else {
// flacData->outData = NULL;
// }
xQueueSend(decoderWriteQHdl, &flacData, portMAX_DELAY);
// xQueueSend(decoderWriteQHdl, &flacData, portMAX_DELAY);
// ESP_LOGE(TAG, "%s: data processed", __func__);
@@ -440,14 +496,14 @@ void metadata_callback(const FLAC__StreamDecoder *decoder,
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
// ESP_LOGI(TAG, "in flac meta cb");
flacData = (decoderData_t *)malloc(sizeof(decoderData_t));
if (flacData == NULL) {
ESP_LOGE(TAG, "in flac meta cb, malloc failed");
return;
}
memset(flacData, 0, sizeof(decoderData_t));
// flacData = (decoderData_t *)malloc(sizeof(decoderData_t));
// if (flacData == NULL) {
// ESP_LOGE(TAG, "in flac meta cb, malloc failed");
//
// return;
// }
//
// memset(flacData, 0, sizeof(decoderData_t));
// save for later
scSet->sr = metadata->data.stream_info.sample_rate;
@@ -457,7 +513,7 @@ void metadata_callback(const FLAC__StreamDecoder *decoder,
ESP_LOGI(TAG, "fLaC sampleformat: %ld:%d:%d", scSet->sr, scSet->bits,
scSet->ch);
xQueueSend(decoderWriteQHdl, &flacData, portMAX_DELAY);
// xQueueSend(decoderWriteQHdl, &flacData, portMAX_DELAY);
// ESP_LOGE(TAG, "%s: data processed", __func__);
}
@@ -476,6 +532,9 @@ void error_callback(const FLAC__StreamDecoder *decoder,
FLAC__StreamDecoderErrorStatusString[status]);
}
/**
*
*/
static void flac_decoder_task(void *pvParameters) {
// FLAC__bool ok = true;
FLAC__StreamDecoderInitStatus init_status;
@@ -510,6 +569,22 @@ static void flac_decoder_task(void *pvParameters) {
}
}
/*
* Add one timeval to another.
*/
tv_t timeval_add(tv_t *a, tv_t *b) {
tv_t result;
result.sec = a->sec + b->sec;
result.usec = a->usec + b->usec;
if (result.usec >= 1000000) {
result.sec += 1;
result.usec -= 1000000;
}
return result;
} // timeval_add
/**
*
*/
@@ -517,14 +592,42 @@ void flac_task(void *pvParameters) {
tv_t currentTimestamp;
decoderData_t *pFlacData = NULL;
snapcastSetting_t *scSet = (snapcastSetting_t *)pvParameters;
FLAC__StreamDecoderInitStatus init_status;
if (flacDecoder != NULL) {
FLAC__stream_decoder_finish(flacDecoder);
FLAC__stream_decoder_delete(flacDecoder);
flacDecoder = NULL;
}
flacDecoder = FLAC__stream_decoder_new();
if (flacDecoder == NULL) {
ESP_LOGE(TAG, "Failed to init flac decoder");
return;
}
init_status = FLAC__stream_decoder_init_stream(
flacDecoder, read_callback, NULL, NULL, NULL, NULL, write_callback,
metadata_callback, error_callback, scSet);
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) {
xQueueReceive(decoderTaskQHdl, &pFlacData,
portMAX_DELAY); // get data from tcp task
portMAX_DELAY); // get data from http task
if (pFlacData != NULL) {
currentTimestamp = pFlacData->timestamp;
// ESP_LOGE(TAG, "Got data with length %ld", pFlacData->bytes);
// ESP_LOGE(TAG, "1");
// ESP_LOGE(TAG, "Got timestamp %lld",
// (uint64_t)currentTimestamp.sec * 1000000 +
// (uint64_t)currentTimestamp.usec);
@@ -535,6 +638,7 @@ void flac_task(void *pvParameters) {
// ESP_LOGE(TAG, "%s: decoderReadQHdl start", __func__);
xQueueSend(decoderReadQHdl, &pFlacData, portMAX_DELAY);
// ESP_LOGE(TAG, "2");
// ESP_LOGE(TAG, "%s: decoderReadQHdl done", __func__);
// and wait until data was
@@ -546,24 +650,50 @@ void flac_task(void *pvParameters) {
// free(pFlacData->inData);
// free(pFlacData);
} else {
// }
// else
// {
uint64_t frameCounter = 0;
if (FLAC__stream_decoder_process_until_end_of_stream(flacDecoder) ==
false) {
// if (FLAC__stream_decoder_process_single(flacDecoder) == false) {
ESP_LOGE(TAG, "%s: decoder error", __func__);
}
// else {
// ESP_LOGW(TAG, "%s: decoder done", __func__);
//}
while (xQueueReceive(decoderWriteQHdl, &pFlacData, pdMS_TO_TICKS(10))) {
pcm_chunk_message_t *pcmData = NULL;
// xSemaphoreGive(decoderWriteSemaphore);
// and wait until it is done
// ESP_LOGE(TAG, "%s: decoderWriteQHdl start", __func__);
xQueueReceive(decoderWriteQHdl, &pFlacData, portMAX_DELAY);
// ESP_LOGE(TAG, "%s: decoderWriteQHdl done", __func__);
// ESP_LOGE(TAG, "3");
if (pFlacData->outData != NULL) {
pcmData = pFlacData->outData;
pcmData->timestamp = currentTimestamp;
size_t decodedSize = pcmData->totalSize; // pFlacData->bytes;
scSet->chkInFrames =
decodedSize / ((size_t)scSet->ch * (size_t)(scSet->bits / 8));
tv_t chunkDuration = {
.sec = 0,
.usec =
(frameCounter * 1000000ULL * (uint64_t)scSet->chkInFrames) /
scSet->sr,
};
pcmData->timestamp = currentTimestamp =
timeval_add(&currentTimestamp, &chunkDuration);
frameCounter++;
// ESP_LOGI(TAG, "%s: got one frame of size %ld, timestamp %ld.%ld",
// __func__, scSet->chkInFrames, currentTimestamp.sec,
// currentTimestamp.usec);
// ESP_LOGW(TAG, "got FLAC decoded chunk size: %ld frames",
// scSet->chkInFrames);
if (player_send_snapcast_setting(scSet) != pdPASS) {
ESP_LOGE(TAG,
"Failed to "
@@ -597,6 +727,61 @@ void flac_task(void *pvParameters) {
}
}
}
// else {
// pcm_chunk_message_t *pcmData = NULL;
//
// // xSemaphoreGive(decoderWriteSemaphore);
// // and wait until it is done
// // ESP_LOGE(TAG, "%s: decoderWriteQHdl start", __func__);
//
// xQueueReceive(decoderWriteQHdl, &pFlacData, portMAX_DELAY);
//
// // ESP_LOGE(TAG, "%s: decoderWriteQHdl done", __func__);
//
// if (pFlacData->outData != NULL) {
// pcmData = pFlacData->outData;
// pcmData->timestamp = currentTimestamp;
//
// size_t decodedSize = pcmData->totalSize; // pFlacData->bytes;
// scSet->chkInFrames =
// decodedSize / ((size_t)scSet->ch * (size_t)(scSet->bits / 8));
//
// ESP_LOGW(TAG, "got FLAC decoded chunk size: %ld frames",
// scSet->chkInFrames);
//
// 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_processor_worker(pcmData->fragment->payload,
// pcmData->fragment->size, scSet->sr);
// #endif
//
// insert_pcm_chunk(pcmData);
//
// if (pFlacData->inData) {
// free(pFlacData->inData);
// pFlacData->inData = NULL;
// }
//
// if (pFlacData) {
// free(pFlacData);
// pFlacData = NULL;
// }
// } else {
// free_flac_data(pFlacData);
// }
// }
}
}
/**
@@ -636,6 +821,9 @@ void opus_decoder_task(void *pvParameters) {
scSet->chkInFrames = samples_per_frame;
ESP_LOGW(TAG, "got OPUS decoded chunk size: %ld frames",
scSet->chkInFrames);
size_t bytes = samples_per_frame * scSet->ch * scSet->bits / 8;
if (samples_per_frame > 480) {
@@ -787,10 +975,10 @@ static void http_get_task(void *pvParameters) {
opusDecoder = NULL;
}
if (t_flac_decoder_task != NULL) {
vTaskDelete(t_flac_decoder_task);
t_flac_decoder_task = NULL;
}
// if (t_flac_decoder_task != NULL) {
// vTaskDelete(t_flac_decoder_task);
// t_flac_decoder_task = NULL;
// }
if (dec_task_handle != NULL) {
vTaskDelete(dec_task_handle);
@@ -1001,15 +1189,6 @@ static void http_get_task(void *pvParameters) {
firstNetBuf = NULL;
#define TEST_DECODER_TASK 1
decoderWriteSemaphore = xSemaphoreCreateMutex();
xSemaphoreTake(decoderWriteSemaphore, portMAX_DELAY);
decoderReadSemaphore = xSemaphoreCreateMutex();
xSemaphoreGive(decoderReadSemaphore); // only decoder read callback/task
// can give semaphore
while (1) {
rc2 = netconn_recv(lwipNetconn, &firstNetBuf);
if (rc2 != ERR_OK) {
@@ -1374,9 +1553,19 @@ static void http_get_task(void *pvParameters) {
internalState++;
// ESP_LOGI(TAG,
// "chunk with size: %d, at time"
// " %d.%d", wire_chnk.size,
decoderChunk.bytes = wire_chnk.size;
while (!decoderChunk.inData) {
decoderChunk.inData =
(uint8_t *)malloc(decoderChunk.bytes);
if (!decoderChunk.inData) {
vTaskDelay(pdMS_TO_TICKS(1));
}
}
payloadOffset = 0;
// ESP_LOGI(TAG, "chunk with size: %u, at time %ld.%ld",
// wire_chnk.size,
// wire_chnk.timestamp.sec,
// wire_chnk.timestamp.usec);
@@ -1460,81 +1649,11 @@ static void http_get_task(void *pvParameters) {
}
case FLAC: {
#if TEST_DECODER_TASK
pDecData = NULL;
while (!pDecData) {
pDecData = (decoderData_t *)malloc(
sizeof(decoderData_t));
if (!pDecData) {
vTaskDelay(pdMS_TO_TICKS(1));
}
}
pDecData->bytes = tmp_size;
// store timestamp for
// later use
pDecData->timestamp = wire_chnk.timestamp;
pDecData->inData = NULL;
// while ((!pFlacData->inData) && (mallocCnt < 100))
// {
while (!pDecData->inData) {
pDecData->inData =
(uint8_t *)malloc(pDecData->bytes);
if (!pDecData->inData) {
vTaskDelay(pdMS_TO_TICKS(1));
}
}
if (pDecData->inData) {
memcpy(pDecData->inData, start, tmp_size);
pDecData->outData = NULL;
pDecData->type = SNAPCAST_MESSAGE_WIRE_CHUNK;
// send data to separate task which will handle
// this
xQueueSend(decoderTaskQHdl, &pDecData,
portMAX_DELAY);
}
#else
flacData.bytes = tmp_size;
flacData.timestamp =
wire_chnk.timestamp; // store timestamp for
// later use
flacData.inData = start;
pDecData = &flacData;
startTime = esp_timer_get_time();
xSemaphoreTake(decoderReadSemaphore, portMAX_DELAY);
// send data to flac decoder
xQueueSend(decoderReadQHdl, &pDecData,
portMAX_DELAY);
// and wait until data was
// processed
xSemaphoreTake(decoderReadSemaphore, portMAX_DELAY);
// need to release mutex
// afterwards for next round
xSemaphoreGive(decoderReadSemaphore);
#if 0 // enable heap memory analyzing
{
static uint32_t cnt = 0;
if (++cnt % 8 == 0) {
ESP_LOGI(
TAG, "8bit %d, block %d, 32 bit %d, block %d, waiting %d",
heap_caps_get_free_size(MALLOC_CAP_8BIT),
heap_caps_get_largest_free_block(MALLOC_CAP_8BIT),
heap_caps_get_free_size(MALLOC_CAP_32BIT |
MALLOC_CAP_EXEC),
heap_caps_get_largest_free_block(MALLOC_CAP_32BIT
| MALLOC_CAP_EXEC), pcm_chunk_queue_msg_waiting());
}
}
#endif
#endif
memcpy(&decoderChunk.inData[payloadOffset], start,
tmp_size);
payloadOffset += tmp_size;
decoderChunk.outData = NULL;
decoderChunk.type = SNAPCAST_MESSAGE_WIRE_CHUNK;
break;
}
@@ -1624,37 +1743,95 @@ static void http_get_task(void *pvParameters) {
}
case FLAC: {
#if TEST_DECODER_TASK
pDecData = NULL; // send NULL so we know to wait
// for decoded data in task
while (decoderChunk.bytes > 0) {
if (FLAC__stream_decoder_process_single(
flacDecoder) == 0) {
ESP_LOGE(
TAG,
"%s: FLAC__stream_decoder_process_single "
"failed",
__func__);
// ESP_LOGE(TAG, "%s: flacTaskQHdl start
// wireChnk", __func__);
xQueueSend(decoderTaskQHdl, &pDecData,
portMAX_DELAY);
// ESP_LOGE(TAG, "%s: flacTaskQHdl stop wireChnk",
// __func__);
#else
xSemaphoreGive(decoderWriteSemaphore);
// and wait until it is done
xQueueReceive(decoderWriteQHdl, &pDecData,
portMAX_DELAY);
return;
}
}
if (pDecData->outData != NULL) {
pcmData = pDecData->outData;
pcmData->timestamp = wire_chnk.timestamp;
pcm_chunk_message_t *new_pcmChunk;
int32_t ret = allocate_pcm_chunk_memory(
&new_pcmChunk, pcmChunk.bytes);
size_t decodedSize =
pcmData->totalSize; // pFlacData->bytes;
// ESP_LOGE
//(TAG, "block size: %ld", pcmChunk.bytes /
//(scSet.ch * (scSet.bits/8)));
// ESP_LOGE(TAG,
// "decoded size:
// %d",
// decodedSize);
// ESP_LOGI (TAG, "mem %p %p %d",
// flacData->outData,
// flacData->outData->fragment->payload,
// flacData->bytes);
if (ret == 0) {
pcm_chunk_fragment_t *fragment =
new_pcmChunk->fragment;
uint32_t fragmentCnt = 0;
if (fragment->payload != NULL) {
for (int i = 0;
i < pcmChunk.bytes /
(scSet.ch * (scSet.bits / 8));
i++) {
// TODO: for now fragmented payload is not
// supported and the whole chunk is expected
// to be in the first fragment
uint32_t tmpData;
memcpy(&tmpData,
&pcmChunk.outData[fragmentCnt],
(scSet.ch * (scSet.bits / 8)));
// 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) {
volatile uint32_t *test =
(volatile uint32_t *)(&(
fragment->payload[fragmentCnt]));
*test = (volatile uint32_t)tmpData;
}
fragmentCnt +=
(scSet.ch * (scSet.bits / 8));
if (fragmentCnt >= fragment->size) {
fragmentCnt = 0;
fragment = fragment->nextFragment;
}
}
}
new_pcmChunk->timestamp = wire_chnk.timestamp;
#if CONFIG_USE_DSP_PROCESSOR
if (new_pcmChunk.fragment->payload) {
dsp_processor_worker(
new_pcmChunk.fragment->payload,
new_pcmChunk.fragment->size, scSet.sr);
}
#endif
insert_pcm_chunk(new_pcmChunk);
}
free(pcmChunk.outData);
pcmChunk.outData = NULL;
pcmChunk.bytes = 0;
scSet.chkInFrames =
decodedSize / ((size_t)scSet.ch *
(size_t)(scSet.bits / 8));
if (player_send_snapcast_setting(&scSet) !=
pdPASS) {
ESP_LOGE(TAG,
@@ -1668,36 +1845,14 @@ static void http_get_task(void *pvParameters) {
return;
}
endTime = esp_timer_get_time();
#if CONFIG_USE_DSP_PROCESSOR
if ((pcmData) && (pcmData->fragment->payload)) {
dsp_processor_worker(
pcmData->fragment->payload,
pcmData->fragment->size, scSet.sr);
}
#endif
insert_pcm_chunk(pcmData);
// ESP_LOGE(TAG, "duration = %lld", endTime -
// startTime);
pcmData = NULL;
}
#endif
break;
}
case PCM: {
size_t decodedSize = wire_chnk.size;
// ESP_LOGW(TAG, "got
// PCM chunk,
// typedMsgCurrentPos
// %d",
// ESP_LOGW(TAG, "got PCM chunk,"
// "typedMsgCurrentPos %d",
// typedMsgCurrentPos);
if (pcmData) {
@@ -1708,6 +1863,10 @@ static void http_get_task(void *pvParameters) {
decodedSize /
((size_t)scSet.ch * (size_t)(scSet.bits / 8));
ESP_LOGW(TAG,
"got PCM decoded chunk size: %ld frames",
scSet.chkInFrames);
if (player_send_snapcast_setting(&scSet) !=
pdPASS) {
ESP_LOGE(TAG,
@@ -1982,15 +2141,6 @@ static void http_get_task(void *pvParameters) {
// first ensure everything is set up
// correctly and resources are
// available
if (t_flac_decoder_task != NULL) {
vTaskDelete(t_flac_decoder_task);
t_flac_decoder_task = NULL;
}
if (dec_task_handle != NULL) {
vTaskDelete(dec_task_handle);
dec_task_handle = NULL;
}
if (flacDecoder != NULL) {
FLAC__stream_decoder_finish(flacDecoder);
@@ -1998,36 +2148,14 @@ static void http_get_task(void *pvParameters) {
flacDecoder = NULL;
}
if (decoderWriteQHdl != NULL) {
vQueueDelete(decoderWriteQHdl);
decoderWriteQHdl = NULL;
}
if (decoderReadQHdl != NULL) {
vQueueDelete(decoderReadQHdl);
decoderReadQHdl = NULL;
}
if (decoderTaskQHdl != NULL) {
vQueueDelete(decoderTaskQHdl);
decoderTaskQHdl = NULL;
}
if (opusDecoder != NULL) {
opus_decoder_destroy(opusDecoder);
opusDecoder = NULL;
}
if (codec == OPUS) {
decoderTaskQHdl =
xQueueCreate(8, sizeof(decoderData_t *));
if (decoderTaskQHdl == NULL) {
ESP_LOGE(TAG, "Failed to create decoderTaskQHdl");
return;
}
// ESP_LOGI(TAG, "OPUS not
// implemented yet"); return;
// mplemented yet"); return;
uint16_t channels;
uint32_t rate;
uint16_t bits;
@@ -2062,103 +2190,38 @@ static void http_get_task(void *pvParameters) {
OPUS_TASK_CORE_ID);
}
} else if (codec == FLAC) {
decoderTaskQHdl =
xQueueCreate(8, sizeof(decoderData_t *));
if (decoderTaskQHdl == NULL) {
ESP_LOGE(TAG, "Failed to create decoderTaskQHdl");
decoderChunk.bytes = typedMsgLen;
decoderChunk.inData =
(uint8_t *)malloc(decoderChunk.bytes);
memcpy(decoderChunk.inData, p_tmp, typedMsgLen);
decoderChunk.outData = NULL;
decoderChunk.type = SNAPCAST_MESSAGE_CODEC_HEADER;
flacDecoder = FLAC__stream_decoder_new();
if (flacDecoder == NULL) {
ESP_LOGE(TAG, "Failed to init flac decoder");
return;
}
decoderReadQHdl =
xQueueCreate(1, sizeof(decoderData_t *));
if (decoderReadQHdl == NULL) {
ESP_LOGE(TAG, "Failed to create flac read queue");
FLAC__StreamDecoderInitStatus init_status =
FLAC__stream_decoder_init_stream(
flacDecoder, read_callback, NULL, NULL, NULL,
NULL, write_callback, metadata_callback,
error_callback, &scSet);
if (init_status !=
FLAC__STREAM_DECODER_INIT_STATUS_OK) {
ESP_LOGE(TAG, "ERROR: initializing decoder: %s\n",
FLAC__StreamDecoderInitStatusString
[init_status]);
return;
}
decoderWriteQHdl =
xQueueCreate(1, sizeof(decoderData_t *));
if (decoderWriteQHdl == NULL) {
ESP_LOGE(TAG, "Failed to create flac write queue");
return;
}
FLAC__stream_decoder_process_until_end_of_metadata(
flacDecoder);
if (t_flac_decoder_task == NULL) {
xTaskCreatePinnedToCore(
&flac_decoder_task, "flac_decoder_task",
9 * 256, &scSet, FLAC_DECODER_TASK_PRIORITY,
&t_flac_decoder_task,
FLAC_DECODER_TASK_CORE_ID);
}
#if TEST_DECODER_TASK
if (dec_task_handle == NULL) {
xTaskCreatePinnedToCore(
&flac_task, "flac_task", 9 * 256, &scSet,
FLAC_TASK_PRIORITY, &dec_task_handle,
FLAC_TASK_CORE_ID);
}
pDecData =
(decoderData_t *)malloc(sizeof(decoderData_t));
memset(pDecData, 0, sizeof(decoderData_t));
pDecData->bytes = typedMsgLen;
pDecData->inData = (uint8_t *)malloc(typedMsgLen);
memcpy(pDecData->inData, p_tmp, typedMsgLen);
pDecData->outData = NULL;
pDecData->type = SNAPCAST_MESSAGE_CODEC_HEADER;
// ESP_LOGE(TAG, "%s: flacTaskQHdl start codec
// header", __func__);
// send codec header to flac decoder
xQueueSend(decoderTaskQHdl, &pDecData, portMAX_DELAY);
// ESP_LOGE(TAG, "sent codec header");
// send NULL so we know to wait
// for decoded data in task
pDecData = NULL;
xQueueSend(decoderTaskQHdl, &pDecData, portMAX_DELAY);
// ESP_LOGE(TAG, "%s: flacTaskQHdl done codec header",
// ESP_LOGI(TAG, "%s: processed codec header",
// __func__);
#else
if (flacData.outData != NULL) {
free(flacData.outData);
flacData.outData = NULL;
}
flacData.bytes = typedMsgLen;
flacData.inData = p_tmp;
pDecData = &flacData;
// TODO: find a smarter way for
// this wait for task creation done
while (decoderReadQHdl == NULL) {
vTaskDelay(10);
}
xSemaphoreTake(decoderReadSemaphore, portMAX_DELAY);
// send data to flac decoder
xQueueSend(decoderReadQHdl, &pDecData, portMAX_DELAY);
// and wait until data was
// processed
xSemaphoreTake(decoderReadSemaphore, portMAX_DELAY);
// need to release mutex afterwards
// for next round
xSemaphoreGive(decoderReadSemaphore);
// wait until it is done
xQueueReceive(decoderWriteQHdl, &pDecData,
portMAX_DELAY);
ESP_LOGI(TAG, "fLaC sampleformat: %d:%d:%d", scSet.sr,
scSet.bits, scSet.ch);
#endif
} else if (codec == PCM) {
uint16_t channels;
uint32_t rate;

View File

@@ -358,18 +358,52 @@ CONFIG_USE_SAMPLE_INSERTION=y
#
# Audio HAL
#
# CONFIG_AUDIO_BOARD_CUSTOM is not set
CONFIG_AUDIO_BOARD_CUSTOM=y
# CONFIG_ESP_LYRAT_V4_3_BOARD is not set
# CONFIG_ESP_LYRAT_V4_2_BOARD is not set
# CONFIG_ESP_LYRATD_MSC_V2_1_BOARD is not set
# CONFIG_ESP_LYRATD_MSC_V2_2_BOARD is not set
# CONFIG_ESP_LYRAT_MINI_V1_1_BOARD is not set
CONFIG_ESP32_KORVO_DU1906_BOARD=y
CONFIG_ESP32_KORVO_DU1906_DAC_TAS5805M=y
# CONFIG_ESP32_KORVO_DU1906_DAC_ES7148 is not set
CONFIG_ESP32_KORVO_DU1906_ADC_ES7243=y
# CONFIG_ESP32_KORVO_DU1906_BOARD is not set
# end of Audio HAL
#
# Custom Audio Board
#
# CONFIG_DAC_PCM51XX is not set
# CONFIG_DAC_PCM5102A is not set
# CONFIG_DAC_MA120 is not set
# CONFIG_DAC_MA120X0 is not set
CONFIG_DAC_ADAU1961=y
# CONFIG_DAC_MAX98357 is not set
#
# DAC I2C control interface
#
CONFIG_DAC_I2C_SDA=12
CONFIG_DAC_I2C_SCL=14
CONFIG_DAC_I2C_ADDR=0x70
# end of DAC I2C control interface
#
# I2S master interface
#
CONFIG_MASTER_I2S_MCLK_PIN=3
CONFIG_MASTER_I2S_BCK_PIN=15
CONFIG_MASTER_I2S_LRCK_PIN=13
CONFIG_MASTER_I2S_DATAOUT_PIN=4
# end of I2S master interface
#
# I2S slave interface
#
CONFIG_SLAVE_I2S_MCLK_PIN=0
CONFIG_SLAVE_I2S_BCK_PIN=26
CONFIG_SLAVE_I2S_LRCK_PIN=12
CONFIG_SLAVE_I2S_DATAOUT_PIN=5
# end of I2S slave interface
# end of Custom Audio Board
#
# ESP32 DSP processor config
#