Я пытаюсь написать простой музыкальный секвенсор в Javascript.
Звуки будут воспроизводиться SoundManager2
Я быстро понял, что setTimeout и setInterval бесполезныдля такого рода времени.Их точность просто недостаточно хороша.
Вместо этого я пытаюсь вот что:
Создать очередь звуковых событий (массив 2d [ note , время ])
Обработка очереди в цикле while
В псевдокоде это может выглядеть так:
// The queue of time/note values (millisecs)
var q = [[0, C], [250, D], [500, E]]
var begin = (new Date).getTime()
while(q.length > 0 ){
var now = (new Date).getTime()
var eventTime = q[0][0] + begin
if( now >= eventTime){
playNote(q[0][1]) // Play the note
q.shift() // Now that the note has been played, discard it.
}
}
Через отладку яобнаружил, что этот метод кажется достаточно точным (вызов playNote выполняется именно в то время, в которое он должен).
Однако, пока воспроизводится «последовательность», все остальные Javascript (включая бит, который фактически делает звук)приостановлено, что вряд ли является сюрпризом.
Это означает, что у меня есть тишина столько времени, сколько требуется для запуска последовательности, а затем выполняются ВСЕ вызовы playNote.
У меня естьпопытался изолировать цикл while в своей собственной функции, а затем вызвать его через setTimeout, в надежде, что это создаст фоновый поток, выполняющий свою собственную вещь (а именно, проигрывание последовательности), не останавливая все остальные JS-операции.Это не работает
Я также пытался вызвать функцию playNote, используя setTimeout, в надежде, что хотя пользовательский интерфейс действительно заморожен, по крайней мере, последовательность воспроизводится правильно, но это тоже не работает.
Я также попробовал комбинацию, но, как вы уже, наверное, догадались, она тоже не работает.
Итак, мой вопрос:
Как я могу иметь очередьсобытий, обработанных с точной синхронизацией, при этом НЕ останавливая выполнение всех других кодов во время выполнения