mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-07 12:07:09 +03:00
full i2s fix & loudness limited log
This commit is contained in:
@@ -170,7 +170,7 @@ static void raop_sink_start(nm_state_t state_id, int sub_state) {
|
|||||||
esp_netif_get_mac(netif, mac);
|
esp_netif_get_mac(netif, mac);
|
||||||
cmd_handler_chain = raop_cbs.cmd;
|
cmd_handler_chain = raop_cbs.cmd;
|
||||||
|
|
||||||
LOG_INFO( "Starting Airplay for ip %s with servicename %s", inet_ntoa(ipInfo.ip.addr), sink_name);
|
LOG_INFO( "starting Airplay for ip %s with servicename %s", inet_ntoa(ipInfo.ip.addr), sink_name);
|
||||||
raop = raop_create(ipInfo.ip.addr, sink_name, mac, 0, cmd_handler, raop_cbs.data);
|
raop = raop_create(ipInfo.ip.addr, sink_name, mac, 0, cmd_handler, raop_cbs.data);
|
||||||
free(sink_name);
|
free(sink_name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ cspotPlayer::cspotPlayer(const char* name, httpd_handle_t server, int port, cspo
|
|||||||
|
|
||||||
cJSON *item, *config = config_alloc_get_cjson("cspot_config");
|
cJSON *item, *config = config_alloc_get_cjson("cspot_config");
|
||||||
if ((item = cJSON_GetObjectItem(config, "volume")) != NULL) volume = item->valueint;
|
if ((item = cJSON_GetObjectItem(config, "volume")) != NULL) volume = item->valueint;
|
||||||
if ((item = cJSON_GetObjectItem(config, "bitrate")) != NULL) bitrate = item->valueint;
|
if ((item = cJSON_GetObjectItem(config, "bitrate")) != NULL) bitrate = item->valueint;
|
||||||
if ((item = cJSON_GetObjectItem(config, "deviceName") ) != NULL) this->name = item->valuestring;
|
if ((item = cJSON_GetObjectItem(config, "deviceName") ) != NULL) this->name = item->valuestring;
|
||||||
else this->name = name;
|
else this->name = name;
|
||||||
cJSON_Delete(config);
|
cJSON_Delete(config);
|
||||||
@@ -306,8 +306,9 @@ void cspotPlayer::runTask() {
|
|||||||
// Register mdns service, for spotify to find us
|
// Register mdns service, for spotify to find us
|
||||||
bell::MDNSService::registerService( blob->getDeviceName(), "_spotify-connect", "_tcp", "", serverPort,
|
bell::MDNSService::registerService( blob->getDeviceName(), "_spotify-connect", "_tcp", "", serverPort,
|
||||||
{ {"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"} });
|
{ {"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"} });
|
||||||
|
|
||||||
|
CSPOT_LOG(info, "CSpot instance service name %s (id %s)", blob->getDeviceName().c_str(), blob->getDeviceId().c_str());
|
||||||
|
|
||||||
static int count = 0;
|
|
||||||
// gone with the wind...
|
// gone with the wind...
|
||||||
while (1) {
|
while (1) {
|
||||||
clientConnected.wait();
|
clientConnected.wait();
|
||||||
|
|||||||
@@ -163,15 +163,11 @@ static bool cmd_handler(cspot_event_t event, ...) {
|
|||||||
*/
|
*/
|
||||||
static void cspot_sink_start(nm_state_t state_id, int sub_state) {
|
static void cspot_sink_start(nm_state_t state_id, int sub_state) {
|
||||||
const char *hostname;
|
const char *hostname;
|
||||||
uint8_t mac[6];
|
|
||||||
|
|
||||||
cmd_handler_chain = cspot_cbs.cmd;
|
cmd_handler_chain = cspot_cbs.cmd;
|
||||||
network_get_hostname(&hostname);
|
network_get_hostname(&hostname);
|
||||||
|
|
||||||
esp_netif_get_mac(network_get_active_interface(), mac);
|
ESP_LOGI(TAG, "starting Spotify on host %s", hostname);
|
||||||
for (int i = 0; i < 6; i++) sprintf(deviceId + 2*i, "%02x", mac[i]);
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Starting Spotify (CSpot) servicename %s with id %s", hostname, deviceId);
|
|
||||||
|
|
||||||
int port;
|
int port;
|
||||||
httpd_handle_t server = http_get_server(&port);
|
httpd_handle_t server = http_get_server(&port);
|
||||||
|
|||||||
@@ -64,13 +64,17 @@ static const float loudness_envelope_coefficients[EQ_BANDS][POLYNOME_COUNT] = {
|
|||||||
* calculate loudness gains
|
* calculate loudness gains
|
||||||
*/
|
*/
|
||||||
static void calculate_loudness(void) {
|
static void calculate_loudness(void) {
|
||||||
|
char trace[EQ_BANDS * 5 + 1];
|
||||||
|
size_t n = 0;
|
||||||
for (int i = 0; i < EQ_BANDS; i++) {
|
for (int i = 0; i < EQ_BANDS; i++) {
|
||||||
for (int j = 0; j < POLYNOME_COUNT && equalizer.loudness != 0; j++) {
|
for (int j = 0; j < POLYNOME_COUNT && equalizer.loudness != 0; j++) {
|
||||||
equalizer.loudness_gain[i] +=
|
equalizer.loudness_gain[i] +=
|
||||||
loudness_envelope_coefficients[i][j] * pow(equalizer.volume, j);
|
loudness_envelope_coefficients[i][j] * pow(equalizer.volume, j);
|
||||||
}
|
}
|
||||||
equalizer.loudness_gain[i] *= equalizer.loudness / 2;
|
equalizer.loudness_gain[i] *= equalizer.loudness / 2;
|
||||||
|
n += sprintf(trace + n, "%.2g%c", equalizer.loudness_gain[i], i < EQ_BANDS ? ',' : '\0');
|
||||||
}
|
}
|
||||||
|
LOG_INFO("loudness %s", trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
@@ -211,7 +215,6 @@ void equalizer_process(uint8_t *buf, uint32_t bytes) {
|
|||||||
esp_equalizer_set_band_value(equalizer.handle, gain, i, 0);
|
esp_equalizer_set_band_value(equalizer.handle, gain, i, 0);
|
||||||
esp_equalizer_set_band_value(equalizer.handle, gain, i, 1);
|
esp_equalizer_set_band_value(equalizer.handle, gain, i, 1);
|
||||||
active |= gain != 0;
|
active |= gain != 0;
|
||||||
LOG_INFO("EQUALIZER INDEX %u => gain:%.2f, loudness:%.2f,", i, equalizer.gain[i], equalizer.loudness_gain[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// at the end do not activate equalizer if all gain are 0
|
// at the end do not activate equalizer if all gain are 0
|
||||||
|
|||||||
@@ -54,11 +54,22 @@ sure that using rate_delay would fix that
|
|||||||
#define FRAME_BLOCK MAX_SILENCE_FRAMES
|
#define FRAME_BLOCK MAX_SILENCE_FRAMES
|
||||||
#define SPDIF_BLOCK 256
|
#define SPDIF_BLOCK 256
|
||||||
|
|
||||||
// must have an integer ratio with FRAME_BLOCK (see spdif comment)
|
/* we produce FRAME_BLOCK (2048) per loop of the i2s thread so it's better if they fit
|
||||||
#define DMA_SIZE 6144
|
* inside a set of DMA buffer nicely, i.e. DMA_BUF_FRAMES * DMA_BUF_COUNT is a multiple
|
||||||
// FRAME_BLOCK must be a multiple of DMA_BUF_LEN no matter what
|
* of FRAME_BLOCK so that each DMA buffer is filled and we fully empty a FRAME_BLOCK at
|
||||||
#define DMA_BUF_LEN FRAME_BLOCK
|
* each loop. Because one DMA buffer in esp32 is 4092 or below, when using 16 bits
|
||||||
#define DMA_BUF_COUNT (DMA_SIZE / DMA_BUF_LEN)
|
* samples and 2 channels, the best multiple is 512 (512*2*2=2048) and we use 6 of these.
|
||||||
|
* In SPDIF, as we virtually use 32 bits per sample, the next proper multiple would
|
||||||
|
* be 256 but such DMA buffers are too small and this causes stuttering. So we will use
|
||||||
|
* non-multiples which means that at every loop one DMA buffer will be not fully filled.
|
||||||
|
* At least, let's make sure it's not a too small amount of samples so 450*4*2=3600 fits
|
||||||
|
* nicely in one DMA buffer and 2048/450 = 4 buffers + ~1/2 buffer which is acceptable.
|
||||||
|
*/
|
||||||
|
#define DMA_BUF_FRAMES 512
|
||||||
|
#define DMA_BUF_COUNT 12
|
||||||
|
|
||||||
|
#define DMA_BUF_FRAMES_SPDIF 450
|
||||||
|
#define DMA_BUF_COUNT_SPDIF 7
|
||||||
|
|
||||||
#define DECLARE_ALL_MIN_MAX \
|
#define DECLARE_ALL_MIN_MAX \
|
||||||
DECLARE_MIN_MAX(o); \
|
DECLARE_MIN_MAX(o); \
|
||||||
@@ -262,6 +273,8 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
|
|||||||
i2s_config.use_apll = true;
|
i2s_config.use_apll = true;
|
||||||
#endif
|
#endif
|
||||||
i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1; //Interrupt level 1
|
i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1; //Interrupt level 1
|
||||||
|
i2s_config.dma_buf_len = DMA_BUF_FRAMES;
|
||||||
|
i2s_config.dma_buf_count = DMA_BUF_COUNT;
|
||||||
|
|
||||||
if (strcasestr(device, "spdif")) {
|
if (strcasestr(device, "spdif")) {
|
||||||
spdif.enabled = true;
|
spdif.enabled = true;
|
||||||
@@ -278,14 +291,14 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
|
|||||||
i2s_config.sample_rate = output.current_sample_rate * 2;
|
i2s_config.sample_rate = output.current_sample_rate * 2;
|
||||||
i2s_config.bits_per_sample = 32;
|
i2s_config.bits_per_sample = 32;
|
||||||
// Normally counted in frames, but 16 sample are transformed into 32 bits in spdif
|
// Normally counted in frames, but 16 sample are transformed into 32 bits in spdif
|
||||||
i2s_config.dma_buf_len = DMA_BUF_LEN / 2;
|
i2s_config.dma_buf_len = DMA_BUF_FRAMES_SPDIF;
|
||||||
i2s_config.dma_buf_count = DMA_BUF_COUNT * 2;
|
i2s_config.dma_buf_count = DMA_BUF_COUNT_SPDIF;
|
||||||
/*
|
/*
|
||||||
In DMA, we have room for (LEN * COUNT) frames of 32 bits samples that
|
In DMA, we have room for (LEN * COUNT) frames of 32 bits samples that
|
||||||
we push at sample_rate * 2. Each of these pseudo-frames is a single true
|
we push at sample_rate * 2. Each of these pseudo-frames is a single true
|
||||||
audio frame. So the real depth in true frames is (LEN * COUNT / 2)
|
audio frame. So the real depth in true frames is (LEN * COUNT / 2)
|
||||||
*/
|
*/
|
||||||
dma_buf_frames = DMA_BUF_COUNT * DMA_BUF_LEN / 2;
|
dma_buf_frames = i2s_config.dma_buf_len * i2s_config.dma_buf_count / 2;
|
||||||
|
|
||||||
// silence DAC output if sharing the same ws/bck
|
// silence DAC output if sharing the same ws/bck
|
||||||
if (i2s_dac_pin.ws_io_num == i2s_spdif_pin.ws_io_num && i2s_dac_pin.bck_io_num == i2s_spdif_pin.bck_io_num) silent_do = i2s_dac_pin.data_out_num;
|
if (i2s_dac_pin.ws_io_num == i2s_spdif_pin.ws_io_num && i2s_dac_pin.bck_io_num == i2s_spdif_pin.bck_io_num) silent_do = i2s_dac_pin.data_out_num;
|
||||||
@@ -297,9 +310,9 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
|
|||||||
i2s_config.sample_rate = output.current_sample_rate;
|
i2s_config.sample_rate = output.current_sample_rate;
|
||||||
i2s_config.bits_per_sample = BYTES_PER_FRAME * 8 / 2;
|
i2s_config.bits_per_sample = BYTES_PER_FRAME * 8 / 2;
|
||||||
// Counted in frames (but i2s allocates a buffer <= 4092 bytes)
|
// Counted in frames (but i2s allocates a buffer <= 4092 bytes)
|
||||||
i2s_config.dma_buf_len = DMA_BUF_LEN;
|
i2s_config.dma_buf_len = DMA_BUF_FRAMES;
|
||||||
i2s_config.dma_buf_count = DMA_BUF_COUNT;
|
i2s_config.dma_buf_count = DMA_BUF_COUNT;
|
||||||
dma_buf_frames = DMA_BUF_COUNT * DMA_BUF_LEN;
|
dma_buf_frames = i2s_config.dma_buf_len * i2s_config.dma_buf_count;
|
||||||
|
|
||||||
// silence SPDIF output
|
// silence SPDIF output
|
||||||
silent_do = i2s_spdif_pin.data_out_num;
|
silent_do = i2s_spdif_pin.data_out_num;
|
||||||
|
|||||||
Reference in New Issue
Block a user