2017-02-08 3 views
2

Я пытаюсь создать синтезатор/секвенсор с помощью API WebAudio. В основном пытается сделать что-то, что может воспроизводить песню, состоящую из заметок и событий, таких как MIDI, для управления несколькими каналами синтезатора. Но мне все же нужно заняться аспектом синхронизации.Как работает WebAudio? Использует setInterval плохое решение?

Я читал учебники по API WebAudio, но я не совсем понимаю, как работает время/планирование/часы. Сначала я сделал polyphonic synthesizer, в котором воспроизводились ноты для нажатия клавиш, и это не требовало никакого учета времени. Затем я сделал осциллятор воспроизведением массива заметок с определенными временными интервалами, используя setInterval. Однако я заметил в прошлом при переключении вкладок в Google Chrome скорость воспроизведения значительно замедляется, я полагаю, что она менее ресурсоемкая, но другие библиотеки синтезаторов не имели этой проблемы. Также я могу только предположить, что использование setInterval не очень хорошо для гладкого (буферизуется правильного слова?) Воспроизведения, особенно при рассмотрении осцилляторов конвертов ADSR.

Из того, что я читаю, API WebAudio имеет постоянно увеличивающуюся переменную таймера currentTime. Но если заметки хранятся в массиве, и я хочу его циклически с заданной скоростью, как будет обрабатываться таймер WebAudio для итерации массива по заданной скорости? Мой setInterval solution (volume warning) не учитывает таймер WebAudio вообще и просто вызывает voice() с setInterval, чтобы сыграть заметку, перезаписав последний голос.

Есть ли лучшие или эффективные способы воспроизведения/петли последовательности заметок, отличных от setInterval?

Просто обновление для уточнения: Когда я писал этот вопрос, я использую setInterval играть последовательность нот через определенные промежутки времени (например, внеплановые - постоянно запуска/остановки осцилляторы) и было интересно, о более надежных способов играть ноты. Я нашел, что лучшим решением было бы использовать setValueAtTime на osc.frequency, а также GainNode. Для простого прототипа synth это работает хорошо, но более продвинутый синтезатор может использовать таймер на osc.start и osc.stop. Проблема петля песни. Чтобы зацикливаться, мне нужно постоянно планировать больше заметок, чтобы к концу песни оно начиналось. Я могу использовать setInterval, чтобы запланировать весь цикл петель, , но он все равно должен поддерживать время с песней, воспроизводимой, и setInterval (и даже вызовы onmessage веб-работников) можно было бы замедлить, если вкладка неактивна, например. Часы setInterval даже не надежны, поэтому я просто проверяю каждые 5 мс, если (currentTime >= songTime) и планирую, если условие выполнено. Этот метод может быть не слишком эффективным. What I have so far.

ответ

2

Я написал эту статью несколько лет назад: https://www.html5rocks.com/en/tutorials/audio/scheduling/. Он вникает в различия между таймерами веб-аудио и setInterval; Короче говоря, вы не можете «манипулировать временем» в веб-аудио часах, это связано с аппаратными часами в вашей звуковой карте. Вы можете планировать события в своем временном интервале, хотя, используя setInterval в качестве очень нервного/медленного напоминания цикла для планирования новых событий.

Что касается проблем с коммутационными вкладками, это ограничитель скорости 1 Гц, который большинству современных браузеров следует избегать затрат на электроэнергию у людей, использующих setInterval в качестве таймера рендеринга (например, setInterval с интервалом в 16 мс, чтобы попытаться запланировать каждый кадр видео). Вы можете избежать этого двумя способами: взлом с использованием веб-рабочих, который я использую в демо-версии метронома (https://github.com/cwilso/metronome), или вы можете подключиться к нему, когда окно теряет фокус (включение события onblur на объекте окна), чтобы начать планирование больше, чем 1s событий за раз.Единственная проблема заключается в том, что окно снова фокусируется (событие onfocus срабатывает на объекте окна), у вас будет возможность выполнить события, уже запланированные в веб-аудио, на вторую секунду - вы не можете вернуться в окно и сразу же нажать " остановка ", например

setInterval сам по себе не является отличным решением для музыкального времени повторяющихся ритмов, так как он будет дрожать (то есть задерживаться), когда в основной теме (включая сборку мусора) происходит существенный другой материал. Вы начнете слышать дрожание, особенно на менее мощных процессорах.

+0

Я чувствую, что я схожу с ума. Я больше не могу вызвать проблему «setInterval». Только в Chrome это происходит редко и случайным образом, и еще хуже, даже при использовании вашего метода работы с веб-рабочим он даже замедляется. Я использовал метод URI Blob, потому что Chrome специально не может запускать Web Workers локально (Firefox может). http://output.jsbin.com/busonu – bryc

+0

Хмм, я не могу заставить его запускать этот код. Каково ваше оборудование/ОС? – cwilso

+0

Тестирование на _2012 Intel i7 2770/16GB RAM/Win7_ и _2015 Intel i5/8GB RAM/Win10_. Если он не может быть искусственно запущен, есть ли способ обнаружить в коде, если бы произошел «дроссель» или «desync», который не будет возникать на веб-сайте в его собственном потоке? – bryc

Смежные вопросы