Javascript 用于钢琴应用的动态持续时间设置超时功能

Javascript 用于钢琴应用的动态持续时间设置超时功能,javascript,jquery,settimeout,html5-audio,piano,Javascript,Jquery,Settimeout,Html5 Audio,Piano,我正在开发一个钢琴应用程序。我有一个json数组,其中包含注释名称及其播放时间 var data= [{"duration":300,"value":"2C"},{"duration":400,"value":"2D"},{"duration":420,"value":"2E"},{"duration":600,"value":"2F"},{"duration":400,"value":"2G"}]; 我需要按顺序播放2C音符300微秒,2D音符400微秒,2E音符420等等,也就是说在上一个

我正在开发一个钢琴应用程序。我有一个json数组,其中包含注释名称及其播放时间

var data= [{"duration":300,"value":"2C"},{"duration":400,"value":"2D"},{"duration":420,"value":"2E"},{"duration":600,"value":"2F"},{"duration":400,"value":"2G"}];
我需要按顺序播放2C音符300微秒,2D音符400微秒,2E音符420等等,也就是说在上一个音符完成后播放下一个音符

我的所有笔记都有.ogg格式的音频文件,所有笔记的持续时间都是1018.776微秒

为了播放上述json数据的注释,我尝试了javascript的setTimeout函数:

$.each( data, function( key, value ) {
    setTimeout(function(){
        var audioElement = document.createElement('audio');
        audioElement.setAttribute('src', './audio/'+value.value+'.ogg');
        audioElement.play();

    }, value.duration*key); 
});
但这是行不通的。主要问题在于持续时间。当我使用console.log(value.value)时,结果是2C、2D、2E、2G、2F。这里2F和2G的顺序不正确。
那么,如何以正确的顺序播放这些音符及其各自的持续时间呢?

希望在超时后调用其他值

function callAudio (index) {
    var
    value = this[i],
    audioElement = document.createElement('audio');

    if (!value) return;

    audioElement.setAttribute('src', './audio/'+value.value+'.ogg');
    audioElement.play();
    setTimeout(callAudio.bind(this, index++), value.duration);
};

callAudio.call(data, 0);

希望在超时后调用其他值

function callAudio (index) {
    var
    value = this[i],
    audioElement = document.createElement('audio');

    if (!value) return;

    audioElement.setAttribute('src', './audio/'+value.value+'.ogg');
    audioElement.play();
    setTimeout(callAudio.bind(this, index++), value.duration);
};

callAudio.call(data, 0);

您可以使用一个函数来接收数组和索引,然后在延迟后使用下一个索引调用自己

var data= [{"duration":300,"value":"2C"},{"duration":400,"value":"2D"},{"duration":420,"value":"2E"},{"duration":600,"value":"2F"},{"duration":400,"value":"2G"}];

function playNote(data, index) {
    var audioElement = document.createElement('audio');
    audioElement.setAttribute('src', './audio/'+data[index].value+'.ogg');
    audioElement.play();

    if (index + 1 < data.length) {
        setTimeout(function() {
            playNote(data, index + 1);
        }, data[index].duration);
    }
}

