До сих пор мы рассматривали методы отладки при взаимодействии с API веб-аудио. Если вы еще не проверяли его, эта статья, вероятно, избавит вас от пары головной боли: https://medium.com/@alexanderleon/working-with-the-web-audio-api-debugging-tips-45de8b493ee7
Кривые искажения
Под проектированием эффектов искажения я имею в виду, что мы будем создавать кривые искажения. Искажение - это процесс, в котором мы берем образцы звука в форме чисел и накладываем их на внешнюю функцию. Эти функции - наши кривые искажения. Различные кривые дадут разные результаты. Некоторые кривые создадут более тяжелые тона овердрайва; некоторые из них дадут тот классический звук лампового клапана; другие могут дать вам простой богатый звук; и другие, которых вы не знаете, как описать. Создание этих кривых - это больше искусство, чем наука, но всегда полезно иметь немного науки.
Сигмовидные функции
Все кривые искажения, которые я когда-либо видел или писал, были сигмовидными функциями. Эти функции обладают особыми свойствами, без которых трудно жить. Возможности включают:
- переменный наклон, поэтому результат будет нелинейным.
- ограниченный выход, поэтому результат не становится настолько шумным, что исходный звук становится неразличимым.
- Плавная S-образная форма, так что получаемый звук снова не выходит из-под контроля.
Подожди ... переменная крутизна?
Взгляните на эту сигмовидную функцию, которую я только что взял из Интернета без ссылки (рисунок 1).
Обратите внимание, как наклон, крутизна кривой постоянно меняется от -6 до -6? Вот что я имею в виду под переменным наклоном.
Что вы имеете в виду под нелинейным?
Я подойду к этому через минуту.
Давайте посмотрим на сигмовидную функцию. Перейдите на https://www.desmos.com/calculator. Вы должны увидеть чистую декартову плоскость с множеством кнопок и областью для ввода функций. Скопируйте этот текст и вставьте его в один из слотов ввода функции:
(3+20)\cdot x\cdot57\cdot(3/180)/(3+20\cdot\left|x\right|)
Надеюсь, вы увидите на странице рендеринг функции. Если вы исследуете кривые искажения в Интернете, скорее всего, вы столкнетесь с этой функцией. У него много замечательных свойств. Во-первых, он имеет S-образную форму. Когда мы добавляем кривую к звуку, мы накладываем исходные звуковые образцы (в форме чисел) на значения из кривой искажения. S-образная форма функции поможет создать более плавный и естественный звук.
Кого заботят плавные, естественные звуки? Я думал, что суть в том, чтобы создавать эпические электрические звуки! —Человек, читающий эту статью прямо сейчас
Нелинейность
Что ж, даже с помощью описанной выше функции вы обязательно получите сильно искаженные звуки. Процесс наложения звука на кривую искажения создает нелинейную связь между входом и выходом. Один звук из нашей исходной записи с тремя обертонами может воспроизводиться с десятью обертонами; другой с четырьмя обертонами может воспроизводиться с семью обертонами. Сложно сказать. Вот почему это называется нелинейной зависимостью. Кроме того, поскольку мы добавляем исходные звуки с кривой искажения, результат всегда будет более сложным, чем исходный. Так что не бойтесь не получить достаточно твердости. При использовании сигмовидных функций нет предела. Вам просто нужно поэкспериментировать и исследовать различные кривые, чтобы обнаружить звук с искажениями, без которого вы не можете жить.
Засучи рукава
Давайте создадим узел искажения в API веб-аудио и применим его к узлу генератора. Подготовим простой HTML-файл:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Test</title> </head> <body> <script src="test.js"></script> </body> </html>
Скопируйте и вставьте следующее в соответствующий файл javascript:
// test.js var AudioContext = window.AudioContext || window.webkitAudioContext; var audioCtx = new AudioContext(); var oscillatorNode = audioCtx.createOscillator(); var oscillatorGainNode = audioCtx.createGain(); var finish = audioCtx.destination; var distortionGainNode = audioCtx.createGain(); var distortionNode = audioCtx.createWaveShaper(); function makeDistortionCurve(amount) { var k = amount, n_samples = typeof sampleRate === 'number' ? sampleRate : 44100, curve = new Float32Array(n_samples), deg = Math.PI / 180, i = 0, x; for ( ; i < n_samples; ++i ) { x = i * 2 / n_samples - 1; curve[i] = (3 + k)*Math.atan(Math.sinh(x*0.25)*5) / (Math.PI + k * Math.abs(x)); } return curve; } distortionNode.curve = makeDistortionCurve(400); oscillatorNode.connect(oscillatorGainNode); oscillatorGainNode.connect(distortionGainNode); distortionGainNode.connect(distortionNode); distortionNode.connect(finish); oscillatorNode.start(0);
Не слишком увлекательно?
Я знаю, что использование узла осциллятора для проверки искажений не особо грандиозно, но, по крайней мере, это работает! Если вы хотите создать лучший интерфейс, опробовать его и услышать эффекты искажения с реальными звуковыми образцами, подумайте о том, чтобы проверить эту библиотеку звуковых эффектов с открытым исходным кодом, в которую я сейчас работаю: https://github.com/alien35 / Ревун-Плюс
ПОДСКАЗКА: вы тоже можете внести свой вклад!
Мой подход
Помимо простого тестирования случайных функций и надежды на то, что они окажутся сигмовидными функциями, ограниченными границами -1≤x≤1 и -1≤y≤1, я проверяю сигмовидные функции из канона математики и пробую их. Например, в приведенном выше примере гудерманова сигмоидальная функция сочетается с первой сигмоидной функцией, которую мы рассмотрели.
Удачного кодирования!