4 channels output from ESP32
4 channels output from ESP32
Hello,
I am a complete noob with ESP32, so please bear with me.
I understand that many ESP32 have 2 i2s that can be used simultaneously. I wonder if it is possible to get 4 channels of synchronized audio (final use is L+R speakers + two subwoofers). Ideally i would like to convert the two i2s output to two spdif going to two external stereo DACs. As you can imagine it is important that the two spdif signals share the same clock sync.
Has someone managed to do something like that or know of a source of information to achieve it?
4 channel interfaces with 2 spdif outputs are rare and expensive, if a ESP32 could do it, it would be great!!
Once solved, the next question would be how to process an incoming stereo signal to generate the 4 channels and apply the crossovers or alternatively to input (stream? via USB?) the 4 channels already processed. But that is another problem....
thanks a lot for any insight or clue.
M. Ramone
I am a complete noob with ESP32, so please bear with me.
I understand that many ESP32 have 2 i2s that can be used simultaneously. I wonder if it is possible to get 4 channels of synchronized audio (final use is L+R speakers + two subwoofers). Ideally i would like to convert the two i2s output to two spdif going to two external stereo DACs. As you can imagine it is important that the two spdif signals share the same clock sync.
Has someone managed to do something like that or know of a source of information to achieve it?
4 channel interfaces with 2 spdif outputs are rare and expensive, if a ESP32 could do it, it would be great!!
Once solved, the next question would be how to process an incoming stereo signal to generate the 4 channels and apply the crossovers or alternatively to input (stream? via USB?) the 4 channels already processed. But that is another problem....
thanks a lot for any insight or clue.
M. Ramone
Re: 4 channels output from ESP32
I'm working on a 2.1 system too. I leaned on ESP-ADF, in particular the pipeline_a2dp_sink_and_hfp demo (minus the HFP). That was the starting point for my code.
I run the I2S pair as either master + slave, or both as slave (if generating the clock somewhere else). The driver doesn't sync things automatically, but some ESP32 GPIO magic allows WS and BCLK to reside on the same pins for both, and in my experience this allows the second I2S signal to be close enough to "at the same time" to work. (I'm using a single 8-ch out DAC, but in theory it should be the same for two stereo DACs)
I have some audio DSP code in another ADF audio element that I placed in the pipeline between the bluetooth service and the i2s_w. This is where I convert from 2 channels 16-bit signed int PCM input to 4 channels 32-bit float, do EQ biquads, crossovers, volume, etc. and turn the final results into 32-bit signed int PCM. (The DAC I'm using expects 24 bits, I just do 32 bits and it uses the first 24)
For the last part of the pipeline, I'm using a custom dual_i2s_stream.c that is based on ESP-ADF's i2s_stream.c, taking the combined audio data that the DSP code created and splitting it back out for writing to each of the i2s peripherals.
I did this already on an ESP32-S3 with a dual-4ch I2S pair to create an 8ch system, but have to wait a bit before I can test the dual-stereo config on ESP32. But it should work fine
I run the I2S pair as either master + slave, or both as slave (if generating the clock somewhere else). The driver doesn't sync things automatically, but some ESP32 GPIO magic allows WS and BCLK to reside on the same pins for both, and in my experience this allows the second I2S signal to be close enough to "at the same time" to work. (I'm using a single 8-ch out DAC, but in theory it should be the same for two stereo DACs)
I have some audio DSP code in another ADF audio element that I placed in the pipeline between the bluetooth service and the i2s_w. This is where I convert from 2 channels 16-bit signed int PCM input to 4 channels 32-bit float, do EQ biquads, crossovers, volume, etc. and turn the final results into 32-bit signed int PCM. (The DAC I'm using expects 24 bits, I just do 32 bits and it uses the first 24)
For the last part of the pipeline, I'm using a custom dual_i2s_stream.c that is based on ESP-ADF's i2s_stream.c, taking the combined audio data that the DSP code created and splitting it back out for writing to each of the i2s peripherals.
I did this already on an ESP32-S3 with a dual-4ch I2S pair to create an 8ch system, but have to wait a bit before I can test the dual-stereo config on ESP32. But it should work fine
Re: 4 channels output from ESP32
Wow!
Thank you for your answer, that is exactly what I would like to achieve.
Do you have your project documented somewhere? I would be very interested in having a look at the details,
Thanks!
Thank you for your answer, that is exactly what I would like to achieve.
Do you have your project documented somewhere? I would be very interested in having a look at the details,
Thanks!
-
- Posts: 1
- Joined: Thu Aug 04, 2022 6:07 am
Re: 4 channels output from ESP32
One way to do it (might be the same as @thefury) is:
Configure one of the I2S as slave then share the clock signal.
The GPIO trick can be referred to from. After I2S finishes initializing GPIO, use and to connect the clock signals of I2S0 and I2S1 on the same GPIO. This way, the clock output from the master can be directly passed to the slave.
The downside of this approach is that the write interfaces for both I2S still need to be called separately, meaning you have to perform write operations for I2S0 and I2S1 individually.
Configure one of the I2S as slave then share the clock signal.
The GPIO trick can be referred to from
Code: Select all
components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c:
i2s_test_io_config
Code: Select all
esp_rom_gpio_connect_out_signal
Code: Select all
esp_rom_gpio_connect_in_signal
The downside of this approach is that the write interfaces for both I2S still need to be called separately, meaning you have to perform write operations for I2S0 and I2S1 individually.
Re: 4 channels output from ESP32
Thanks, we will test! But isn't the write function blocking? Meaning that it would be hard to send data synchronious over both data lines?bubblesnake wrote: ↑Wed May 29, 2024 8:09 amOne way to do it (might be the same as @thefury) is:
Configure one of the I2S as slave then share the clock signal.
The GPIO trick can be referred to from. After I2S finishes initializing GPIO, useCode: Select all
components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c: i2s_test_io_config
andCode: Select all
esp_rom_gpio_connect_out_signal
to connect the clock signals of I2S0 and I2S1 on the same GPIO. This way, the clock output from the master can be directly passed to the slave.Code: Select all
esp_rom_gpio_connect_in_signal
The downside of this approach is that the write interfaces for both I2S still need to be called separately, meaning you have to perform write operations for I2S0 and I2S1 individually.
Re: 4 channels output from ESP32
Yep, this is the way L-KAYA guided me to on GitHub https://github.com/espressif/esp-idf/is ... 1033331842bubblesnake wrote: ↑Wed May 29, 2024 8:09 amOne way to do it (might be the same as @thefury) is:
Configure one of the I2S as slave then share the clock signal.
The GPIO trick can be referred to from. After I2S finishes initializing GPIO, useCode: Select all
components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c: i2s_test_io_config
andCode: Select all
esp_rom_gpio_connect_out_signal
to connect the clock signals of I2S0 and I2S1 on the same GPIO. This way, the clock output from the master can be directly passed to the slave.Code: Select all
esp_rom_gpio_connect_in_signal
The downside of this approach is that the write interfaces for both I2S still need to be called separately, meaning you have to perform write operations for I2S0 and I2S1 individually.
The problem with using two separate I2S peripherals is you can't guarantee them starting the data at the same time even if they're sharing clock, so the second pair will be out of phase by a nondeterministic amount that you would have to correct for with some other thing reinterpreting your audio on the other end (use 8 bits for channel number and 24 bits of data for example, read them and determine the phase alignment and adjust sample by sample til they're aligned, don't know if this could be done on esp32 alone by the same pin reuse trick)
Who is online
Users browsing this forum: No registered users and 56 guests