0

I'm pretty new to Javascript and coding in general so go easy on me!

I've made a (very) simple metronome in HTML, JS, etc using setInterval - I'm aware there are limitations to this, and that it's not the most accurate method of doing so etc. With that being said, on the various desktop browsers it seems to work relatively well. However:

  • On desktop Safari (15.1) the audio doesn't seem to play properly - it's audible but muffled.

  • On every mobile browser I've tried (Safari, Firefox, Chrome - unsure which versions) it doesn't seem to work at all.

Any help with this would be greatly appreciated - I've included the code for the actual metronome part below. I have to assume the issues relate to setInterval somehow, I'm just hoping someone can shed some light on why exactly it doesn't work.

Cheers!

  const sound = document.querySelector('audio');
  const powerButton = document.querySelector('.on-button');
  let poweredOn = false;
  let metronome;
  let milliseconds;

  function playSound() {
      if (milliseconds != Infinity) {
        sound.currentTime = 0;
        sound.play();
      }
    }

  function setMilliseconds() {
    let tempo = document.querySelector('.tempo').value;
    milliseconds = 60000 / tempo;


    if (poweredOn == true) {
      clearInterval(metronome);
      if (milliseconds >= 100) {
        playSound();
        metronome = setInterval(playSound, milliseconds);
        }
    }

    if ((!tempo || milliseconds < 100) && poweredOn == true) {
      poweredOn = false;
      clearInterval(metronome);
      powerButton.classList.remove('switched-on');
    }
  }

  function activate() {
    if (milliseconds) {
      let tempo = document.querySelector('.tempo').value;
      poweredOn = poweredOn ? false : true ;
      if (poweredOn && milliseconds) {
        if (milliseconds < 100 || !milliseconds || !tempo) {
          this.classList.add('invalid');
          setTimeout(() => {
            this.classList.remove('invalid');
          }, 100)
          poweredOn = false;
        } else {
          this.classList.add('switched-on');
          playSound();
          metronome = setInterval(playSound, milliseconds);
        }
      } else {
        this.classList.remove('switched-on');
        clearInterval(metronome);
      }
    } else {
      this.classList.add('invalid');
      setTimeout(() => {
        this.classList.remove('invalid');
      }, 100)
    }
  }

EDIT - I've added all of the JS from the metronome, rather than just the one function. I've since changed it to use a recurring setTimeout rather than setInterval, so that I can adjust the interval as I go to compensate for drift - debugging that is suggesting that the issue could be with the audio playing on mobile, rather than the intervals themselves. Any thoughts?

  • So did you verify that the playSound part works? Hard for us to guess without having no clue what that does. Did you debug on mobile to see what part is failing? – epascarello Dec 21 '21 at 16:38
  • I've added that, it's just an audio element triggered by 'sound.currentTime = 0; sound.play()' though. I assumed it was working as it played once when I activate the metronome, but - as per my edit - maybe not – benjaminkitson Dec 21 '21 at 17:52
  • Note that in a lot of browsers audio is not allowed to play (or even create an AudioContext) unless the user has interacted with the page. Is your metronome tied to "not doing anything until the user clicks a button to start it" or the like? – Mike 'Pomax' Kamermans Mar 15 '22 at 22:28
  • The user has to click a button to start the metronome - it defaults to being off on load. This occurred to me as well, but the fact that it works fine in Chrome and FireFox suggests to me that it's a different issue. – benjaminkitson Mar 17 '22 at 16:53

0 Answers0