ozdemirburak / morse-code-translator

Translate text to Morse code and vice versa, with the option to play Morse code audio.
https://morsecodetranslator.com
MIT License
216 stars 57 forks source link

Failed to execute 'stop' on 'AudioScheduledSourceNode': cannot call stop without calling start first. #25

Closed phpsollution closed 1 year ago

phpsollution commented 1 year ago

Hi @ozdemirburak When i am clicking first time on the playicon then the audio has been start playing but as soon as i am clicking again to pause the audio it showing me this error "Failed to execute 'stop' on 'AudioScheduledSourceNode': cannot call stop without calling start first."

I am unable to understand what i am making wrong. Please help some one.

const morse = require('morse-decoder');
const togglePlay = (event) => {
      const audio = morse.audio('My Text');
      if (event.target.className === 'playicon') {
          audio.play();
          event.target.className = 'pauseicon';
      } else {
          audio.stop();
          event.target.className = 'playicon';
      }
  }

<div className="playicon" onClick={togglePlay}></div>
salmanAhmad143 commented 1 year ago

Hey @phpsollution @ozdemirburak @chris--jones Have you got the solution? I am also facing the same error when i am trying to stop the morse it giving me the same error

image

const audio = morse.audio('My Text');

if(notPlaying) {
     audio.play();
} else {
     audio.stop();
}

Please suggest any one. Waiting for your reply.

chris--jones commented 1 year ago

I haven't seen this happen before my only guess is some sort of race condition. The current implementation of play/stop is kind of broken because AudioBufferSourceNodes aren't supposed to have start and stop called more than once - so audio.stop() is probably more of a dispose.

To make functionality similar to what you're expecting would require some refactoring in the library - only calling start for the first play on the source, tracking the currentTime (should be exposed I guess) and either altering the playRate or gain to simulate a pause on stop rather than outright stopping the source (although we'd still want a clean way to dispose of the audio source).

The current workaround is to create new audio instances when you play:

let audio;
if(notPlaying) {
     audio = morse.audio('My Text')
     audio.play();
} else {
     audio.stop();
}

note this won't enable you to pause and resume though.

ozdemirburak commented 1 year ago

Chris' response should work as a workaround; therefore, I'm closing this issue. However, another issue can be opened for adding the pause/play option.

Completely refactoring the audio generation is another option. There are other potential changes mentioned here on #27.

chris--jones commented 1 year ago

I know this is closed, but it also occurred to me that you can use the wave functions to get an audio blob that you can pause, play and seek to your heart's content.

As an example consider this which binds the rendered audio to an audio element with controls:

<audio id="morse" controls />
<script>
    const morse = window['morse-decoder'];
    const audioOutput = morse.audio('Go ahead, pause this audio');
    audioOutput.getWaveUrl().then((url) => {
        document.querySelector('#morse')
        .setAttribute('src', url);
    });
</script>

image

I'll submit a PR to add more examples to the readme, since there's a few other omissions such as how to even use the minified js on a web page as I have above.

ozdemirburak commented 1 year ago

That's a really smart approach.