Blog / Javascript

Metrônomo com JavaScript

TTulio Faria 26 de mai. de 2017 4 min de leitura
Metrônomo com JavaScript

O metrônomo um dispositivo que deixa uma batida constante e ajuda os músicos a manterem um ritmo quando estão treinando. Esse ritmo pode aumentar ou diminuir de acordo com a escolha do músico.

Teremos um HTML simples, e primeiro vamos criar um input type range para gerar uma barra que será onde vamos controlar a velocidade do nosso metrônomo. Nele conseguimos colocar qual o valor mínimo e qual o valor máximo. Vamos pegar o do google como exemplo, o mínimo será 40 e o máximo 218. Um value inicial e um ID para conseguirmos recuperar este valor.

Em seguida, vamos colocar o áudio que será tocado (no meu caso tenho um clap.wav e um botão play para controlar o metrônomo).

<html>
    <head>
        <tittle>Metronomo</tittle>
    </head>
    <body>
        <input type="range"  min="40" max="218" value="40" id="bpm"/>
        <audio src="clap.wav"></audio>
        <button id="play">Play</button>
    </body>
<html>

Ele ficará assim:

Exemplo 1

Também é interessante colocarmos antes do input um H1 com o número inicial de batida que está configurado.

<h1>40bpm</h1>

Feito isso, podemos começar a adicionar um pouco de comportamento. Vamos colocar o script no corpo do HTML mesmo, pois a intenção no exemplo é só demonstrar como poderíamos reconstruir o metrônomo.

Toda vez que trocar o valor do range tem que ser trocado o que está escrito em H1. Então vamos pegar o BPM e o H1. Toda vez que o BPM mudar, ou seja, dar um change, o h1 tem que mudar também. Lembrando que essa técnica de colocar todos os seletores em cima é chamada de cash.

Primeiro faremos um teste com um valor fixo criando uma função que faz o play. Vamos chamá-la de tick e um intervalo fixo, que em sequência vamos resolver.

Nessa função tick, temos que pegar o áudio

<script>
    const bpm = document.getElementById('bpm')
    const h1 = document.querySelector('h1')
    const play = document.getElementByld('play')
    const.audio = document.querySelector('audio')
    let currentBpm = 40
    function tick(){
        audio.currentTime= 0
        audio.play()
    }
    bpm.addEventListener('change', function(){
        h1.innerHTML = this.value + ' bpm'
        currentBpm = parseInt(this.value)
    })
    play.addEventListener('click', function(){
        const timer = setInterval(tick, 100)
    })
    </script>

Agora vamos pensar um pouco: Se precisamos ter 40 batimentos por minuto e o minuto tem 60 segundos, 60 segundos tem 60 mil milissegundos, temos que distribuir 40 batidas dentro de 60 mil, então vamos dividir isso no valor do Bpm, ficando assim:

play.addEventListener('click', function () {
  const timer = setInterval(tick, (60 * 1000) / currentBpm)
})

Precisamos agora de uma forma para desligar essa batida, para isso vamos usar declarar o let isPlaying, o timer, e um if para, caso ele estiver tocando, darmos um clearInterval nesse timer.

<script>
    const bpm = document.getElementById('bpm')
    const h1 = document.querySelector('h1')
    const play = document.getElementByld('play')
    const.audio = document.querySelector('audio')
    let currentBpm = 40
    let isPlaying = false
    let timer = null
    function tick(){
        audio.currentTime= 0
        audio.play()
    }
    bpm.addEventListener('change', function(){
        h1.innerHTML = this.value + ' bpm'
        currentBpm = parseInt(this.value)
    })
    play.addEventListener('click', function(){
        if(isPlaying){
            clearInterval(timer)
        } else {
            const timer = setInterval(tick, (60*1000)/currentBpm)
        }
        isPlaying = !isPlaying
    })
</script>

Uma vez que estartamos o timer, ele começa a tocar. Ao clicar novamente, ele para, pois carrega na página com valor null. Ao clicarmos, damos um valor para ele e clicando de novo ele cai no isPlaying = !isPlaying que faz ele voltar a Null. Chamamos isso de toggle.

Também podemos trocar o texto do botão para play caso esteja tocando e Stop para quando estiver parado. Perceba que, ao apertar o play, ele começa a tocar apenas no próximo tick, pois o setInterval demora esse tick. Podemos fazer ele começar já com esse tick.

play.addEventListener('click', function () {
  if (isPlaying) {
    play.innerHTML = 'Play'
    clearInterval(timer)
  } else {
    tick()
    play.innerHTML = 'Stop'
    const timer = setInterval(tick, (60 * 1000) / currentBpm)
  }
  isPlaying = !isPlaying
})

Para esse valor atualizar sempre que mudamos o range, temos que fazer um if, que vai limpar o intervalo e começar um novo valor baseado no cálculo.

bpm.addEventListener('change', function () {
  h1.innerHTML = this.value + ' bpm'
  currentBpm = parseInt(this.value)
  if (isPlaying) {
    clearInterval(timer)
    timer = setInterval(tick, (60 * 1000) / currentBpm)
  }
})

Com isso, acabamos de construir um metrônomo.

Essa é uma ideia do que se pode construir com javaScript e HTML. Algumas outras ideias faremos posteriormente.

Confira o passo a passo em vídeo:

Curta o DevPleno no Facebook, inscreva-se no canal e não se esqueça de cadastrar seu e-mail para não perder as novidades. Abraço!

T
Escrito por
Tulio Faria

Mestre em Sistemas de Informação pela USP e criador do DevPleno. Iniciou sua carreira como professor com apenas 18 anos em um curso técnico, foram 11 anos em sala de aula formando desenvolvedores fullstack no sul de Minas Gerais.

Javascript
Compartilhar X LinkedIn
Continue lendo

Insights relacionados