pschatzmann / arduino-audio-tools

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

ESP32-A1S SD card on custom board doesn't work #234

Closed jwktje closed 2 years ago

jwktje commented 2 years ago

Hey Phil,

I'm really loving the library so far. I made a custom PCB with the ESP32-A1S after working with the AudioKit succesfully. I wired up the SD like mentioned here which worked fine in other projects. However I can't get it to work with the arduino-audio-tools library.

Where can I define the pins that are used for the SD card so that my current wiring works?

pschatzmann commented 2 years ago

I would suggest to stick with the same pins that the AudioKit and Lyrat are using: This gives you the advantage that you can also use sd_mmc easily.

The logic which is defining the pins is defined in https://github.com/pschatzmann/arduino-audiokit/blob/main/src/AudioKitHAL.h: just search for p_spi->begin(PIN_AUDIO_KIT_SD_CARD_CLK, PIN_AUDIO_KIT_SD_CARD_MISO, PIN_AUDIO_KIT_SD_CARD_MOSI, PIN_AUDIO_KIT_SD_CARD_CS);

You could e.g. deactivate the automatic setup and then do it in your sketch with your pins.

jwktje commented 2 years ago

Thanks for the quick response @pschatzmann I tried to do what you advised but I'm probably doing it wrong. Would I still be able to use the AudioKit classes with my custom board? Or is AudioKitStream probably what causes my issues? Any help would be greatly appreciated!

Here is a minimal version of my sketch that produces the error:

#define AUDIOKIT_SETUP_SD 0
#define AUDIOKIT_SD_SPI SPI
#define SD_CS         5
#define SPI_MOSI      23
#define SPI_MISO      19
#define SPI_SCK       18
#define USE_SDFAT

#include "FS.h"
#include "SD.h"
#include "SPI.h"

#include "AudioTools.h"
#include "AudioLibs/AudioKit.h"
#include "AudioCodecs/CodecMP3Helix.h"

const char *startFilePath="/";
const char* ext="mp3";
int speedMz = 10;
AudioSourceSdFat source(startFilePath, ext, 5 /*SD CS Pin*/, speedMz);
AudioKitStream kit;
MP3DecoderHelix decoder;
AudioPlayer player(source, kit, decoder);

void setup() {
  Serial.begin(115200);
  Serial.println("Boot");

  //SD Init
  pinMode(SD_CS, OUTPUT);
  digitalWrite(SD_CS, HIGH);
  SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
  if (!SD.begin(SD_CS)) {
    Serial.println("Card Mount Failed");
    return;
  }

  //Audio init
  AudioLogger::instance().begin(Serial, AudioLogger::Error);

  // setup output
  auto cfg = kit.defaultConfig(TX_MODE);
  cfg.sample_rate = 48000;
  cfg.buffer_size = 512;
  cfg.buffer_count = 64;
  kit.setVolume(50);
  kit.begin(cfg);
  player.setVolume(1);
  player.begin();
}

void loop()
{
  player.copy();
}

This is what the log shows:

12:31:59.428 -> Boot
12:32:00.105 -> Error:   audio_hal handle is null
12:32:00.141 -> [E] AudioPlayer.h : 217 - SD.begin failed with cs=5!
12:32:00.141 -> begin() failed
12:32:00.141 -> Do not reformat the SD.
12:32:00.141 -> No card, wrong chip select pin, or wiring error?
12:32:00.141 -> SdError: 0X1,0XFF
pschatzmann commented 2 years ago

You would add your logic after kit.begin(cfg); and it would be SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI, SD_CS);

jwktje commented 2 years ago

@pschatzmann I'm also still working on this issue. I can only get 128kbps MP3's to run without glitching. Even when using an AudioConfigLocal.h with this content;

#pragma once
#define DEFAULT_BUFFER_SIZE 1024 // 2048
#define DEFAULT_SAMPLE_RATE 44100
#define I2S_BUFFER_SIZE 512
#define I2S_BUFFER_COUNT 5 // 20

What can I do to improve this? Ideally I'd want to play 256kbps or higher. Is that possible? Or should I switch to WAV? What would get me the best performance?

Update:

Just tested with WAV and performance increased drastically! I am now using the AudioPlayer class but really I just wanna choose a file by name and copy all of it to the DAC. I found the copyAll() function but can't see an example on how to use it. Any pointers?

pschatzmann commented 2 years ago

The AudioPlayer plays all files in all subdirectories. You can select a specific directory. To select one or more individual files you can call setFileFilter() on the AudioSource.

I am confused regarding your MP3. I am usually using mp3 with a sample rate of 44.1kHz which gives a bitrate of 1.4Mbps w/o any issues. Did you set the log level to Warning ? Have your tried an alternative MP3 Decoder e.g. LibMAD ? Did you try to increase the I2S_BUFFER_COUNT and/or I2S_BUFFER_SIZE

jwktje commented 2 years ago

I haven't tried LibMAD but I did increase both the buffer count and size to no effect. On every of my 3 projects that use your library the mp3 performance is glitchy on anything above 128kbps. They all use the ESP32-A1S and the MP3DecoderHelix. Could the Helix decoder be the bottleneck? WAV works without issue.

In general should WAV give better performance than MP3 or shouldn't that make a difference?

pschatzmann commented 2 years ago

WAV is stored in PCM format, so the processor doesn't need to do any decoding but can just copy the audio data from the source to the destination. If you use any compressed format the processor needs to do some decoding which requires a lot of calculations.

I rarely created any MP3 files myself and I never had any issues with the mp3 internet streams. The few MP3 files I created in Audicity are by default with Medium Quality (145-185kbps) and this is working just fine.

How did you create your file ? Can you maybe share your example ? I suggest that you try out a streaming mp3 example to exclude that the issue comes from the SD drive performance

jwktje commented 2 years ago

Hey Phil. I was on holiday without computer hence the late response.

I also created my MP3's with Audacity but on a higher bitrate (256kbps and up). The lower ones (below 192kbps) all worked fine. But it's good to know that WAV is less CPU intensive. I can easily spare the space on the SD card so I will go with WAV files.

Thanks for confirming my suspicion that WAV is simpler to use for the MCU.