I2s connection pruduces distorted sound

I have an esp8622 board. It's Connected through i2s to a DAC. The DAC module I have is a Max98357.
here is the ebay listing i purchased: https://www.ebay.com/itm/274747480846?ssPageName=STRK%3AMEBIDX%3AIT&_trksid=p2060353.m2749.l2649

I am playing sound from a WAV file with the SD card library.
When I play the songs it gets oddly distorted.

I believe my connections are correct and the data i am reading is correct. because
while trouble shooting, if i slow down the sample rate from the original, the distortion seem to goes away (but obviously the speed and pitch is lowered).

I chose an esp board because i thought it would be "fast" enough for the task?
the wav im playing has a sample rate of 48000 which is high for audio... not sure if this is a problem.

Anyways I hope someone would have possible suggestions why this might not be working! im kinda lost.
anyway here is the code followed by the serial output:

#include "SPI.h"
#include "SD.h"
#include <I2S.h>

const int chipSelect = 0;// sd pin
File f;
String dir="";

int channels;
int rate;
int bits;
int bytes;
int songcount;
int nowplaying;
 

void setup() {
  int i;
   songcount=0; nowplaying = -1;
   Serial.begin(9600); 
   delay(1000);
   Serial.println("=====alive=====");
 
  if (!SD.begin(chipSelect)) { Serial.println("---could Not Open card---"); while (1); }
  File datafile = SD.open("/");
 
 // read files on the SD card and find WAV file
 // this part works
   
    bool b = false;
    while(!b) {
        f = datafile.openNextFile();
        if(f) {  bool yy = Ending(f.name(),".wav",4);
        if(yy){songcount++;
        dir = dir + "#"+f.name();}}else{b=true;} 
  }

if(songcount==0){Serial.print("no wav files found on card");while(1==1){}}
 Serial.print("Waves found: ");  Serial.println(songcount);
 i = 0; 
 
 // reads the wav file header information and sets the read position to the audio data 
 // this part works well too
 
if(load(songname(0))){nowplaying=0; }else{Serial.println("Invalad song");}

 if (!I2S.begin(I2S_PHILIPS_MODE, rate, bits)) {
    Serial.println("Failed to initialize I2S!");
    while (1); }else{Serial.print("i2s ready :");}
    f.seek(44);
}

void loop() {

  // here is the problem
  // sound is oddly slow and distorted
  
   if(I2S.availableForWrite()>0) {
    int volt = intSigned();
    short shore = (short)volt;
    I2S.write(shore);}

}

 int intSigned() {
      byte a = f.read();
      byte b = f.read();  
      int r = (int16_t)(b << 8) + a ;
     return r;
}  

serial output looks good!
=====alive=====
Waves found: 3
-----------Loading: '001metalchristmas.wav'--------------------------
Name: 001metalchristmas.wav
Channels: 2
Rate: 48000
Bits: 16
bytes: 2
i2s ready :

I don't know how wed you are to that particular hardware, but I highly recommend giving the PJRC Teensy Family and Teensy Audio Library a look.

The library has extensive support for I2S, DAC, ADC, .wav file play, filtering, effects, etc. All I2S data transfers are handled with DMA. It's geared toward 16-bit samples (per stereo channel) at 44.1 Ksamples / second. So, I'd suggest you use one of the available audio tools to resample your .wav file to that rate. There are tricks to boost the sample rate, success in that endeavor would depend on your coding ability.

Sounds like you are swamping the processor and it can't keep up at 48kSPS.
I note you are handling the signal sample by sample rather than in blocks, which may be a contributary factor. Perhaps declare intSigned as inline? Or bite the bullet and convert the code to read blocks from the SD card and pass blocks to the I2S library.

Unfortunatly, I was hoping to read the samples together so that i may adjust volume.
if processor speed is my problem, i can defiantly reduce the Sample rate of my sound files with my PC. Also, I can change everything to mono, My "machine" only has one speaker. hopefully, that should speed me up.

but its good to know that speed is the problem!!!

I looked at your link. i have never looked into teensy boards. the name is misleading. apparently, the teensy 4.1 advertise a clock speed 8 or 10 times faster than my esp. I actually ordered one today on your advice! I should get it in a few days.

If the task is slowing down my esp this is a problem. i have other tasks it needs to do while reading.
If the I2S protocal is slowing down my code. then hopefully DMA should be the answer!

Anyways, the reason i fear sound libraries is because i need to know exactly when each sample is read.

my code will be expanded to trigger lights (or other boards that trigger lights).
i will eventually have an array of indexes and things to do at each index.
So im not sure if i can get or check the current sample index back from a library?

Anyways, thank you for the recommendation and knowledge!

I highly doubt your light triggering will need timing down to the sample level (~22.7 us). The library works in chunks of 128 samples (~2.9 ms). That has been more than adequate for my sound-reactive projects.

Agreed. within a couple hundred samples should be accurate enough!
do you mind linking me to the library i should use for a teensy 4.1?

All Teensy-specific libraries are downloaded when you install the Teensyduino Arduino IDE Extension.

1 Like