roboforum.ru

Технический форум по робототехнике.

Звуки R2D2 на Ардуино

Звуки R2D2 на Ардуино

Eruman » 27 май 2012, 21:47

Возникла необходимость обозначать эмоции наших роботов, и сразу вспомнили про замечательного персонажа из "Звездных войн". Варианты с применением спец.микросхем и карт памяти отпали, т.к. наши роботы собираются по бюджетной схеме на Атмега8, плюс драйвер моторов к1128кт4.

Решили программировать. Скачали архив со звуковыми файлами, проанализировали спектр, нарисовали частотные графики, написали программу по синтезу. Сильно не ругайтесь, писалось на скорую руку, комментариев нету, а те что есть - не важны. Библиотеку брал тут http://arduino.cc/playground/Code/Summer
Правки и дополнения приветствуются.
Свистит похоже, на мой слух. Некоторых звуков не хватает, но мы над этим работаем ;)

Код: Выделить всёРазвернуть
#include <Summer.h>

int sPIN = 3;
Summer summer = Summer(sPIN);

void setup() {
  summer.setTempo(1);  //30
}

void loop() {
    sim_R();
    delay(70);
    sim_O();
    delay(70);
    sim_B();
    delay(70);
    sim_O();
    delay(70);
    sim_Question();
    delay(1500);
    sim_N();
    delay(70);
    sim_O();
    delay(70);
    delay(1500);
    sim_Z();
    delay(70);
    sim_O();
    delay(70);
    sim_R();
    delay(70);
    sim_R();
    delay(70);
    sim_O();
    delay(70);
    delay(1500);
}

void sim_Z() {
playFreqGlissando(2300, 1900, 1, 1100); //1100
delay(28); //700
playFreqGlissando(1800, 1700, 1, 1000); //1000
delay(36); //900
playFreqGlissando(2000, 2200, 1, 1100); //1100
}

void sim_Y() {
playFreqGlissando(1800, 1700, 1, 1000); //1000
delay(36); //900
playFreqGlissando(1900, 2200, 1, 800); //800
delay(28); //700
playFreqGlissando(2300, 1900, 1, 1100); //1100
}

void sim_X() {
playFreqGlissando(5000, 2000, 1, 500); //500
playFreqGlissando(2000, 1200, 1, 500); //500
playFreqGlissando(1200, 800, 1, 500); //500
delay(56); //1400
playFreqGlissando(600, 1000, 1, 700); //700
playFreqGlissando(1000, 2000, 1, 700); //700
playFreqGlissando(2000, 2200, 1, 500); //500
}

void sim_W() {
playFreqGlissando(550, 750, 1, 500); //500
playFreqGlissando(750, 1200, 1, 500); //500
playFreqGlissando(1200, 2000, 1, 500); //500
playFreqGlissando(2000, 2100, 1, 300); //300
delay(32); //800
summer.playTone(2350,36); //900
playFreqGlissando(2350, 1600, 1, 500); //500
}

void sim_V() {
summer.playTone(2350,36); //900
playFreqGlissando(2350, 1200, 1, 700); //700
delay(32); //800
playFreqGlissando(700, 600, 1, 300); //300
playFreqGlissando(600, 750, 1, 900); //900
}

void sim_U() {
playFreqGlissando(1800, 2400, 1, 700); //700
summer.playTone(2400,36); //900
delay(32); //800
playFreqGlissando(2200, 1800, 1, 700); //700
playFreqGlissando(1800, 1750, 1, 900); //900
}

void sim_T() {
playFreqGlissando(2000, 2700, 1, 900); //900
summer.playTone(2700,20); //500
delay(16); //400
summer.playTone(3100,24); //600
playFreqGlissando(3100, 2000, 1, 500); //500
playFreqGlissando(2000, 1000, 1, 1200); //1200
}

