Устройство вокальных звуковых эффектов на Arduino

Устройство вокальных звуковых эффектов на Arduino

Эта основанная на Arduino коробка вокальных звуковых эффектов сдвигает и искажает входящие звуковые сигналы для получения разнообразных звуковых эффектов. Данный проект – мой первый опыт цифровой обработки сигнала в реальном времени при помощи Arduino. Входящий сигнал с микрофона с частотой около 40 кГц проходит цифровую обработку и выводиться в виде 8 битного аудио с частотой 40кГц. Чтобы минимизировать объем необходимых Arduino вычислений, для обработки входящего звукового сигнала я использовал метод называемый гранулярный синтез. По сути, входящий в Arduino звук режется и храниться в виде маленьких частей (длиной в миллисекунду или микросекунду), называемых «гранулами». Затем они индивидуально меняются и воспроизводятся. Они могут быть удлинены или укорочены, растянуты или сжаты, воспроизведены в обратном порядке, повторены несколько раз или смешаны с другими гранулами. Вы можете прослушать образец аудио сигнала после коробки эффектов ниже:

Гранулярный синтез дает уникальный тип искажений, вызванных разрывами между отдельными гранулами в выходном сигнале. Иногда это искажение дает эффект, который я могу опасть как "разрыв" звука, в других случаях оно добавляет новые частоты, которых раньше не было в аудио сигнал. Например, в произведении Aphex Twin, гранулярный синтез особенно заметен примерно на 3 минуте.  Другой пример гранулярного синтеза, с питч-шифтером и эффектом наложения на произведении Paul Lansky. Моя любимая вещь, которую делает эта коробка эффектов – это использование питч-шифтера для получения андрогинного звука. Эта идея появилась у меня после прослушивания большого количества произведений Fever Ray прошлой зимой, в которых слышно питч-шифтер, и время от времени её голос звучит как мужской.

Список элементов

1x Arduino Uno REV 3

7x резистор 10кОм 0.25Вт

9x резистор 20кОм 0.25Вт  

1x резистор 1кОм 0.25Вт

1x потенциометр 50кОм

1x аудио потенциометр 10кОм  со встроенным тумблером.  (Он будет использоваться для регулировки громкости и вкл/выкл устройства)

5x рифленая ручка 0,25"

2x щелочная батарея 9В

2x разъем для 9В батарей

1x макетная плата

1х тумблер

2x BLS штырьки

3х панель под микросхемы 8 выводов

1x двойной ОУ TL082

3x резистор 100кОм 0.25Вт

1x электролитический конденсатор 10мкФ

1x конденсатор47нФ

3x конденсатор 0.1uF

2x потенциометр 1мОм

1x логарифмический потенциометр 1мОм

1x BLS штырьки

1x потенциометр 10кОм

1x DPDT тумблер

2x 1/4" стерео джек

2х яркий 5мм светодиод

2x резистор 100Ом 0.25Вт

2x двойной ОУ TS922IN (одиночный ОУ TS924 также будет работать, но его нет в наличии)

Дополнительные материалы:

Провода №22

Припой

Наждак

Фанера

Столярный клей

Термоклей

Шурупы

Схема

Для облегчения понимания схемы, я разбил её на три части.

На первой схеме показан аудио выход. В этом проекте звук выводиться через 8 битный R2R ЦАП с цифровых контактов 0-7 Arduino. Этот сигнал проходит через усилитель, ФНЧ и потенциометр регулировки громкости, прежде чем попасть на динамик.

На второй схеме показан микрофонный вход. Сигнал с микрофона проходит через усилитель и отсекатель постоянной составляющей перед отправкой его на аналоговый вывод A0 Arduino.

На третьей схеме показана связь элементов управления с Arduino. В этом проекте есть два светодиодных индикатора: один индикатор отсечения и один выходной индикатора. Три потенциометра управляют величиной дробления, pitch (смещением) и wet/dry mix, а переключатель управляет направлением воспроизведения (вперед или назад).

BLS штырьки

