diff --git a/components/dsp_processor/CMakeLists.txt b/components/dsp_processor/CMakeLists.txt index eecdece..6caabe8 100644 --- a/components/dsp_processor/CMakeLists.txt +++ b/components/dsp_processor/CMakeLists.txt @@ -1,10 +1,6 @@ set(COMPONENT_REQUIRES) -set(COMPONENT_PRIV_REQUIRES audio_board audio_sal audio_hal esp-dsp) +set(COMPONENT_PRIV_REQUIRES esp-dsp) list(APPEND COMPONENT_ADD_INCLUDEDIRS ./include) set(COMPONENT_SRCS ./dsp_processor.c) register_component() - -# IDF >=4 -idf_component_get_property(audio_board_lib audio_board COMPONENT_LIB) -set_property(TARGET ${audio_board_lib} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${COMPONENT_LIB}) diff --git a/components/lightsnapcast/CMakeLists.txt b/components/lightsnapcast/CMakeLists.txt index f5921f3..42ed42f 100644 --- a/components/lightsnapcast/CMakeLists.txt +++ b/components/lightsnapcast/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "snapcast.c" "player.c" INCLUDE_DIRS "include" - REQUIRES custom_board libbuffer json libmedian audio_board esp_wifi driver esp_timer) + REQUIRES libbuffer json libmedian esp_wifi driver esp_timer) diff --git a/components/lightsnapcast/include/player.h b/components/lightsnapcast/include/player.h index d4812df..0138832 100644 --- a/components/lightsnapcast/include/player.h +++ b/components/lightsnapcast/include/player.h @@ -63,7 +63,7 @@ typedef struct snapcastSetting_s { uint32_t pcmBufSize; } snapcastSetting_t; -int init_player(void); +int init_player(i2s_std_gpio_config_t pin_config0_, i2s_port_t i2sNum_); int deinit_player(void); int32_t allocate_pcm_chunk_memory(pcm_chunk_message_t **pcmChunk, size_t bytes); diff --git a/components/lightsnapcast/player.c b/components/lightsnapcast/player.c index 9f4de4f..812faf6 100644 --- a/components/lightsnapcast/player.c +++ b/components/lightsnapcast/player.c @@ -24,7 +24,6 @@ #include #include "MedianFilter.h" -#include "board_pins_config.h" #include "driver/gptimer.h" #include "driver/i2s_std.h" #include "player.h" @@ -99,11 +98,14 @@ static bool gpTimerRunning = false; static void player_task(void *pvParameters); -extern esp_err_t audio_set_mute(bool mute); +extern void audio_set_mute(bool mute); static i2s_chan_handle_t tx_chan = NULL; // I2S tx channel handler static bool i2sEnabled = false; +i2s_std_gpio_config_t pin_config0; +i2s_port_t i2sNum; + /** * */ @@ -137,8 +139,25 @@ esp_err_t my_i2s_channel_enable(i2s_chan_handle_t handle) { /** * */ -static esp_err_t player_setup_i2s(i2s_port_t i2sNum, - snapcastSetting_t *setting) { +static esp_err_t player_setup_i2s(snapcastSetting_t *setting) { + // ensure save setting + int32_t sr = setting->sr; + if (sr == 0) { + sr = 44100; + } + + // ensure save setting + int bits = setting->bits; + if (bits == 0) { + bits = I2S_DATA_BIT_WIDTH_16BIT; + } + + // ensure save setting + uint32_t chkInFrames = setting->chkInFrames; + if (chkInFrames == 0) { + chkInFrames = 1152; + } + #if USE_SAMPLE_INSERTION i2sDmaBufCnt = 22; // OPUS has a minimum frame size of 120 @@ -153,7 +172,7 @@ static esp_err_t player_setup_i2s(i2s_port_t i2sNum, int __dmaBufLen; __dmaBufCnt = 1; - __dmaBufLen = setting->chkInFrames; + __dmaBufLen = chkInFrames; while ((__dmaBufLen >= __dmaBufMaxLen) || (__dmaBufCnt <= 1)) { if ((__dmaBufLen % 2) == 0) { __dmaBufCnt *= 2; @@ -170,11 +189,11 @@ static esp_err_t player_setup_i2s(i2s_port_t i2sNum, i2sDmaBufMaxLen = __dmaBufLen; // check i2s_set_get_apll_freq() how it is done - fi2s_clk = 2 * setting->sr * - I2S_MCLK_MULTIPLE_256; // setting->ch * setting->bits * m_scale; + fi2s_clk = + 2 * sr * I2S_MCLK_MULTIPLE_256; // setting->ch * setting->bits * m_scale; - apll_normal_predefine[0] = setting->bits; - apll_normal_predefine[1] = setting->sr; + apll_normal_predefine[0] = bits; + apll_normal_predefine[1] = sr; if (rtc_clk_apll_coeff_calc( fi2s_clk, &apll_normal_predefine[5], &apll_normal_predefine[2], &apll_normal_predefine[3], &apll_normal_predefine[4]) == 0) { @@ -184,16 +203,16 @@ static esp_err_t player_setup_i2s(i2s_port_t i2sNum, #define UPPER_SR_SCALER 1.0001 #define LOWER_SR_SCALER 0.9999 - apll_corr_predefine[0][0] = setting->bits; - apll_corr_predefine[0][1] = setting->sr * UPPER_SR_SCALER; + apll_corr_predefine[0][0] = bits; + apll_corr_predefine[0][1] = sr * UPPER_SR_SCALER; if (rtc_clk_apll_coeff_calc( fi2s_clk * UPPER_SR_SCALER, &apll_corr_predefine[0][5], &apll_corr_predefine[0][2], &apll_corr_predefine[0][3], &apll_corr_predefine[0][4]) == 0) { ESP_LOGE(TAG, "ERROR, fi2s_clk * %f", UPPER_SR_SCALER); } - apll_corr_predefine[1][0] = setting->bits; - apll_corr_predefine[1][1] = setting->sr * LOWER_SR_SCALER; + apll_corr_predefine[1][0] = bits; + apll_corr_predefine[1][1] = sr * LOWER_SR_SCALER; if (rtc_clk_apll_coeff_calc( fi2s_clk * LOWER_SR_SCALER, &apll_corr_predefine[1][5], &apll_corr_predefine[1][2], &apll_corr_predefine[1][3], @@ -217,21 +236,6 @@ static esp_err_t player_setup_i2s(i2s_port_t i2sNum, }; ESP_ERROR_CHECK(i2s_new_channel(&tx_chan_cfg, &tx_chan, NULL)); - board_i2s_pin_t pin_config0; - get_i2s_pins(i2sNum, &pin_config0); - - // ensure save setting - int32_t sr = setting->sr; - if (sr == 0) { - sr = 44100; - } - - // ensure save setting - int bits = setting->bits; - if (bits == 0) { - bits = I2S_DATA_BIT_WIDTH_16BIT; - } - ESP_LOGI(TAG, "player_setup_i2s: dma_buf_len is %ld, dma_buf_count is %ld, sample " "rate: %ld, bits: %d", @@ -260,35 +264,7 @@ static esp_err_t player_setup_i2s(i2s_port_t i2sNum, .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(bits, I2S_SLOT_MODE_STEREO), #endif - .gpio_cfg = - { - .mclk = pin_config0.mck_io_num, - .bclk = pin_config0.bck_io_num, - .ws = pin_config0.ws_io_num, - .dout = pin_config0.data_out_num, - .din = pin_config0.data_in_num, - .invert_flags = - { -#if CONFIG_INVERT_MCLK_LEVEL - .mclk_inv = true, - -#else - .mclk_inv = false, -#endif - -#if CONFIG_INVERT_BCLK_LEVEL - .bclk_inv = true, -#else - .bclk_inv = false, -#endif - -#if CONFIG_INVERT_WORD_SELECT_LEVEL - .ws_inv = true, -#else - .ws_inv = false, -#endif - }, - }, + .gpio_cfg = pin_config0, }; ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &tx_std_cfg)); @@ -367,11 +343,14 @@ int deinit_player(void) { /** * call before http task creation! */ -int init_player(void) { +int init_player(i2s_std_gpio_config_t pin_config0_, i2s_port_t i2sNum_) { int ret = 0; deinit_player(); + pin_config0 = pin_config0_; + i2sNum = i2sNum_; + currentSnapcastSetting.buf_ms = 0; currentSnapcastSetting.chkInFrames = 0; currentSnapcastSetting.codec = NONE; @@ -386,7 +365,7 @@ int init_player(void) { xSemaphoreGive(snapcastSettingsMux); } - ret = player_setup_i2s(I2S_NUM_0, ¤tSnapcastSetting); + ret = player_setup_i2s(¤tSnapcastSetting); if (ret < 0) { ESP_LOGE(TAG, "player_setup_i2s failed: %d", ret); @@ -1224,7 +1203,7 @@ static void player_task(void *pvParameters) { audio_set_mute(true); my_i2s_channel_disable(tx_chan); - ret = player_setup_i2s(I2S_NUM_0, &__scSet); + ret = player_setup_i2s(&__scSet); if (ret < 0) { ESP_LOGE(TAG, "player_setup_i2s failed: %d", ret); diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 523ded6..1364c75 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,7 +1,8 @@ idf_component_register(SRCS "main.c" INCLUDE_DIRS "." - PRIV_REQUIRES esp_timer esp_wifi nvs_flash audio_board audio_hal audio_sal net_functions opus flac ota_server - ui_http_server network_interface + + PRIV_REQUIRES esp_timer esp_wifi nvs_flash wifi_interface audio_board audio_hal audio_sal net_functions opus flac ota_server + ui_http_server network_interface custom_board ) set_source_files_properties(main.c PROPERTIES COMPILE_FLAGS -Wno-implicit-fallthrough) diff --git a/main/main.c b/main/main.c index 8868030..3345663 100644 --- a/main/main.c +++ b/main/main.c @@ -100,7 +100,6 @@ TaskHandle_t t_http_get_task = NULL; #define NORMAL_SYNC_LATENCY_BUF 1000000 // in µs struct timeval tdif, tavg; -static audio_board_handle_t board_handle = NULL; /* snapast parameters; configurable in menuconfig */ #define SNAPCAST_SERVER_USE_MDNS CONFIG_SNAPSERVER_USE_MDNS @@ -134,6 +133,15 @@ dspFlows_t dspFlow = dspfEQBassTreble; #endif #endif +typedef struct audioDACdata_s { + bool mute; + int volume; +} audioDACdata_t; + +audioDACdata_t audioDAC_data; +static QueueHandle_t audioDACQHdl = NULL; +SemaphoreHandle_t audioDACSemaphore = NULL; + typedef struct decoderData_s { uint32_t type; // should be SNAPCAST_MESSAGE_CODEC_HEADER // or SNAPCAST_MESSAGE_WIRE_CHUNK @@ -404,14 +412,35 @@ void error_callback(const FLAC__StreamDecoder *decoder, /** * */ -esp_err_t audio_set_mute(bool mute) { - if (!board_handle) { - ESP_LOGW(TAG, "audio board not initialized yet"); +void init_snapcast(QueueHandle_t audioQHdl) { + audioDACQHdl = audioQHdl; + audioDACSemaphore = xSemaphoreCreateMutex(); + audioDAC_data.mute = true; + audioDAC_data.volume = 100; +} - return ESP_OK; - } else { - return audio_hal_set_mute(board_handle->audio_hal, mute); +/** + * + */ +void audio_set_mute(bool mute) { + xSemaphoreTake(audioDACSemaphore, portMAX_DELAY); + if (mute != audioDAC_data.mute) { + audioDAC_data.mute = mute; + xQueueOverwrite(audioDACQHdl, &audioDAC_data); } + xSemaphoreGive(audioDACSemaphore); +} + +/** + * + */ +void audio_set_volume(int volume) { + xSemaphoreTake(audioDACSemaphore, portMAX_DELAY); + if (volume != audioDAC_data.volume) { + audioDAC_data.volume = volume; + xQueueOverwrite(audioDACQHdl, &audioDAC_data); + } + xSemaphoreGive(audioDACSemaphore); } #define INTERFACE_ETH 0 @@ -2259,8 +2288,7 @@ static void http_get_task(void *pvParameters) { (double)server_settings_message.volume / 100); } #endif - audio_hal_set_mute(board_handle->audio_hal, - server_settings_message.muted); + audio_set_mute(server_settings_message.muted); } if (scSet.volume != server_settings_message.volume) { @@ -2270,9 +2298,7 @@ static void http_get_task(void *pvParameters) { (double)server_settings_message.volume / 100); } #else - audio_hal_set_volume( - board_handle->audio_hal, - server_settings_message.volume); + audio_set_volume(server_settings_message.volume); #endif } @@ -2675,6 +2701,9 @@ void app_main(void) { gpio_config(&cfg); #endif + board_i2s_pin_t pin_config0; + get_i2s_pins(I2S_NUM_0, &pin_config0); + #if CONFIG_AUDIO_BOARD_CUSTOM && CONFIG_DAC_ADAU1961 // some codecs need i2s mclk for initialization @@ -2689,9 +2718,6 @@ void app_main(void) { }; ESP_ERROR_CHECK(i2s_new_channel(&tx_chan_cfg, &tx_chan, NULL)); - board_i2s_pin_t pin_config0; - get_i2s_pins(I2S_NUM_0, &pin_config0); - i2s_std_clk_config_t i2s_clkcfg = { .sample_rate_hz = 44100, .clk_src = I2S_CLK_SRC_APLL, @@ -2723,7 +2749,7 @@ void app_main(void) { #endif ESP_LOGI(TAG, "Start codec chip"); - board_handle = audio_board_init(); + audio_board_handle_t board_handle = audio_board_init(); if (board_handle) { ESP_LOGI(TAG, "Audio board_init done"); } else { @@ -2748,13 +2774,42 @@ void app_main(void) { #endif // ESP_LOGI(TAG, "init player"); - init_player(); + i2s_std_gpio_config_t i2s_pin_config0 = { + .mclk = pin_config0.mck_io_num, + .bclk = pin_config0.bck_io_num, + .ws = pin_config0.ws_io_num, + .dout = pin_config0.data_out_num, + .din = pin_config0.data_in_num, + .invert_flags = + { +#if CONFIG_INVERT_MCLK_LEVEL + .mclk_inv = true, + +#else + .mclk_inv = false, +#endif + +#if CONFIG_INVERT_BCLK_LEVEL + .bclk_inv = true, +#else + .bclk_inv = false, +#endif + +#if CONFIG_INVERT_WORD_SELECT_LEVEL + .ws_inv = true, +#else + .ws_inv = false, +#endif + }, + }; + + QueueHandle_t audioQHdl = xQueueCreate(1, sizeof(audioDACdata_t)); + + init_snapcast(audioQHdl); + init_player(i2s_pin_config0, I2S_NUM_0); // ensure there is no noise from DAC { - board_i2s_pin_t pin_config0; - get_i2s_pins(I2S_NUM_0, &pin_config0); - gpio_config_t gpioCfg = { .pin_bit_mask = BIT64(pin_config0.mck_io_num) | BIT64(pin_config0.data_out_num) | @@ -2822,4 +2877,22 @@ void app_main(void) { // continue; // } // } + + audioDACdata_t dac_data; + audioDACdata_t dac_data_old = { + .mute = true, + .volume = 100, + }; + + while (1) { + if (xQueueReceive(audioQHdl, &dac_data, portMAX_DELAY) == pdTRUE) { + if (dac_data.mute != dac_data_old.mute) { + audio_hal_set_mute(board_handle->audio_hal, dac_data.mute); + } + if (dac_data.volume != dac_data_old.volume) { + audio_hal_set_volume(board_handle->audio_hal, dac_data.volume); + } + dac_data_old = dac_data; + } + } }