From 9d0a17552c91488f0d6cb6e831f32bc401de079e Mon Sep 17 00:00:00 2001 From: raul Date: Sun, 4 Dec 2022 17:12:01 +0100 Subject: [PATCH 1/5] read audio data as 32 bit in dsp_processor --- components/dsp_processor/dsp_processor.c | 26 ++++++++---------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/components/dsp_processor/dsp_processor.c b/components/dsp_processor/dsp_processor.c index 8aa6f51..9bf7e26 100644 --- a/components/dsp_processor/dsp_processor.c +++ b/components/dsp_processor/dsp_processor.c @@ -44,6 +44,7 @@ dsp_processor (char *audio, size_t chunk_size, dspFlows_t dspFlow) int16_t len = chunk_size / 4; int16_t valint; uint16_t i; + volatile uint32_t *audio_tmp = (uint32_t *)audio; //volatile needed to ensure 32 bit access if ((sbuffer0 == NULL) || (sbufout0 == NULL) || (sbuftmp0 == NULL)) { @@ -66,8 +67,7 @@ dsp_processor (char *audio, size_t chunk_size, dspFlows_t dspFlow) for (i = 0; i < len; i++) { sbuffer0[i] = dynamic_vol * 0.5 - * ((float)((int16_t) (audio[i * 4 + 1] << 8) - + audio[i * 4 + 0])) + * ((float)((int16_t)(audio_tmp[i] & 0xFFFF))) / 32768; } BIQUAD (sbuffer0, sbufout0, len, bq[6].coeffs, bq[6].w); @@ -75,17 +75,14 @@ dsp_processor (char *audio, size_t chunk_size, dspFlows_t dspFlow) for (i = 0; i < len; i++) { valint = (int16_t) (sbufout0[i] * 32768); - - audio[i * 4 + 0] = (valint & 0x00ff); - audio[i * 4 + 1] = ((valint & 0xff00) >> 8); + audio_tmp[i] = (audio_tmp[i]&0xFFFF0000) + (uint32_t)valint; } // channel 1 for (i = 0; i < len; i++) { sbuffer0[i] = dynamic_vol * 0.5 - * ((float)((int16_t) (audio[i * 4 + 3] << 8) - + audio[i * 4 + 2])) + * ((float)((int16_t)((audio_tmp[i] & 0xFFFF0000) >> 16))) / 32768; } BIQUAD (sbuffer0, sbufout0, len, bq[7].coeffs, bq[7].w); @@ -93,8 +90,7 @@ dsp_processor (char *audio, size_t chunk_size, dspFlows_t dspFlow) for (i = 0; i < len; i++) { valint = (int16_t) (sbufout0[i] * 32768); - audio[i * 4 + 2] = (valint & 0x00ff); - audio[i * 4 + 3] = ((valint & 0xff00) >> 8); + audio_tmp[i] = (audio_tmp[i]&0xFFFF) + ((uint32_t)valint << 16); } } break; @@ -105,8 +101,7 @@ dsp_processor (char *audio, size_t chunk_size, dspFlows_t dspFlow) for (i = 0; i < len; i++) { sbuffer0[i] = dynamic_vol * 0.5 - * ((float)((int16_t) (audio[i * 4 + 1] << 8) - + audio[i * 4 + 0])) + * ((float)((int16_t)(audio_tmp[i] & 0xFFFF))) / 32768; } BIQUAD (sbuffer0, sbuftmp0, len, bq[0].coeffs, bq[0].w); @@ -115,16 +110,14 @@ dsp_processor (char *audio, size_t chunk_size, dspFlows_t dspFlow) for (i = 0; i < len; i++) { valint = (int16_t) (sbufout0[i] * 32768); - audio[i * 4 + 0] = (valint & 0x00ff); - audio[i * 4 + 1] = ((valint & 0xff00) >> 8); + audio_tmp[i] = (audio_tmp[i]&0xFFFF0000) + (uint32_t)valint; } // Process audio ch1 HIGH PASS FILTER for (i = 0; i < len; i++) { sbuffer0[i] = dynamic_vol * 0.5 - * ((float)((int16_t) (audio[i * 4 + 3] << 8) - + audio[i * 4 + 2])) + * ((float)((int16_t)((audio_tmp[i] & 0xFFFF0000) >> 16))) / 32768; } BIQUAD (sbuffer0, sbuftmp0, len, bq[2].coeffs, bq[2].w); @@ -133,8 +126,7 @@ dsp_processor (char *audio, size_t chunk_size, dspFlows_t dspFlow) for (i = 0; i < len; i++) { valint = (int16_t) (sbufout0[i] * 32768); - audio[i * 4 + 2] = (valint & 0x00ff); - audio[i * 4 + 3] = ((valint & 0xff00) >> 8); + audio_tmp[i] = (audio_tmp[i]&0xFFFF) + ((uint32_t)valint << 16); } } break; From 3e038dd64f326e10e28a362b373055497fb2d5c9 Mon Sep 17 00:00:00 2001 From: raul Date: Sun, 4 Dec 2022 22:35:43 +0100 Subject: [PATCH 2/5] Add software volume mixer. Add fadeout --- components/dsp_processor/dsp_processor.c | 24 ++++++++- .../dsp_processor/include/dsp_processor.h | 1 + main/Kconfig.projbuild | 8 +++ main/main.c | 50 +++++++++++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/components/dsp_processor/dsp_processor.c b/components/dsp_processor/dsp_processor.c index 9bf7e26..052e38a 100644 --- a/components/dsp_processor/dsp_processor.c +++ b/components/dsp_processor/dsp_processor.c @@ -37,10 +37,11 @@ static uint32_t currentChunkDurationMs = 0; static ptype_t bq[8]; +static double dynamic_vol = 1.0; + int dsp_processor (char *audio, size_t chunk_size, dspFlows_t dspFlow) { - double dynamic_vol = 1.0; int16_t len = chunk_size / 4; int16_t valint; uint16_t i; @@ -58,6 +59,17 @@ dsp_processor (char *audio, size_t chunk_size, dspFlows_t dspFlow) { case dspfStereo: { + //set volume + if (dynamic_vol != 1.0) + { + for (i = 0; i < len; i++) + { + audio_tmp[i] = ((uint32_t) (dynamic_vol + * ((float)((int16_t)((audio_tmp[i] & 0xFFFF0000) >> 16)))) << 16) + + (uint32_t) (dynamic_vol + * ((float)((int16_t)(audio_tmp[i] & 0xFFFF)))); + } + } } break; @@ -374,4 +386,14 @@ dsp_set_xoverfreq (uint8_t freqh, uint8_t freql, uint32_t samplerate) } } } + +void +dsp_set_vol (double volume) +{ + if (volume >= 0 && volume <= 1.0) + { + ESP_LOGI (TAG, "Set volume to %f", volume); + dynamic_vol = volume; + } +} #endif diff --git a/components/dsp_processor/include/dsp_processor.h b/components/dsp_processor/include/dsp_processor.h index 5d8ee95..5865a0c 100644 --- a/components/dsp_processor/include/dsp_processor.h +++ b/components/dsp_processor/include/dsp_processor.h @@ -42,5 +42,6 @@ typedef struct pnode { void dsp_setup_flow(double freq, uint32_t samplerate, uint32_t chunkDurationMs); int dsp_processor(char *audio, size_t chunk_size, dspFlows_t dspFlow); void dsp_set_xoverfreq(uint8_t, uint8_t, uint32_t); +void dsp_set_vol(double volume); #endif /* _DSP_PROCESSOR_H_ */ diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 344c76a..1cb3dbb 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -31,6 +31,14 @@ menu "Snapcast Configuration" default "esp-snapclient" help Name of the client to register the snapserver. + + config SNAPCLIENT_USE_SOFT_VOL + bool "Use software volume" + default false + depends on USE_DSP_PROCESSOR + help + Use software volume mixer instead of hardware mixer. + endmenu menu "SNTP Configuration" diff --git a/main/main.c b/main/main.c index 10cf31b..963c6c7 100644 --- a/main/main.c +++ b/main/main.c @@ -103,6 +103,7 @@ static audio_board_handle_t board_handle = NULL; #endif #define SNAPCAST_BUFF_LEN CONFIG_SNAPCLIENT_BUFF_LEN #define SNAPCAST_CLIENT_NAME CONFIG_SNAPCLIENT_NAME +#define SNAPCAST_USE_SOFT_VOL CONFIG_SNAPCLIENT_USE_SOFT_VOL /* Logging tag */ static const char *TAG = "SC"; @@ -785,6 +786,7 @@ static void http_get_task(void *pvParameters) { uint32_t typedMsgLen = 0; uint32_t offset = 0; uint32_t tmpData = 0; + int flow_drain_counter = 0; #define BASE_MESSAGE_STATE 0 #define TYPED_MESSAGE_STATE 1 @@ -1405,6 +1407,20 @@ static void http_get_task(void *pvParameters) { endTime = esp_timer_get_time(); #if CONFIG_USE_DSP_PROCESSOR + if (flow_drain_counter > 0) { + flow_drain_counter--; + double dynamic_vol = ((double)scSet.volume/100 / (20 - flow_drain_counter)); + if (flow_drain_counter == 0) { +#if SNAPCAST_USE_SOFT_VOL + dsp_set_vol(0.0); +#else + dsp_set_vol(1.0); +#endif + audio_hal_set_mute(board_handle->audio_hal, + server_settings_message.muted); + } + dsp_set_vol(dynamic_vol); + } dsp_setup_flow(500, scSet.sr, scSet.chkDur_ms); dsp_processor(pcmData->fragment->payload, pcmData->fragment->size, dspFlow); @@ -1443,6 +1459,20 @@ static void http_get_task(void *pvParameters) { } #if CONFIG_USE_DSP_PROCESSOR + if (flow_drain_counter > 0) { + flow_drain_counter--; + double dynamic_vol = ((double)scSet.volume/100 / (20 - flow_drain_counter)); + if (flow_drain_counter == 0) { +#if SNAPCAST_USE_SOFT_VOL + dsp_set_vol(0.0); +#else + dsp_set_vol(1.0); +#endif + audio_hal_set_mute(board_handle->audio_hal, + server_settings_message.muted); + } + dsp_set_vol(dynamic_vol); + } dsp_setup_flow(500, scSet.sr, scSet.chkDur_ms); dsp_processor(pcmData->fragment->payload, pcmData->fragment->size, dspFlow); @@ -1982,12 +2012,32 @@ static void http_get_task(void *pvParameters) { // Volume setting using ADF HAL // abstraction if (scSet.muted != server_settings_message.muted) { +#if CONFIG_USE_DSP_PROCESSOR + if (server_settings_message.muted) { + flow_drain_counter = 20; + } + else { + flow_drain_counter = 0; + audio_hal_set_mute(board_handle->audio_hal, + server_settings_message.muted); +#if SNAPCAST_USE_SOFT_VOL + dsp_set_vol((double)server_settings_message.volume/100); +#else + dsp_set_vol(1.0); +#endif + } +#else audio_hal_set_mute(board_handle->audio_hal, server_settings_message.muted); +#endif } if (scSet.volume != server_settings_message.volume) { +#if SNAPCAST_USE_SOFT_VOL + dsp_set_vol((double)server_settings_message.volume/100); +#else audio_hal_set_volume(board_handle->audio_hal, server_settings_message.volume); +#endif } scSet.cDacLat_ms = server_settings_message.latency; From ee4fc197aee95a2d97ea05e7f2c270527f1a1aa5 Mon Sep 17 00:00:00 2001 From: raul Date: Sun, 4 Dec 2022 22:44:34 +0100 Subject: [PATCH 3/5] Remove unused buffer length setting and use host name from settings --- main/Kconfig.projbuild | 8 +------- main/main.c | 3 +-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 1cb3dbb..b0d79a3 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -19,16 +19,10 @@ menu "Snapcast Configuration" depends on !SNAPSERVER_USE_MDNS help Port of the snapserver to connect to. - - config SNAPCLIENT_BUFF_LEN - int "snapcast protocol buffer len" - default 4000 - help - Size of the snapclient protocol messages buffer (in bytes). config SNAPCLIENT_NAME string "snapclient name" - default "esp-snapclient" + default "ESP32-Caster" help Name of the client to register the snapserver. diff --git a/main/main.c b/main/main.c index 963c6c7..36e4145 100644 --- a/main/main.c +++ b/main/main.c @@ -101,7 +101,6 @@ static audio_board_handle_t board_handle = NULL; #define SNAPCAST_SERVER_HOST CONFIG_SNAPSERVER_HOST #define SNAPCAST_SERVER_PORT CONFIG_SNAPSERVER_PORT #endif -#define SNAPCAST_BUFF_LEN CONFIG_SNAPCLIENT_BUFF_LEN #define SNAPCAST_CLIENT_NAME CONFIG_SNAPCLIENT_NAME #define SNAPCAST_USE_SOFT_VOL CONFIG_SNAPCLIENT_USE_SOFT_VOL @@ -723,7 +722,7 @@ static void http_get_task(void *pvParameters) { // init hello message hello_message.mac = mac_address; - hello_message.hostname = "ESP32-Caster"; + hello_message.hostname = SNAPCAST_CLIENT_NAME; hello_message.version = (char *)VERSION_STRING; hello_message.client_name = "libsnapcast"; hello_message.os = "esp32"; From f7a86208e3e5246649dd54a8cfea889cfe9e17a7 Mon Sep 17 00:00:00 2001 From: raul Date: Sun, 4 Dec 2022 23:21:19 +0100 Subject: [PATCH 4/5] fix fadeout --- main/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main/main.c b/main/main.c index 36e4145..336c3d6 100644 --- a/main/main.c +++ b/main/main.c @@ -1411,9 +1411,9 @@ static void http_get_task(void *pvParameters) { double dynamic_vol = ((double)scSet.volume/100 / (20 - flow_drain_counter)); if (flow_drain_counter == 0) { #if SNAPCAST_USE_SOFT_VOL - dsp_set_vol(0.0); + dynamic_vol = 0; #else - dsp_set_vol(1.0); + dynamic_vol = 1; #endif audio_hal_set_mute(board_handle->audio_hal, server_settings_message.muted); @@ -1463,9 +1463,9 @@ static void http_get_task(void *pvParameters) { double dynamic_vol = ((double)scSet.volume/100 / (20 - flow_drain_counter)); if (flow_drain_counter == 0) { #if SNAPCAST_USE_SOFT_VOL - dsp_set_vol(0.0); + dynamic_vol = 0; #else - dsp_set_vol(1.0); + dynamic_vol = 1; #endif audio_hal_set_mute(board_handle->audio_hal, server_settings_message.muted); From b6b295f6d679461a0da514a18aa968530e93ba61 Mon Sep 17 00:00:00 2001 From: raul Date: Sat, 10 Dec 2022 21:54:01 +0100 Subject: [PATCH 5/5] Make dspFlow configurable through menuconfig --- main/Kconfig.projbuild | 16 ++++++++++++++++ main/main.c | 10 +++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index b0d79a3..e8a67e3 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -33,6 +33,22 @@ menu "Snapcast Configuration" help Use software volume mixer instead of hardware mixer. + choice SNAPCLIENT_DSP_FLOW + prompt "DSP flow" + default SNAPCLIENT_DSP_FLOW_STEREO + help + Select the DSP flow to use. + + config SNAPCLIENT_DSP_FLOW_STEREO + bool "Stereo flow" + + config SNAPCLIENT_DSP_FLOW_BASSBOOST + bool "Bassboost flow" + + config SNAPCLIENT_DSP_FLOW_BIAMP + bool "Bi-Amp flow" + endchoice + endmenu menu "SNTP Configuration" diff --git a/main/main.c b/main/main.c index 336c3d6..40657d6 100644 --- a/main/main.c +++ b/main/main.c @@ -113,7 +113,15 @@ extern char mac_address[18]; SemaphoreHandle_t timeSyncSemaphoreHandle = NULL; #if CONFIG_USE_DSP_PROCESSOR -uint8_t dspFlow = dspfStereo; // dspfBiamp; // dspfStereo; // dspfBassBoost; +#if CONFIG_SNAPCLIENT_DSP_FLOW_STEREO +dspFlows_t dspFlow = dspfStereo; // dspfBiamp; // dspfStereo; // dspfBassBoost; +#endif +#if CONFIG_SNAPCLIENT_DSP_FLOW_BASSBOOST +dspFlows_t dspFlow = dspfBassBoost; +#endif +#if CONFIG_SNAPCLIENT_DSP_FLOW_BIAMP +dspFlows_t dspFlow = dspfBiamp; +#endif #endif typedef struct flacData_s {