Припаяйте BLS штырьки на макетную плату, и вы сможете установить Arduino прямо на неё. К сожалению, расстояние между цифровыми контактами 7 и 8 Arduino не стандартное 2,54 мм, поэтому старайтесь избегать их использования(аналоговые контакты тоже можно использовать для цифрового ввода/вывода). Если вам надо использовать их, попробуйте найти  длинные BLS штырьки, которые можно подогнуть (рис. 4 – из другого проекта).

ЦАП

Припаяйте восемь 20кОм резисторов на контакты D0-D7 Arduino, как показано на фотографии.

Припаяйте семь 10кОм резисторов между ранее припаянными резисторами 20кОм. Добавьте дополнительный резистор 20кОм, у резистору 20кОм, подключенному к D0Arduino (основа лестницы).

Подсоедините другой конец резистора 20кОм к GND Arduino.

Тестирование ЦАП

Подключите выход ЦАП к осциллографу, также необходимо подключить GND. Прошейте Arduino предоставленным ниже кодом. ЦАП должен выдавать синусоиду колеблющуюся от 0 до 5В с частотой ~63 Гц (см. фото). Если вы не знаете, как пользоваться/читать показания осциллографа посмотрите эту статью. 

Немного информации о коде: Я использовал прерывания от таймера для увеличения переменной t с частотой 40 кГц. Когда t достигает 627, оно сбрасывается в ноль (это происходит с частотой 40000/628=63 Гц). При этом, в основном цикле Arduino посылает значения от 0 (00000000 в двоичной системе) до 255 (11111111 в двоичной системе) на цифровые выводы 0-7 (PORTD). Значение вычисляется по следующей формуле:

PORTD=byte(127+127*sin(2*t/100));

Пока t увеличивается от 0 до 627, синус проходит один полный цикл. Значение отправляемое в  PORTD представляет собой синусоиду с частотой 63Гц и амплитудой 127, колеблющейся вокруг 127. ЦАП преобразует это в напряжение от 0 до 5В, если в PORTD  отправлен 0, напряжение равно 0В, а если 255, то 5В.

8 контактная панелька и буфер

Припаяйте 8 контактную панельку на плату. Подключите GND к контакту 4, 5В к контакту 8, и выход ЦАП к 3. Спаяйте контакты 1 и 2 вместе. Это заставляет сигнал идти через повторитель напряжения. Повторитель напряжения действует как буфер, защищая выход с ЦАП от любых нагрузок, которые позже появляются в цепи.

Подключение потенциометра

Припаяйте три провода к экспоненциальному потенциометру 10кОм (с маркировкой «А»), как показано на рисунке 3. Припаяйте красный провод к контакту 1, зеленый провод к контакту 5, и черный провод к GND/ контакту 4. Соедините контакты 6 и 7 вместе (рис. 2). Этот потенциометр будет регулировать амплитуду сигнала – это регулятор громкости. Он делает это, работая как переменный делитель напряжения.

Вторая 8 контактная панелька

Припаяйте вторую 8 контактную панельку и подключите GND к контакту 4 и 5В к контакту 8.

Делитель напряжения

Припаяйте резистор 10кОм к контакту 7 первого TS922IN. Припаяйте резистор 2кОм к резистору 10кОм и припаяйте второй вывод резистора 2кОм к GND. Это еще один делитель напряжения, и его цель – это масштабирование сигнала на 2000/(10000+2000)=1/6 его амплитуды. Это сделано для того, чтобы при включении максимальной громкости, устройство не оглушало меня. В отличие от делителя напряжения сделанного ранее, это постоянный, не регулируемый делитель. Масштабированный сигнал выходит из соединения двух резисторов.

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

RC фильтр нижних частот

Задача ФНЧ в этой части схемы заключается в удалении цифровых артефактов с выхода ЦАП, при этом не теряя детали  более высоких частот.

Теория Найквиста утверждает, что для частоты дискретизации х Гц, максимальная частота, которая может быть получена, равна х/2Гц. Так что если у вас частота дискретизации 40 кГц (стандарт большинства аудио), то максимальная частота, которую вы можете воспроизвести это 20 кГц (верхняя граница звукового спектра).

