pschatzmann / arduino-audio-tools

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

Issue with playing mp3 from SD card with spdif output? #888

Closed pwilkowski closed 1 year ago

pwilkowski commented 1 year ago

Hello

I am having some troubles trying to play mp3 with spdif out, no sound is being produced

Its is on ESP32 ESP-WROOM-32

My setup:

const char *startFilePath="/";
const char* ext="mp3";
AudioSourceSDFAT* source;
SPDIFOutput* spdif;
MP3DecoderHelix decoder; 
AudioPlayer* player;

void setup() {
    AudioLogger::instance().begin(Serial, AudioLogger::Info);
    spdif = new SPDIFOutput();
    auto cfg = spdif->defaultConfig();
    cfg.pin_data = 27;
    cfg.sample_rate = 44100;
    cfg.channels = 2;
    cfg.bits_per_sample = 16;
    spdif->begin(cfg);

    source = new AudioSourceSDFAT(startFilePath, ext, 5);
    player = new AudioPlayer(*source, *spdif, decoder);
    player->begin();
}
void loop() {
    player->copy();
}

log

[I] I2SConfig.h : 113 - rx/tx mode: TX_MODE
[I] I2SConfig.h : 114 - port_no: 0
[I] I2SConfig.h : 115 - is_master: Master
[I] I2SConfig.h : 116 - sample rate: 88200
[I] I2SConfig.h : 117 - bits per sample: 32
[I] I2SConfig.h : 118 - number of channels: 2
[I] I2SConfig.h : 119 - i2s_format: I2S_STD_FORMAT
[I] I2SConfig.h : 121 - auto_clear: true
[I] I2SConfig.h : 123 - use_apll: true
[I] I2SConfig.h : 126 - fixed_mclk: 22579200
[I] I2SConfig.h : 128 - buffer_count:6
[I] I2SConfig.h : 129 - buffer_size:512
[I] I2SConfig.h : 143 - pin_data: 27
[I] AudioSourceSDFAT.h : 53 - SD chipSelect: 5
[I] AudioSourceSDFAT.h : 54 - SD speedMHz: 2
[I] AudioSourceSDFAT.h : 55 - ext: mp3
[I] AudioPlayer.h : 348 - setVolume(1.000000)
[I] VolumeStream.h : 186 - setVolume: 1.000000
[I] VolumeStream.h : 186 - setVolume: 1.000000
[I] AudioTypes.h : 85 - sample_rate: 0
[I] AudioTypes.h : 86 - channels: 0
[I] AudioTypes.h : 87 - bits_per_sample: 16
[I] MetaDataID3.h : 564 - virtual void audio_tools::MetaDataID3::begin()
[I] AudioSourceSDFAT.h : 101 - selectStream SDFAT: 0
[I] AudioSourceSDFAT.h : 120 - -> selectStream: /testold.mp3
[I] StreamCopy.h : 74 - buffer_size=1024
Starting up app[I] StreamCopy.h : 139 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
[I] StreamCopy.h : 139 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
[I] StreamCopy.h : 139 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
[I] AudioPlayer.h : 239 - sample_rate: 44100
[I] AudioPlayer.h : 240 - bits_per_sample: 16
[I] AudioPlayer.h : 241 - channels: 2
[I] VolumeStream.h : 186 - setVolume: 1.000000
[I] VolumeStream.h : 186 - setVolume: 1.000000
[I] AudioTypes.h : 85 - sample_rate: 44100
[I] AudioTypes.h : 86 - channels: 2
[I] AudioTypes.h : 87 - bits_per_sample: 16
[I] I2SConfig.h : 113 - rx/tx mode: TX_MODE
[I] I2SConfig.h : 114 - port_no: 0
[I] I2SConfig.h : 115 - is_master: Master
[I] I2SConfig.h : 116 - sample rate: 88200
[I] I2SConfig.h : 117 - bits per sample: 32
[I] I2SConfig.h : 118 - number of channels: 2
[I] I2SConfig.h : 119 - i2s_format: I2S_STD_FORMAT
[I] I2SConfig.h : 121 - auto_clear: true
[I] I2SConfig.h : 123 - use_apll: true
[I] I2SConfig.h : 126 - fixed_mclk: 22579200
[I] I2SConfig.h : 128 - buffer_count:6
[I] I2SConfig.h : 129 - buffer_size:512
[I] I2SConfig.h : 143 - pin_data: 23
[I] StreamCopy.h : 139 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops

any idea what could be wrong? I checked with oscilloscope and pin out is 0V flat

pwilkowski commented 1 year ago

