Диспетчеризация действий с помощью обратного вызова в Redux

Я работаю над созданием пошагового секвенсора в Redux, чтобы помочь мне в обучении. Что мне нужно, это какие-то универсальные часы, которые работают как "тик", чтобы обеспечить музыкальное время. Поэтому я планировал использовать библиотеку Tone.js, которая основана на API Web Audio. Там есть следующая функция:

Tone.Transport.scheduleRepeat(function(time){
//do something with the time
}, "8n");

Вы предоставляете функцию обратного вызова, которая вызывается каждый раз, когда транспорт достигает определенной позиции. Мой наивный подход состоял в том, чтобы позволить обратному вызову отправлять действие, которое увеличивает количество тиков в моем магазине. Это не работает, потому что действия должны быть простыми объектами. Каковы возможности, чтобы заставить это работать?

Я все еще работаю над получением правильного понимания основных базовых принципов Redux, поэтому я не уверен в этом, но могу ли я каким-то образом перехватить обратный вызов с помощью промежуточного программного обеспечения и просто пропустить его, когда он действительно будет вызван?

Будет ли это правильное направление? Какие библиотеки, примеры или концепции я мог бы изучить, чтобы понять, как это можно сделать?

Это даже правильное направление или я должен подходить к этому по-другому? Если так, то как?

Или, может быть, у вас есть идея, как лучше всего обеспечить глобальную синхронизацию для различных компонентов в приложении Redux?

4 ответа

Я углубился в подробности в https://www.html5rocks.com/en/tutorials/audio/scheduling/, но вкратце - вы не должны использовать обратные вызовы Javascript для музыкальной синхронизации. Это не достаточно точно. Вот почему у нас есть веб-аудио планирование.

Очень интересный вопрос, это любимый проект, который я тоже хотел решить, но еще не написал ни одного LOC.:)

Что касается времени, вы можете использовать промежуточное программное обеспечение для этого, или даже <Clock /> компонент, который запускает scheduler сам и отправляет действие на каждый тик (вероятно, со временем в качестве полезной нагрузки).

Сложной частью, однако, является общий дизайн вашего приложения. Немного изучив Tone.js, я понял, что вам нужно отделить аудио часть от визуального. Это означает, что ваше состояние Redux должно быть связано только с представлением вашего пошагового секвенсора (я представляю что-то вроде списка дорожек (каналов / инструментов), и ваша звуковая логика должна быть за пределами этого.

Я хотел бы сохранить массив дорожек, каждый из которых сам является массивом "шагов", которые определяют, являются ли они "активными" или нет. Опять же, это связано только с пользовательским интерфейсом. Нажав на шаг, чтобы активировать его, вы должны изменить свое состояние с помощью создателя действий, а также настроить все, что вам позже понадобится для игры с Tone.js.

При воспроизведении вашей песни вам нужно будет выставить этот такт, чтобы продвинуть текущий активный "шаг", чтобы вы могли выделить его в пользовательском интерфейсе.

Вот аппетитный Codepen, подражающий Roland TR-808, чтобы захватить идеи:

http://codepen.io/pixelass/details/adyLPR

А вот соответствующий раздел в вики Tone.js по синхронизации аудио и пользовательского интерфейса:

https://github.com/Tonejs/Tone.js/wiki/Performance

Извините, я не могу вам помочь, может быть, вы опередили меня и у вас уже есть рабочий код, которым вы могли бы поделиться.

В основном cwilso ответил правильно. Если вы хотите планировать функции JS для музыкального времени, вам не следует использовать обратные вызовы.

Если есть функция Tone.js, которую вы хотите реализовать на основе этого времени, избегайте Redux и вызывайте эти функции Tone.js напрямую, либо в функциях обратного вызова, либо в функции Tone.Transport.schedule.

Если вы создаете секвенсор, я бы порекомендовал зациклить Tone.Transport, исходя из желаемой длины, и составить расписание для нот, которые будут нажиматься в определенные моменты на временной шкале (если это то, что вы ищете). Проверьте loopStart и loopEnd в документах для справки ( http://tonejs.github.io/docs/).

Если эта функциональность необходима для визуальных ссылок, возможно, именно поэтому вам нужен обратный вызов Redux, я могу привести пример того, как вы можете сделать это ниже:

function incrementTick() {
  return { type: 'INCREMENT_TICK' }
}

// inside your component once the increment function has been connected
Tone.Transport.scheduleRepeat((time) => {
  this.props.incrementTick()
}, "8n");

Надеюсь это поможет.

Я работаю над приложением, связанным со звуком, и столкнулся с проблемой управления частью веб-аудио API, а также с избыточностью.

Я решил, что это только сохранение представления состояния звука в хранилище избыточных данных (простые объекты JS; что вы будете хранить в базе данных и использовать для инициализации приложения). Эта сохраненная информация используется для визуализации пользовательского интерфейса.

У меня есть сервисный класс 'engine', который прослушивает все изменения в магазине, именно здесь создаются и хранятся все веб-аудио материалы. Он содержит в основном копию редукторов из хранилища приставок, но применяет изменения к веб-аудио узлам.

Например, я отправляю действие:

{type:"set-gain", payload:{trackid:3, value:0.7} }

Хранилище редуксов просто обновит обычный объект трека JS до нового значения усиления, механизм найдет связанный с ним узел усиления (или создаст его с помощью добавления и т. Д.) И установит для него значение.

В вашем случае вы бы отправили действие для установки времени, в хранилище редуксов сохраните его как обычный объект JS, в части движка вы используете веб-аудио планирование для его установки.

Другие вопросы по тегам