earlephilhower / ESP8266Audio

Arduino library to play MOD, WAV, FLAC, MIDI, RTTTL, MP3, and AAC files on I2S DACs or with a software emulated delta-sigma DAC on the ESP8266 and ESP32
GNU General Public License v3.0
2.03k stars 432 forks source link

Cannot play sound more than once #604

Open BorisBrock opened 1 year ago

BorisBrock commented 1 year ago

I have created the following class to play sound effects on an ESP32 (with a MAX98357A):

void SoundPlayer::Init()
{
    SPIFFS.begin();

    mOutput = new AudioOutputI2S();
    mOutput->SetPinout(PIN_OUT_AUDIO_BCLK, PIN_OUT_AUDIO_LCLK, PIN_OUT_AUDIO_DATA);
    mGenerator = new AudioGeneratorWAV();
    mMyTestSound = new AudioFileSourceSPIFFS("/test.wav");
}

void SoundPlayer::Update()
{
    if (mGenerator->isRunning())
    {
        if (!mGenerator->loop())
            mGenerator->stop();
    }
}

void SoundPlayer::Play()
{
    // Stop any running sounds
    if (mGenerator->isRunning())
        mGenerator->stop();

    // Play the selected sound
    mGenerator->begin(mMyTestSound, mOutput);
}

On the first call of Play() the sound plays just fine. After that nothing gets played any more. What is the correct way to play the same sound multiple times (with as little overhead as possible)?

knuf-kandler commented 1 year ago

one way - recreate all necessary objects during replay. second way - rewrite generator so it si not closing the file with the stop or add loop function

Rich968 commented 1 year ago

mGenerator ->stop() closes the wav file. You need to re-open the file before playing it again. ie mMyTestSound->open("/test.wav"); mGenerator->begin(mMyTestSound, mOutput);

electromechpro commented 2 months ago

I, too, cannot figure out how to play a sound more than once, and have been searching for days to try and find an answer. I am using a M5stack Tough (similar to Cre2), and playing an mp3 from SD card using the touchbutton code from the examples. I was able to get the sound to play only by putting part of the code in each of the header, setup, loop and eventDisplay sections. If one were to delete and reopen the file, where would this code go? If an example were made somewhere to repeat a sound with either a pin state change, software button or function, it would be appreciated.

`/ 7/22/24 File to make M5Tough play Sound.mp3 from SD card in mp3 directory when a touch button is pushed. So far, it only plays once. Need to figure out how to make it play again. /

pragma mark - Depend ESP8266Audio and ESP8266_Spiram libraries

include

include <driver/i2s.h>

include

include "AudioFileSourceSD.h"

include "AudioFileSourceID3.h"

include "AudioGeneratorMP3.h"

include "AudioOutputI2S.h"

AudioGeneratorMP3 mp3; AudioFileSourceSD file; AudioOutputI2S out; AudioFileSourceID3 id3;

define OUTPUT_GAIN 100 //appears to be a percent

// This program tested for M5Buttons

ButtonColors on_clrs = { BLUE, WHITE, WHITE }; ButtonColors off_clrs = { BLACK, WHITE, WHITE }; Button bl(20, 200, 80, 40, false, "A", off_clrs, on_clrs, MC_DATUM); Button b2(120, 200, 80, 40, false, "B", off_clrs, on_clrs, MC_DATUM); Button b3(220, 200, 80, 40, false, "C", off_clrs, on_clrs, MC_DATUM);

void eventDisplay(Event &e) { M5.Lcd.fillRect(0, 0, 320, 150, BLACK); Serial.printf("%-12s finger%d %-18s (%3d, %3d) --> (%3d, %3d) ", e.typeName(), e.finger, e.objName(), e.from.x, e.from.y, e.to.x, e.to.y);

Serial.printf("( dir %d deg, dist %d, %d ms )\r\n", e.direction(), e.distance(), e.duration);

char info[50]; //print the button name sprintf(info, "Btn %s wasPressed", e.objName()); M5.Lcd.drawString(info, 160, 100);

mp3->begin(id3, out); //Try to move this to the loop and run on conditional inputs. //mp3->begin() looks like it plays once. //try mp3->loop() to continuously play. } void setup() { M5.begin(); M5.Axp.SetSpkEnable(true); M5.Lcd.setTextSize(2); M5.Lcd.setTextDatum(MC_DATUM); M5.Buttons.draw(); //add handler for the buttons bl.addHandler(eventDisplay, E_ALL); b2.addHandler(eventDisplay, E_ALL); b3.addHandler(eventDisplay, E_ALL);

file = new AudioFileSourceSD("/mp3/Sound.mp3"); //Name the sound "Sound.mp3" and stick it in the mp3 directory of the SD card. id3 = new AudioFileSourceID3(file); out = new AudioOutputI2S(0, 0); // Output to builtInDAC out->SetPinout(12, 0, 2); out->SetOutputModeMono(true); out->SetGain((float)OUTPUT_GAIN / 100.0); mp3 = new AudioGeneratorMP3(); }

void loop() { M5.update(); if (mp3->isRunning()) { //this is needed somehow or mp3 will not play. Moving it into the event handler if (!mp3->loop()) mp3->stop(); //does not work. } }`

electromechpro commented 2 months ago

Sorry code tags did not work right.