При использовании ФНЧ с сигналом с частотой среза 20 кГц, вы можете сгладить "ступеньки" сигнала, сохраняя при этом общую его форму нетронутой. Я использовал простой RC фильтр для достижения этой цели: последовательно соединённые резистор и конденсатор подключенные к GND. Подключите резистор к входному сигналу, а конденсатор к GND, и в месте соединения этих двух элементов будет отфильтрованным.

Рассчитать значения конденсатора и резистора, необходимые для ФНЧ можно по следующему уравнению:

Частота среза = 1/ (2*pi*R*C)

Для частоты среза 20.000 Гц и резистора 1кОм:

20000=1/(2*3.14*1000*C)

C =~ 8nF

Конденсатор 8 nF я округлил до 0.01uF. При этом частота среза около 16 кГц. Вы можете по перебирать разные значения и посмотреть, что вам больше всего нравиться. Мне обычно нравится глубокая фильтрация, так как она убирает больше шумов.

Припаяйте 1кОм резистор на выход делителя напряжения сделанного в предыдущем шаге (если вы не делали его, то припаяйте резистор прямо к контакту 7). Припаяйте конденсатор 0.01uF последовательно с этим резистором GND. Припаяйте провод от места соединения конденсатора и резистора к контакту 5 второй панельки.

Ещё буфер

Я сделаю второй повторитель напряжения на ОУ, соединённых параллельно, чтобы они могли давать в два раза больший ток. Как и прежде, повторитель напряжения действует как буфер, защищая входящий сигнал от нагрузки на наушники, которые в конечном итоге будут присоединены к выходу буфера.

Припаяйте провод между двумя не инвертирующими входами ОУ(контакты 5 и 3 второй панельки).  Припаяйте другой провод двумя выходами (контакты 1 и 7 второй панельки). На нижней стороне платы спаяйте инвертирующие входы и выходы

Отсекатель постоянной составляющей

После всех делителей напряжения, сигнал на выходе ОУ колеблется от 0 до 1В (или от 0 до 5, если вы не использовали делитель напряжения). Перед отправкой сигнала на колонки/наушники, колебание должно быть компенсировано. Это достигается путем пропускания сигнала через конденсатор.

Припаяйте GND конденсатора 100uF (или больше) к выходу второго операционного усилителя. Сигнала с его + будет колебаться вокруг 0В.

Аудио разъем

Отвинтите пластиковый корпус аудио разъема. Припаяйте черный провод (GND) к более крупному контакту, и зеленый провод (выходной сигнала) к двум более коротким контактам. Это стерео разъем, но из Arduino выходит моно сигнал, поэтому просто подаем моно сигнал на стерео выход.

Используйте термоклей для фиксации соединений и предотвращения короткого замыкания. Припаяйте зеленый провод к + конденсатора 100uF и черный провод к GND.

Схема микрофона

На рис. 1 показан сигнал, идущий прямо из микрофона на осциллограф. Сигнал относительно слаб, амплитуда всего 200 мВ. Обратите внимание, что сигнал колеблется около 0 вольт – это типично для аудио сигнала. В идеале, нужен сигнал с амплитудой 2,5В колеблющийся вокруг 2,5. Таким образом, сигнал находится в пределах 0-5В; Arduino будет в состоянии измерить его с максимальным разрешением и без деления. Для того, чтобы сделать это, необходимо отсекать постоянную составляющую сигнала и усиливать его. Отсечение постоянной составляющей значит изменение уровня, вокруг которого будут колебания. Усиление означает увеличение амплитуды (расстояние между центром и максимальной или минимальной точкой) сигнала. Усиление также защищает микрофон от нагрузок, которые могут возникнуть позже как буфер, что предотвращает искажение.

На рис. 2 показан тот же сигнал после усиления, и вы можете увидеть, что высота импульсов возросла так, что сигнал колеблется между -2,5 и 2,5В (амплитуда 2,5В). На рис. 4 показан сигнал после отсечения постоянной составляющей; Амплитуда 2,5 В, но центр сигнала 2.5В вместо 0В, поэтому сигнал никогда не опускается ниже 0В. (Примечание: небольшие изменения формы сигнала на рисунке 3 и 4 обусловлены моим голосом и не имеет отношения к схеме). Сигнал на рис. 3 можно подавать на аналоговый контакт Arduino.

