Recently there was a discussion on how to output more then 2 channels via I2S. I2S is limited to 2 channels, but the ESP32 has 2 I2S ports, so we can output a maximum of 4 channels!

Arduino Sketch

I have added a small example that shows how this can be done using my AudioTools library:

#include <SPI.h>
#include <SD.h>
#include "AudioTools.h"
#include "AudioCodecs/CodecMP3Helix.h"

const int chipSelect=10;
AudioInfo info(44100, 2, 16);
I2SStream i2s_1; // final output
I2SStream i2s_2; // final out
ChannelsSelectOutput out;
WAVDecoder wav;
EncodedAudioOutput decoder(&out, &wav); // Decoding stream
StreamCopy copier; 
File audioFile;

void setup(){
  Serial.begin(115200);
  AudioLogger::instance().begin(Serial, AudioLogger::Info);  

  // setup file
  SD.begin(chipSelect);
  audioFile = SD.open("/Music/ch4.wav");

  // setup i2s
  auto config1 = i2s_1.defaultConfig(TX_MODE);
  config1.copyFrom(info);
  config1.port_no = 0;
  i2s_1.begin(config1);
  auto config2 = i2s_2.defaultConfig(TX_MODE);
  config2.copyFrom(info);
  config2.port_no = 1;
  i2s_2.begin(config2);

  // split channels to different i2s ports
  out.addOutput(i2s_1, 0, 1);
  out.addOutput(i2s_2, 2, 3);
  //out.addNotifyAudioChange(i2s_1);
  //out.addNotifyAudioChange(i2s_2);
  out.begin(info);

  // setup decoder
  decoder.begin();

  // begin copy
  copier.begin(decoder, audioFile);
}

void loop(){
  if (!copier.copy()) {
    stop();
  }
}

We define 2 separate I2SStream audio sink objects. The data source is a decoded WAV file that has audio with 4 channels and we just need to use a ChannelsSelectOutput as additional intermediary sink. This allows us to define which channels should go to which final output. In the example channel 0 and 1 go to the I2S on port 0 and the channels 2 and 3 go to port 1.

Please note that these output destinations are not automatically notified about format changes, so if you want this to happen, you need to add the corresponding addNotifyAudioChange() statements yourself.

This API might be changing, so please check the potentially updated example on Github!


5 Comments

Bertrand BALDACH · 29. April 2024 at 22:24

Hi Phil, thanks a lot for that incredible library. I’ve discovered it 2 weeks ago and it’s an amazing work. I’ve try to implement the example with 2 DAC (PCM5102A) and an ESP32 DEVKIT V1.
The first DAC is connected to
config1.pin_bck = 25;
config1.pin_ws = 33;
config1.pin_data = 32
and the second one to
config2.pin_bck = 14;
config2.pin_ws = 15;
config2.pin_data = 22;

but I only have sound (with a lot of glitch on DAC1)

In the terminal I have that “error” : [W] AudioOutput.h : 843 – Could not write all samples

Do you have an idea ?

thank you

Seb · 9. April 2024 at 17:30

Hello, thank you for this interesting library!
I have a related question : is it possible to process 4 channel i2s inputs?

    pschatzmann · 9. April 2024 at 17:35

    I2S is a stereo protocol, in order to input 4 channels you need to attach 2 ADCs to the 2 I2S ports that the ESP32 supports.
    Some ESP32 variants support TDM, but this has not been tested with my library.

Tim Kindle · 20. March 2024 at 15:18

I just wanted to thank you all for placing all of these marvelous resources in one place and arranging them with the vast amount of intelligence that you do here. I think that your area of focus is aimed at a spot that can most assuredly do the most good for fast, effective and importantly – inexpensive experimentation in the field of electronically generated music and sound (processing, et al).
I am a geezer who has been around long enough to see the evolution of sound production/manipulation starting with hacking the properties of magnetic tape and tube circuits and to me, you are continuing this nuts and bolts – 2 – sound tradition into the 21st century! Thank You!

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *