schreibfaul1 / ESP32-audioI2S

Play mp3 files from SD via I2S
GNU General Public License v3.0
1.13k stars 289 forks source link

Bad quality (disturbances, random noise) when playing mp3 files (but not the first time after reset) #246

Closed chgaertner closed 2 years ago

chgaertner commented 2 years ago

Hi Wolle,

first of all thank you for sharing this library! It works great for playing internet radio. A few days ago I started to use it for playing mp3 files from the built-in SD card of my Lolin D32 pro (PSRAM enabled) and I discoverend a strange behaviour. The first time I play a mp3 file the quality is fine, but all other mp3 files are played in a bad quality with disturbances and random noises. After I reset the board, I again can play one mp3 file in good quality and the other files in bad quality.

The sketch I use for testing is quite simple. It starts playing a mp3 file and when the audio_eof_mp3 callback is called, it plays the mp3 file again.

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

#define SPISD_CS     4  // GPIO for chip select (SD)
#define I2S_DOUT    25  // GPIO for digital out (I2S)
#define I2S_LRC     26  // GPIO for LRC (I2S)
#define I2S_BCLK    27  // GPIO for BCLK (I2S)
Audio audio;

void setup(void) {
  Serial.begin(115200);
  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  pinMode(SPISD_CS, OUTPUT);
  digitalWrite(SPISD_CS, HIGH);
  if (!SD.begin(SPISD_CS)) {
    return;
  }
  audio.setVolume(12);
  audio.connecttoFS(SD, "/01/001_Melodie2.mp3");
}

void loop() {
  audio.loop();
}

void audio_info(const char *info) {
  Serial.print("info        ");
  Serial.println(info);
}
void audio_eof_mp3(const char *info) {
  Serial.print("eof_mp3     ");
  Serial.println(info);
  audio.connecttoFS(SD, "/01/001_Melodie2.mp3");
}

The output from the console is as follows:

22:03:14.205 -> Buffer filled: 0, Buffer free: 4294967295
22:03:14.205 -> info        PSRAM found, inputBufferSize: 283615 bytes
22:03:14.374 -> info        buffers freed, free Heap: 274184 bytes
22:03:14.374 -> info        Reading file: "/01/001_Melodie2.mp3"
22:03:14.408 -> info        MP3Decoder has been initialized, free Heap: 250240 bytes
22:03:14.408 -> Buffer filled: 0, Buffer free: 283615
22:03:15.289 -> info        stream ready
22:03:15.289 -> info        Content-Length: 1312181
22:03:15.289 -> info        file has no mp3 tag, skip metadata
22:03:15.323 -> info        Audio-Length: 1312181
22:03:15.323 -> info        syncword found at pos 0
22:03:15.323 -> info        Channels: 2
22:03:15.323 -> info        SampleRate: 44100
22:03:15.323 -> info        BitsPerSample: 16
22:03:15.323 -> info        BitRate: 192000
22:03:15.424 -> Buffer filled: 282988, Buffer free: 627
22:03:16.439 -> Buffer filled: 282988, Buffer free: 627
(...)
22:03:57.157 -> Buffer filled: 282988, Buffer free: 627
22:03:58.208 -> Buffer filled: 279614, Buffer free: 4001
22:03:59.221 -> Buffer filled: 255164, Buffer free: 28451
22:04:00.236 -> Buffer filled: 230713, Buffer free: 52902
22:04:01.250 -> Buffer filled: 206262, Buffer free: 77353
22:04:02.263 -> Buffer filled: 181812, Buffer free: 101803
22:04:03.309 -> Buffer filled: 157361, Buffer free: 126254
22:04:04.322 -> Buffer filled: 132911, Buffer free: 150704
22:04:05.337 -> Buffer filled: 108460, Buffer free: 175155
22:04:06.351 -> Buffer filled: 84009, Buffer free: 199606
22:04:07.347 -> Buffer filled: 59559, Buffer free: 224056
22:04:08.365 -> Buffer filled: 35108, Buffer free: 248507
22:04:09.412 -> Buffer filled: 10657, Buffer free: 272958
22:04:10.053 -> info        End of file "/01/001_Melodie2.mp3"
22:04:10.053 -> eof_mp3     /01/001_Melodie2.mp3
22:04:10.256 -> info        buffers freed, free Heap: 273832 bytes
22:04:10.256 -> info        Reading file: "/01/001_Melodie2.mp3"
22:04:10.290 -> info        MP3Decoder has been initialized, free Heap: 250196 bytes
22:04:11.171 -> info        stream ready
22:04:11.171 -> info        Content-Length: 1312181
22:04:11.171 -> info        file has no mp3 tag, skip metadata
22:04:11.205 -> Buffer filled: 283615, Buffer free: 0
22:04:11.205 -> info        Audio-Length: 1312181
22:04:11.205 -> info        syncword found at pos 0
22:04:11.205 -> info        Channels: 2
22:04:11.205 -> info        SampleRate: 44100
22:04:11.205 -> info        BitsPerSample: 16
22:04:11.205 -> info        BitRate: 192000
22:04:12.186 -> Buffer filled: 282988, Buffer free: 627
22:04:13.204 -> Buffer filled: 282988, Buffer free: 627
(...)
22:04:52.946 -> Buffer filled: 282988, Buffer free: 627
22:04:53.964 -> Buffer filled: 282122, Buffer free: 1493
22:04:55.006 -> Buffer filled: 257671, Buffer free: 25944
22:04:56.023 -> Buffer filled: 233221, Buffer free: 50394
22:04:57.039 -> Buffer filled: 208770, Buffer free: 74845
22:04:58.055 -> Buffer filled: 184320, Buffer free: 99295
22:04:59.070 -> Buffer filled: 159869, Buffer free: 123746
22:05:00.084 -> Buffer filled: 135418, Buffer free: 148197
22:05:01.101 -> Buffer filled: 110968, Buffer free: 172647
22:05:02.114 -> Buffer filled: 86517, Buffer free: 197098
22:05:03.160 -> Buffer filled: 62066, Buffer free: 221549
22:05:04.171 -> Buffer filled: 37616, Buffer free: 245999
22:05:05.184 -> Buffer filled: 13165, Buffer free: 270450
22:05:05.926 -> info        End of file "/01/001_Melodie2.mp3"
22:05:05.926 -> eof_mp3     /01/001_Melodie2.mp3

I notice two differences between the first and the second part:

  1. At the beginning, the log reads "Buffer free: 4294967295" which on the one hand seems a bit much :-) and on the other hand is a value that is never reachad again, because after the playback of a mp3 file the free buffer is reported as 283615. Although I am aware of the fact that my Lolin board does not have 4 GB buffer, I am curious because 277 kB free buffer after playback seems to be too less.
  2. The information about the PSRAM is only printed once. This might be by design but it might also be an indication that the PSRAM is not used any more??

Additionally, I compiled the sketch with PSRAM disabled and I encounter the same problems as mentioned above. The filled/free buffer values are as follows:

before start -> Buffer filled: 0, Buffer free: 4294967295
during playback -> Buffer filled: 5772, Buffer free: 627
after playback -> Buffer filled: 0, Buffer free: 6399

Best regards, Christian

FrankBoesing commented 2 years ago

I've seen this with PSRAM, too - I think, in my case - the reason is the REV1 chip with the known PSRAM Bug. The workaround does not help in all cases, it seems.

chgaertner commented 2 years ago

I've seen this with PSRAM, too - I think, in my case - the reason is the REV1 chip with the known PSRAM Bug. The workaround does not help in all cases, it seems.

Hi Frank, thank you for your reply. Can you give me some additional information about the bug you mentioned and which workaround you tried? I would like to give it a try. Thank you!

FrankBoesing commented 2 years ago

I think it was adding -mfix-esp32-psram-cache-issue to build_flags (in Platformio)

chgaertner commented 2 years ago

I think it was adding -mfix-esp32-psram-cache-issue to build_flags (in Platformio)

Hi Frank, first of all thank you for pushing me to PlatformIO, which I have read about but never used before. Your message encouraged me to give it a try and after a few hours it looks much more comfortable than the Arduino IDE. :-)

I have tried the following build flags ...

build_flags = 
    -DBOARD_HAS_PSRAM
    -DCONFIG_SPIRAM_CACHE_WORKAROUND
    -mfix-esp32-psram-cache-issue

but this made no change regarding the bad audio quality for all files (except the first one). I also tried to use the last two flags alternatively but still no change. :-(

What seems a bit weird is the fact that I am also testing webradio streems and they play without any problem (even switching between them). They are mp3 streams ("content-type: audio/mpeg, format is mp3"), so the same decoding routines should be in effect as when playing a mp3 file.

FrankBoesing commented 2 years ago

Hi,, yes, the decoding is the same code. That workaround did no work for me, too, I had these effects with stream too. Not that often.. 2-3 times in 10 Minutes. However, it could be a different issue...

chgaertner commented 2 years ago

Hi,, yes, the decoding is the same code. That workaround did no work for me, too, I had these effects with stream too. Not that often.. 2-3 times in 10 Minutes. However, it could be a different issue...

In the meantime I have spent hours after hours hoping to find the solution or at least a workaround, but unfortunately I do not make any progress. :-(

I have used several SD cards, I have played mp3 files with different bitrates. I have modified my source code to use different SPI buses for the SD card and the RFID reader. I have tried several bus speeds for the SPI bus, I have used different GPIOs for the RFID board, I have enabled and disabled PSRAM. I have tried different build flags in PlatformIO. Nothing did solve the problems. Webstreams always play in a perfect quality (even at a higher bitrate than the local files!), but all mp3 files play in a bad quality except the first one after reboot.

I am seriously thinking about giving up. The last chance I see is trying a different board (Lolin D32 instead of D32 pro), which needs an external SD card reader. Let's see how long it takes to get these parts from Aliexpress. I have also ordered a new RFID board which can be connected via I2C instead of SPI. Hope dies last ...

Greetings from Mödling, Christian

FrankBoesing commented 2 years ago

Can you send me the used files?
f dot boesing (at) gmx germany

chgaertner commented 2 years ago

Can you send me the used files? f dot boesing (at) gmx germany

Hi Frank, of course I could send you one of the mp3 files which I am using for test purposes. But I encounter this effect with all mp3 files I tried (CBR, VBR, different bitrates, mono, stereo, ...).

I tried two new approaches:

  1. I compiled and uploaded a version of ESPuino, which I suppose is well known to you. Surprisingly I have the same problems, although there are two major differences to my own source code: (a) ESPuino is using a completely different audio library (as far as I can judge from a quick code review) and (b) ESPuino is using FreeRTOS to keep tasks separated from each other (like xTaskCreatePinnedToCore). The fact that I have the same problems leads me to the conclusion that the reason might be a hardware problem with the Lolin D32 pro in general (the bug you mentioned above) or with my device in particular.
  2. To be able to locate the problem, I have ordered a Lolin D32 (not the "pro" version) without the built-in SD card reader. I will use an external SD card reader and I am curious if I will see any difference. I will also try to connect the SD card reader not via SPI but via MMC. And I have designed a very simple PCB which I can use to connect the Lolin D32 pro, the MAX98357A and the RC522. Although I have tested the setup with high quality cables (no breadboard!) and a grid-style PC board ("Lochrasterplatine"), I want to double check that it is no connection/contact issue. I have already received the Lolin D32 board and I am expection the SD card reader and the PCB within the next days. I will report my findings here as soon as possible.

Greetings, Christian

chgaertner commented 2 years ago

Dear all,

I have a solution regarding the disturbances that frustrated me over the last weeks. :-)

Short version: A combination of an apparently defective MAX98357A and problems with one or more circuit paths on the grid-style PC board ("Lochrasterplatine").

Long version: When I received my PCB board and soldered the components in place (LOLIN D32 pro, RFID-RC522, MAX98357A), I noticed that the disturbances were nearly gone. I had spare parts of the LOLIN D32 pro and the RFID-RC522 which I exchanged for the original parts before. This did not cause any improvement, so I ordered a new MAX98357A to be able to exclude this component as reason for the problems as well. When I used the new MAX98357A on the PCB board, all disturbances were gone and the sound was clear. To double check, I used the new MAX98357A on the grid-style PC board and the quality was noticeable better than before.

Lessons learned:

  1. A breadboard is always a bad choice (which I already knew); a grid-style PC board is much better, but not always the best solution (or maybe the layout of the circuit paths caused an interference??); a PCB board is the best choice. Unfortunately it is not as quickly available as an grid-style PC board unless I am willing to transfer a number of chocolate bars to the colleague in my company who is responsible for the production of our prototype PCB boards. :-)
  2. Always have spare parts of each component at hand.

Frank, thank you for your help!

I will close this issue because the problem I described is solved.

Greetings, Christian