1

I'm trying to test playing audio using a HTMLAudioElement and a AudioSourceNode. For the later application I need two features:

  1. The pitch must be preserved after the playbackRate changed.
  2. The volume needs to be changed to a value greater than 1.

Because feature 2 I added a workaround with the AudioSourceNode and the GainNode.

I need the audio file as ArrayBuffer in the later app that's why I added the file reading part before.

Problem:

The code works fine with Chrome and Opera, but not with Firefox. The playBackRate is set to 2, but the playbackRate of audio signal did not change. Why is that's the case and how can I fix it?

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Timestretching 2</title>
  <script type="text/javascript">
      var audioContext = window.AudioContext // Default
          || window.webkitAudioContext // Safari and old versions of Chrome
          || window.mozAudioContext
          || false;

      function play() {
          var fileInput = document.getElementById("file");
          var file = fileInput.files[0];

          var reader = new FileReader();
          reader.onload = function (event) {
              console.log("finished!");
              console.log(event.srcElement.result);

              var audioCtxt = new audioContext();
              var url = URL.createObjectURL(new File([event.srcElement.result], "test.wav"));
              var player = new Audio();

              const source = audioCtxt.createMediaElementSource(player);
              player.src = url;
              console.log("wait to play");
              player.addEventListener("canplay", function () {
                  // create a gain node to set volume greater than 1
                  const gainNode = audioCtxt.createGain();
                  gainNode.gain.value = 2.0; // double the volume
                  source.connect(gainNode);
                  gainNode.connect(audioCtxt.destination);

                  player.playbackRate = 2.0;
                  player.play();
                  player.playbackRate = 2.0;

                  console.log("playbackRate is " + player.playbackRate);
              });
          };

          reader.onprogress = function (progress) {
              console.log(progress.loaded / progress.total);
          };

          reader.onerror = function (error) {
              console.error(error);
          };

          reader.readAsArrayBuffer(file);
      }
  </script>
</head>
<body>
<input id="file" type="file" value="Audio Datei auswählen"/>
<button onclick="play()">PLAY</button>
</body>
</html>
julianpoemp
  • 1,965
  • 3
  • 14
  • 29
  • Given https://bugzilla.mozilla.org/show_bug.cgi?id=966247#c43 it seems you already know why: FF is broken here. However, no need to create a report, [there is already one](https://bugzilla.mozilla.org/show_bug.cgi?id=1517199).. Now for the workaround, do you really need to use an HTMLAudioElement here? Can't you use an AudioBuffer instead and do it all from WebAudioAPI? – Kaiido Aug 07 '19 at 12:28
  • @Kaiido unfortunately no. The feature to preserve the pitch is very important for my app. I used Web Audio API before, but in order to preserve the pitch I had to use third party libraries that are very old and not further developed. That's why I want to switch to HTML5 Audio. Perhaps I have to limit the features for firefox users and recommend them to switch to Chrome... – julianpoemp Aug 07 '19 at 12:57

0 Answers0