void sim_S() {
playFreqGlissando(1900, 2700, 1, 900); //900
summer.playTone(2700,20); //500
delay(16); //400
summer.playTone(3100,24); //600
playFreqGlissando(3100, 2200, 1, 500); //500
playFreqGlissando(2200, 1000, 1, 1200); //1200
}

void sim_R() {
playFreqGlissando(2100, 2300, 1, 1100); //1100
//summer.playTone(1100,32); //800
delay(32); //800
delay(16); //400
summer.playTone(2400,48); //1200
//summer.playTone(1100,24); //600
}

void sim_Question() {
summer.playTone(2400,40); //1000
summer.playTone(1000,32); //800
delay(28); //700
playFreqGlissando(1700, 2400, 1, 1000); //1000
summer.playTone(2400,32); //800
delay(28); //700
playFreqGlissando(2200, 1700, 1, 800); //800
summer.playTone(1700,24); //600
delay(28); //700
playFreqGlissando(1900, 2700, 1, 800); //800
summer.playTone(2700,21); //300
}

void sim_O() {
playFreqGlissando(700, 600, 1, 250); //250
playFreqGlissando(600, 800, 1, 200); //200
playFreqGlissando(800, 600, 1, 200); //200
playFreqGlissando(600, 800, 1, 200); //200
playFreqGlissando(800, 600, 1, 200); //200
playFreqGlissando(600, 800, 1, 200); //200
playFreqGlissando(800, 700, 1, 250); //250
}

void sim_N() {
summer.playTone(2400,40); //1000
summer.playTone(1000,32); //800
playFreqGlissando(2300, 1900, 1, 1200); //1200
playFreqGlissando(1100, 1000, 1, 600); //600
}

void sim_Left() {
summer.playTone(1450,60); //1500
delay(80); //2000
summer.playTone(2650,100); //2500
}

void sim_I() {
playFreqGlissando(1600, 4200, 1, 30);
playFreqGlissando(4200, 600, 1, 30);
playFreqGlissando(600, 800, 1, 30);
playFreqGlissando(800, 3600, 1, 30);
playFreqGlissando(3600, 700, 1, 30);
summer.playTone(700,5); //150
playFreqGlissando(700, 3200, 1, 30);
playFreqGlissando(3200, 600, 1, 30);
summer.playTone(600,5); //150
playFreqGlissando(600, 2900, 1, 30);
playFreqGlissando(2900, 400, 1, 300);
}

void sim_H() {
summer.playTone(700,5); //150
playFreqGlissando(700, 3700, 1, 30);
playFreqGlissando(3700, 700, 1, 30);
summer.playTone(700,5); //150
playFreqGlissando(700, 3400, 1, 30);
playFreqGlissando(3400, 700, 1, 30);
summer.playTone(700,5); //150
playFreqGlissando(700, 3400, 1, 30);
playFreqGlissando(3400, 700, 1, 30);
summer.playTone(700,5); //150
playFreqGlissando(700, 3400, 1, 30);
playFreqGlissando(3400, 700, 1, 30);
summer.playTone(700,5); //150
playFreqGlissando(700, 3400, 1, 30);
playFreqGlissando(3400, 700, 1, 30);
summer.playTone(700,5); //150
}

void sim_G() {
summer.playTone(3000,28); //700
playFreqGlissando(3000, 2100, 1, 600); //600
playFreqGlissando(2100, 1400, 1, 700); //700
playFreqGlissando(1400, 1100, 1, 500); //500
}

void sim_F() {
playFreqGlissando(5000, 1700, 1, 500); //500
playFreqGlissando(1700, 1100, 1, 500); //500
playFreqGlissando(1700, 800, 1, 500); //500
}

void sim_E() {
playFreqGlissando(1400, 1300, 1, 1000);
playFreqGlissando(1600, 1650, 1, 700);
}

void sim_D() {
playFreqGlissando(2100, 2300, 1, 1000);
playFreqGlissando(1000, 1100, 1, 700);
}