playNote(data, 0);
var data=[{“duration”:300,“value”:“2C”},{“duration”:400,“value”:“2D”},{“duration”:420,“value”:“2E”},{“duration”:600,“value”:“2F”},{“duration”:400,“value”:“2G”};
功能playNote(数据、索引){
var audioElement=document.createElement('audio');
audioElement.setAttribute('src','./audio/'+data[index].value+'.ogg');
audioElement.play();
if(索引+1<数据长度){
setTimeout(函数(){
playNote(数据,索引+1);
},数据[索引]。持续时间);
}
}
playNote(数据,0);

您可以使用一个函数来接收数组和索引,然后在延迟后使用下一个索引调用自己

var data= [{"duration":300,"value":"2C"},{"duration":400,"value":"2D"},{"duration":420,"value":"2E"},{"duration":600,"value":"2F"},{"duration":400,"value":"2G"}];

function playNote(data, index) {
    var audioElement = document.createElement('audio');
    audioElement.setAttribute('src', './audio/'+data[index].value+'.ogg');
    audioElement.play();

    if (index + 1 < data.length) {
        setTimeout(function() {
            playNote(data, index + 1);
        }, data[index].duration);
    }
}

playNote(data, 0);
var data=[{“duration”:300,“value”:“2C”},{“duration”:400,“value”:“2D”},{“duration”:420,“value”:“2E”},{“duration”:600,“value”:“2F”},{“duration”:400,“value”:“2G”};
功能playNote(数据、索引){
var audioElement=document.createElement('audio');
audioElement.setAttribute('src','./audio/'+data[index].value+'.ogg');
audioElement.play();
if(索引+1<数据长度){
setTimeout(函数(){
playNote(数据,索引+1);
},数据[索引]。持续时间);
}
}
playNote(数据,0);

您需要使用递归函数而不是循环:

function playNotes(notes) {
    var i = 0;
    playNextNote();
    function playNextNote() {
        if (i < notes.length) {
            var value = notes[i];
            var audioElement = document.createElement('audio');
            audioElement.setAttribute('src', './audio/'+value.value+'.ogg');
            audioElement.play();
            i++;
            setTimeout(playNextNote, value.duration);
        }
    }
}
函数播放注释(注释){
var i=0;
playNextNote();
函数playNextNote(){
如果(i

这样,在当前音符完成之前,不会触发下一个音符开始播放。

您需要使用递归函数而不是循环:

function playNotes(notes) {
    var i = 0;
    playNextNote();
    function playNextNote() {
        if (i < notes.length) {
            var value = notes[i];
            var audioElement = document.createElement('audio');
            audioElement.setAttribute('src', './audio/'+value.value+'.ogg');
            audioElement.play();
            i++;
            setTimeout(playNextNote, value.duration);
        }
    }
}
函数播放注释(注释){
var i=0;
playNextNote();
函数playNextNote(){
如果(i

这样,在当前音符完成之前,不会触发下一个音符开始播放。

您使用此代码进行了一些假设-我看到的第一个假设是声音文件会立即加载。您可能遇到的问题是,到目前为止,循环没有跟踪延迟-因此基本上您正在调用setTimeout({play},400)和setTimeout({play},500)之后立即调用setTimeout,因此它们在500毫秒后重叠到800毫秒

我写我认为你在寻找的东西的方式如下:

var audio = $.map(data, function(key,val) {return $("<audio>",{src:val.value})});
audio.each(function(indx, $ele) {
      if(indx !=0){
          audio[indx-1].on("ended", function(){$ele.get().play()});//play next sound when previous one finishes playing
      }
});
var audio=$.map(数据,函数(key,val){return$(“”,{src:val.value})});
音频。每个(功能(indx,$ele){
如果(indx!=0){
音频[indx-1]。打开(“结束”,函数(){$ele.get().play()});//在前一个声音播放完后播放下一个声音
}
});

您对这段代码做了一些假设——我看到的第一个假设是声音文件会立即加载。您可能遇到的问题是,到目前为止,循环没有跟踪延迟-因此基本上您正在调用setTimeout({play},400)和setTimeout({play},500)之后立即调用setTimeout,因此它们在500毫秒后重叠到800毫秒

我写我认为你在寻找的东西的方式如下:

var audio = $.map(data, function(key,val) {return $("<audio>",{src:val.value})});
audio.each(function(indx, $ele) {
      if(indx !=0){
          audio[indx-1].on("ended", function(){$ele.get().play()});//play next sound when previous one finishes playing
      }
});
var audio=$.map(数据,函数(key,val){return$(“”,{src:val.value})});
音频。每个(功能(indx,$ele){
如果(indx!=0){
音频[indx-1]。打开(“结束”,函数(){$ele.get().play()});//在前一个声音播放完后播放下一个声音
}
});

只是提醒一下:“我尝试过jQuery的setTimeout函数”setTimeout是本机javascript的函数,而不是jQuery。Thanx Carl Markham,我已经编辑过了,但是你能帮我解决这个问题吗?javascript定时器的精度几乎达不到微秒。您甚至不能保证毫秒精度,因为如果JS事件线程饱和,回调将延迟。@MattBall,那么解决方案是什么?有图书馆吗??有什么建议吗?如何用钢琴作曲?我已将所有笔记、顺序和持续时间存储在数据库中。当用户点击合成的音乐名称时,音乐播放。我试过的代码在上面的问题中。那么,如何修复它呢??Thanx提前..您可以尝试使用
end
事件侦听器,而不是
setTimeout
。只是提醒一下:“我试过jQuery的setTimeout函数”setTimeout是本机javascript的函数,而不是jQuery。Thanx Carl Markham,我已经编辑过了,但是你能帮我解决这个问题吗?javascript定时器的精度几乎达不到微秒。你不是