Всем привет.
Две недели назад я приобрел Arduino Duemilanove. Помигал светодиодом, поиграл с LCD, и далее по списку из папки Examples. Остановился на стандартном примере Play Melody и решил его немного развить. Сразу скажу — я чайник в создании и обработке звука, поэтому и термины, и эффекты для будущего синтезатора (если его можно так назвать) придумывал в процессе.
Функции
Клавиши
Всего четыре клавиши с разницей примерно 130 Гц, частота повышается слева направо. Кнопок побольше под рукой не оказалось, использовал мелкие, которые шли в комплекте с Arduino.
Эффект
Эта кнопка меняет множитель-функцию частоты. Функция меняется с заданным шагом и на заданном промежутке, и даже если клавиша не зажата, эффект будет продолжаться. Например, при выборе функции X*X (где X меняется от 0 до 1) получается что-то вроде диско-выстрела. Пока в коде только три эффекта: sin(x) (0;3.14), x*x (0;1), 1-x(0;1).
Запись
Здесь все просто, на каждой итерации записываем значение частоты в массив, а когда массив заполнен, воспроизводим его значения в цикле. Правда, играть на фоне полученного «семпла» не получается, игра на клавишах создает дополнительную задержку и он сильно тормозит (у кого есть решение, буду рад). Позже добавил светодиод рядом с кнопкой, светится во время записи.
Бит
Меняет промежуток между отдельными двойными сигналами и ширину сигналов. Если зажать клавишу и покрутить B, звук похож на постепенную остановку прыгающего мяча и наоборот.
Частота
Меняет промежутки между отдельными сигналами.
Схема
Шесть кнопок, два потенциометра, динамик и светодиод + Arduino. Динамик и кнопки подключены подряд к цифровым входам 2, 3, 4, 5, 6, 7, 8, светодиод к 13; потенциометры к аналоговым входам 0 и 1;
Код
#include <Math.h>
float M=1;
float x=0;
int F,N,i,pl,d1,d2,d3,d4,d5,d6;
int eff=0;
int limit=0;
float st;
int arr[700];
int timer=0;
int rec=0;
int buf=0;
int beat=0;
void play(int F,int N, float M){
for(i=0;i<N/50;i++){
digitalWrite(2, HIGH);
delayMicroseconds((F+1000)*2*M);
digitalWrite(2, LOW);
delayMicroseconds((F+1000)*2*M);
}
if(N!=50){
delay(N*0.1);
}
}
void button(int num){
F-=150*(num-1);
pl=1;
eff=buf;
if(eff!=0){
x=0;
}
if(rec==1){
arr[timer]=F+1000;
}
}
void setup()
{
pinMode(8, INPUT);
pinMode(7, INPUT);
pinMode(6, INPUT);
pinMode(5, INPUT);
pinMode(4, INPUT);
pinMode(3, INPUT);
pinMode(2, OUTPUT);
pinMode(13, OUTPUT);
}
void loop()
{
F = analogRead(A0);
N = analogRead(A1);
d1 = digitalRead(3);
d2 = digitalRead(4);
d3 = digitalRead(5);
d4 = digitalRead(6);
d5 = digitalRead(7);
d6 = digitalRead(8);
if(x>limit){
if(buf<4){
buf=eff;
} else {
buf=0;
}
eff=0;
x=0;
}
if(rec==1){
timer++;
arr[timer]=0;
if(pl==0){
delayMicroseconds(F);
}
digitalWrite(13, HIGH);
} else if(rec==2){
timer++;
}
if(eff==0){
pl=0;
}else{
x+=st;
}
if(N<50){
N=50;
eff=buf;
}
if(d1==1){
button(1);
}
if(d2==1){
button(2);
}
if(d3==1){
button(3);
}
if(d4==1){
button(4);
}
if(d5==1){
if(buf>3){
buf=0;
}
eff=buf;
eff++;
pl=1;
}
if(d6==1){
if(rec==0){
rec=1;
}else if(rec==2){
rec=0;
timer=0;
}
}
if(rec==2 && arr[timer]!=0){
play(arr[timer],N,1);
}
if(pl==1){
if(eff==0){
play(F,N,1);
} else if(eff==1){
limit=3.14;
st=0.025;
M=sin(x);
} else if(eff==2){
limit=1.2;
st=0.01;
M=x*x;
} else if(eff==3){
limit=1;
st=0.025;
M=x+0.5;
}
play(F,N,M);
}
if(rec==1 & timer>698){
timer=0;
rec=2;
digitalWrite(13, LOW);
}
if(timer>698){
timer=0;
}
}
Корпус
Так как это не претендует на готовое устройство, я сделал картонный корпус, собрал схему на макетной плате и поместил внутрь. Паяльник остался нетронутым.
Улучшения
Очевидное улучшение клавиш — подключить клавиатуру, где каждая клавиша меняет сопротивление на единственный аналоговый вход. Можно добавить вывод mini-jack для записи непосредственно на компьютер или подключения к усилителю, составить целую библиотеку эффектов… список ограничен вашей фантазией.