void sim_C() {
playFreqGlissando(400, 550, 1, 14000);
playFreqGlissando(550, 400, 1, 1200);
}

void sim_B() {
playFreqGlissando(1900, 3600, 1, 2900); //4000
playFreqGlissando(3600, 4200, 1, 1900); //1000
playFreqGlissando(4200, 3600, 1, 1900); //1000
playFreqGlissando(3600, 2500, 1, 1900); //3000
delay(4); //100
summer.playTone(1900,92); //2300
summer.playTone(2600,24); //600
summer.playTone(1600,100); //3000
}

void sim_A() {
summer.playTone(1600,100); //3000
summer.playTone(2600,24); //600
summer.playTone(1900,92); //2300
delay(4); //100
playFreqGlissando(2500, 3600, 1, 1900); //3000
playFreqGlissando(3600, 4200, 1, 1900); //1000
playFreqGlissando(4200, 3600, 1, 1900); //1000
playFreqGlissando(3600, 1900, 1, 1900); //4000
}

void playFreqGlissando( float freqFrom, float freqTo, float duty, float duration ) {

  duration=duration/8*3;

  int stepLength = 20; //30
  int i, numberOfSteps;
  float freqStep, freq;

  numberOfSteps  =  duration/stepLength;
  freqStep =  (freqTo - freqFrom)/numberOfSteps;

  freq = freqFrom;
  for ( i=0; i < numberOfSteps; i++ ) {
    //summer.playTone(freq, stepLength);
    summer.playTone(freq, duty);
    freq = freq  + freqStep ;
  }
  summer.playTone(freqTo, stepLength);
}

Re: Звуки R2D2 на Ардуино

igor-k » 02 фев 2013, 11:48

Покажите как выглядит "вживую" )

Re: Звуки R2D2 на Ардуино

CyberLab » 02 фев 2013, 12:58

Можно записать с десяток семплов и воспроизводить их комбинации библиотекой PlaySound.h http://www.cyber-place.ru/showthread.php?t=274

Re: Звуки R2D2 на Ардуино

Eruman » 08 фев 2013, 11:59

В живую покажу как с детьми дойдем в очередной раз до темы , пока не до них. Готовых поделок не сохранилось, разбежались по рукам.

А семплирование звуков мы сознательно избегали, ибо памяти не много у меги8.

Re: Звуки R2D2 на Ардуино

Romikgy » 08 фев 2013, 12:59

а как определялись частоты и длительности на буквы?

Re: Звуки R2D2 на Ардуино

Eruman » 08 фев 2013, 18:59

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

Re: Звуки R2D2 на Ардуино

Romikgy » 08 фев 2013, 19:05

а можно увидеть в цифрах этот глазок?

Re: Звуки R2D2 на Ардуино

Eruman » 14 июн 2017, 18:53

Проморгал почему-то последний вопрос :)

Отвечу, "лучше поздно, чем никогда", авось кому полезно окажется.

Итак, берем звуки R2D2, например с сайта http://www.r2d2translator.com
Отдельные буквы он не конвертирует, поэтому берем пару, например "aa".
Загружаем звуковой файл, конвертируем в WAV, читаем любой программой, отображающей спектрограмму, например программой Cool Editor Pro.
Переключаемся в режим "Спектр", и изучаем картинку. Переписываем с абсцисс и ординат соответственно длительности и частоты главных звуков, и имитируем их с помощью собственной программы.

Этот способ актуален для чипов с малым объемом памяти, для Atmega168 лучше подходит прямое воспроизведение, например, посредством библиотеки Talkie. Тот же файл, сжатый через FreeMath, занимает менее 100 байт.
Вложения
1.PNG
Исходный звук
2.PNG
Любуемся спектрограммой звука
3.PNG
Изучаем длительность и частоту экстремумов
4.png
Зеленым выделил частоты, которые нужно сгенерировать программно


Rambler\'s Top100 Mail.ru counter