Is there a way to trigger events after an oscillator finishes playing using the webaudio API? I am attempting to update my Vue component reactively to display data in the DOM while a note is being played. Here's a snippet of my code:
<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()
})
}
}
}
I am aiming to have the sequence
of pitches (currently just one) displayed on screen for the duration that the note plays, then vanish - indicating that pop
is triggered only after the note has finished playing. Any help with this issue would be greatly appreciated. Thank you.