Есть ли способ перезапускать осциллятор Web Audio API с начала каждый раз при нажатии кнопки?

Вопросы и ответы

Я в процессе создания синтезатора бас-барабана с использованием Web Audio API. Мне удалось заставить кнопку запускать функцию, которая генерирует синусоидальную волну с изменением высоты тона и громкости, но кнопка, похоже, работает только один раз, и при повторном нажатии звук не воспроизводится с начала.

const audioCtx = new AudioContext(); // Инициализация аудиоконтекста
const osc = audioCtx.createOscillator(); // Создание осциллятора
const volume = audioCtx.createGain(); // Создание усилителя

osc.type = "sine"; // Установка типа исходной формы волны
osc.frequency.value = 440; // Установка частоты осциллятора

osc.start(); // Начать воспроизведение осциллятора
osc.connect(volume); // Установка назначения для осциллятора  

function generateKick() {
   volume.gain.value = 1;
   osc.frequency.setTargetAtTime(22, 0, 0.1);
   volume.gain.setTargetAtTime(0, audioCtx.currentTime, 0.1);
   volume.connect(audioCtx.destination);

}

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

JSFiddle

Я пытался вставить функцию osc.start() внутрь своей функции, но это не сработало, так как функция .start() не может быть вызвана более одного раза.

Я не эксперт в Web Audio, но использование setValueAtTime для сброса громкости и частоты перед каждым вызовом setTargetAtTime похоже, решает проблему (я также вынес volume.connect за пределы функции, чтобы она выполнялась только один раз):

const audioCtx = new AudioContext(); // Инициализация аудиоконтекста
const osc = audioCtx.createOscillator(); // Создание осциллятора
const volume = audioCtx.createGain(); // Создание усилителя

osc.type = "sine"; // Установка типа исходной формы волны
osc.frequency.value = 440; // Установка частоты осциллятора

osc.start(); // Начать воспроизведение осциллятора
osc.connect(volume); // Установка назначения для осциллятора  

volume.gain.value = 0;
volume.connect(audioCtx.destination);

function generateKick() {
   volume.gain.setValueAtTime(1, audioCtx.currentTime);
   volume.gain.setTargetAtTime(0, audioCtx.currentTime, 0.1);

   osc.frequency.setValueAtTime(440, audioCtx.currentTime);
   osc.frequency.setTargetAtTime(22, audioCtx.currentTime, 0.1);
}

Ответ

Чтобы перезапустить осциллятор в Web Audio API каждый раз, когда вы нажимаете кнопку, нужно создавать новый осциллятор и новую цепь для подключения в вашей функции generateKick. Ниже представлен исправленный код, который решает вашу проблему.

Исправленный код

const audioCtx = new AudioContext(); // Инициализация Audio Context

function generateKick() {
    const osc = audioCtx.createOscillator(); // Создание нового осциллятора
    const volume = audioCtx.createGain(); // Создание нового Gain

    osc.type = "sine"; // Установка типа волны
    osc.frequency.value = 440; // Установка начальной частоты осциллятора

    volume.gain.setValueAtTime(1, audioCtx.currentTime); // Установка начальной громкости
    volume.gain.setTargetAtTime(0, audioCtx.currentTime + 0.1, 0.1); // Установка целевой громкости для затухания

    osc.frequency.setValueAtTime(440, audioCtx.currentTime); // Установка начальной частоты
    osc.frequency.setTargetAtTime(22, audioCtx.currentTime + 0.1, 0.1); // Установка целевой частоты для сдвига

    osc.connect(volume); // Подключение осциллятора к ganho
    volume.connect(audioCtx.destination); // Подключение gain к выходу

    osc.start(); // Запуск осциллятора
    osc.stop(audioCtx.currentTime + 0.2); // Остановка осциллятора через 0.2 секунды
}

// Пример кнопки (не забудьте добавить HTML-код для кнопки)
document.getElementById('kickButton').addEventListener('click', generateKick);

Объяснение кода:

  1. Создание нового осциллятора: Каждый раз, когда вызывается функция generateKick, создается новый экземпляр осциллятора и объекта Gain. Это позволяет заново инициализировать все параметры звука.

  2. Установка громкости и частоты: Значения громкости и частоты настраиваются перед их изменением с помощью setTargetAtTime, чтобы создать нужный эффект.

  3. Подключение: Осциллятор подключается к объекту Gain, который затем подключается к выходу звука.

  4. Автоостановка: Исключительно для того, чтобы звук не продолжался бесконечно, осциллятор останавливается через 0.2 секунды после начала.

Как использовать:

Добавьте кнопку в HTML с ID kickButton и свяжите её с функцией generateKick, как показано в примере. Этот подход позволяет каждому клику запускать новый экземпляр осциллятора, обеспечивая, чтобы каждый клик создавал новый звук, начиная с начала.

Оцените материал
Добавить комментарий

Капча загружается...