From 3e038dd64f326e10e28a362b373055497fb2d5c9 Mon Sep 17 00:00:00 2001 From: raul Date: Sun, 4 Dec 2022 22:35:43 +0100 Subject: [PATCH] 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;