Използване на Audio API за създаване на вокодер

сигнал
В последната статия се запознахме малко с Audio API и написахме прост визуализатор на сигнала. Сега е време да копаете по-дълбоко и да изпробвате нови функции на API. Но ние се нуждаем от цел, към която ще се стремим, и в този случай нашата цел ще бъде правилно да се подиграем на входящия сигнал и неговите характеристики. С други думи, ще напишем малък вокодер.

Тъй като крайният код се оказа доста голям, статията ще разгледа най-важните и интересни фрагменти от гледна точка на Audio API. Разбира се, можете да видите крайния резултат на демото.

Избор на източник на сигнал

Така че Audio API поддържа три типа източник на сигнал:

  1. Източник, създаден с аудио маркера
  2. Аудио буфер
  3. Външен аудио поток (поток) (микрофон или друг аудио поток, включително външен)

Демо примерът имплементира и трите вида източници, както и възможността за превключване между тях. Ще разгледаме може би най-интересния от тях, а именно външния аудио поток от микрофона.

За да достигнем до нашия източник, първо трябва да получим разрешението на потребителя за това и да заснемем аудиопотока. И какво мислите, не е нужно да правим тонове код за това, а просто използваме една функция, нареченаgetUserMedia. Тази магическа функция приема три аргумента:

  1. Типът данни, до които се осъществява достъп. Представлява обект от формата -
  2. Функция за улавяне на медия, която приема уловения поток като аргумент.
  3. Функция за обработка на грешки, възникнали по време на заснемане.

Като цяло, като се вземат предвид различните спецификации на браузъра, нашата функция за инициализация ще изглежда така:

Да видим какво става тук. Първо създаваме аудиоконтекст за нашата страница (което е описано в предишната статия), след което виждаме нова функцияBufferLoader. Той се занимава с това, че с помощта на XHR2 изтегля външни аудио файлове и внимателно ги съхранява в буфера. В нашия случай ще ни трябва, за да изтеглим един аудио ефект, който ще бъде описан по-долу. Тази функция не е стандартна и ще трябва да я напишем.

След като заредим ефекта, ние улавяме аудио потока и, ако потребителят го е разрешил, тогава ще трябва да свържем заснетия сигнал с нашия аудио контекст. За да направим това, ще използваме функциятаcreateMediaStreamSource. Сега нашият входен сигнал е на наше разположение и, повярвайте ми, ние особено му се подиграваме.

Обработка и модификация на сигнали