Update: I think there may be something wrong with spdif class as it seems to write couple of bytes and then dies?

[I] I2SConfig.h : 113 - rx/tx mode: TX_MODE
[I] I2SConfig.h : 114 - port_no: 0
[I] I2SConfig.h : 115 - is_master: Master
[I] I2SConfig.h : 116 - sample rate: 88200
[I] I2SConfig.h : 117 - bits per sample: 32
[I] I2SConfig.h : 118 - number of channels: 2
[I] I2SConfig.h : 119 - i2s_format: I2S_STD_FORMAT
[I] I2SConfig.h : 121 - auto_clear: true
[I] I2SConfig.h : 123 - use_apll: true
[I] I2SConfig.h : 126 - fixed_mclk: 22579200
[I] I2SConfig.h : 128 - buffer_count:6
[I] I2SConfig.h : 129 - buffer_size:512
[I] I2SConfig.h : 143 - pin_data: 27
idx.txt 99 bytes
idx-def.txt 7 bytes
testold.mp3 6110818 bytes
test.mp3x   118814943 bytes
    7344836 bytes
    7434681 bytes
file size 6110818
file is av 6110818
file is av ptr 1073489712
[I] StreamCopy.h : 74 - buffer_size=1594848797
[I] StreamCopy.h : 60 - buffer_size=1024
Starting up apptrying to write
[I] StreamCopy.h : 139 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
trying to write
[I] StreamCopy.h : 139 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
trying to write
[I] StreamCopy.h : 139 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
trying to write
[I] I2SConfig.h : 113 - rx/tx mode: TX_MODE
[I] I2SConfig.h : 114 - port_no: 0
[I] I2SConfig.h : 115 - is_master: Master
[I] I2SConfig.h : 116 - sample rate: 88200
[I] I2SConfig.h : 117 - bits per sample: 32
[I] I2SConfig.h : 118 - number of channels: 2
[I] I2SConfig.h : 119 - i2s_format: I2S_STD_FORMAT
[I] I2SConfig.h : 121 - auto_clear: true
[I] I2SConfig.h : 123 - use_apll: true
[I] I2SConfig.h : 126 - fixed_mclk: 22579200
[I] I2SConfig.h : 128 - buffer_count:6
[I] I2SConfig.h : 129 - buffer_size:512
[I] I2SConfig.h : 143 - pin_data: 23
[I] StreamCopy.h : 139 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
trying to write
[I] StreamCopy.h : 139 - StreamCopy::copy 1024 -> 0 -> 0 bytes - in 0 hops
failed to write

or maybe there needs to be delay somewhere?

EDIT1: I have narrowed it down to this fragment

                LOGI("StreamCopy::onWrite 4x");
                // get the data now
                bytes_read = 0;
                if (bytes_to_read>0){
                    bytes_read = from->readBytes((uint8_t*)&buffer[0], bytes_to_read);
                }
                LOGI("StreamCopy::onWrite 5x");

It dies somewhere in between

pschatzmann commented 1 year ago

I just tried the orginal test case which does not show this issue.

So it must come from your file: I suggest that you try to create some test cases with reading and decoding mp3 files...

pwilkowski commented 1 year ago

I spend good couple of hours trying various test cases and this example works for me:

https://github.com/pschatzmann/arduino-audio-tools/blob/9d259461b7ae2f0ce0299f32350e9f79500dda02/examples/examples-basic-api/basic-a2dp-spdif/basic-a2dp-spdif.ino#L3

This is where i started from, unfortunately your example with sine wave spdif did not work. I just hear cracking from speakers.

I have tested this in both arduino and platformio.

my pio config:

[env:upesy_wroom]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
board_build.partitions = min_spiffs.csv
monitor_filters = esp32_exception_decoder
lib_deps =
    greiman/SdFat@^2.2.2
    https://github.com/pschatzmann/arduino-libhelix
    https://github.com/pschatzmann/arduino-libmad.git
    https://github.com/pschatzmann/arduino-audiokit
    https://github.com/pschatzmann/arduino-audio-tools.git
build_flags =
    -Ofast
    -DI2S_BUFFER_COUNT=8
    -DI2S_BUFFER_SIZE=256
    -DDEFAULT_BUFFER_SIZE=2048

At the same time i tested ESP8266 with another library and the same mp3 files: https://github.com/earlephilhower/ESP8266Audio BUT for some reason the same code and his library DOES NOT work on esp32

And it works without issues, reason why i want to use esp32 is that other hardware does not seem to work well with 8266 like lcd display and im starting to lack pins. Thus i found your library.

Here is the repository that works (ESP8266 and ESP8266Audio lib): https://github.com/kaminaris/Mp3Player8266

