Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在JavaScript中发生的samean audioContext事件中触发或安排文档事件。?_Javascript_Html_Queue_Audiocontext - Fatal编程技术网

如何在JavaScript中发生的samean audioContext事件中触发或安排文档事件。?

如何在JavaScript中发生的samean audioContext事件中触发或安排文档事件。?,javascript,html,queue,audiocontext,Javascript,Html,Queue,Audiocontext,我已经根据[此代码][1]改编了节拍器应用程序。我有一个工作版本,其中包括一个“Apps.js”文件来触发metronome,然后是一个带有metronome脚本的“metronome.js”文件。我想显示播放按钮闪烁时,节拍器点击发生。我知道我可以通过添加一个不同的颜色圈,并在节拍器单击期间快速切换它的开关来轻松实现这一点,但我不知道如何安排显示 我应该在HTML文件中查找事件,还是在JavaScript文件中与节拍器单击一起安排事件。我不愿意承认,我只理解其中的60%,这让我很难理解,但这似

我已经根据[此代码][1]改编了节拍器应用程序。我有一个工作版本,其中包括一个“Apps.js”文件来触发metronome,然后是一个带有metronome脚本的“metronome.js”文件。我想显示播放按钮闪烁时,节拍器点击发生。我知道我可以通过添加一个不同的颜色圈,并在节拍器单击期间快速切换它的开关来轻松实现这一点,但我不知道如何安排显示

我应该在HTML文件中查找事件,还是在JavaScript文件中与节拍器单击一起安排事件。我不愿意承认,我只理解其中的60%,这让我很难理解,但这似乎是一个普遍的解决方案应该存在。对于这个问题,“apps.js”中唯一重要的事情是在单击播放按钮时绑定Metronome类中的
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] :

我找到了一些有用的资源