Батареи

Две 9В батареи необходимы для питания TL082. Двухполюсный тумблер (DPDT) используется как выключатель питания на обе батареи. На самом деле в DPDT тумблере два отдельных тумблера, но они управляются одним и тем же механизмом. Припаяйте красные провода от разъемов для батарей на каждый переключатель(на одну сторону). Припаяйте красные провода к среднему контакту каждого переключателя. При необходимости используйте термоклей для фиксации.

Панелька для усилителя и питание

Припаяйте 8-контактную панельку на плату. Как показано на рисунке цоколевки TL082, + V подключается к контакту 8 и -V подключается к контакту 4. Подключите на красной провод с середины DPDT тумблера к контакту 8. Давайте дадим разъему этой батареи №1. Припаяйте черный провод от разъема №2 к 4 контакту панельки. Припаяйте черный провод от разъема №1 и оставшийся красный провод вместе на плату, это средняя точка(0В)  в питании +9В/-9В. Припаяйте её к GND Arduino.

Микрофонный вход

Отвинтите пластиковый корпус разъёма 1/4". Если у вас есть моно микрофон, отсоедините правый контакт. Я также немного уменьшил большой контакт GND. Припаяйте черный провод к GND и зеленый провод к другому контакту. Используйте термоклей для предотвращения короткого замыкания.

Не инвертирующий усилитель

Припаяйте провода от 1/4" гнезда к плате. Припаяйте черный провод к GND Arduino и зеленый провод к контакту 5 8 контактной панельки.

Припаяйте 100кОм резистор между контактами 6 и 7 8 контактной панельки.

Припаяйте два провода к потенциометру, так чтобы он работал как переменный резистор.  Припаяйте один провод (неважно какой) к GND, а второй к 6 контакту панельки. Он будет контролировать амплитуду входного сигнала микрофона.

Отсекатель постоянной составляющей

Схема отсекателя постоянной составляющей состоит из двух конденсаторов и делителя напряжения. Припаяйте электролитический конденсатор 10мкФ, так что бы его + подключался к 7 контакту панельки.

Припаяйте конденсатор 47нФ к GND конденсатора 10мкФ. Другой контакт конденсатора 47нФ припаяйте к GND.

Сделайте делитель напряжения Arduino +5 В и GND путем подключения двух резисторов 100кОм резисторов между 5В и землей. Подключите место соединения резисторов к месту соединения конденсаторов. Это позволит добавить 2,5В к усиленному сигналу с микрофона.

Подключите аналоговый вход 0 к соединению двух конденсаторов.

Простой аудио выход

Загрузите код в Arduino. Этот код считывает сигнал, поступающий в A0, преобразовывает его в число от 0 до 255, и выводит его на ЦАП. На осциллографе на фотографии, синий сигнал с микрофона и желтый сигнал прямо после ЦАП. Обратите внимание, что каждая ступенька на выходе ЦАП длиться около 125us. Соответственно, частота дискретизации 1/125us или 8 кГц. Далее я буду вручную устанавливать счетчик АЦП и снижать разрешение ЦАП Arduino  с 10 бит (0-1023) до 8 бит (0-255), чтобы увеличить скорость и поднять частоту дискретизации.