Here is the repository that doesn't work (previous attempts are in main.txt): https://github.com/kaminaris/Mp3Player32

So idk what kind of mp3 files are suppose to be there to work?

pschatzmann commented 1 year ago

I don't really have any way to test the SPDIF so I am afraid that I can't really help: I just know that some users confirmed that it was working for them.

Any mp3 with a standard bitrate should work w/o any changes. If you use some mp3 with some extreme or insane bitrate you will need to adjust the buffer size as explained in the Readme of the libhelix library. (I was using the bitrate classification from Audacity)

But if the basic sine test output is not working for you there is no point in trying the more complex mp3 scenario...

https://github.com/pschatzmann/arduino-audio-tools/wiki/It's-not-working

pwilkowski commented 1 year ago

i reencoded all my mp3 files to 128k because esp8266 was not able to keep up with higher bitrate ones

as for the its not working page, it doesn't explain why bluetooth audio example works. My bet goes to data not being processed correctly for mp3 -> spdif and maybe bluetooth already preprocesses pcm samples in some way to make it compatible?

pschatzmann commented 1 year ago

No, Bluetooth expects PCM with exactly 16bit, 2 channels at 44100 samples per second.

If the A2DP example is working, then I tend to think that you just messed up the I2S pins! or some other output settings are different.

pwilkowski commented 1 year ago

I had exact same config on my test case as A2DP example (set to pin 27)

Which is why it was really weird for me than code from above did not work because when reading mp3 it stated exactly that. 44100, 2 channels, 16 bit

I also tried feeding Mp3 Decoder manually and it seem to produce some output, oscilloscope showed some data but there was no sound.

pschatzmann commented 1 year ago

Maybe you should play around with the i2s buffer settings: If you check the A2DP example a buffer_count=30 and buffer_size = 384 is used. This is optimized for the output size (384) produced by A2DP and gives a total buffer size of 11520.

pwilkowski commented 1 year ago

Yes i did try with couple settings as you can see in build flags:

build_flags =
    -Ofast
    -DI2S_BUFFER_COUNT=8
    -DI2S_BUFFER_SIZE=256
    -DDEFAULT_BUFFER_SIZE=2048

first thing ive checked was 30 and 384

pschatzmann commented 1 year ago

I don't think 384 is a good value for mp3. I suggest that you try something like 23 * 512. I would also suggest to try to remove the DDEFAULT_BUFFER_SIZE and just use the default value if 1K

In any case you should first try to make sure that you get the simples sine example working stable

pwilkowski commented 1 year ago

Ive rebuild the project with

build_flags =
    -Ofast
    -DI2S_BUFFER_COUNT=8
    -DI2S_BUFFER_SIZE=11776

and now it mcu resets

tried also with I2S_BUFFER_SIZE=512

and cannot hear anything anymore, still trying to get sine to work

EDIT: Scratch that, removing -DDEFAULT_BUFFER_SIZE=2048 was the issue, it has to be bigger than 1024 otherwise i dont hear anything

Altho it still makes just cracking sounds

EDIT2:

Changing I2S_BUFFER_COUNT changes cracking sound frequency

pwilkowski commented 1 year ago

@pschatzmann i managed to get it working, i can hear sine wave, the issue was frequent Serial Writes

However mp3 still doesn't work, what can i do?

EDIT:

Current code:

#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include "SdFat.h"

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

typedef int16_t sound_t;  // sound will be represented as int16_t (with 2 bytes)
AudioInfo info(44100, 2, 16);
// SineWaveGenerator<sound_t> sineWave(32000);      // subclass of SoundGenerator with max amplitude of 32000
// GeneratedSoundStream<sound_t> sound(sineWave);   // Stream generated from sine wave

SPDIFOutput* out;
StreamCopy* copier; // copies sound into i2s
EncodedAudioStream* dec;

SdFat SDx;
FsFile audioFile;

// Arduino Setup
void setup() {
    // Open Serial
    Serial.begin(115200);
    AudioLogger::instance().begin(Serial, AudioLogger::Info);

    if (!SDx.begin(SdSpiConfig(5, DEDICATED_SPI, SD_SCK_MHZ(10)))) {
        SDx.initErrorHalt(&Serial);
    }

    auto root = SDx.open("/");
    audioFile = SDx.open("/Heart Attack.mp3");

    // start I2S
    Serial.println("starting SPDIF...");
    out = new SPDIFOutput();
    auto config = out->defaultConfig();
    config.copyFrom(info);
    config.pin_data = 25;
    out->begin(config);

    dec = new EncodedAudioStream(out, new MP3DecoderHelix());
    dec->setNotifyAudioChange(*out);
    dec->begin();

    copier = new StreamCopy();
    copier->begin(*dec, audioFile);
    // Setup sine wave
    // sineWave.begin(info, N_B4);
    Serial.println("started...");
}

