javascripthtmlbeepjavascript-oscillator

How to beep on evey button click


Html application needs to beep on every button touch.

Tried code below in desktop and Android browsers.

In desktop browser (latest Chrome) after clicking rapidly 100 times in button beep is disabled after 100 clicks.

In mobile browser (Android 11 or 8 Zebra Enterprise Browser) after 10 touches to button beeping stops.

Chrome console log does not contain any warning or error message. It shows beeping message but beep does not occur.

How to fix this so that beeping occurs in every button click or touch?

<html>
<head>
<script>
function beep () {
  const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
  const oscillator = audioCtx.createOscillator()
  const gainNode = audioCtx.createGain()
  oscillator.connect(gainNode)
  gainNode.connect(audioCtx.destination)
  gainNode.gain.value = 1 // volume;
  oscillator.frequency.value = 3000 // frequency;
  oscillator.type = 'sine' // type;
  console.log('beep')
  oscillator.start()
  setTimeout(
    function () {
      oscillator.stop()
    },
    70 // duration
  )
}
</script>
</head>

<body>

<button type="button" onclick="beep()">
+
</button>
</body>
</html>

Solution

  • The reason why beeping stops after a certain number of clicks or touches is that the audio context is being created every time the button is clicked, and there is a limit on the number of audio contexts that can be created.

    To fix this, you can create the audio context only once, outside of the beep function, and reuse it every time the button is clicked.

    <html>
        <head>
            <script>
            const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
            const gainNode = audioCtx.createGain()
            gainNode.connect(audioCtx.destination)
            gainNode.gain.value = 1 // volume;
    
            function beep () {
                const oscillator = audioCtx.createOscillator()
                oscillator.connect(gainNode)
                oscillator.frequency.value = 3000 // frequency;
                oscillator.type = 'sine' // type;
                console.log('beep')
                oscillator.start()
                setTimeout(
                    function () {
                        oscillator.stop()
                    },
                    70 // duration
                )
            }
            </script>
        </head>
    
        <body>
            <button type="button" onclick="beep()">+</button>
        </body>
    </html>