int incomingAudio; void setup(){ for (byte i=0;i<8;i++){ pinMode(i,OUTPUT);//set digital pins 0-7 as outputs } pinMode(A0,INPUT); } void loop(){ incomingAudio = analogRead(A0);//read input from A0 incomingAudio = incomingAudio/4;//scale from 10 bit to 8 bit PORTD = incomingAudio;//send out DAC }

В приведенном ниже коде я пренебрег функцией analogRead(), чтобы увеличить частоту дискретизации. Я вручную установил счетчик АЦП 500кГц и читал 8 битное значение с аналогового входа 0 напрямую из ADCH. Я установил счетчик АЦП 500кГц потому что АЦП использует 13 тактов, чтобы прочитать новое аналоговое значение. 500/13 = 38.5кГц, что довольно близко к 40кГц (стандартная частота дискретизации звука), и не вносит дополнительные шумы.

void setup(){ DDRD=0xFF;//set port d (digital pin s0-7) as outputs DDRC=0x00;//set all analog pins as inputs //set up continuous sampling of analog pin 0 //clear ADCSRA and ADCSRB registers ADCSRA = 0; ADCSRB = 0; ADMUX |= (1 << REFS0); //set reference voltage ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz ADCSRA |= (1 << ADATE); //enabble auto trigger ADCSRA |= (1 << ADEN); //enable ADC ADCSRA |= (1 << ADSC); //start ADC measurements } void loop(){ PORTD = ADCH;//send 8 bit value from analog pin 0 to DAC }

В коде я вызвал выход на ЦАП с помощью прерывания АЦП. Это прерывание похоже на прерывания от других таймеров Arduino, но это прерывание происходит только когда получено новое значение АЦП (в данном случае со скоростью ~38.5кГц, или каждый 26us).

void setup(){ DDRD=0xFF;//set port d (digital pin s0-7) as outputs DDRC=0x00;//set all analog pins as inputs cli();//diable interrupts //set up continuous sampling of analog pin 0 //clear ADCSRA and ADCSRB registers ADCSRA = 0; ADCSRB = 0; ADMUX |= (1 << REFS0); //set reference voltage ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz ADCSRA |= (1 << ADATE); //enabble auto trigger ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete ADCSRA |= (1 << ADEN); //enable ADC ADCSRA |= (1 << ADSC); //start ADC measurements sei();//enable interrupts } ISR(ADC_vect) {//when new ADC value ready PORTD = ADCH;//send 8 bit value from analog pin 0 to DAC } void loop(){ }

Воспроизведение сигнала в два раза меньшей частотой

Приведенный ниже код записывает короткий отрезок входящего сигнала в один из двух массивов: buffer1 и buffer2. Также введена переменная "scale.". Эта переменная используется для масштабирования воспроизведения аудио хранимого в буфер для того, чтобы изменить частоту. Приведенный ниже код устанавливает значение scale 2, что удваивает продолжительность времени, необходимого ЦАП для вывода хранимого аудио. Как вы можете видеть на картинке выше, выход с ЦАП (желтый) равен половине частоты на входе микрофона (синий).

byte buffer1[1000]; byte buffer2[1000]; byte incomingAudio;//storage variable int i = 0;//index variable int iscale = 0;//index variable int scale = 2; boolean toggle = 0; boolean rec = 1; int limit = 1000; void setup(){ DDRD=0xFF;//set port d (digital pin s0-7) as outputs DDRC=0x00;//set all analog pins as inputs cli();//diable interrupts //set up continuous sampling of analog pin 0 //clear ADCSRA and ADCSRB registers ADCSRA=0; ADCSRB = 0; ADMUX |= (1 << REFS0); //set reference voltage ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz ADCSRA |= (1 << ADATE); //enabble auto trigger ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete ADCSRA |= (1 << ADEN); //enable ADC ADCSRA |= (1 << ADSC); //start ADC measurements sei();//enable interrupts } ISR(ADC_vect) {//when new ADC value ready incomingAudio = ADCH; if (rec){ if (toggle){ buffer1[i] = incomingAudio;//store incoming PORTD = buffer2[iscale];//send out DAC } else{ buffer2[i] = incomingAudio;//store incoming PORTD = buffer1[iscale];//send out DAC } } else{ if (toggle){ PORTD = buffer2[iscale];//send out DAC } else{ PORTD = buffer1[iscale];//send out DAC } } i += 1; iscale = i/scale; if (i==limit){ rec = 0;//stop recording } if (i == (limit*scale)){ i = 0; iscale = 0; toggle^=1; rec = 1; } } void loop(){ }

RC потенциометры

Так как АЦП занят преобразованием поступающего звука на A0 в цифру, три потенциометра управления (размер, pitch и wet/dry ) должны проверяться при помощи цифрового вывода. Это может быть реализовано при помощи RC-цепи. В этой схеме используется цифровой вывод Arduino для измерения времени, необходимого для заряда конденсатора. Это время связано с сопротивлением цепи, которое устанавливается потенциометром. Таким образом, мы можем косвенно измерить сопротивление потенциометра.

Припаяйте BLS штырьки на цифровые выводы 9-13. Припаяйте резистор 10кОм и конденсатор 0,1 мкФ последовательно к контактам 10-12. Припаяйте свободный вывод конденсаторов 0.1мкФ вместе и подключите к +5В Arduino. Подключите один из крайних контактов двух линейных потенциометров 1 МОм в точку соединения резистора и конденсатора подключенных к выводам  11 и 12. Подключите один крайний контакт логарифмического потенциометра 1 МОм в точку соединения резистора и конденсатора подключенных к цифровому выводу 10. Припаяйте средние контакты каждого потенциометра к GND.

Если хотите, вы можете увеличить разрешение любого из этих элементов за счет увеличения емкости 0.1мкФ на 1 мкФ или 10мкФ, но это необходимо учитывать в конечной программе.

Переключатель

Этот переключатель позволяет воспроизводить записанные фрагменты в обратном порядке. Припаяйте резистор 10кОм к одному из контактов выключателя. Припаяйте красный провод к другому выводу резистора и подключите его к GND. Припаяйте провод в место соединения переключателя и резистора и подключите к 9 цифровому контакту Arduino. Припаяйте черный провод к оставшемуся контакту и подключите его к GND.

Светодиодные индикаторы

Припаяйте резисторы 100Ом на аноды двух белых светодиодов. Подключите катоды светодиодов к GND. Подключите анод одного из светодиодов к цифровому выводу 13 – это индикатор отсечения. Второй индикатор будет подключен к переключателю далее.

Выходной выключатель

Этот переключатель включает индикатор, чтобы показать, что выход включен. Припаяйте два провода к задней части потенциометра 10 кОм. Подключите один провод к +5В Arduino, а другой к аноду индикатора. Другой вывод индикатора подключается к GND.

Корпус

Я разработал треугольный корпус в Corel Draw и вырезал его из 1/4" фанеры при помощи лазерного резака. На двух сторонах есть вход и выход, а также управление (разъемы, светодиодные индикаторы и потенциометр усиления). На передней панели расположены отверстия для остальных элементы управления (вкл/выкл, реверс, wet/dry смешение, потенциометр сдвига, потенциометр смесителя, потенциометр длины гранулы). На нижнем торце находится отверстие для легкого доступа к USB-порту Arduino.

Фанера в три слоя покрыта лаком, и склеена при помощи столярного клея. По углам корпуса приклеены небольшие треугольники, что позволяет прикрепить заднюю панель шурупами

Прикрепите Arduino на штырьки на плате и приступите к установке элементов в корпус.  Сначала я установил потенциометры и переключатели на переднюю панели, а затем разъемы, индикаторы и потенциометры на стороны. Наконец, я установил USB-порт Arduino в квадратное отверстие в нижней части корпуса. Я установил туда Arduino навсегда, но вы можете установить заднюю панель на винты, что бы при необходимости вынуть его.

Чертеж корпуса в Corel прилагается.

Батареи

Установите батареи в разъемы и закрепите их в углах корпуса при помощи липучки. Привинтите заднюю панель. Установите ручки на потенциометры и закрепите их винтами.

Конечная прошивка

Вот окончательный код для проекта. Основные идеи обработки звука уже объяснены выше. Я только добавил немного кода, который работает с потенциометрами и переключателями, позволяя менять значения нескольких переменных: "scale," "grain," "forward," и "wet" и "dry."

Скачать файлы к проекту

Оригинал статьи на английском языке (перевод: Александр Касьянов для сайта cxem.net)


Категория: Для музыкантов
Метки:

Написать коментарий

*
= 5 + 8

Добавить изображение

Последние статьи