David J.
David J.

Reputation: 1913

Asynchronous Events with WebAudio API

How can I program events to happen once an oscillator has stopped playing using the webaudio API? I'm trying to get data to show up in the DOM while the note is playing, reactively, by updating my Vue component. My code looks like this:

<template>
    <div id="player">
        <div>{{ currentTime }}</div>
        <button @click="start">play</button>
        <div>{{ sequence }}</div>
    </div>
</template>
<script>

 var audioContext = new AudioContext()

 function getRandomInt(min, max) {
     min = Math.ceil(min);
     max = Math.floor(max);
     return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
 }

 export default {
     name: 'player',
     data: function(){
         return {
             sequence: [],
             toRecall: null,
             frequencies: [110, 220, 440, 880],
             lives: 3,
             n: 2,
             currentTime: null,
             stop: false
         }
     },
     methods: {

         playNote: function(startTime, delay, duration){
             var self=this
             return new Promise(function(accept, reject){
                 var pitch = getRandomInt(-12, 13)

                 self.sequence.push(pitch)
                 var startTime = audioContext.currentTime + delay
                 var endTime = startTime + duration
                 var oscillator = audioContext.createOscillator()
                 oscillator.connect(audioContext.destination)
                 oscillator.type = 'sawtooth'
                 oscillator.start(startTime)
                 oscillator.stop(endTime)
                 accept()
             })                          
         },
         start: function(){
             var self=this
             this.currentTime = audioContext.currentTime
             this.playNote(0, 0, 1).then(function(){
                 // do once the note is done playing
                 self.sequence.pop()
             })

         }
     }
 }

Specifically, I want the sequence of pitches (just one for now) to show up on the screen for the 1 second that the note plays, then disappear -- just to prove that pop is only being called once the note is done playing. Can anyone help me with this? Thanks.

Upvotes: 1

Views: 536

Answers (1)

Raymond Toy
Raymond Toy

Reputation: 6056

See https://webaudio.github.io/web-audio-api/#dom-audioscheduledsourcenode-onended. And since an OscillatorNode is an AudioScheduledSourceNode, you can do something like

oscillator.onended = function () { /* Remove note from display, or whatever */ };

Upvotes: 1

Related Questions