Кабы не было зимы...
- Войдите на сайт для отправки комментариев
Вс, 05/12/2021 - 14:43
//кабы не было зимы
#define PAUZA 0
#include "pitches.h"
int SPEAKER=5;//определяем вывод для подключения звукоизлучателя
const int notes_times[]PROGMEM = {//массив нот и длительностей
NOTE_B3,400, NOTE_B3,400, NOTE_B4,600, NOTE_FS4,200,
NOTE_A4,400, NOTE_G4,400, NOTE_E4,800,PAUZA,50,
NOTE_D4,400, NOTE_D4,400, NOTE_D5,600, NOTE_C5,200, NOTE_C5,400,NOTE_B4,400,PAUZA,800,
NOTE_D5,400,NOTE_C5,400, NOTE_A4,400,NOTE_FS4,400, NOTE_C5,400,NOTE_B4,400,NOTE_B4,800,
NOTE_B3,400, NOTE_B3,400, NOTE_B4,600, NOTE_A4,200,NOTE_A4,400, NOTE_G4,400, PAUZA,800,
NOTE_B3,400, NOTE_B3,400, NOTE_B4,600, NOTE_FS4,200,
NOTE_A4,400, NOTE_G4,400, NOTE_E4,800,PAUZA,50,
NOTE_D4,400, NOTE_D4,400, NOTE_D5,600, NOTE_C5,200, NOTE_C5,400,NOTE_B4,400,PAUZA,400,
NOTE_E5,800,NOTE_C5,400, NOTE_A4,400, NOTE_FS4,400, NOTE_C5,400,NOTE_B4,400,NOTE_B4,800,PAUZA,50,
NOTE_B3,400, NOTE_B3,400, NOTE_B4,600, NOTE_A4,200,NOTE_A4,400, NOTE_G4,400, PAUZA,400,
NOTE_E5,800,NOTE_C5,400, NOTE_A4,400, NOTE_FS4,400, NOTE_C5,400,NOTE_B4,400,NOTE_B4,800,PAUZA,50,
NOTE_B3,400, NOTE_B3,400, NOTE_B4,600, NOTE_DS4,200,NOTE_FS4,400, NOTE_E4,400, PAUZA,800
};
float temp=0.8;//задаём темп исполнения мелодии
int dlina= sizeof(notes_times)/sizeof(notes_times[0]);//определяем длину массива
void setup(){
}
void loop(){
for (int i = 0; i < dlina; i=i+2){
tone(SPEAKER, pgm_read_word(¬es_times[i]),pgm_read_word(¬es_times[i+1])*temp);
delay(pgm_read_word(¬es_times[i+1])*temp+20);
}
delay(5000);//пауза между повторами мелодии
}
Давайте пособираем новогодние мелодии для Ардуино пищалки в подобном формате. У меня супруга училась в музыкальной школе, забила мне пару массивов на слух и сказала: это всё очень весело и прикольно звучит..., но отвали уже.
/************************************************* * Public Constants *************************************************/ #define NOTE_B0 31 #define NOTE_C1 33 #define NOTE_CS1 35 #define NOTE_D1 37 #define NOTE_DS1 39 #define NOTE_E1 41 #define NOTE_F1 44 #define NOTE_FS1 46 #define NOTE_G1 49 #define NOTE_GS1 52 #define NOTE_A1 55 #define NOTE_AS1 58 #define NOTE_B1 62 #define NOTE_C2 65 #define NOTE_CS2 69 #define NOTE_D2 73 #define NOTE_DS2 78 #define NOTE_E2 82 #define NOTE_F2 87 #define NOTE_FS2 93 #define NOTE_G2 98 #define NOTE_GS2 104 #define NOTE_A2 110 #define NOTE_AS2 117 #define NOTE_B2 123 #define NOTE_C3 131 #define NOTE_CS3 139 #define NOTE_D3 147 #define NOTE_DS3 156 #define NOTE_E3 165 #define NOTE_F3 175 #define NOTE_FS3 185 #define NOTE_G3 196 #define NOTE_GS3 208 #define NOTE_A3 220 #define NOTE_AS3 233 #define NOTE_B3 247 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 #define NOTE_CS5 554 #define NOTE_D5 587 #define NOTE_DS5 622 #define NOTE_E5 659 #define NOTE_F5 698 #define NOTE_FS5 740 #define NOTE_G5 784 #define NOTE_GS5 831 #define NOTE_A5 880 #define NOTE_AS5 932 #define NOTE_B5 988 #define NOTE_C6 1047 #define NOTE_CS6 1109 #define NOTE_D6 1175 #define NOTE_DS6 1245 #define NOTE_E6 1319 #define NOTE_F6 1397 #define NOTE_FS6 1480 #define NOTE_G6 1568 #define NOTE_GS6 1661 #define NOTE_A6 1760 #define NOTE_AS6 1865 #define NOTE_B6 1976 #define NOTE_C7 2093 #define NOTE_CS7 2217 #define NOTE_D7 2349 #define NOTE_DS7 2489 #define NOTE_E7 2637 #define NOTE_F7 2794 #define NOTE_FS7 2960 #define NOTE_G7 3136 #define NOTE_GS7 3322 #define NOTE_A7 3520 #define NOTE_AS7 3729 #define NOTE_B7 3951 #define NOTE_C8 4186 #define NOTE_CS8 4435 #define NOTE_D8 4699 #define NOTE_DS8 4978
то-есть сначала пишем неправильные ноты, а потом через
floattemp=0.8;//задаём темп исполнения мелодииприводим их к норме?Не, это темп исполнения меняется, т.е. быстро-медленно, частоты нот не меняются.
Не, это темп исполнения меняется, т.е. быстро-медленно, частоты нот не меняются.
длительность, есть только целая, половинная, четвертная, восьмая и т.д. ...андриано точно в теме, мои познания ограничиваются школьной программой
Не, это темп исполнения меняется, т.е. быстро-медленно, частоты нот не меняются.
длительность, есть только целая, половинная, четвертная, восьмая и т.д. ...андриано точно в теме, мои познания ограничиваются школьной программой
не умничай! ;)))
длительность ноты НИКАК не привязана к реальной длительности в секундах, а лишь определяет соотношение длительностей в произведении.
Часто играют "120 ударов в минуту" = 120 четвертных в минуту, но это на уроках в музыкалке, а не в реальности. На концерте могут играть и медленнее и, что чаще, - сильно быстрее. Особенно рок или джаз, да "дунувши" хорошо! ;))))
четвертная - одна 250-я а не одна 200-я ...НЕ?
Совсем НЕ )) Четвертная == 1/4 целой: ни более того ))
Длительность нот безотносительно размера и темпа - сферический конь. Как уже правильно сказали, длительность в музыке - величина относительная, к реальному времени времени звучания прикладывается через темп. Вообще, длительность нот это скорее про РИТМ (чередование нот разной длительности) :)
Совсем НЕ )) Четвертная == 1/4 целой: ни более того ))
у нас длительность TONE в миллисекундах, логично было бы привести в дробях от секунды, да и ТЕМП тогда получается не 0,8 а 1, НЕ?
а как звучит в этом случае?
//кабы не было зимы #define PAUZA 0 #include "pitches.h" int SPEAKER=5;//определяем вывод для подключения звукоизлучателя const int notes_times[]PROGMEM = {//массив нот и длительностей NOTE_B3,500, NOTE_B3,500, NOTE_B4,750, NOTE_FS4,250, NOTE_A4,500, NOTE_G4,500, NOTE_E4,1000,PAUZA,50, NOTE_D4,500, NOTE_D4,500, NOTE_D5,750, NOTE_C5,250, NOTE_C5,500,NOTE_B4,500,PAUZA,1000, NOTE_D5,500,NOTE_C5,500, NOTE_A4,500,NOTE_FS4,500, NOTE_C5,500,NOTE_B4,500,NOTE_B4,1000, NOTE_B3,500, NOTE_B3,500, NOTE_B4,750, NOTE_A4,250,NOTE_A4,500, NOTE_G4,500, PAUZA,1000, NOTE_B3,500, NOTE_B3,500, NOTE_B4,750, NOTE_FS4,250, NOTE_A4,500, NOTE_G4,500, NOTE_E4,1000,PAUZA,50, NOTE_D4,500, NOTE_D4,500, NOTE_D5,750, NOTE_C5,250, NOTE_C5,500,NOTE_B4,500,PAUZA,500, NOTE_E5,1000,NOTE_C5,500, NOTE_A4,500, NOTE_FS4,500, NOTE_C5,500,NOTE_B4,500,NOTE_B4,1000,PAUZA,50, NOTE_B3,500, NOTE_B3,500, NOTE_B4,750, NOTE_A4,250,NOTE_A4,500, NOTE_G4,500, PAUZA,500, NOTE_E5,1000,NOTE_C5,500, NOTE_A4,500, NOTE_FS4,500, NOTE_C5,500,NOTE_B4,500,NOTE_B4,1000,PAUZA,50, NOTE_B3,500, NOTE_B3,500, NOTE_B4,750, NOTE_DS4,250,NOTE_FS4,500, NOTE_E4,500, PAUZA,1000 }; float temp=1.0;//задаём темп исполнения мелодии int dlina= sizeof(notes_times)/sizeof(notes_times[0]);//определяем длину массива void setup(){ } void loop(){ for (int i = 0; i < dlina; i=i+2){ tone(SPEAKER, pgm_read_word(¬es_times[i]),pgm_read_word(¬es_times[i+1])*temp); delay(pgm_read_word(¬es_times[i+1])*temp+20); } delay(5000);//пауза между повторами мелодии }Грустно звучит, у меня веселее.
Давайте пособираем новогодние мелодии для Ардуино пищалки в подобном формате. У меня супруга училась в музыкальной школе, забила мне пару массивов на слух и сказала: это всё очень весело и прикольно звучит..., но отвали уже.
Зачем такие сложности?
Написать простейший конвертер из MIDI в нужный формат, а уж MIDI в И-нете как грязи...
Грустно звучит, у меня веселее.
а да, тут я накосячил, тогда темп надо 0,65
Грустно звучит, у меня веселее.
а да, тут я накосячил, тогда темп надо 0,65
Да вроде одинаково теперь звучат (на мой слух :-)
Давайте пособираем новогодние мелодии для Ардуино пищалки в подобном формате. У меня супруга училась в музыкальной школе, забила мне пару массивов на слух и сказала: это всё очень весело и прикольно звучит..., но отвали уже.
Зачем такие сложности?
Написать простейший конвертер из MIDI в нужный формат, а уж MIDI в И-нете как грязи...
Интересно, попробую вникнуть, правда я совсем далёк от формата этого.
//маленькой ёлочке холодно зимой #define PAUZA 0 #include "pitches.h" int SPEAKER=5;//определяем вывод для подключения звукоизлучателя const int notes_times[]PROGMEM = {//массив нот и длительностей NOTE_G4,600, NOTE_E4,400, NOTE_E4,400, NOTE_G4,600, NOTE_E4,400, NOTE_E4,400, NOTE_G4,400, NOTE_F4,400, NOTE_E4,400, NOTE_D4,400, NOTE_C4,1000,PAUZA,750,NOTE_A4,600, NOTE_C5,400, NOTE_A4,400, NOTE_G4,600, NOTE_E4,400, NOTE_E4,400, NOTE_G4,400, NOTE_F4,400, NOTE_E4,400, NOTE_D4,400, NOTE_C4,1000,PAUZA,750, NOTE_A4,600, NOTE_C5,400, NOTE_A4,400, NOTE_G4,600, NOTE_E4,400, NOTE_E4,400, NOTE_G4,400, NOTE_F4,400, NOTE_E4,400, NOTE_D4,400, NOTE_C4,1000 }; float temp=0.9;//задаём темп исполнения мелодии int dlina= sizeof(notes_times)/sizeof(notes_times[0]);//определяем длину массива void setup(){ } void loop(){ for (int i = 0; i < dlina; i=i+2){ tone(SPEAKER, pgm_read_word(¬es_times[i]),pgm_read_word(¬es_times[i+1])*temp); delay(pgm_read_word(¬es_times[i+1])*temp+20); } delay(5000);//пауза между повторами мелодии }Ещё мелодия.
можно добавить микрофон и сделать викторину угадай мелодию, по хлопку, осталось добавить мелодий, памяти еще вагон
можно добавить микрофон и сделать викторину угадай мелодию, по хлопку, осталось добавить мелодий, памяти еще вагон
Интересный концепт, надо обдумать.
Ещё на тему наступающего.
//рождество-"кристмас" #define PAUZA 0 #include "pitches.h" int SPEAKER=5;//определяем вывод для подключения звукоизлучателя const int notes_times[]PROGMEM = {//массив нот и длительностей NOTE_D4,800, NOTE_G4,800, NOTE_G4,400, NOTE_A4,400, NOTE_G4,400, NOTE_FS4,400, NOTE_E4,800, NOTE_E4, 800, NOTE_E4,800,PAUZA,50, NOTE_A4,800, NOTE_A4,400, NOTE_B4,400, NOTE_A4,400, NOTE_G4,400,NOTE_FS4,800,NOTE_D4,800,NOTE_D4,800,PAUZA,50, NOTE_B4,800, NOTE_B4,400, NOTE_C5,400, NOTE_B4,400, NOTE_A4,400, NOTE_G4,800, NOTE_E4,800,PAUZA,50, NOTE_D4, 400, NOTE_D4,400, NOTE_E4,800, NOTE_A4,800, NOTE_FS4,800,PAUZA,50, NOTE_G4,1600,PAUZA,1500, NOTE_D4,800, NOTE_G4,800, NOTE_G4, 800, NOTE_G4,800,PAUZA,50, NOTE_FS4,1600,PAUZA,50, NOTE_FS4,800,PAUZA,50, NOTE_G4,800, NOTE_FS4, 800, NOTE_E4,800,PAUZA,50, NOTE_D4,1600,PAUZA,50, NOTE_A4,800, NOTE_B4,800, NOTE_A4, 800, NOTE_G4,800,PAUZA,50, NOTE_D5,800, NOTE_D4, 800,NOTE_D4,400, NOTE_D4,400,PAUZA,50, NOTE_E4,800, NOTE_A4,800, NOTE_FS4,800,PAUZA,50, NOTE_G4,2400, }; float temp=0.6;//задаём темп исполнения мелодии int dlina= sizeof(notes_times)/sizeof(notes_times[0]);//определяем длину массива void setup(){ } void loop(){ for (int i = 0; i < dlina; i=i+2){ tone(SPEAKER, pgm_read_word(¬es_times[i]),pgm_read_word(¬es_times[i+1])*temp); delay(pgm_read_word(¬es_times[i+1])*temp+20); } delay(5000);//пауза между повторами мелодии }И совсем не в тему, но как на ардуино звучит!!!, аж щемит :-)
// Вальс "Мой ласковый и нежный зверь" #define PAUZA 0 #include "pitches.h" int SPEAKER=5;//определяем вывод для подключения звукоизлучателя const int notes_times[]PROGMEM = {//массив нот и длительностей NOTE_C4,1200, NOTE_E4,1200, NOTE_A4,1200, NOTE_C5,800, NOTE_B4,400,PAUZA,50, NOTE_E4,1200, NOTE_C5,800, NOTE_B4, 400, NOTE_C5,800, NOTE_B4, 400,NOTE_C5,800, NOTE_B4, 400,PAUZA,50, NOTE_C4,1200, NOTE_E4,1200, NOTE_A4,1200, NOTE_B4,400, NOTE_D5,600,NOTE_C5,400, NOTE_F4,1200, NOTE_D5,800, NOTE_C5, 400, NOTE_D5,800, NOTE_C5, 400,NOTE_D5,800, NOTE_C5,400,PAUZA,50, NOTE_D4,1200, NOTE_F4,1200, NOTE_A4,1200, NOTE_D5,400, NOTE_E5,600,NOTE_D5,200,PAUZA,50, NOTE_F5,2000, NOTE_E5,400, NOTE_AS4,2400, PAUZA,50, NOTE_A4,400, NOTE_D5,600, NOTE_CS5,200, NOTE_CS5,1200, NOTE_A4,400,NOTE_F5,600,NOTE_E5,200,NOTE_E5,1200,PAUZA,50, NOTE_CS5,400, NOTE_AS4,400, NOTE_A4, 400, NOTE_AS4,400, NOTE_A4, 400,NOTE_AS4,400, NOTE_AS4, 1200,NOTE_A4, 1200,PAUZA,50, NOTE_F4,1200, NOTE_F4,1200, NOTE_F4,1200, NOTE_F4,400, NOTE_G4,600,NOTE_A4,200,PAUZA,50, NOTE_AS4,2000, NOTE_D4,400, NOTE_CS4,2400, PAUZA,50, NOTE_E4,1200, NOTE_E4,1200, NOTE_E4,1200, NOTE_E4,400, NOTE_G4,600,NOTE_F4,200,PAUZA,50, NOTE_F4,2000, NOTE_A4,400, PAUZA,50,NOTE_A3,1200,PAUZA,50, NOTE_A3,400, NOTE_AS3,400, NOTE_C4, 400,PAUZA,50, NOTE_D4,1200, NOTE_D4,1200, NOTE_D4, 400, NOTE_E4,400, NOTE_F4, 400,NOTE_G4,400, NOTE_A4, 400,NOTE_AS4, 400,PAUZA,50, NOTE_D5,1200, NOTE_E5,800, NOTE_F5,400, NOTE_AS4,2400,PAUZA,50, NOTE_AS4,400, NOTE_A4,600, NOTE_G4,200, NOTE_G4,400, NOTE_A4,400,NOTE_AS4,400,NOTE_D5,1200,NOTE_AS4,400,NOTE_F5,600,NOTE_E5,200,PAUZA,50, NOTE_E5,1200,PAUZA,50 }; float temp=0.7;//задаём темп исполнения мелодии int dlina= sizeof(notes_times)/sizeof(notes_times[0]);//определяем длину массива void setup(){ } void loop(){ for (int i = 0; i < dlina; i=i+2){ tone(SPEAKER, pgm_read_word(¬es_times[i]),pgm_read_word(¬es_times[i+1])*temp); delay(pgm_read_word(¬es_times[i+1])*temp+10); } delay(5000);//пауза между повторами мелодии }Давай ещё, собираю потихоньку в общий скетч, на выходных поищу модуль с микрофоном, попробую подоткнуть...
Давай ещё, собираю потихоньку в общий скетч, на выходных поищу модуль с микрофоном, попробую подоткнуть...
Весело у вас тут. Андриано уже намекнул, я - повторю: чем не устраивают уже написанные коды для МИДИ декодеров на Ардуино?
https://habr.com/ru/post/454394/
Например вот! ;)) аж на тиньке85
гугл забанили или пользоваться не умею
Давай ещё, собираю потихоньку в общий скетч, на выходных поищу модуль с микрофоном, попробую подоткнуть...
Весело у вас тут. Андриано уже намекнул, я - повторю: чем не устраивают уже написанные коды для МИДИ декодеров на Ардуино?
https://habr.com/ru/post/454394/
Например вот! ;)) аж на тиньке85
Соображалки просто не хватает, но что низкоомный динамик можно через конденсатор это я понял.
//в лесу родилась ёлочка #define PAUZA 0 #include "pitches.h" int SPEAKER=5;//определяем вывод для подключения звукоизлучателя const int notes_times[]PROGMEM = {//массив нот и длительностей NOTE_C4,400, NOTE_A4,400, NOTE_A4,400, NOTE_G4,400, NOTE_A4,400, NOTE_F4,400, NOTE_C4,400, NOTE_C4,400, NOTE_C4,400, NOTE_A4,400, NOTE_A4,400, NOTE_AS4,400, NOTE_G4,400, NOTE_C5,1000,PAUZA, 500, NOTE_C5,400, NOTE_D4,400, NOTE_D4,400, NOTE_AS4,400,NOTE_AS4,400,NOTE_A4,400, NOTE_G4,400, NOTE_F4,400, NOTE_C4,400, NOTE_A4,400, NOTE_A4,400, NOTE_G4,400, NOTE_A4,400, NOTE_F4,1000 }; float temp=1.2;//задаём темп исполнения мелодии int dlina= sizeof(notes_times)/sizeof(notes_times[0]);//определяем длину массива void setup(){ } void loop(){ for (int i = 0; i < dlina; i=i+2){ tone(SPEAKER, pgm_read_word(¬es_times[i]),pgm_read_word(¬es_times[i+1])*temp); delay(pgm_read_word(¬es_times[i+1])*temp+20); } delay(5000);//пауза между повторами мелодии }Колокольчики однако.
// Колокольчики-"джингл белз" #define PAUZA 0 #include "pitches.h" int SPEAKER=5;//определяем вывод для подключения звукоизлучателя const int notes_times[]PROGMEM = {//массив нот и длительностей NOTE_C4,800, NOTE_A4,800, NOTE_G4,800, NOTE_F4,800, NOTE_C4,1600,PAUZA,800, NOTE_C4,400,NOTE_C4,400, NOTE_C4,800, NOTE_A4,800, NOTE_G4,800, NOTE_F4,800, NOTE_D4,2400,PAUZA,800, NOTE_D4,800, NOTE_AS4,800, NOTE_A4,800, NOTE_G4,800, NOTE_E4,2400,PAUZA,800, NOTE_C5,800, NOTE_C5,800, NOTE_AS4,800, NOTE_G4,800, NOTE_A4,2400,PAUZA,800, NOTE_C4,800, NOTE_A4,800, NOTE_G4,800, NOTE_F4,800, NOTE_C4,2400,PAUZA,800, NOTE_C4,800, NOTE_A4,800, NOTE_G4,800, NOTE_F4,800, NOTE_D4,1600,PAUZA,800,NOTE_D4,800, NOTE_D4,800, NOTE_AS4,800, NOTE_A4,800, NOTE_G4,800,NOTE_C5,800,NOTE_C5,800,NOTE_C5,800,NOTE_C5,800, PAUZA,50, NOTE_D5,800, NOTE_C5,800, NOTE_AS4,800, NOTE_G4,800, NOTE_F4,2400,PAUZA,800,PAUZA,50, NOTE_A4,800, NOTE_A4,800, NOTE_A4,1600, PAUZA,50, NOTE_A4,800, NOTE_A4,800, NOTE_A4,1600, PAUZA,50, NOTE_A4,800, NOTE_C5,800, NOTE_F4,800, NOTE_G4,800,NOTE_A4,2400,PAUZA,800,PAUZA,50, NOTE_AS4,800, NOTE_AS4,800, NOTE_AS4,800, NOTE_AS4,800,PAUZA,50, NOTE_AS4,800,NOTE_A4,800,NOTE_A4,800,NOTE_A4,400, NOTE_A4,400,PAUZA,50, NOTE_A4,800, NOTE_G4,800, NOTE_G4,800, NOTE_A4,800,PAUZA,50, NOTE_G4,1600, NOTE_C5,1600, PAUZA,50, NOTE_A4,800, NOTE_A4,800, NOTE_A4,1600, PAUZA,50, NOTE_A4,800, NOTE_A4,800, NOTE_A4,1600, PAUZA,50, NOTE_A4,800, NOTE_C5,800, NOTE_F4,800, NOTE_G4,800,NOTE_A4,2400,PAUZA,800,PAUZA,50, NOTE_AS4,800, NOTE_AS4,800, NOTE_AS4,800, NOTE_AS4,800,PAUZA,50, NOTE_AS4,800,NOTE_A4,800,NOTE_A4,800,NOTE_A4,400, NOTE_A4,400,PAUZA,50, NOTE_C5,800, NOTE_C5,800, NOTE_AS4,800, NOTE_G4,800, NOTE_F4,2400,PAUZA,800,PAUZA,50, PAUZA,50 }; float temp=0.3;//задаём темп исполнения мелодии int dlina= sizeof(notes_times)/sizeof(notes_times[0]);//определяем длину массива void setup(){ } void loop(){ for (int i = 0; i < dlina; i=i+2){ tone(SPEAKER, pgm_read_word(¬es_times[i]),pgm_read_word(¬es_times[i+1])*temp); delay(pgm_read_word(¬es_times[i+1])*temp+10); } delay(5000);//пауза между повторами мелодии }Для сравнения взял и попробовал имеющийся в инете конвертер из "миди в скетч".
Вальс "про зверя". Нюансов много (без музыканта опять никак), ну и скетч конечно монумент - ни поправить, ни изменить.
Float в delay не работает. А так - вполне в структуру/массив уложить можно.
Давай ещё, собираю потихоньку в общий скетч, на выходных поищу модуль с микрофоном, попробую подоткнуть...
Весело у вас тут. Андриано уже намекнул, я - повторю: чем не устраивают уже написанные коды для МИДИ декодеров на Ардуино?
https://habr.com/ru/post/454394/
Например вот! ;)) аж на тиньке85
Соображалки просто не хватает, но что низкоомный динамик можно через конденсатор это я понял.
так это на Тиньке, на нано такое не сделать (((
ЗЫ и альтернативы судя по калькулятору фьюзов не особо
С помощью "блокнота нотепад"?
Давай ещё, собираю потихоньку в общий скетч, на выходных поищу модуль с микрофоном, попробую подоткнуть...
Весело у вас тут. Андриано уже намекнул, я - повторю: чем не устраивают уже написанные коды для МИДИ декодеров на Ардуино?
https://habr.com/ru/post/454394/
Например вот! ;)) аж на тиньке85
Соображалки просто не хватает, но что низкоомный динамик можно через конденсатор это я понял.
так это на Тиньке, на нано такое не сделать (((
ЗЫ и альтернативы судя по калькулятору фьюзов не особо
Где то я видел, кажется на УНО, фрагмент мелодии без tone(), нот,длительностей. Но там как то всё хитро описано и нет готового результата для повторения простыми обывателями.
Если генератор/конвертор не позволяет внести в него исправления для формирования другого кода, то нотепадом... Ну, или по этому результату пройтись питоном/пёрлом. Не сильно Удобно, но на безрыбье, как грицца...
https://www.extramaster.net/tools/midiToArduino/
Я как то не подумал о вариантах готового скетча в этом конверторе. Его внешний вид напомнил мне как я учился слайды презентаций делать :-)
Ежели эта штука в браузере работает, то может там JS внутрях страницы. А это натурально скриптовый язык, исходники которого подрихтовать можно.
Где то я видел, кажется на УНО, фрагмент мелодии без tone(), нот,длительностей. Но там как то всё хитро описано и нет готового результата для повторения простыми обывателями.
Мелодия без нот и длительностей?
А Вы уверены, что это была мелодия?
Найти не могу.., что я в поисковике забивал?, не помню, но суть что многоинструментальная мелодия воспроизводится на один динамик ардуиной. большая вроде была статья с теорией.
Но я нашёл проект попроще
https://www.instructables.com/Arduino-Synthesizer-With-FM/
поковыряюсь, может перековеркаю под извлечение нот с заданными длительностями.
На всякий случай напомню о проекте, который я здесь как-то давно размещал: http://arduino.ru/forum/proekty/floppy-hdd-music
Ну это концептуально-законченное изделие для ценителей эксклюзива.
А тут замысел вместо tone() получить нотоиграние голосами разных инструментов. Опять мне не ясно, почему автор не сделал библиотеку "исполнения инструментных нот", тем более с возможностью одновременной игры до 4 штук (аккорд вроде это).
на Arriny85, четырёхголосый тоже неплохо звучит, только на нано это не сделать, не удержался - заказал сегодня десяток тинек85, и платки к ним чуток поменьше
Изуродовал я авторский вариант.
Сделал так.
В массив вбиваем ноты, длительности, ставим паузы если надо и циклично играем на 12 инструментах мелодию в один голос (для примера вбил все 18 нот по секунде на каждую). Одновременное звучание нескольких нот не знаю как сделать, исполнение мелодии на нескольких инструментах - тем более. Автор запретил прерывания, пришлось запрет снять для работы миллис.
Из исходника удалил лишнее, что смог, как убрать лишние каналы (свести от 4 до 1) не знаю :-)
//instrument definitions 0 1 2 3 4 5 6 7 8 9 10 11 #define ninstr 12 // piano xlphn guitar cmbll bell funky vibr metal violin bass trumpt harm unsigned int ldness[ninstr] = { 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}; // loudness unsigned int pitch0[ninstr] = { 12, 12, 12, 12, 24, 24, 0, 12, 24, 12, 12, 24}; // pitch of key0 unsigned int ADSR_a[ninstr] = { 4096, 8192, 8192, 8192, 4096, 512, 512, 8192, 128, 128, 256, 256}; // attack parameter unsigned int ADSR_d[ninstr] = { 8, 64, 16, 16, 16, 16, 16, 8, 16, 16, 64, 32}; // decay parameter unsigned int ADSR_s[ninstr] = { 0, 0, 0, 0, 0, 0, 0, 0, 240, 240, 192, 192}; // sustain parameter unsigned int ADSR_r[ninstr] = { 64, 128, 32, 32, 64, 32, 32, 32, 32, 32, 64, 64}; // release parameter unsigned int FM_inc[ninstr] = { 256, 512, 768, 400, 200, 96, 528, 244, 256, 128, 64, 160}; // FM frequency wrt pitch unsigned int FM_a1[ninstr] = { 128, 512, 512, 1024, 512, 0, 1024, 2048, 256, 256, 384, 256}; // FM amplitude start unsigned int FM_a2[ninstr] = { 64, 0, 128, 128, 128, 512, 768, 512, 128, 128, 256, 128}; // FM amplitude end unsigned int FM_dec[ninstr] = { 64, 128, 128, 128, 32, 128, 128, 128, 128, 128, 64, 64}; // FM decay //define the pitch2key mapping #define NOTE_C4 0 #define NOTE_CS4 1 #define NOTE_D4 2 #define NOTE_DS4 3 #define NOTE_E4 4 #define NOTE_F4 5 #define NOTE_FS4 6 #define NOTE_G4 7 #define NOTE_GS4 8 #define NOTE_A4 9 #define NOTE_AS4 10 #define NOTE_B4 11 #define NOTE_C5 12 #define NOTE_CS5 13 #define NOTE_D5 14 #define NOTE_DS5 15 #define NOTE_E5 16 #define NOTE_F5 17 #define PAUZA 18 #define nokey 255 #define instrkey 254 //set up array with sine values in signed 8-bit numbers const float pi = 3.14159265; char sine[256]; void setsine() { for (int i = 0; i < 256; ++i) { sine[i] = (sin(2 * 3.14159265 * (i + 0.5) / 256)) * 128; } } //setup frequencies/phase increments, starting at C3=0 to B6. (A4 is defined as 440Hz) unsigned int tone_inc[48]; void settones() { for (byte i=0; i<48; i++){ tone_inc[i]= 440.0 * pow(2.0, ( (i-21) / 12.0)) * 65536.0 / (16000000.0/512) + 0.5; } } byte instr=1;//счётчик инструмента включённого ///////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// long Y=0;//переменная хранения моментов времени int k=0;// счётчик прогресса исполнения мелодии const int notes_times[]PROGMEM = { // Колокольчики-"джингл белз" NOTE_C4,800, NOTE_A4,800, NOTE_G4,800, NOTE_F4,800, NOTE_C4,1600,PAUZA,800, NOTE_C4,400,NOTE_C4,400, NOTE_C4,800, NOTE_A4,800, NOTE_G4,800, NOTE_F4,800, NOTE_D4,2400,PAUZA,800, NOTE_D4,800, NOTE_AS4,800, NOTE_A4,800, NOTE_G4,800, NOTE_E4,2400,PAUZA,800, NOTE_C5,800, NOTE_C5,800, NOTE_AS4,800, NOTE_G4,800, NOTE_A4,2400,PAUZA,800, NOTE_C4,800, NOTE_A4,800, NOTE_G4,800, NOTE_F4,800, NOTE_C4,2400,PAUZA,800, NOTE_C4,800, NOTE_A4,800, NOTE_G4,800, NOTE_F4,800, NOTE_D4,1600,PAUZA,800,NOTE_D4,800, NOTE_D4,800, NOTE_AS4,800, NOTE_A4,800, NOTE_G4,800,NOTE_C5,800,NOTE_C5,800,NOTE_C5,800,NOTE_C5,800, PAUZA,50, NOTE_D5,800, NOTE_C5,800, NOTE_AS4,800, NOTE_G4,800, NOTE_F4,2400,PAUZA,800,PAUZA,50, NOTE_A4,800, NOTE_A4,800, NOTE_A4,1600, PAUZA,50, NOTE_A4,800, NOTE_A4,800, NOTE_A4,1600, PAUZA,50, NOTE_A4,800, NOTE_C5,800, NOTE_F4,800, NOTE_G4,800,NOTE_A4,2400,PAUZA,800,PAUZA,50, NOTE_AS4,800, NOTE_AS4,800, NOTE_AS4,800, NOTE_AS4,800,PAUZA,50, NOTE_AS4,800,NOTE_A4,800,NOTE_A4,800,NOTE_A4,400, NOTE_A4,400,PAUZA,50, NOTE_A4,800, NOTE_G4,800, NOTE_G4,800, NOTE_A4,800,PAUZA,50, NOTE_G4,1600, NOTE_C5,1600, PAUZA,50, NOTE_A4,800, NOTE_A4,800, NOTE_A4,1600, PAUZA,50, NOTE_A4,800, NOTE_A4,800, NOTE_A4,1600, PAUZA,50, NOTE_A4,800, NOTE_C5,800, NOTE_F4,800, NOTE_G4,800,NOTE_A4,2400,PAUZA,800,PAUZA,50, NOTE_AS4,800, NOTE_AS4,800, NOTE_AS4,800, NOTE_AS4,800,PAUZA,50, NOTE_AS4,800,NOTE_A4,800,NOTE_A4,800,NOTE_A4,400, NOTE_A4,400,PAUZA,50, NOTE_C5,800, NOTE_C5,800, NOTE_AS4,800, NOTE_G4,800, NOTE_F4,2400,PAUZA,800,PAUZA,50, PAUZA,100 }; float temp=0.4;//задаём темп исполнения мелодии int dlina= sizeof(notes_times)/sizeof(notes_times[0]);//определяем длину массива ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// void setup() { //disable all inerrupts to avoid glitches отключите все прерывания, чтобы избежать сбоев // noInterrupts(); //setup the array with sine values настройте массив со значениями синуса setsine(); //setup array with tone frequency phase increments установочная матрица с приращениями фазы тональной частоты settones(); //Set a fast PWM signal on TIMER1A, 9-bit resolution, 31250Hz pinMode(9, OUTPUT);// вывод для динамика TCCR1A = 0B10000010; //9-bit fast PWM TCCR1B = 0B00001001; ///////////////////////////////////////////////////////////////////////////////// pinMode(7, INPUT);//кнопку подключить digitalWrite(7, HIGH);// включить подтягивающий резистор к ней ///////////////////////////////////////////////////////////////////////////////// } //initialize the main parameters of the pulse length setting инициализируйте основные параметры настройки длительности импульса #define nch 4 //number of channels that can produce sound simultaneously количество каналов, которые могут воспроизводить звук одновременно unsigned int phase[nch] = {0,0,0,0}; int inc[nch] = {0,0,0,0}; byte amp[nch] = {0,0,0,0}; unsigned int FMphase[nch]= {0,0,0,0}; unsigned int FMinc[nch] = {0,0,0,0}; unsigned int FMamp[nch] = {0,0,0,0}; // main function (forced inline) to update the pulse length основная функция (принудительная встроенная) для обновления длительности импульса inline void setPWM() __attribute__((always_inline)); inline void setPWM() { //wait for the timer to complete loop подождите, пока таймер завершит цикл while ((TIFR1 & 0B00000001) == 0); //Clear(!) the overflow bit by writing a 1 to it TIFR1 |= 0B00000001; //increment the phases of the FM FMphase[0] += FMinc[0]; FMphase[1] += FMinc[1]; FMphase[2] += FMinc[2]; FMphase[3] += FMinc[3]; //increment the phases of the note phase[0] += inc[0]; phase[1] += inc[1]; phase[2] += inc[2]; phase[3] += inc[3]; //calculate the output value and set pulse width for timer2 int val = sine[(phase[0]+sine[FMphase[0]>>8]*FMamp[0]) >> 8] * amp[0]; val += sine[(phase[1]+sine[FMphase[1]>>8]*FMamp[1]) >> 8] * amp[1]; val += sine[(phase[2]+sine[FMphase[2]>>8]*FMamp[2]) >> 8] * amp[2]; val += sine[(phase[3]+sine[FMphase[3]>>8]*FMamp[3]) >> 8] * amp[3]; //set the pulse length OCR1A = val/128 + 256; } //properties of each note played свойства каждой сыгранной ноты byte iADSR[nch] = {0, 0, 0, 0}; unsigned int envADSR[nch] = {0, 0, 0, 0}; unsigned int ADSRa[nch] = {0, 0, 0, 0}; unsigned int ADSRd[nch] = {0, 0, 0, 0}; unsigned int ADSRs[nch] = {0, 0, 0, 0}; unsigned int ADSRr[nch] = {0, 0, 0, 0}; byte amp_base[nch] = {0, 0, 0, 0}; unsigned int inc_base[nch] = {0, 0, 0, 0}; unsigned int FMa0[nch] = {0, 0, 0, 0}; int FMda[nch] = {0, 0, 0, 0}; unsigned int FMinc_base[nch]= {0, 0, 0, 0}; unsigned int FMdec[nch] = {0, 0, 0, 0}; unsigned int FMexp[nch] = {0, 0, 0, 0}; unsigned int FMval[nch] = {0, 0, 0, 0}; byte keych[nch] = {0, 0, 0, 0}; unsigned int tch[nch] = {0, 0, 0, 0}; byte keypressed; byte keyreleased; ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// // main loop. Duration of loop is determined by number of setPWM calls // Each setPWMcall corresponds to 512 cylcles=32mus // Tloop= 32mus * #setPWM. #setPWM=15 gives Tloop=0.48ms void loop() { keypressed = nokey; keyreleased = nokey; if(digitalRead (7)==LOW){//если нажали кнопку то... for(int i=0;i< dlina;i=i+2){//...сыграть мелодию... if(k==i&&millis()-Y>10){Y=millis();k++;if(pgm_read_word(¬es_times[i])!=PAUZA){keypressed = pgm_read_word(¬es_times[i]);}} if(k==i+1&&millis()-Y>pgm_read_word(¬es_times[i+1])*temp){Y=millis();k++;if(pgm_read_word(¬es_times[i])!=PAUZA){keyreleased = pgm_read_word(¬es_times[i]);}} setPWM();//#0 } if(k==dlina){k=0;}//... и повторить её снова при долгом удержании кнопки }else {k=0;}//при повторном нажатии кнопки начать исполнение сначала osnova();// вынес в отдельную функцию часть исходника автора } ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// void osnova(){ setPWM(); //#1 //find the best channel to start a new note найдите лучший канал, чтобы начать новую заметку byte nextch = 255; //first check if the key is still being played сначала проверьте, воспроизводится ли еще клавиша if (iADSR[0] > 0 and keypressed == keych[0])nextch = 0; if (iADSR[1] > 0 and keypressed == keych[1])nextch = 1; if (iADSR[2] > 0 and keypressed == keych[2])nextch = 2; if (iADSR[3] > 0 and keypressed == keych[3])nextch = 3; //then check for an empty channel затем проверьте, нет ли пустого канала if (nextch == 255) { if (iADSR[0] == 0)nextch = 0; if (iADSR[1] == 0)nextch = 1; if (iADSR[2] == 0)nextch = 2; if (iADSR[3] == 0)nextch = 3; } //otherwise use the channel with the longest playing note в противном случае используйте канал с самой длинной воспроизводимой нотой if (nextch == 255) { nextch = 0; if (tch[0] > tch[nextch])nextch = 0; if (tch[1] > tch[nextch])nextch = 1; if (tch[2] > tch[nextch])nextch = 2; if (tch[3] > tch[nextch])nextch = 3; } setPWM(); //#3 //initiate new note if needed при необходимости инициируйте новую заметку if (keypressed != nokey) { phase[nextch]=0; amp_base[nextch] = ldness[instr]; inc_base[nextch] = tone_inc[pitch0[instr]+keypressed]; ADSRa[nextch]=ADSR_a[instr]; ADSRd[nextch]=ADSR_d[instr]; ADSRs[nextch]=ADSR_s[instr]<<8; ADSRr[nextch]=ADSR_r[instr]; iADSR[nextch] = 1; FMphase[nextch]=0; FMinc_base[nextch] = ((long)inc_base[nextch]*FM_inc[instr])/256; FMa0[nextch] = FM_a2[instr]; FMda[nextch] = FM_a1[instr]-FM_a2[instr]; FMexp[nextch]=0xFFFF; FMdec[nextch]=FM_dec[instr]; keych[nextch] = keypressed; tch[nextch] = 0; } setPWM(); //#4 //stop a note if the button is released остановите заметку, если кнопка отпущена if (keyreleased != nokey) { if (keych[0] == keyreleased)iADSR[0] = 4; if (keych[1] == keyreleased)iADSR[1] = 4; if (keych[2] == keyreleased)iADSR[2] = 4; if (keych[3] == keyreleased)iADSR[3] = 4; } setPWM(); //#5 //update FM decay exponential обновление FM-спад экспоненциальный FMexp[0]-=(long)FMexp[0]*FMdec[0]>>16; FMexp[1]-=(long)FMexp[1]*FMdec[1]>>16; FMexp[2]-=(long)FMexp[2]*FMdec[2]>>16; FMexp[3]-=(long)FMexp[3]*FMdec[3]>>16; setPWM(); //#6 //adjust the ADSR envelopes отрегулируйте конверты ADSR for (byte ich = 0; ich < nch; ich++) { if (iADSR[ich] == 4) { if (envADSR[ich] <= ADSRr[ich]) { envADSR[ich] = 0; iADSR[ich] = 0; } else envADSR[ich] -= ADSRr[ich]; } if (iADSR[ich] == 2) { if (envADSR[ich] <= (ADSRs[ich] + ADSRd[ich])) { envADSR[ich] = ADSRs[ich]; iADSR[ich] = 3; } else envADSR[ich] -= ADSRd[ich]; } if (iADSR[ich] == 1) { if ((0xFFFF - envADSR[ich]) <= ADSRa[ich]) { envADSR[ich] = 0xFFFF; iADSR[ich] = 2; } else envADSR[ich] += ADSRa[ich]; } tch[ich]++; setPWM(); //#7-10 } //update the tone for channel 0 обновите звуковой сигнал для канала 0 amp[0] = (amp_base[0] * (envADSR[0] >> 8)) >> 8; inc[0] = inc_base[0]; FMamp[0] = FMa0[0] + ((long)FMda[0] * FMexp[0]>>16); FMinc[0] = FMinc_base[0]; setPWM(); //#11 //update the tone for channel 1 amp[1] = (amp_base[1] * (envADSR[1] >> 8)) >> 8; inc[1] = inc_base[1]; FMamp[1] = FMa0[1] + ((long)FMda[1] * FMexp[1]>>16); FMinc[1] = FMinc_base[1]; setPWM(); //#12 //update the tone for channel 2 amp[2] = (amp_base[2] * (envADSR[2] >> 8)) >> 8; inc[2] = inc_base[2]; FMamp[2] = FMa0[2] + ((long)FMda[2] * FMexp[2]>>16); FMinc[2] = FMinc_base[2]; setPWM(); //#13 //update the tone for channel 3 amp[3] = (amp_base[3] * (envADSR[3] >> 8)) >> 8; inc[3] = inc_base[3]; FMamp[3] = FMa0[3] + ((long)FMda[3] * FMexp[3]>>16); FMinc[3] = FMinc_base[3]; setPWM(); //#14 //update counters счетчики обновлений tch[0]++; tch[1]++; tch[2]++; tch[3]++; setPWM(); //#15 } ///////////////////////////////////////////////////////Подключил колонки от ПК, сделал вариант для исполнения по кнопке. Звучит потрясающе (взял ксилофон)! Автор молодец!
float в avr вроде 7 значащих цифр, то-есть указанная точность ПИ излишняя, знающие поправят если не так
PS я тоже оценил качество звука )))
float в avr вроде 7 значащих цифр, то-есть указанная точность ПИ излишняя, знающие поправят если не так
PS я тоже оценил качество звука )))
float везде одинаковая и везде 24 двоичных разряда (один из которых не нуждается в хранении).
PS я тоже оценил качество звука )))
Ну, не знаю, по моим скромным ушам - шендевр. Вот вариант пианино по вальсу "мой нежный и ласковый зверь". Даже захотелось найти модуль-усилитель под динамик для Ардуино с питанием 3-5 Вольт :-)
//instrument definitions #define ninstr 12 // piano xlphn guitar cmbll bell funky vibr metal violin bass trumpt harm unsigned int ldness[ninstr] = { 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}; // loudness unsigned int pitch0[ninstr] = { 0, 0, 0, 12, 24, 24, 0, 12, 24, 12, 12, 24}; // pitch of key0 unsigned int ADSR_a[ninstr] = { 4096, 8192, 8192, 8192, 4096, 512, 512, 8192, 128, 128, 256, 256}; // attack parameter unsigned int ADSR_d[ninstr] = { 256, 256, 512, 16, 8, 16, 16, 8, 16, 16, 64, 32}; // decay parameter unsigned int ADSR_s[ninstr] = { 0, 0, 0, 0, 0, 0, 0, 0, 240, 240, 192, 192}; // sustain parameter unsigned int ADSR_r[ninstr] = { 64, 128, 32, 32, 16, 32, 32, 32, 32, 32, 64, 64}; // release parameter unsigned int FM_inc[ninstr] = { 256, 512, 768, 400, 200, 96, 528, 244, 256, 128, 64, 160}; // FM frequency wrt pitch unsigned int FM_a1[ninstr] = { 128, 512, 512, 1024, 512, 0, 1024, 2048, 256, 256, 384, 256}; // FM amplitude start unsigned int FM_a2[ninstr] = { 64, 0, 128, 128, 128, 512, 768, 512, 128, 128, 256, 128}; // FM amplitude end unsigned int FM_dec[ninstr] = { 64, 128, 128, 128, 32, 128, 128, 128, 128, 128, 64, 64}; // FM decay //define the pitch2key mapping #define NOTE_C4 0 #define NOTE_CS4 1 #define NOTE_D4 2 #define NOTE_DS4 3 #define NOTE_E4 4 #define NOTE_F4 5 #define NOTE_FS4 6 #define NOTE_G4 7 #define NOTE_GS4 8 #define NOTE_A4 9 #define NOTE_AS4 10 #define NOTE_B4 11 #define NOTE_C5 12 #define NOTE_CS5 13 #define NOTE_D5 14 #define NOTE_DS5 15 #define NOTE_E5 16 #define NOTE_F5 17 #define NOTE_FS5 18 #define NOTE_G5 19 #define NOTE_GS5 20 #define NOTE_A5 21 #define NOTE_AS5 22 #define NOTE_B5 23 #define NOTE_C6 24 #define NOTE_CS6 25 #define NOTE_D6 26 #define NOTE_DS6 27 #define NOTE_E6 28 #define NOTE_F6 29 #define NOTE_FS6 30 #define NOTE_G6 31 #define NOTE_GS6 32 #define NOTE_A6 33 #define NOTE_AS6 34 #define NOTE_B6 35 #define PAUZA 50 #define nokey 255 #define instrkey 254 //set up array with sine values in signed 8-bit numbers const float pi = 3.14159265; char sine[256]; void setsine() { for (int i = 0; i < 256; ++i) { sine[i] = (sin(2 * 3.14159265 * (i + 0.5) / 256)) * 128; } } //setup frequencies/phase increments, starting at C3=0 to B6. (A4 is defined as 440Hz) unsigned int tone_inc[48]; void settones() { for (byte i=0; i<48; i++){ tone_inc[i]= 440.0 * pow(2.0, ( (i-21) / 12.0)) * 65536.0 / (16000000.0/512) + 0.5; } } byte instr=0;//счётчик инструмента включённого ///////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// long Y=0;//переменная хранения моментов времени int k=0;// счётчик прогресса исполнения мелодии int i=0;// const int notes_times[]PROGMEM = { // вальс - "мой ласковый и нежный зверь" NOTE_C5,1200, NOTE_E5,1200, NOTE_A5,1200, NOTE_C6,800, NOTE_B5,400,PAUZA,50, NOTE_E5,1200, NOTE_C6,800, NOTE_B5, 400, NOTE_C6,800, NOTE_B5, 400,NOTE_C6,800, NOTE_B5, 400,PAUZA,50, NOTE_C5,1200, NOTE_E5,1200, NOTE_A5,1200, NOTE_B5,400, NOTE_D6,600,NOTE_C6,400, NOTE_F5,1200, NOTE_D6,800, NOTE_C6, 400, NOTE_D6,800, NOTE_C6, 400,NOTE_D6,800, NOTE_C6,400,PAUZA,50, NOTE_D5,1200, NOTE_F5,1200, NOTE_A5,1200, NOTE_D6,400, NOTE_E6,600,NOTE_D6,200,PAUZA,50, NOTE_F6,2000, NOTE_E6,400, NOTE_AS5,2400, PAUZA,50, NOTE_A5,400, NOTE_D6,600, NOTE_CS6,200, NOTE_CS6,1200, NOTE_A5,400,NOTE_F6,600,NOTE_E6,200,NOTE_E6,1200,PAUZA,50, NOTE_CS6,400, NOTE_AS6,400, NOTE_A5, 400, NOTE_AS5,400, NOTE_A5, 400,NOTE_AS5,400, NOTE_AS5, 1200,NOTE_A5, 1200,PAUZA,50, NOTE_F5,1200, NOTE_F5,1200, NOTE_F5,1200, NOTE_F5,400, NOTE_G5,600,NOTE_A5,200,PAUZA,50, NOTE_AS5,2000, NOTE_D5,400, NOTE_CS5,2400, PAUZA,50, NOTE_E5,1200, NOTE_E5,1200, NOTE_E5,1200, NOTE_E5,400, NOTE_G5,600,NOTE_F5,200,PAUZA,50, NOTE_F5,2000, NOTE_A5,400, PAUZA,50,NOTE_A4,1200,PAUZA,50, NOTE_A4,400, NOTE_AS4,400, NOTE_C5, 400,PAUZA,50, NOTE_D5,1200, NOTE_D5,1200, NOTE_D5, 400, NOTE_E5,400, NOTE_F5, 400,NOTE_G5,400, NOTE_A5, 400,NOTE_AS5, 400,PAUZA,50, NOTE_D6,1200, NOTE_E6,800, NOTE_F6,400, NOTE_AS6,2400,PAUZA,50, NOTE_AS5,400, NOTE_A5,600, NOTE_G5,200, NOTE_G5,400, NOTE_A5,400,NOTE_AS5,400,NOTE_D6,1200,NOTE_AS5,400,NOTE_F6,600,NOTE_E6,200,PAUZA,50, NOTE_E6,1200,PAUZA,5000 }; float temp=0.7;//задаём темп исполнения мелодии int dlina= sizeof(notes_times)/sizeof(notes_times[0]);//определяем длину массива ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// void setup() { //disable all inerrupts to avoid glitches отключите все прерывания, чтобы избежать сбоев // noInterrupts(); //setup the array with sine values настройте массив со значениями синуса setsine(); //setup array with tone frequency phase increments установочная матрица с приращениями фазы тональной частоты settones(); //Set a fast PWM signal on TIMER1A, 9-bit resolution, 31250Hz pinMode(9, OUTPUT);// вывод для динамика TCCR1A = 0B10000010; //9-bit fast PWM TCCR1B = 0B00001001; ///////////////////////////////////////////////////////////////////////////////// pinMode(7, INPUT);//кнопку подключить digitalWrite(7, HIGH);// включить подтягивающий резистор к ней ///////////////////////////////////////////////////////////////////////////////// } //initialize the main parameters of the pulse length setting инициализируйте основные параметры настройки длительности импульса #define nch 4 //number of channels that can produce sound simultaneously количество каналов, которые могут воспроизводить звук одновременно unsigned int phase[nch] = {0,0,0,0}; int inc[nch] = {0,0,0,0}; byte amp[nch] = {0,0,0,0}; unsigned int FMphase[nch]= {0,0,0,0}; unsigned int FMinc[nch] = {0,0,0,0}; unsigned int FMamp[nch] = {0,0,0,0}; // main function (forced inline) to update the pulse length основная функция (принудительная встроенная) для обновления длительности импульса inline void setPWM() __attribute__((always_inline)); inline void setPWM() { //wait for the timer to complete loop подождите, пока таймер завершит цикл while ((TIFR1 & 0B00000001) == 0); //Clear(!) the overflow bit by writing a 1 to it TIFR1 |= 0B00000001; //increment the phases of the FM FMphase[0] += FMinc[0]; FMphase[1] += FMinc[1]; FMphase[2] += FMinc[2]; FMphase[3] += FMinc[3]; //increment the phases of the note phase[0] += inc[0]; phase[1] += inc[1]; phase[2] += inc[2]; phase[3] += inc[3]; //calculate the output value and set pulse width for timer2 int val = sine[(phase[0]+sine[FMphase[0]>>8]*FMamp[0]) >> 8] * amp[0]; val += sine[(phase[1]+sine[FMphase[1]>>8]*FMamp[1]) >> 8] * amp[1]; val += sine[(phase[2]+sine[FMphase[2]>>8]*FMamp[2]) >> 8] * amp[2]; val += sine[(phase[3]+sine[FMphase[3]>>8]*FMamp[3]) >> 8] * amp[3]; //set the pulse length OCR1A = val/128 + 256; } //properties of each note played свойства каждой сыгранной ноты byte iADSR[nch] = {0, 0, 0, 0}; unsigned int envADSR[nch] = {0, 0, 0, 0}; unsigned int ADSRa[nch] = {0, 0, 0, 0}; unsigned int ADSRd[nch] = {0, 0, 0, 0}; unsigned int ADSRs[nch] = {0, 0, 0, 0}; unsigned int ADSRr[nch] = {0, 0, 0, 0}; byte amp_base[nch] = {0, 0, 0, 0}; unsigned int inc_base[nch] = {0, 0, 0, 0}; unsigned int FMa0[nch] = {0, 0, 0, 0}; int FMda[nch] = {0, 0, 0, 0}; unsigned int FMinc_base[nch]= {0, 0, 0, 0}; unsigned int FMdec[nch] = {0, 0, 0, 0}; unsigned int FMexp[nch] = {0, 0, 0, 0}; unsigned int FMval[nch] = {0, 0, 0, 0}; byte keych[nch] = {0, 0, 0, 0}; unsigned int tch[nch] = {0, 0, 0, 0}; byte keypressed; byte keyreleased; ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// // main loop. Duration of loop is determined by number of setPWM calls // Each setPWMcall corresponds to 512 cylcles=32mus // Tloop= 32mus * #setPWM. #setPWM=15 gives Tloop=0.48ms void loop() { keypressed = nokey; keyreleased = nokey; if(digitalRead (7)==LOW){//если нажали кнопку то... for(int i=0;i< dlina;i=i+2){//...сыграть мелодию... if(k==i&&millis()-Y>10){Y=millis();k++;if(pgm_read_word(¬es_times[i])!=PAUZA){keypressed = pgm_read_word(¬es_times[i]);}} if(k==i+1&&millis()-Y>pgm_read_word(¬es_times[i+1])*temp){Y=millis();k++;if(pgm_read_word(¬es_times[i])!=PAUZA){keyreleased = pgm_read_word(¬es_times[i]);}} setPWM();//#0 } if(k==dlina){k=0;}//... и повторить её снова при долгом удержании кнопки }else {k=0;}//при повторном нажатии кнопки начать исполнение сначала osnova();// вынес в отдельную функцию часть исходника автора } ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// void osnova(){ setPWM(); //#1 //find the best channel to start a new note найдите лучший канал, чтобы начать новую заметку byte nextch = 255; //first check if the key is still being played сначала проверьте, воспроизводится ли еще клавиша if (iADSR[0] > 0 and keypressed == keych[0])nextch = 0; if (iADSR[1] > 0 and keypressed == keych[1])nextch = 1; if (iADSR[2] > 0 and keypressed == keych[2])nextch = 2; if (iADSR[3] > 0 and keypressed == keych[3])nextch = 3; //then check for an empty channel затем проверьте, нет ли пустого канала if (nextch == 255) { if (iADSR[0] == 0)nextch = 0; if (iADSR[1] == 0)nextch = 1; if (iADSR[2] == 0)nextch = 2; if (iADSR[3] == 0)nextch = 3; } //otherwise use the channel with the longest playing note в противном случае используйте канал с самой длинной воспроизводимой нотой if (nextch == 255) { nextch = 0; if (tch[0] > tch[nextch])nextch = 0; if (tch[1] > tch[nextch])nextch = 1; if (tch[2] > tch[nextch])nextch = 2; if (tch[3] > tch[nextch])nextch = 3; } setPWM(); //#3 //initiate new note if needed при необходимости инициируйте новую заметку if (keypressed != nokey) { phase[nextch]=0; amp_base[nextch] = ldness[instr]; inc_base[nextch] = tone_inc[pitch0[instr]+keypressed]; ADSRa[nextch]=ADSR_a[instr]; ADSRd[nextch]=ADSR_d[instr]; ADSRs[nextch]=ADSR_s[instr]<<8; ADSRr[nextch]=ADSR_r[instr]; iADSR[nextch] = 1; FMphase[nextch]=0; FMinc_base[nextch] = ((long)inc_base[nextch]*FM_inc[instr])/256; FMa0[nextch] = FM_a2[instr]; FMda[nextch] = FM_a1[instr]-FM_a2[instr]; FMexp[nextch]=0xFFFF; FMdec[nextch]=FM_dec[instr]; keych[nextch] = keypressed; tch[nextch] = 0; } setPWM(); //#4 //stop a note if the button is released остановите заметку, если кнопка отпущена if (keyreleased != nokey) { if (keych[0] == keyreleased)iADSR[0] = 4; if (keych[1] == keyreleased)iADSR[1] = 4; if (keych[2] == keyreleased)iADSR[2] = 4; if (keych[3] == keyreleased)iADSR[3] = 4; } setPWM(); //#5 //update FM decay exponential обновление FM-спад экспоненциальный FMexp[0]-=(long)FMexp[0]*FMdec[0]>>16; FMexp[1]-=(long)FMexp[1]*FMdec[1]>>16; FMexp[2]-=(long)FMexp[2]*FMdec[2]>>16; FMexp[3]-=(long)FMexp[3]*FMdec[3]>>16; setPWM(); //#6 //adjust the ADSR envelopes отрегулируйте конверты ADSR for (byte ich = 0; ich < nch; ich++) { if (iADSR[ich] == 4) { if (envADSR[ich] <= ADSRr[ich]) { envADSR[ich] = 0; iADSR[ich] = 0; } else envADSR[ich] -= ADSRr[ich]; } if (iADSR[ich] == 2) { if (envADSR[ich] <= (ADSRs[ich] + ADSRd[ich])) { envADSR[ich] = ADSRs[ich]; iADSR[ich] = 3; } else envADSR[ich] -= ADSRd[ich]; } if (iADSR[ich] == 1) { if ((0xFFFF - envADSR[ich]) <= ADSRa[ich]) { envADSR[ich] = 0xFFFF; iADSR[ich] = 2; } else envADSR[ich] += ADSRa[ich]; } tch[ich]++; setPWM(); //#7-10 } //update the tone for channel 0 обновите звуковой сигнал для канала 0 amp[0] = (amp_base[0] * (envADSR[0] >> 8)) >> 8; inc[0] = inc_base[0]; FMamp[0] = FMa0[0] + ((long)FMda[0] * FMexp[0]>>16); FMinc[0] = FMinc_base[0]; setPWM(); //#11 //update the tone for channel 1 amp[1] = (amp_base[1] * (envADSR[1] >> 8)) >> 8; inc[1] = inc_base[1]; FMamp[1] = FMa0[1] + ((long)FMda[1] * FMexp[1]>>16); FMinc[1] = FMinc_base[1]; setPWM(); //#12 //update the tone for channel 2 amp[2] = (amp_base[2] * (envADSR[2] >> 8)) >> 8; inc[2] = inc_base[2]; FMamp[2] = FMa0[2] + ((long)FMda[2] * FMexp[2]>>16); FMinc[2] = FMinc_base[2]; setPWM(); //#13 //update the tone for channel 3 amp[3] = (amp_base[3] * (envADSR[3] >> 8)) >> 8; inc[3] = inc_base[3]; FMamp[3] = FMa0[3] + ((long)FMda[3] * FMexp[3]>>16); FMinc[3] = FMinc_base[3]; setPWM(); //#14 //update counters счетчики обновлений tch[0]++; tch[1]++; tch[2]++; tch[3]++; setPWM(); //#15 } ///////////////////////////////////////////////////////Автор пишет, что можно самому придумать инструмент по 10 параметрам. Хочется подобрать котёнка и дудочку.
Странно, почему такие возможности не реализованы штатно в Ардуино ИДЕ?
Странно, почему такие возможности не реализованы штатно в Ардуино ИДЕ?
какие?
какие?
Аудиопроцессор, видима, и многоголосая полифония. :))))
Ну, типа НОТА(С4,струна,1000); два,три знаковых инструмента. Понятно, что ресурсы МК уйдут, но с другой стороны сколько библиотек не очень дружно работают.
какие?
Аудиопроцессор, видима, и многоголосая полифония. :))))
Нет, хотелось бы баланс сохранить. У автора "многонотие" слышно в его ролике, у меня не получилось с миллис сделать. Но вот попробовать последовательность нот мелодии сыграть на разных инструментах можно.
PS я тоже оценил качество звука )))
Автор пишет, что можно самому придумать инструмент по 10 параметрам. Хочется подобрать котёнка и дудочку.
интересно, можно сделать глюкофон?
float в avr вроде 7 значащих цифр, то-есть указанная точность ПИ излишняя, знающие поправят если не так
PS я тоже оценил качество звука )))
float везде одинаковая и везде 24 двоичных разряда (один из которых не нуждается в хранении).
не скажите, в MYSQL не так:
TINYINT 0 - 255
SMALLINT 0 - 65535
MEDIUMINT 0 - 16777215
INT 0 - 4294967295
BIGINT (8 байт)
FLOAT ;-)))
PS я тоже оценил качество звука )))
Автор пишет, что можно самому придумать инструмент по 10 параметрам. Хочется подобрать котёнка и дудочку.
интересно, можно сделать глюкофон?
Вот этот не похож?
//instrument definitions #define ninstr 12 // piano xlphn guitar cmbll bell funky vibr metal violin bass trumpt harm unsigned int ldness[ninstr] = { 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}; // loudness unsigned int pitch0[ninstr] = { 0, 0, 0, 12, 24, 24, 0, 12, 24, 12, 12, 0}; // pitch of key0 unsigned int ADSR_a[ninstr] = { 4096, 8192, 8192, 8192, 4096, 512, 512, 8192, 128, 128, 256, 4096}; // attack parameter unsigned int ADSR_d[ninstr] = { 256, 256, 512, 16, 8, 16, 16, 8, 16, 16, 64, 128}; // decay parameter unsigned int ADSR_s[ninstr] = { 0, 0, 0, 0, 0, 0, 0, 0, 240, 240, 192, 0}; // sustain parameter unsigned int ADSR_r[ninstr] = { 64, 128, 32, 32, 16, 32, 32, 32, 32, 32, 64, 4096}; // release parameter unsigned int FM_inc[ninstr] = { 256, 512, 768, 400, 200, 96, 528, 244, 256, 128, 64, 64}; // FM frequency wrt pitch unsigned int FM_a1[ninstr] = { 128, 512, 512, 1024, 512, 0, 1024, 2048, 256, 256, 384, 256}; // FM amplitude start unsigned int FM_a2[ninstr] = { 64, 0, 128, 128, 128, 512, 768, 512, 128, 128, 256, 128}; // FM amplitude end unsigned int FM_dec[ninstr] = { 64, 128, 128, 128, 32, 128, 128, 128, 128, 128, 64, 128}; // FM decay //define the pitch2key mapping #define NOTE_C4 0 #define NOTE_CS4 1 #define NOTE_D4 2 #define NOTE_DS4 3 #define NOTE_E4 4 #define NOTE_F4 5 #define NOTE_FS4 6 #define NOTE_G4 7 #define NOTE_GS4 8 #define NOTE_A4 9 #define NOTE_AS4 10 #define NOTE_B4 11 #define NOTE_C5 12 #define NOTE_CS5 13 #define NOTE_D5 14 #define NOTE_DS5 15 #define NOTE_E5 16 #define NOTE_F5 17 #define NOTE_FS5 18 #define NOTE_G5 19 #define NOTE_GS5 20 #define NOTE_A5 21 #define NOTE_AS5 22 #define NOTE_B5 23 #define NOTE_C6 24 #define NOTE_CS6 25 #define NOTE_D6 26 #define NOTE_DS6 27 #define NOTE_E6 28 #define NOTE_F6 29 #define NOTE_FS6 30 #define NOTE_G6 31 #define NOTE_GS6 32 #define NOTE_A6 33 #define NOTE_AS6 34 #define NOTE_B6 35 #define PAUZA 50 #define nokey 255 #define instrkey 254 //set up array with sine values in signed 8-bit numbers const float pi = 3.14159265; char sine[256]; void setsine() { for (int i = 0; i < 256; ++i) { sine[i] = (sin(2 * 3.14159265 * (i + 0.5) / 256)) * 128; } } //setup frequencies/phase increments, starting at C3=0 to B6. (A4 is defined as 440Hz) unsigned int tone_inc[48]; void settones() { for (byte i=0; i<48; i++){ tone_inc[i]= 440.0 * pow(2.0, ( (i-21) / 12.0)) * 65536.0 / (16000000.0/512) + 0.5; } } byte instr=11;//счётчик инструмента включённого ///////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// long Y=0;//переменная хранения моментов времени int k=0;// счётчик прогресса исполнения мелодии int i=0;// const int notes_times[]PROGMEM = { // кабы не было зимы NOTE_B4,400, NOTE_B4,400, NOTE_B5,600, NOTE_FS5,200, NOTE_A5,400, NOTE_G5,400, NOTE_E5,800,PAUZA,50, NOTE_D5,400, NOTE_D5,400, NOTE_D6,600, NOTE_C6,200, NOTE_C6,400,NOTE_B5,400,PAUZA,800, NOTE_D6,400,NOTE_C6,400, NOTE_A5,400,NOTE_FS5,400, NOTE_C6,400,NOTE_B5,400,NOTE_B5,800, NOTE_B4,400, NOTE_B4,400, NOTE_B5,600, NOTE_A5,200,NOTE_A5,400, NOTE_G5,400, PAUZA,800, NOTE_B4,400, NOTE_B4,400, NOTE_B5,600, NOTE_FS5,200, NOTE_A5,400, NOTE_G5,400, NOTE_E5,800,PAUZA,50, NOTE_D5,400, NOTE_D5,400, NOTE_D6,600, NOTE_C6,200, NOTE_C6,400,NOTE_B5,400,PAUZA,400, NOTE_E6,800,NOTE_C6,400, NOTE_A5,400, NOTE_FS5,400, NOTE_C6,400,NOTE_B5,400,NOTE_B5,800,PAUZA,50, NOTE_B4,400, NOTE_B4,400, NOTE_B5,600, NOTE_A5,200,NOTE_A5,400, NOTE_G5,400, PAUZA,400, NOTE_E6,800,NOTE_C6,400, NOTE_A5,400, NOTE_FS5,400, NOTE_C6,400,NOTE_B5,400,NOTE_B5,800,PAUZA,50, NOTE_B4,400, NOTE_B4,400, NOTE_B5,600, NOTE_DS5,200,NOTE_FS5,400, NOTE_E5,400,PAUZA,5000 }; float temp=0.9;//задаём темп исполнения мелодии int dlina= sizeof(notes_times)/sizeof(notes_times[0]);//определяем длину массива ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// void setup() { //disable all inerrupts to avoid glitches отключите все прерывания, чтобы избежать сбоев // noInterrupts(); //setup the array with sine values настройте массив со значениями синуса setsine(); //setup array with tone frequency phase increments установочная матрица с приращениями фазы тональной частоты settones(); //Set a fast PWM signal on TIMER1A, 9-bit resolution, 31250Hz pinMode(9, OUTPUT);// вывод для динамика TCCR1A = 0B10000010; //9-bit fast PWM TCCR1B = 0B00001001; ///////////////////////////////////////////////////////////////////////////////// pinMode(7, INPUT);//кнопку подключить digitalWrite(7, HIGH);// включить подтягивающий резистор к ней ///////////////////////////////////////////////////////////////////////////////// } //initialize the main parameters of the pulse length setting инициализируйте основные параметры настройки длительности импульса #define nch 4 //number of channels that can produce sound simultaneously количество каналов, которые могут воспроизводить звук одновременно unsigned int phase[nch] = {0,0,0,0}; int inc[nch] = {0,0,0,0}; byte amp[nch] = {0,0,0,0}; unsigned int FMphase[nch]= {0,0,0,0}; unsigned int FMinc[nch] = {0,0,0,0}; unsigned int FMamp[nch] = {0,0,0,0}; // main function (forced inline) to update the pulse length основная функция (принудительная встроенная) для обновления длительности импульса inline void setPWM() __attribute__((always_inline)); inline void setPWM() { //wait for the timer to complete loop подождите, пока таймер завершит цикл while ((TIFR1 & 0B00000001) == 0); //Clear(!) the overflow bit by writing a 1 to it TIFR1 |= 0B00000001; //increment the phases of the FM FMphase[0] += FMinc[0]; FMphase[1] += FMinc[1]; FMphase[2] += FMinc[2]; FMphase[3] += FMinc[3]; //increment the phases of the note phase[0] += inc[0]; phase[1] += inc[1]; phase[2] += inc[2]; phase[3] += inc[3]; //calculate the output value and set pulse width for timer2 int val = sine[(phase[0]+sine[FMphase[0]>>8]*FMamp[0]) >> 8] * amp[0]; val += sine[(phase[1]+sine[FMphase[1]>>8]*FMamp[1]) >> 8] * amp[1]; val += sine[(phase[2]+sine[FMphase[2]>>8]*FMamp[2]) >> 8] * amp[2]; val += sine[(phase[3]+sine[FMphase[3]>>8]*FMamp[3]) >> 8] * amp[3]; //set the pulse length OCR1A = val/128 + 256; } //properties of each note played свойства каждой сыгранной ноты byte iADSR[nch] = {0, 0, 0, 0}; unsigned int envADSR[nch] = {0, 0, 0, 0}; unsigned int ADSRa[nch] = {0, 0, 0, 0}; unsigned int ADSRd[nch] = {0, 0, 0, 0}; unsigned int ADSRs[nch] = {0, 0, 0, 0}; unsigned int ADSRr[nch] = {0, 0, 0, 0}; byte amp_base[nch] = {0, 0, 0, 0}; unsigned int inc_base[nch] = {0, 0, 0, 0}; unsigned int FMa0[nch] = {0, 0, 0, 0}; int FMda[nch] = {0, 0, 0, 0}; unsigned int FMinc_base[nch]= {0, 0, 0, 0}; unsigned int FMdec[nch] = {0, 0, 0, 0}; unsigned int FMexp[nch] = {0, 0, 0, 0}; unsigned int FMval[nch] = {0, 0, 0, 0}; byte keych[nch] = {0, 0, 0, 0}; unsigned int tch[nch] = {0, 0, 0, 0}; byte keypressed; byte keyreleased; ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// // main loop. Duration of loop is determined by number of setPWM calls // Each setPWMcall corresponds to 512 cylcles=32mus // Tloop= 32mus * #setPWM. #setPWM=15 gives Tloop=0.48ms void loop() { keypressed = nokey; keyreleased = nokey; if(digitalRead (7)==LOW){//если нажали кнопку то... for(int i=0;i< dlina;i=i+2){//...сыграть мелодию... if(k==i&&millis()-Y>10){Y=millis();k++;if(pgm_read_word(¬es_times[i])!=PAUZA){keypressed = pgm_read_word(¬es_times[i]);}} if(k==i+1&&millis()-Y>pgm_read_word(¬es_times[i+1])*temp){Y=millis();k++;if(pgm_read_word(¬es_times[i])!=PAUZA){keyreleased = pgm_read_word(¬es_times[i]);}} setPWM();//#0 } if(k==dlina){k=0;}//... и повторить её снова при долгом удержании кнопки }else {k=0;}//при повторном нажатии кнопки начать исполнение сначала osnova();// вынес в отдельную функцию часть исходника автора } ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// void osnova(){ setPWM(); //#1 //find the best channel to start a new note найдите лучший канал, чтобы начать новую заметку byte nextch = 255; //first check if the key is still being played сначала проверьте, воспроизводится ли еще клавиша if (iADSR[0] > 0 and keypressed == keych[0])nextch = 0; if (iADSR[1] > 0 and keypressed == keych[1])nextch = 1; if (iADSR[2] > 0 and keypressed == keych[2])nextch = 2; if (iADSR[3] > 0 and keypressed == keych[3])nextch = 3; //then check for an empty channel затем проверьте, нет ли пустого канала if (nextch == 255) { if (iADSR[0] == 0)nextch = 0; if (iADSR[1] == 0)nextch = 1; if (iADSR[2] == 0)nextch = 2; if (iADSR[3] == 0)nextch = 3; } //otherwise use the channel with the longest playing note в противном случае используйте канал с самой длинной воспроизводимой нотой if (nextch == 255) { nextch = 0; if (tch[0] > tch[nextch])nextch = 0; if (tch[1] > tch[nextch])nextch = 1; if (tch[2] > tch[nextch])nextch = 2; if (tch[3] > tch[nextch])nextch = 3; } setPWM(); //#3 //initiate new note if needed при необходимости инициируйте новую заметку if (keypressed != nokey) { phase[nextch]=0; amp_base[nextch] = ldness[instr]; inc_base[nextch] = tone_inc[pitch0[instr]+keypressed]; ADSRa[nextch]=ADSR_a[instr]; ADSRd[nextch]=ADSR_d[instr]; ADSRs[nextch]=ADSR_s[instr]<<8; ADSRr[nextch]=ADSR_r[instr]; iADSR[nextch] = 1; FMphase[nextch]=0; FMinc_base[nextch] = ((long)inc_base[nextch]*FM_inc[instr])/256; FMa0[nextch] = FM_a2[instr]; FMda[nextch] = FM_a1[instr]-FM_a2[instr]; FMexp[nextch]=0xFFFF; FMdec[nextch]=FM_dec[instr]; keych[nextch] = keypressed; tch[nextch] = 0; } setPWM(); //#4 //stop a note if the button is released остановите заметку, если кнопка отпущена if (keyreleased != nokey) { if (keych[0] == keyreleased)iADSR[0] = 4; if (keych[1] == keyreleased)iADSR[1] = 4; if (keych[2] == keyreleased)iADSR[2] = 4; if (keych[3] == keyreleased)iADSR[3] = 4; } setPWM(); //#5 //update FM decay exponential обновление FM-спад экспоненциальный FMexp[0]-=(long)FMexp[0]*FMdec[0]>>16; FMexp[1]-=(long)FMexp[1]*FMdec[1]>>16; FMexp[2]-=(long)FMexp[2]*FMdec[2]>>16; FMexp[3]-=(long)FMexp[3]*FMdec[3]>>16; setPWM(); //#6 //adjust the ADSR envelopes отрегулируйте конверты ADSR for (byte ich = 0; ich < nch; ich++) { if (iADSR[ich] == 4) { if (envADSR[ich] <= ADSRr[ich]) { envADSR[ich] = 0; iADSR[ich] = 0; } else envADSR[ich] -= ADSRr[ich]; } if (iADSR[ich] == 2) { if (envADSR[ich] <= (ADSRs[ich] + ADSRd[ich])) { envADSR[ich] = ADSRs[ich]; iADSR[ich] = 3; } else envADSR[ich] -= ADSRd[ich]; } if (iADSR[ich] == 1) { if ((0xFFFF - envADSR[ich]) <= ADSRa[ich]) { envADSR[ich] = 0xFFFF; iADSR[ich] = 2; } else envADSR[ich] += ADSRa[ich]; } tch[ich]++; setPWM(); //#7-10 } //update the tone for channel 0 обновите звуковой сигнал для канала 0 amp[0] = (amp_base[0] * (envADSR[0] >> 8)) >> 8; inc[0] = inc_base[0]; FMamp[0] = FMa0[0] + ((long)FMda[0] * FMexp[0]>>16); FMinc[0] = FMinc_base[0]; setPWM(); //#11 //update the tone for channel 1 amp[1] = (amp_base[1] * (envADSR[1] >> 8)) >> 8; inc[1] = inc_base[1]; FMamp[1] = FMa0[1] + ((long)FMda[1] * FMexp[1]>>16); FMinc[1] = FMinc_base[1]; setPWM(); //#12 //update the tone for channel 2 amp[2] = (amp_base[2] * (envADSR[2] >> 8)) >> 8; inc[2] = inc_base[2]; FMamp[2] = FMa0[2] + ((long)FMda[2] * FMexp[2]>>16); FMinc[2] = FMinc_base[2]; setPWM(); //#13 //update the tone for channel 3 amp[3] = (amp_base[3] * (envADSR[3] >> 8)) >> 8; inc[3] = inc_base[3]; FMamp[3] = FMa0[3] + ((long)FMda[3] * FMexp[3]>>16); FMinc[3] = FMinc_base[3]; setPWM(); //#14 //update counters счетчики обновлений tch[0]++; tch[1]++; tch[2]++; tch[3]++; setPWM(); //#15 } ///////////////////////////////////////////////////////:-)
Сам сделал, но не дудочка.
Ну, не знаю, по моим скромным ушам - шендевр. Вот вариант пианино по вальсу "мой нежный и ласковый зверь". Даже захотелось найти модуль-усилитель под динамик для Ардуино с питанием 3-5 Вольт :-)
Автор пишет, что можно самому придумать инструмент по 10 параметрам. Хочется подобрать котёнка и дудочку.
что-то на нано не заиграл (((
А кнопку надо нажать (7 пин) и держать чтобы играла мелодия. Я на уно экспериментирую.
А кнопку надо нажать (7 пин) и держать чтобы играла мелодия. Я на уно экспериментирую.
на предыдущей работает, на этой нет, ардуино нано, компилируется и заливается без ошибок