Page 1 of 1

I2S Audio Crackling / Pops

Posted: Wed Feb 28, 2018 11:15 pm
by boogle
I'm having some trouble getting I2S audio to play how I'd like it to. When connected directly to Adafruit's MAX98357A breakout I get the occasional light pop at the start / end of the audio stream. It's not terrible and I can suppress it by ensuring audio samples fade in/out.

However, if I relay the audio through to another ESP32 I get fairly bad crackling throughout the audio playback. So the flow is: Embedded wave file > ESP32[1] I2S Output > ESP32[2] I2S Input > ESP32[2] I2S Output > MAX98357A Breakout.
The flow in bold is the problematic one.

The I2S relay setup looks like this:

Code: Select all

// Input
inputPortNum = I2S_NUM_0;

inputI2sConfig.mode = (i2s_mode_t)(I2S_MODE_SLAVE | I2S_MODE_RX);
inputI2sConfig.sample_rate = 44100;
inputI2sConfig.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
inputI2sConfig.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT;
inputI2sConfig.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB);
inputI2sConfig.dma_buf_count = 4;
inputI2sConfig.dma_buf_len = 440;
inputI2sConfig.intr_alloc_flags = 0;
inputI2sConfig.use_apll = true;

inputPinConfig.bck_io_num = PIN_I2S_BCLK_INPUT;
inputPinConfig.ws_io_num = PIN_I2S_LRC_INPUT;
inputPinConfig.data_out_num = -1; // Not used
inputPinConfig.data_in_num = PIN_I2S_DATA_INPUT;

ESP_ERROR_CHECK(i2s_driver_install(inputPortNum, &inputI2sConfig, 0, NULL));
ESP_ERROR_CHECK(i2s_set_pin(inputPortNum, &inputPinConfig));
i2s_set_clk(inputPortNum, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO);

// Output
outputPortNum = I2S_NUM_1;

outputI2sConfig.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX);
outputI2sConfig.sample_rate = 44100;
outputI2sConfig.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
outputI2sConfig.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT;
outputI2sConfig.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB);
outputI2sConfig.dma_buf_count = 4;
outputI2sConfig.dma_buf_len = 440;
outputI2sConfig.intr_alloc_flags = 0;
outputI2sConfig.use_apll = true;

outputPinConfig.bck_io_num = PIN_I2S_BCLK_OUTPUT;
outputPinConfig.ws_io_num = PIN_I2S_LRC_OUTPUT;
outputPinConfig.data_out_num = PIN_I2S_DATA_OUTPUT;
outputPinConfig.data_in_num = -1; // Not used

ESP_ERROR_CHECK(i2s_driver_install(outputPortNum, &outputI2sConfig, 0, NULL));
ESP_ERROR_CHECK(i2s_set_pin(outputPortNum, &outputPinConfig));
i2s_set_clk(outputPortNum, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO);

ESP_ERROR_CHECK(i2s_start(inputPortNum));
ESP_ERROR_CHECK(i2s_start(outputPortNum));
The relay task is super simple:

Code: Select all

while (true)
{
	// Read a chunk of data from input
	memset(buffer, 0, sizeof(buffer));
	int size = i2s_read_bytes(inputPortNum, buffer, sizeof(buffer), 5 / portTICK_PERIOD_MS); // I've tried different delays here, including no delay
	if (size <= 0)
	{
		i2s_write_bytes(outputPortNum, buffer, sizeof(buffer), portMAX_DELAY);
		continue;
	}

	// Write to output until we have nothing left
	int written = 0;
	while (written < size)
		written += i2s_write_bytes(outputPortNum, &buffer[written], size - written, portMAX_DELAY);
}
Apologies if the code isn't super clear, I've been moving things around / playing to try and resolve the crackling.

The task loop relays audio, if any has been sent through. If it hasn't, it'll send the blank buffer which is essentially silence. The silence plays perfectly, no crackling. It's only when audio comes through that the crackling starts.

On a side note, is it possible to have the I2S driver send silence instead of the last buffer if it receives no data in time? I've yet to come across a situation where a buffer underrun doesn't result in annoying buzzes. Silence would definitely be the preferred output if there's no data.

Re: I2S Audio Crackling / Pops

Posted: Tue Mar 06, 2018 11:13 pm
by BuddyCasino
On a side note, is it possible to have the I2S driver send silence instead of the last buffer if it receives no data in time? I've yet to come across a situation where a buffer underrun doesn't result in annoying buzzes. Silence would definitely be the preferred output if there's no data.
+1 for that

Re: I2S Audio Crackling / Pops

Posted: Fri Jan 18, 2019 2:16 pm
by iw5dxh
Hi, I'm having the same problem too with a very similar setup.

Bluetooth->ESP32-Bluetooth->I2S->external codec->audio with the a2dp-sink example from stock compiled and flashed.

I have some cracks at the beginning of the audio stream. After some (periodic) cracks the system starts playing without problem (I tried about one hour of continuous playing).

Anyone else is havig the same problem? (or better suggest me a direction to investigate ?)

Thank you all!!

Re: I2S Audio Crackling / Pops

Posted: Fri Apr 22, 2022 8:55 am
by Larnasoft
Hi, is this issue solved? Because I experience a similar problem. My ESP32 works as BT sink. The I2S DAC is a TLV320AIC304 which works as I2S slave. The code is tightly based on the a2dp_sink example. I hear crackles in the first half second of BT playback. Short playbacks under about one second (e.g. windows sounds) are completely full of crackles. Longer playbacks works well.
Any ideas?

Re: I2S Audio Crackling / Pops

Posted: Mon Jan 29, 2024 8:42 pm
by Chevelle
I am not sure what causes the pop at the beginning of a play but I do know that if the library supports the use of the SD line, that can be mitigated.

The crackling is most likely cause by ringing on the LRC, BCLK, and/or the DIN lines. Just add small resistors in each of those lines and that should take care of it. 10-50 ohms should take care of it.