// Arduino loop - copy sound to out
void loop() {
    copier->copy();
}

Log am getting:


starting SPDIF...
[I] I2SConfig.h : 113 - rx/tx mode: TX_MODE
[I] I2SConfig.h : 114 - port_no: 0
[I] I2SConfig.h : 115 - is_master: Master
[I] I2SConfig.h : 116 - sample rate: 88200
[I] I2SConfig.h : 117 - bits per sample: 32
[I] I2SConfig.h : 118 - number of channels: 2
[I] I2SConfig.h : 119 - i2s_format: I2S_STD_FORMAT
[I] I2SConfig.h : 121 - auto_clear: true
[I] I2SConfig.h : 123 - use_apll: true
[I] I2SConfig.h : 126 - fixed_mclk: 22579200
[I] I2SConfig.h : 128 - buffer_count:50
[I] I2SConfig.h : 129 - buffer_size:256
[I] I2SConfig.h : 143 - pin_data: 25
[I] AudioEncoded.h : 269 - virtual void audio_tools::EncodedAudioOutput::setNotifyAudioChange(audio_tools::AudioInfoSupport&)
[I] StreamCopy.h : 74 - buffer_size=2048
started...
[I] StreamCopy.h : 143 - StreamCopy::copy 2048 -> 2048 -> 2048 bytes - in 1 hops
[I] StreamCopy.h : 143 - StreamCopy::copy 2048 -> 2048 -> 2048 bytes - in 1 hops
[I] StreamCopy.h : 143 - StreamCopy::copy 2048 -> 2048 -> 2048 bytes - in 1 hops
[I] CodecMP3Helix.h : 136 - c 2, s 44100, bps 16
[I] I2SConfig.h : 113 - rx/tx mode: TX_MODE
[I] I2SConfig.h : 114 - port_no: 0
[I] I2SConfig.h : 115 - is_master: Master
[I] I2SConfig.h : 116 - sample rate: 88200
[I] I2SConfig.h : 117 - bits per sample: 32
[I] I2SConfig.h : 118 - number of channels: 2
[I] I2SConfig.h : 119 - i2s_format: I2S_STD_FORMAT
[I] I2SConfig.h : 121 - auto_clear: true
[I] I2SConfig.h : 123 - use_apll: true
[I] I2SConfig.h : 126 - fixed_mclk: 22579200
[I] I2SConfig.h : 128 - buffer_count:50
[I] I2SConfig.h : 129 - buffer_size:256
[I] I2SConfig.h : 143 - pin_data: 23
[I] StreamCopy.h : 143 - StreamCopy::copy 2048 -> 2048 -> 2048 bytes - in 1 hops
[I] StreamCopy.h : 143 - StreamCopy::copy 2048 -> 2048 -> 2048 bytes - in 1 hops
[I] StreamCopy.h : 143 - StreamCopy::copy 2048 -> 2048 -> 2048 bytes - in 1 hops
[I] StreamCopy.h : 143 - StreamCopy::copy 2048 -> 2048 -> 2048 bytes - in 1 hops```
pwilkowski commented 1 year ago

We are getting somewhere, i can finally hear sound! but it is distorted tho:

I have added -DSPDIF_DATA_PIN=25 and it seems to be somewhat fixed, for some reason spdif keeps defaulting to 23 which is used for SD card.

current settings

build_flags =
    -Ofast
    -DI2S_BUFFER_COUNT=50
    -DI2S_BUFFER_SIZE=256
    -DDEFAULT_BUFFER_SIZE=4096
    -DSPDIF_DATA_PIN=25

Unfortunately it cannot handle 320kbps songs but its somewhat expected. So, this may be good material for example.

What worries me the most is lack of stereo

pschatzmann commented 1 year ago

I committed a correction that should address the issue with the pin

pwilkowski commented 1 year ago

Thanks, Any idea why only one speaker plays? When playing with PC it works on both but here, left speaker is silent

EDIT:

Seems like this is an issue with joint stereo encoded files, for some reason one channel is quieter. Stereo seem to work fine, not sure if its issue with code or my mp3 files so i believe we are finally done with this one. It works so here is the repo if you want example to add:

https://github.com/kaminaris/Mp3Player32/blob/master/src/main.cpp

PS. SD.h doesn't work, Probably some issue with library, SdFat works.