pschatzmann / arduino-audio-tools

Arduino Audio Tools (a powerful Audio library not only for Arduino)
GNU General Public License v3.0
1.54k stars 237 forks source link

Dual I2S output not producing sound on Arduino 3.x.x #1709

Closed qniens closed 2 months ago

qniens commented 2 months ago

Problem Description

I'm trying to output 4 channels on both I2S peripherals of the ESP32. I modified the streams-sd_wav4-i2s.ino sketch to work with a sine wave, since the original sketch doesn't work without an audio file.

The MCK seems to be working fine because the ADAU1701 DSP, which is in slave mode and requires an active MCK to boot, is powered on. However, there is no data or audio being received on either serial port. Could this be an issue with my sketch, or is it a potential bug?

Device Description

ESP32 devkit

Sketch

#include "AudioTools.h"

const int chipSelect = 10;
AudioInfo info(44100, 2, 16);
AudioInfo info4(44100, 4, 16);
I2SStream i2s_1;  // final output port 0
I2SStream i2s_2;  // final output port 1
ChannelsSelectOutput out;

SineWaveGenerator<int16_t> sine;
GeneratedSoundStream<int16_t> in(sine); 
StreamCopy copier;

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

  sine.setFrequency(200);

  // setup i2s
  auto config1 = i2s_1.defaultConfig(TX_MODE);
  config1.copyFrom(info);
  config1.port_no = 0;
  config1.pin_bck = 16;
  config1.pin_ws = 33;
  config1.pin_data = 32;
  config1.pin_mck = 3;
  i2s_1.begin(config1);

  auto config2 = i2s_2.defaultConfig(TX_MODE);
  config2.copyFrom(info);
  config2.port_no = 1;
  config2.pin_bck = 16;
  config2.pin_ws = 33;
  config2.pin_data = 14;
  config2.pin_mck = 3;
  i2s_2.begin(config2);

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

  // 4 channels
  out.begin(info4);

  copier.begin(out, in);
}

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

Other Steps to Reproduce

No response

What is your development environment

Arduino IDE 2.3.2 with Arduino 3.0.5

I have checked existing issues, discussions and online documentation

pschatzmann commented 2 months ago

Please follow the advince given in the Wiki. As far as I can see, you just forgot to open the input...

qniens commented 2 months ago

You're right, my apologies for not reading the advice provided in the Wiki earlier. I ran some test code and successfully produced sound using a single I2S peripheral. However, when I try to use both peripherals simultaneously, things go wrong. The second I2S output sounds fine, but the first one becomes distorted — the sine wave, for example, sounds metallic.

Could this issue be related to sharing the BCK, WS, and MCK pins?

Here’s the relevant updated code:

#include <Arduino.h>
#include "AudioTools.h"

AudioInfo info(44100, 2, 16);
AudioInfo info4(44100, 4, 16);
I2SStream i2s_1;  // final output port 0
I2SStream i2s_2;  // final output port 1

SineWaveGenerator<int16_t> sineWave1(4000);  
GeneratedSoundStream<int16_t> sound1(sineWave1); 
ChannelsSelectOutput out;
StreamCopy copier;

void setup(){
  delay(1000);
  Serial.begin(115200);
  AudioLogger::instance().begin(Serial, AudioLogger::Warning);

  // setup i2s
  auto config1 = i2s_1.defaultConfig(TX_MODE);
  config1.copyFrom(info);
  config1.port_no = 0;
  config1.pin_bck = 16;
  config1.pin_ws = 33;
  config1.pin_data = 32;
  config1.pin_mck = 3;
  i2s_1.begin(config1);

  auto config2 = i2s_2.defaultConfig(TX_MODE);
  config2.copyFrom(info);
  config2.port_no = 1;
  config2.pin_bck = 16;
  config2.pin_ws = 33;
  config2.pin_data = 14;
  config2.pin_mck = 3;
  i2s_2.begin(config2);

  // Setup sine wave
  sineWave1.begin(info, N_B4);

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

  copier.begin(out, sound1);

  Serial.println("started...");
}

void loop(){
  static int counter = 0;
  if (!copier.copy()) {
    Serial.println("stop");
    stop();
  }

  counter++;
  if (counter > 1000) {
    Serial.println(".");
    counter = 0;
  }
}
pschatzmann commented 2 months ago

I think out should be 2 channels as well and use 0,1 for the second i2s as well: You want to send the same data to both is2 ports

qniens commented 2 months ago

Thank you for your prompt response. Unfortunately, the issue persists. The second I2S output works well, but the first one still sounds distorted, with a metallic tone. You can also see the difference in the Sigmastudio screenshot, where the gains are visibly not the same. sigma

In your test with the 4-channel WAV file, did you use separate pins for both I2S peripherals? Also, it seems there's no MCK being used, based on the code example I'm looking at. I2S Output of 4 Channels with an ESP32

Adjusted code

  // split channels to different i2s ports
  out.addOutput(i2s_1, 0, 1);
  out.addOutput(i2s_2, 0, 1);
  //out.addOutput(i2s_2, 2, 3);
  //out.begin(info4);
  out.begin(info);
pschatzmann commented 2 months ago

Not sure about the impact if you use the same pins

qniens commented 2 months ago

Ok, probably the sharing of pins is causing the problems. Thank you for your time