ESP8266Audio icon indicating copy to clipboard operation
ESP8266Audio copied to clipboard

Cannot play sound more than once

Open BorisBrock opened this issue 1 year ago • 4 comments

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)?

BorisBrock avatar Mar 01 '23 09:03 BorisBrock

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

knuf-kandler avatar Mar 04 '23 14:03 knuf-kandler

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);

Rich968 avatar Mar 04 '23 19:03 Rich968

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 <M5Tough.h> #include <driver/i2s.h> #include <WiFi.h> #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 avatar Jul 25 '24 19:07 electromechpro

Sorry code tags did not work right.

electromechpro avatar Jul 25 '24 19:07 electromechpro