Време е да напишем функция, която безмилостно да се подиграва на входния поток. Помислете за методите, които ще използваме:

  • createGain- Този метод ни позволява да усилим нашия сигнал. Има един параметърgain— стойност на усилването
  • createConvolver— Този метод позволява навиване на сигнали (добавяне). Методът има два параметъраbuffer— тук се записва импулсната характеристика, с която се добавя входният сигнал. В нашия случай това е външният файл, който беше споменат по-горе. Ще използваме този метод, за да получим ефекта на постепенно намаляване на интензивността на звука по време на многократните му отражения. Всъщност това не е тривиална задача и за да я решите, ще трябва да направите не крехки изчисления, но ние мамим и използваме готовата импулсна характеристика, от която има много в интернет. Вторият параметърnormalize- показва дали ще бъде възможно мащабиране на импулсаХарактеристика.
  • createDynamicsCompressor- Внедрява ефекта на компресия на аудио сигнала. С други думи, компресията намалява разликата между най-тихия и най-силния звук. Методът има следните параметри:threshold(Прагово ниво, определя стойността, над която компресорът започва да затихва сигнала),ratio(определя интензитета на затихването на сигнала),attack(това е времето, което изтича между превишаването на праговата стойност и момента на активиране на компресора. Експериментирането с този параметър позволява за да получите специални ефекти, например можете да направите звука на бас барабана забележимо по-чист),release(това е времето, което изтича между падането на нивото на входния сигнал под прага и точката, в която компресорът спира да отслабва сигнала.

Нека използваме тези методи и да хвърлим нашата функция за трансформация:

Всички стойности, като силата на звука или стойността, при която започва компресията, могат да бъдат обвързани с потребителския интерфейс, за да се променят в реално време, както е направено в демонстрацията. В резултат на преминаване на сигнала през нашата функция ще получим леко усилена версия с ехо ефект на изхода (като че ли говорите с кофа на главата или в каска). Но все още няма да получим принципно нов звук на изхода, което означава, че продължаваме напред. Следващата стъпка е да се опитате да приложите ефекта на модулация на пръстена.

Пръстенова модулация

Ring modulation е аудио ефект, който беше много популярен в "рошавите" години и се използваше за създаване на гласове на всякакви чудовища и роботи. Същността на този ефект е, че имаме два сигнала, единият се нарича носител (носител) и е синтезиран сигнал с произволна честота, а вторият е модулиращсигнал и тези сигнали се умножават. В резултат на това получаваме нов сигнал с изкривяване и метални нотки. За да приложите това чудо, помислете за следните методи:

  • createOscillator- Този метод ви позволява да генерирате сигнали с произволна честота и форма. Той има три параметъра:тип(Форма на вълната: 1 - синус, 2 - квадрат, 3 - трион, 4 - триъгълник),frequency(честота на сигнала),detune(detune - отклонение на честотата. Всяка октава се състои от 1200 цента, а всеки полутон се състои от 100 цента. Като посочите разстройка от 1 200, можете да промените на една октава нагоре и да посочите денастройката -1200 с една октава надолу.)
  • createBiquadFilter— Метод позволява прилагане на честотно филтриране. Методът има четири параметъра:frequency(Честота, на която се основава филтърът),gain(ниво на усилване на честотата),Q(Коефициент на качество),type— типове филтриране, които се поддържат извън кутията:

  1. lowpass - нискочестотен филтър (отрязва всичко над избраната честота)
  2. highpass - високочестотен филтър (отрязва всичко под избраната честота)
  3. bandpass - лентов филтър (пропуска само определена честотна лента)
  4. lowshelf - рафт при ниски честоти (означава, че всичко под избраната честота е усилено или отслабено),
  5. highshelf - рафт при високи честоти (означава, че всичко над избраната честота е усилено или отслабено),
  6. peaking - теснолентов пиков филтър (усилва определена честота, популярното име е "камбанен филтър"),
  7. прорез - теснолентов прорезен филтър (отслабва определена честота, популярното наименование е „филтър за тапи“),
  8. allpass - филтър, който пропуска всички честоти на сигнала с еднаквоусилване, но промяна на фазата на сигнала. Това се случва, когато забавянето на честотата се промени. Обикновено такъв филтър се описва с един параметър - честотата, при която фазовото изместване достига 90°.

Е, това е напълно достатъчно, за да реализираме плановете си. В резултат на това функцията AudioModulation ще се трансформира в:

Е, това е съвсем различен въпрос, след всичко това ще получим доста прикрит „роботизиран сигнал“, но, както се казва, никога няма твърде много добро и затова ще добавим еквалайзер към цялото това великолепие за ръчно регулиране на различни честоти и ще го реализираме с помощта на вече познатата функцияcreateBiquadFilterс тип highshelf.

Честотно филтриране

Като начало, нека създадем масив с настройките, чрез които ще изграждаме филтри:

Параметрите в него са ниво на усилване и честота. Сега f-тата, която създава филтрите:

В резултат на това f-тата трансформация ще приеме формата:

Е, сега имаме пълноправен еквалайзер и можем да усилим или намалим всяка честота в сигнала. И ако бяхме "куки", щяхме да спрем дотук и с чиста съвест да мъчим микрофона, докато си играем с настройките, но искаме повече. И тук, така да се каже, ще добавим черешка на тортата - ще се опитаме да внедрим ефект, нареченpitch shifter.

Смяна на ключ

Същността на ефекта е, че неговото копие се добавя към сигнала, който изостава от основния тон с всеки интервал в рамките на две октави нагоре или надолу. Това е много фантастичен ефект и е адски сложен за прилагане, така че ще направим опростена версия, така да се каже. За да започнем да работим върху този ефект, ще ни трябва интерфейс, който ни позволява да получаваме сигнални данни, коитобихме могли да променим. За да го създадем, ще използваме дискретната трансформация на Фурие (по-точно нейната разновидност на прозоречната трансформация на Фурие) и метода, познат ни от миналата статия,createScriptProcessor. Необходими са три параметъра:buffer(размер на рамка или прозорец с данни, който се избира от сигнала за единица време),numberOfInputChannels(брой входни канали),numberOfOutputChannels(брой изходни канали). Резултатът от извикването на този метод ще бъде създаването на интерфейсния обект, от който се нуждаем. Полученият обект има собствено събитиеonaudioprocess, което се задейства всеки път, когато се вземе нова извадка от данни от сигнала. Като цяло трансформацията на нашия сигнал ще изглежда така:

Сега, работейки с параметрите на височината и припокриването, можем да получим ефекта на ускоряване или забавяне на произношението. За изчисления ще трябва да внедрим функциитеhannWindow(функцията за изчисление на прозореца на Hann) иlinearInterpolation(функцията за линейна интерполация). Окончателната версия на нашата функция и трансформация ще бъде както следва:

Е, сега с чиста съвест можем да се насладим на свършената работа. Разбира се, не можете да спрете дотук и например да добавите визуализатор на спектъра, някакъв модерен ефект като Phaser, но това зависи от вас. Сега, след като се задълбочихме в Audio API, става ясно, че благодарение на механизмите, които сега са достъпни за разработчиците, е възможно да се внедрят почти всякакви ефекти и обработка на аудио сигнали. Вие сте ограничени само от вашето въображение. Можете да видите окончателната версия с различни източници на сигнал с контролен интерфейс тук: