Unable to do simple audio transformations
Posted: Mon Oct 09, 2023 9:55 pm
I'm trying to do a I2S microphone + headphone example program with basic audio manipulation (eg: gain, delay, etc...)
I have successfully done the simple part that gets the data from the microphone (using the INMP441, 24bits @ 48kHz), and sends it to the headphones (using the UDA1334, 24bits @ 48kHz).
I'm using ESP-IDFv5.1.1 in VSCode, on the ESP32-S3 N32R8
The I2S parameters are :
(this is generated on startup)
However, I don't know how to change the gain. I've done some research and found that, to change the gain of a signal, you have to multiply the sampled signal by the gain.
When I do it, I only get noise on the output.
When I don't try to modify the gain, the output is acting normal, I can hear myself talk into the mic.
Here is a "simplified" version of the whole code, I only removed methods & variables not used in this part (tell me if you need more but this is really the part responsible for the I2S data)
Note: I also tried using the example given by Espressif, although in the example the I2S is 16bits, but got the same result
I have successfully done the simple part that gets the data from the microphone (using the INMP441, 24bits @ 48kHz), and sends it to the headphones (using the UDA1334, 24bits @ 48kHz).
I'm using ESP-IDFv5.1.1 in VSCode, on the ESP32-S3 N32R8
The I2S parameters are :
(this is generated on startup)
Polling interval: 1000ms
Buffer size: 1920 bytes
DMA frame number: 240 bytes
DMA description number: 9 bytes
--- Input ---
Bits per sample: 24
Frame length: 32
Sample rate: 48kHz
Channels: Stereo
Bit shift: Yes
Left align: Yes
--- Output ---
Bits per sample: 24
Frame length: 32
Sample rate: 48kHz
Channels: Stereo
Bit shift: No
Left align: No
However, I don't know how to change the gain. I've done some research and found that, to change the gain of a signal, you have to multiply the sampled signal by the gain.
When I do it, I only get noise on the output.
When I don't try to modify the gain, the output is acting normal, I can hear myself talk into the mic.
Here is a "simplified" version of the whole code, I only removed methods & variables not used in this part (tell me if you need more but this is really the part responsible for the I2S data)
Note: I also tried using the example given by Espressif, although in the example the I2S is 16bits, but got the same result
- #define CONVERT8bits(n,o) (uint8_t)((n>>8*o)&0xFF)
- double gain = 1.5;
- void setAudioGain(uint8_t *buffer, size_t bLength, double gain) {
- uint32_t *sample = calloc(2,sizeof(uint32_t)); // L : R
- for (uint32_t sIndex = 0; sIndex < bLength; sIndex += 6 * 4) {
- for (uint8_t j=0;j<6*4;j+=6){
- // Here, Left = 0 and Right = 1
- sample[Left] = buffer[sIndex + j + 0 ]<<16 | buffer[sIndex + j + 1 ]<<8 | buffer[sIndex + j + 2 ];
- sample[Right] = buffer[sIndex + j + 3 ]<<16 | buffer[sIndex + j + 4 ]<<8 | buffer[sIndex + j + 5 ];
- sample[Left] = (uint32_t)((double)sample[Left]*gain);
- sample[Right] = (uint32_t)((double)sample[Right]*gain);
- *((uint8_t *)(buffer + sIndex + j + 0 )) = CONVERT8bits(sample[Left],2); // Left Channel MSB
- *((uint8_t *)(buffer + sIndex + j + 1 )) = CONVERT8bits(sample[Left],1); // Left Channel
- *((uint8_t *)(buffer + sIndex + j + 2 )) = CONVERT8bits(sample[Left],0); // Left Channel LSB
- *((uint8_t *)(buffer + sIndex + j + 3 )) = CONVERT8bits(sample[Right],2); // Right Channel MSB
- *((uint8_t *)(buffer + sIndex + j + 4 )) = CONVERT8bits(sample[Right],1); // Right Channel
- *((uint8_t *)(buffer + sIndex + j + 5 )) = CONVERT8bits(sample[Right],0); // Right Channel LSB
- }
- }
- free(sample);
- }
- static void audio_task(void *args) {
- uint8_t *data = calloc(BUFFER_SIZE,sizeof(uint8_t));
- audio_init();
- while (true) {
- i2s_channel_read(i2s_rx, data, BUFFER_SIZE, &n_bytes_read, 10e3); // 10 sec max
- setAudioGain(data, BUFFER_SIZE, 1.1); // If I comment this, the sound is normal
- i2s_channel_write(i2s_tx, data, BUFFER_SIZE, &n_bytes_write, 10e3); // 10 sec max
- }
- free(data);
- vTaskDelete(NULL);
- }