如何在JavaScript中发生的samean audioContext事件中触发或安排文档事件。?
我已经根据[此代码][1]改编了节拍器应用程序。我有一个工作版本,其中包括一个“Apps.js”文件来触发metronome,然后是一个带有metronome脚本的“metronome.js”文件。我想显示播放按钮闪烁时,节拍器点击发生。我知道我可以通过添加一个不同的颜色圈,并在节拍器单击期间快速切换它的开关来轻松实现这一点,但我不知道如何安排显示 我应该在HTML文件中查找事件,还是在JavaScript文件中与节拍器单击一起安排事件。我不愿意承认,我只理解其中的60%,这让我很难理解,但这似乎是一个普遍的解决方案应该存在。对于这个问题,“apps.js”中唯一重要的事情是在单击播放按钮时绑定Metronome类中的如何在JavaScript中发生的samean audioContext事件中触发或安排文档事件。?,javascript,html,queue,audiocontext,Javascript,Html,Queue,Audiocontext,我已经根据[此代码][1]改编了节拍器应用程序。我有一个工作版本,其中包括一个“Apps.js”文件来触发metronome,然后是一个带有metronome脚本的“metronome.js”文件。我想显示播放按钮闪烁时,节拍器点击发生。我知道我可以通过添加一个不同的颜色圈,并在节拍器单击期间快速切换它的开关来轻松实现这一点,但我不知道如何安排显示 我应该在HTML文件中查找事件,还是在JavaScript文件中与节拍器单击一起安排事件。我不愿意承认,我只理解其中的60%,这让我很难理解,但这似
start/stop
函数
这是Metronome.js代码:
class Metronome
{
constructor(tempo = 120)
{
this.audioContext = null;
this.notesInQueue = []; // notes that have been put into the web audio and may or may not have been played yet {note, time}
this.currentQuarterNote = 0;
this.totalBeats = 0;
this.tempo = tempo;
this.lookahead = 25; // How frequently to call scheduling function (in milliseconds)
this.scheduleAheadTime = 0.1; // How far ahead to schedule audio (sec)
this.nextNoteTime = 0.0; // when the next note is due
this.isRunning = false;
this.intervalID = null;
this.beats=4;
this.mode='none';
}
nextNote()
{
// Advance current note and time by a quarter note (crotchet if you're posh)
var secondsPerBeat = 60.0 / this.tempo; // Notice this picks up the CURRENT tempo value to calculate beat length.
this.nextNoteTime += secondsPerBeat; // Add beat length to last beat time
this.currentQuarterNote++; // Advance the beat number, wrap to zero
if (this.currentQuarterNote == this.beats) {
this.currentQuarterNote = 0;
}
this.totalBeats++; // Advance the beat number, wrap to zero
}
scheduleNote(beatNumber, time)
{
// push the note on the queue, even if we're not playing.
this.notesInQueue.push({ note: beatNumber, time: time });
// create an oscillator
const osc = this.audioContext.createOscillator();
const envelope = this.audioContext.createGain();
const modeProb={'none':0, 'easy':0.2, 'medium':0.35, 'hard':0.45, 'god':0.6,};
//console.log(this.totalBeats)
osc.frequency.value = (beatNumber == 0 ) ? 1000 : 800;
//remove some beats to practive rhythm stability
if(this.totalBeats>this.beats*2){
osc.frequency.value = (Math.random() < modeProb[this.mode]) ? 0 : osc.frequency.value;
};
//osc.frequency.value = (beatNumber % 4 == 0) ? 0 : 800;
envelope.gain.value = 1;
envelope.gain.exponentialRampToValueAtTime(1, time + 0.001);
envelope.gain.exponentialRampToValueAtTime(0.001, time + 0.02);
osc.connect(envelope);
envelope.connect(this.audioContext.destination);
osc.start(time);
osc.stop(time + 0.03);
//alert(this.mode);
}
scheduler()
{
// while there are notes that will need to play before the next interval, schedule them and advance the pointer.
while (this.nextNoteTime < this.audioContext.currentTime + this.scheduleAheadTime ) {
this.scheduleNote(this.currentQuarterNote, this.nextNoteTime);
this.nextNote();
}
}
start()
{
if (this.isRunning) return;
if (this.audioContext == null)
{
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
}
this.isRunning = true;
this.currentQuarterNote = 0;
this.nextNoteTime = this.audioContext.currentTime + 0.05;
this.intervalID = setInterval(() => this.scheduler(), this.lookahead);
}
stop()
{
this.isRunning = false;
clearInterval(this.intervalID);
}
startStop()
{
if (this.isRunning) {
this.stop();
}
else {
this.start();
}
}
}
类节拍器
{
构造函数(速度=120)
{
this.audioContext=null;
this.notesInQueue=[];//已放入web音频中且可能已播放或可能尚未播放的笔记{note,time}
此.currentQuarterNote=0;
这个.totalBeats=0;
this.tempo=节奏;
this.lookahead=25;//调用调度函数的频率(毫秒)
this.scheduleAheadTime=0.1;//音频调度的提前时间(秒)
this.nextNoteTime=0.0;//下次备忘到期时
this.isRunning=false;
this.intervalID=null;
这个。拍数=4;
这个.mode='none';
}
nextNote()
{
//将当前音符和时间提前四分之一个音符(如果你是时髦的话,就用四分之一个音符)
var secondsPerBeat=60.0/this.tempo;//请注意,这将拾取当前的节拍值以计算节拍长度。
this.nextNoteTime+=secondsPerBeat;//将拍长添加到最后一拍时间
this.currentQuarterNote++;//将节拍数提前,换行为零
if(this.currentQuarterNote==this.beats){
此.currentQuarterNote=0;
}
this.totalBeats++;//将节拍数提前,换行为零
}
计划注释(编号、时间)
{
//即使我们不玩,也要把纸条按在队列上。
this.notesInQueue.push({note:beatNumber,time:time});
//创建一个振荡器
const osc=this.audioContext.create振荡器();
const信封=this.audioContext.createGain();
const modeProb={'none':0,“easy':0.2,'medium':0.35,'hard':0.45,'god':0.6,};
//console.log(this.totalBeats)
osc.frequency.value=(beatNumber==0)?1000:800;
//去掉一些节拍来练习节奏的稳定性
if(this.totalBeats>this.beats*2){
osc.frequency.value=(Math.random()this.scheduler(),this.lookahead);
}
停止()
{
this.isRunning=false;
clearInterval(此为有效期);
}
startStop()
{
如果(此.isRunning){
这个。停止();
}
否则{
这个。start();
}
}
}
[1] :我找到了一些有用的资源