Кабы не было зимы...

lilik
Offline
Зарегистрирован: 19.10.2017
//кабы не было зимы
#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(&notes_times[i]),pgm_read_word(&notes_times[i+1])*temp);
delay(pgm_read_word(&notes_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

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

то-есть сначала пишем неправильные ноты, а потом через float temp=0.8;//задаём темп исполнения мелодии приводим их к норме?

lilik
Offline
Зарегистрирован: 19.10.2017

Не, это темп исполнения меняется, т.е. быстро-медленно, частоты нот не меняются.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lilik пишет:

Не, это темп исполнения меняется, т.е. быстро-медленно, частоты нот не меняются.

длительность, есть только целая, половинная, четвертная, восьмая и т.д. ...андриано точно в теме, мои познания ограничиваются школьной программой

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ua6em пишет:

lilik пишет:

Не, это темп исполнения меняется, т.е. быстро-медленно, частоты нот не меняются.

длительность, есть только целая, половинная, четвертная, восьмая и т.д. ...андриано точно в теме, мои познания ограничиваются школьной программой

не умничай! ;)))

длительность ноты НИКАК не привязана к реальной длительности в секундах, а лишь определяет соотношение длительностей в произведении.

Часто играют "120 ударов в минуту" = 120 четвертных в минуту, но это на уроках в музыкалке, а не в реальности. На концерте могут играть и медленнее и, что чаще, - сильно быстрее. Особенно рок или джаз, да "дунувши" хорошо! ;))))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

четвертная - одна 250-я а не одна 200-я ...НЕ?

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Совсем НЕ )) Четвертная == 1/4 целой: ни более того ))

Длительность нот безотносительно размера и темпа - сферический конь. Как уже правильно сказали, длительность в музыке - величина относительная, к реальному времени времени звучания прикладывается через темп. Вообще, длительность нот это скорее про РИТМ (чередование нот разной длительности) :)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Rumata пишет:

Совсем НЕ )) Четвертная == 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(&notes_times[i]),pgm_read_word(&notes_times[i+1])*temp);
delay(pgm_read_word(&notes_times[i+1])*temp+20);
  }
  delay(5000);//пауза между повторами мелодии 
  } 
  

 

lilik
Offline
Зарегистрирован: 19.10.2017

Грустно звучит, у меня веселее.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

lilik пишет:

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

Зачем такие сложности?

Написать простейший конвертер из MIDI в нужный формат, а уж MIDI в И-нете как грязи...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lilik пишет:

Грустно звучит, у меня веселее.

а да, тут я накосячил, тогда темп надо 0,65

lilik
Offline
Зарегистрирован: 19.10.2017

ua6em пишет:

lilik пишет:

Грустно звучит, у меня веселее.

а да, тут я накосячил, тогда темп надо 0,65

Да вроде одинаково теперь звучат (на мой слух :-)

 

lilik
Offline
Зарегистрирован: 19.10.2017

andriano пишет:

lilik пишет:

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

Зачем такие сложности?

Написать простейший конвертер из MIDI в нужный формат, а уж MIDI в И-нете как грязи...

Интересно, попробую вникнуть, правда я совсем далёк  от формата этого. 

lilik
Offline
Зарегистрирован: 19.10.2017
//маленькой ёлочке холодно зимой
#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(&notes_times[i]),pgm_read_word(&notes_times[i+1])*temp);
delay(pgm_read_word(&notes_times[i+1])*temp+20);
  }
  delay(5000);//пауза между повторами мелодии 
  } 

Ещё мелодия.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

можно добавить микрофон и сделать викторину угадай мелодию, по хлопку, осталось добавить мелодий, памяти еще вагон

lilik
Offline
Зарегистрирован: 19.10.2017

ua6em пишет:

можно добавить микрофон и сделать викторину угадай мелодию, по хлопку, осталось добавить мелодий, памяти еще вагон

Интересный концепт, надо обдумать.

lilik
Offline
Зарегистрирован: 19.10.2017

Ещё на тему наступающего.

//рождество-"кристмас"
#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(&notes_times[i]),pgm_read_word(&notes_times[i+1])*temp);
delay(pgm_read_word(&notes_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(&notes_times[i]),pgm_read_word(&notes_times[i+1])*temp);
delay(pgm_read_word(&notes_times[i+1])*temp+10);
  }
  delay(5000);//пауза между повторами мелодии 
  } 

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Давай ещё, собираю потихоньку в общий скетч, на выходных поищу модуль с микрофоном, попробую подоткнуть...

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ua6em пишет:

Давай ещё, собираю потихоньку в общий скетч, на выходных поищу модуль с микрофоном, попробую подоткнуть...

Весело у вас тут. Андриано уже намекнул, я - повторю: чем не устраивают уже написанные коды для МИДИ декодеров на Ардуино?

https://habr.com/ru/post/454394/

Например вот! ;)) аж на тиньке85

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

гугл забанили или пользоваться не умею

lilik
Offline
Зарегистрирован: 19.10.2017

wdrakula пишет:

ua6em пишет:

Давай ещё, собираю потихоньку в общий скетч, на выходных поищу модуль с микрофоном, попробую подоткнуть...

Весело у вас тут. Андриано уже намекнул, я - повторю: чем не устраивают уже написанные коды для МИДИ декодеров на Ардуино?

https://habr.com/ru/post/454394/

Например вот! ;)) аж на тиньке85

Соображалки просто не хватает, но что низкоомный динамик можно через конденсатор это я понял.

lilik
Offline
Зарегистрирован: 19.10.2017
//в лесу родилась ёлочка
#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(&notes_times[i]),pgm_read_word(&notes_times[i+1])*temp);
delay(pgm_read_word(&notes_times[i+1])*temp+20);
  }
  delay(5000);//пауза между повторами мелодии 
  } 

 

lilik
Offline
Зарегистрирован: 19.10.2017

Колокольчики однако.

// Колокольчики-"джингл белз"
#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(&notes_times[i]),pgm_read_word(&notes_times[i+1])*temp);
delay(pgm_read_word(&notes_times[i+1])*temp+10);
  }
  delay(5000);//пауза между повторами мелодии 
  } 
  

Для сравнения взял и попробовал имеющийся в инете конвертер из "миди в скетч".

// Credit:
// Midi to Arduino Converter
//     - Andy Tran (extramaster), 2015
// https://www.extramaster.net/tools/midiToArduino/
//
// Process:
// Midi -> Midi tracks -> Note mappings -> Frequency
//
// CC0

// Set this to be the pin that your buzzer resides in. (Note that you can only have one buzzer actively using the PWM signal at a time).
int tonePin = 5;
void setup() {

}

void midi() {

    tone(tonePin, 195, 900.0);
    delay(1000.0);
    tone(tonePin, 246, 900.0);
    delay(1000.0);
    tone(tonePin, 329, 900.0);
    delay(1000.0);
    tone(tonePin, 391, 600.0);
    delay(666.666666667);
    tone(tonePin, 369, 300.0);
    delay(333.333333333);
    tone(tonePin, 246, 3600.0);
    delay(4000.0);
    tone(tonePin, 195, 900.0);
    delay(1000.0);
    tone(tonePin, 246, 900.0);
    delay(1000.0);
    tone(tonePin, 329, 900.0);
    delay(1000.0);
    tone(tonePin, 369, 300.0);
    delay(333.333333333);
    tone(tonePin, 440, 450.0);
    delay(500.0);
    tone(tonePin, 391, 150.0);
    delay(166.666666667);
    tone(tonePin, 261, 3600.0);
    delay(4000.0);
    tone(tonePin, 220, 900.0);
    delay(1000.0);
    tone(tonePin, 261, 900.0);
    delay(1000.0);
    tone(tonePin, 329, 900.0);
    delay(1000.0);
    tone(tonePin, 440, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 450.0);
    delay(500.0);
    tone(tonePin, 440, 150.0);
    delay(166.666666667);
    tone(tonePin, 523, 1800.0);
    delay(2000.0);
    tone(tonePin, 349, 1800.0);
    delay(2000.0);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 440, 450.0);
    delay(500.0);
    tone(tonePin, 415, 150.0);
    delay(166.666666667);
    tone(tonePin, 415, 900.0);
    delay(1000.0);
    tone(tonePin, 329, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 450.0);
    delay(500.0);
    tone(tonePin, 493, 150.0);
    delay(166.666666667);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 415, 300.0);
    delay(333.333333333);
    tone(tonePin, 698, 450.0);
    delay(500.0);
    tone(tonePin, 659, 150.0);
    delay(166.666666667);
    tone(tonePin, 698, 300.0);
    delay(333.333333333);
    tone(tonePin, 659, 450.0);
    delay(500.0);
    tone(tonePin, 698, 150.0);
    delay(166.666666667);
    tone(tonePin, 698, 900.0);
    delay(1000.0);
    tone(tonePin, 659, 600.0);
    delay(666.666666667);
    tone(tonePin, 82, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    tone(tonePin, 587, 300.0);
    delay(333.333333333);
    tone(tonePin, 659, 300.0);
    delay(333.333333333);
    tone(tonePin, 698, 900.0);
    delay(1000.0);
    tone(tonePin, 440, 900.0);
    delay(1000.0);
    tone(tonePin, 415, 1800.0);
    delay(2000.0);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    tone(tonePin, 587, 450.0);
    delay(500.0);
    tone(tonePin, 523, 150.0);
    delay(166.666666667);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    delay(1000.0);
    tone(tonePin, 659, 450.0);
    delay(500.0);
    tone(tonePin, 329, 450.0);
    delay(500.0);
    delay(333.333333333);
    tone(tonePin, 329, 150.0);
    delay(166.666666667);
    tone(tonePin, 261, 150.0);
    delay(166.666666667);
    tone(tonePin, 220, 150.0);
    delay(166.666666667);
    tone(tonePin, 164, 150.0);
    delay(166.666666667);
    tone(tonePin, 220, 900.0);
    delay(1000.0);
    tone(tonePin, 220, 900.0);
    delay(1000.0);
    tone(tonePin, 220, 300.0);
    delay(333.333333333);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 293, 300.0);
    delay(333.333333333);
    tone(tonePin, 329, 300.0);
    delay(333.333333333);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 440, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 600.0);
    delay(666.666666667);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    tone(tonePin, 349, 1800.0);
    delay(2000.0);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 329, 450.0);
    delay(500.0);
    tone(tonePin, 293, 150.0);
    delay(166.666666667);
    tone(tonePin, 293, 300.0);
    delay(333.333333333);
    tone(tonePin, 329, 300.0);
    delay(333.333333333);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 440, 900.0);
    delay(1000.0);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 450.0);
    delay(500.0);
    tone(tonePin, 493, 150.0);
    delay(166.666666667);
    tone(tonePin, 493, 600.0);
    delay(666.666666667);
    tone(tonePin, 246, 600.0);
    delay(666.666666667);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    tone(tonePin, 123, 600.0);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    tone(tonePin, 123, 600.0);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 440, 450.0);
    delay(500.0);
    tone(tonePin, 415, 150.0);
    delay(166.666666667);
    tone(tonePin, 415, 900.0);
    delay(1000.0);
    tone(tonePin, 329, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 450.0);
    delay(500.0);
    tone(tonePin, 493, 150.0);
    delay(166.666666667);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 415, 300.0);
    delay(333.333333333);
    tone(tonePin, 698, 450.0);
    delay(500.0);
    tone(tonePin, 659, 150.0);
    delay(166.666666667);
    tone(tonePin, 698, 300.0);
    delay(333.333333333);
    tone(tonePin, 659, 450.0);
    delay(500.0);
    tone(tonePin, 698, 150.0);
    delay(166.666666667);
    tone(tonePin, 698, 900.0);
    delay(1000.0);
    tone(tonePin, 659, 600.0);
    delay(666.666666667);
    tone(tonePin, 82, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    tone(tonePin, 587, 300.0);
    delay(333.333333333);
    tone(tonePin, 659, 300.0);
    delay(333.333333333);
    tone(tonePin, 698, 900.0);
    delay(1000.0);
    tone(tonePin, 440, 900.0);
    delay(1000.0);
    tone(tonePin, 415, 1800.0);
    delay(2000.0);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    tone(tonePin, 587, 450.0);
    delay(500.0);
    tone(tonePin, 523, 150.0);
    delay(166.666666667);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    delay(1000.0);
    tone(tonePin, 659, 450.0);
    delay(500.0);
    tone(tonePin, 329, 450.0);
    delay(500.0);
    delay(333.333333333);
    tone(tonePin, 329, 150.0);
    delay(166.666666667);
    tone(tonePin, 261, 150.0);
    delay(166.666666667);
    tone(tonePin, 220, 150.0);
    delay(166.666666667);
    tone(tonePin, 164, 150.0);
    delay(166.666666667);
    tone(tonePin, 220, 900.0);
    delay(1000.0);
    tone(tonePin, 220, 900.0);
    delay(1000.0);
    tone(tonePin, 220, 300.0);
    delay(333.333333333);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 293, 300.0);
    delay(333.333333333);
    tone(tonePin, 329, 300.0);
    delay(333.333333333);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 440, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 600.0);
    delay(666.666666667);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    tone(tonePin, 349, 1800.0);
    delay(2000.0);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 329, 450.0);
    delay(500.0);
    tone(tonePin, 293, 150.0);
    delay(166.666666667);
    tone(tonePin, 293, 300.0);
    delay(333.333333333);
    tone(tonePin, 329, 300.0);
    delay(333.333333333);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 440, 900.0);
    delay(1000.0);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 450.0);
    delay(500.0);
    tone(tonePin, 493, 150.0);
    delay(166.666666667);
    tone(tonePin, 493, 1800.0);
    delay(2000.0);
    delay(2000.0);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    delay(666.666666667);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 440, 450.0);
    delay(500.0);
    tone(tonePin, 415, 150.0);
    delay(166.666666667);
    tone(tonePin, 415, 900.0);
    delay(1000.0);
    tone(tonePin, 329, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 450.0);
    delay(500.0);
    tone(tonePin, 493, 150.0);
    delay(166.666666667);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 415, 300.0);
    delay(333.333333333);
    tone(tonePin, 698, 450.0);
    delay(500.0);
    tone(tonePin, 659, 150.0);
    delay(166.666666667);
    tone(tonePin, 698, 300.0);
    delay(333.333333333);
    tone(tonePin, 659, 450.0);
    delay(500.0);
    tone(tonePin, 698, 150.0);
    delay(166.666666667);
    tone(tonePin, 698, 900.0);
    delay(1000.0);
    tone(tonePin, 659, 600.0);
    delay(666.666666667);
    tone(tonePin, 82, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    tone(tonePin, 587, 300.0);
    delay(333.333333333);
    tone(tonePin, 659, 300.0);
    delay(333.333333333);
    tone(tonePin, 698, 900.0);
    delay(1000.0);
    tone(tonePin, 440, 900.0);
    delay(1000.0);
    tone(tonePin, 415, 1800.0);
    delay(2000.0);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 300.0);
    delay(333.333333333);
    tone(tonePin, 587, 450.0);
    delay(500.0);
    tone(tonePin, 523, 150.0);
    delay(166.666666667);
    tone(tonePin, 523, 900.0);
    delay(1000.0);
    delay(1000.0);
    tone(tonePin, 659, 450.0);
    delay(500.0);
    tone(tonePin, 329, 450.0);
    delay(500.0);
    delay(333.333333333);
    tone(tonePin, 329, 150.0);
    delay(166.666666667);
    tone(tonePin, 261, 150.0);
    delay(166.666666667);
    tone(tonePin, 220, 150.0);
    delay(166.666666667);
    tone(tonePin, 164, 150.0);
    delay(166.666666667);
    tone(tonePin, 220, 900.0);
    delay(1000.0);
    tone(tonePin, 220, 900.0);
    delay(1000.0);
    tone(tonePin, 220, 300.0);
    delay(333.333333333);
    tone(tonePin, 246, 300.0);
    delay(333.333333333);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 293, 300.0);
    delay(333.333333333);
    tone(tonePin, 329, 300.0);
    delay(333.333333333);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 440, 900.0);
    delay(1000.0);
    tone(tonePin, 493, 600.0);
    delay(666.666666667);
    tone(tonePin, 523, 300.0);
    delay(333.333333333);
    tone(tonePin, 349, 1800.0);
    delay(2000.0);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 329, 450.0);
    delay(500.0);
    tone(tonePin, 293, 150.0);
    delay(166.666666667);
    tone(tonePin, 293, 300.0);
    delay(333.333333333);
    tone(tonePin, 329, 300.0);
    delay(333.333333333);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 440, 900.0);
    delay(1000.0);
    tone(tonePin, 349, 300.0);
    delay(333.333333333);
    tone(tonePin, 523, 450.0);
    delay(500.0);
    tone(tonePin, 493, 150.0);
    delay(166.666666667);
    tone(tonePin, 415, 3600.0);
    delay(4000.0);
    tone(tonePin, 220, 300.0);
    delay(333.333333333);
    tone(tonePin, 261, 300.0);
    delay(333.333333333);
    tone(tonePin, 329, 300.0);
    delay(333.333333333);
    tone(tonePin, 1318, 900.0);
    delay(1000.0);

}

void loop() {
    // Play midi
    midi();
}


Вальс "про зверя". Нюансов много (без музыканта опять никак), ну и скетч конечно монумент - ни поправить, ни изменить.

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Float в delay не работает. А так - вполне в структуру/массив уложить можно.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lilik пишет:

wdrakula пишет:

ua6em пишет:

Давай ещё, собираю потихоньку в общий скетч, на выходных поищу модуль с микрофоном, попробую подоткнуть...

Весело у вас тут. Андриано уже намекнул, я - повторю: чем не устраивают уже написанные коды для МИДИ декодеров на Ардуино?

https://habr.com/ru/post/454394/

Например вот! ;)) аж на тиньке85

Соображалки просто не хватает, но что низкоомный динамик можно через конденсатор это я понял.

так это на Тиньке, на нано такое не сделать (((

ЗЫ и альтернативы судя по калькулятору фьюзов не особо

lilik
Offline
Зарегистрирован: 19.10.2017

sadman41 пишет:
Float в delay не работает. А так - вполне в структуру/массив уложить можно.

С помощью "блокнота нотепад"?

lilik
Offline
Зарегистрирован: 19.10.2017

ua6em пишет:

lilik пишет:

wdrakula пишет:

ua6em пишет:

Давай ещё, собираю потихоньку в общий скетч, на выходных поищу модуль с микрофоном, попробую подоткнуть...

Весело у вас тут. Андриано уже намекнул, я - повторю: чем не устраивают уже написанные коды для МИДИ декодеров на Ардуино?

https://habr.com/ru/post/454394/

Например вот! ;)) аж на тиньке85

Соображалки просто не хватает, но что низкоомный динамик можно через конденсатор это я понял.

так это на Тиньке, на нано такое не сделать (((

ЗЫ и альтернативы судя по калькулятору фьюзов не особо

Где то я видел, кажется на УНО, фрагмент мелодии без tone(), нот,длительностей. Но там как то всё хитро описано и нет готового результата для повторения простыми обывателями.

sadman41
Offline
Зарегистрирован: 19.10.2016

Если генератор/конвертор не позволяет внести в него исправления для формирования другого кода, то нотепадом... Ну, или по этому результату пройтись питоном/пёрлом. Не сильно Удобно, но на безрыбье, как грицца...

lilik
Offline
Зарегистрирован: 19.10.2017

https://www.extramaster.net/tools/midiToArduino/

Я как то не подумал о вариантах готового скетча в этом конверторе. Его внешний вид напомнил мне как я учился слайды презентаций делать :-)

sadman41
Offline
Зарегистрирован: 19.10.2016

Ежели эта штука в браузере работает, то может там JS внутрях страницы. А это натурально скриптовый язык, исходники которого подрихтовать можно.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

lilik пишет:

Где то я видел, кажется на УНО, фрагмент мелодии без tone(), нот,длительностей. Но там как то всё хитро описано и нет готового результата для повторения простыми обывателями.

Мелодия без нот и длительностей?

А Вы уверены, что это была мелодия?

lilik
Offline
Зарегистрирован: 19.10.2017

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

Но я нашёл проект попроще

https://www.instructables.com/Arduino-Synthesizer-With-FM/

поковыряюсь, может перековеркаю под извлечение нот с заданными длительностями.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

На всякий случай напомню о проекте, который я здесь как-то давно размещал: http://arduino.ru/forum/proekty/floppy-hdd-music

lilik
Offline
Зарегистрирован: 19.10.2017

Ну это концептуально-законченное изделие для ценителей эксклюзива.

А тут замысел вместо tone() получить нотоиграние голосами разных инструментов. Опять мне не ясно, почему автор не сделал библиотеку "исполнения инструментных нот", тем более с возможностью одновременной игры до 4 штук (аккорд вроде это).

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

на Arriny85, четырёхголосый тоже неплохо звучит, только на нано это не сделать, не удержался - заказал сегодня десяток тинек85, и платки к ним чуток поменьше

lilik
Offline
Зарегистрирован: 19.10.2017

Изуродовал я авторский вариант.

// Arduino polyphonic FM sound 
// * 31250 Hz sampling rate
// * 9-bit resolution
// * 4-fold polyphony (4 different tones can play simulatenously)
// * FM-synthesis with time-varying modulation amplitude
// * ADSR envelopes
// * 12 preset instruments
// Through PWM with timer1, sound is generated on pin 9
// instrument-select button on A5
// 18 sound keys on the remaining i/o pins
// by Rolf Oldeman Feb 2019 
// Licence CC BY-NC-SA 2.5 https://creativecommons.org/licenses/by-nc-sa/2.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]  = {   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,   32,   16,   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 keyC4   0
#define keyC4s  1
#define keyD4   2
#define keyD4s  3
#define keyE4   4
#define keyF4   5
#define keyF4s  6
#define keyG4   7
#define keyG4s  8
#define keyA4   9
#define keyA4s 10
#define keyB4  11
#define keyC5  12
#define keyC5s 13
#define keyD5  14
#define keyD5s 15
#define keyE5  16
#define keyF5  17

#define nokey 255
#define instrkey 254

//define the pin to key mapping for 18-key keyboard 
#define pinD0 keyC5    //Arduino pin D0
#define pinD1 keyB4    //Arduino pin D1
#define pinD2 keyA4s   //Arduino pin D2
#define pinD3 keyA4    //Arduino pin D3
#define pinD4 keyG4s   //Arduino pin D4
#define pinD5 keyG4    //Arduino pin D5
#define pinD6 keyF4s   //Arduino pin D6
#define pinD7 keyF4    //Arduino pin D7
#define pinB0 keyE4    //Arduino pin D8
#define pinB1 nokey    //Arduino pin D9  used for audio out
#define pinB2 keyD4s   //Arduino pin D10
#define pinB3 keyD4    //Arduino pin D11 
#define pinB4 keyC4s   //Arduino pin D12
#define pinB5 keyC4    //Arduino pin D13
#define pinB6 nokey    //Arduino pin D14 inexistent
#define pinB7 nokey    //Arduino pin D15 inexistent
#define pinC0 keyC5s   //Arduino pin A0
#define pinC1 keyD5    //Arduino pin A1
#define pinC2 keyD5s   //Arduino pin A2
#define pinC3 keyE5    //Arduino pin A2
#define pinC4 keyF5    //Arduino pin A3
#define pinC5 instrkey //Arduino pin A4
#define pinC6 nokey    //Arduino pin A5 inexistent
#define pinC7 nokey    //Arduino pin A6 inexistent


//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 butstatD=0;
byte butstatB=0;
byte butstatC=0;
byte prevbutstatD=0;
byte prevbutstatB=0;
byte prevbutstatC=0;

byte instr=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;

  //setup pins for input with pull-up 
  if(pinD0 != nokey){DDRD &=~(1<<0);PORTD |=(1<<0);}; 
  if(pinD1 != nokey){DDRD &=~(1<<1);PORTD |=(1<<1);}; 
  if(pinD2 != nokey){DDRD &=~(1<<2);PORTD |=(1<<2);}; 
  if(pinD3 != nokey){DDRD &=~(1<<3);PORTD |=(1<<3);}; 
  if(pinD4 != nokey){DDRD &=~(1<<4);PORTD |=(1<<4);}; 
  if(pinD5 != nokey){DDRD &=~(1<<5);PORTD |=(1<<5);}; 
  if(pinD6 != nokey){DDRD &=~(1<<6);PORTD |=(1<<6);}; 
  if(pinD7 != nokey){DDRD &=~(1<<7);PORTD |=(1<<7);}; 
  if(pinB0 != nokey){DDRB &=~(1<<0);PORTB |=(1<<0);}; 
  if(pinB1 != nokey){DDRB &=~(1<<1);PORTB |=(1<<1);}; 
  if(pinB2 != nokey){DDRB &=~(1<<2);PORTB |=(1<<2);}; 
  if(pinB3 != nokey){DDRB &=~(1<<3);PORTB |=(1<<3);}; 
  if(pinB4 != nokey){DDRB &=~(1<<4);PORTB |=(1<<4);}; 
  if(pinB5 != nokey){DDRB &=~(1<<5);PORTB |=(1<<5);}; 
  if(pinB6 != nokey){DDRB &=~(1<<6);PORTB |=(1<<6);}; 
  if(pinB7 != nokey){DDRB &=~(1<<7);PORTB |=(1<<7);}; 
  if(pinC0 != nokey){DDRC &=~(1<<0);PORTC |=(1<<0);}; 
  if(pinC1 != nokey){DDRC &=~(1<<1);PORTC |=(1<<1);}; 
  if(pinC2 != nokey){DDRC &=~(1<<2);PORTC |=(1<<2);}; 
  if(pinC3 != nokey){DDRC &=~(1<<3);PORTC |=(1<<3);}; 
  if(pinC4 != nokey){DDRC &=~(1<<4);PORTC |=(1<<4);}; 
  if(pinC5 != nokey){DDRC &=~(1<<5);PORTC |=(1<<5);}; 
  if(pinC6 != nokey){DDRC &=~(1<<6);PORTC |=(1<<6);}; 
  if(pinC7 != nokey){DDRC &=~(1<<7);PORTC |=(1<<7);}; 
   
  //store button setting at startup
  butstatD = PIND;
  butstatB = PINB;
  butstatC = PINC;
}


//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}; 


// 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() {

  //read and interpret input buttons
  prevbutstatD = butstatD;
  prevbutstatB = butstatB;
  prevbutstatC = butstatC;
  butstatD = PIND;
  butstatB = PINB;
  butstatC = PINC;
  byte keypressed = nokey;
  byte keyreleased = nokey;
  if(butstatD!=prevbutstatD){
    if ( pinD0!=nokey and (butstatD & (1<<0)) == 0 and (prevbutstatD & (1<<0)) >  0 ) keypressed  = pinD0;
    if ( pinD0!=nokey and (butstatD & (1<<0)) >  0 and (prevbutstatD & (1<<0)) == 0 ) keyreleased = pinD0;
    if ( pinD1!=nokey and (butstatD & (1<<1)) == 0 and (prevbutstatD & (1<<1)) >  0 ) keypressed  = pinD1;
    if ( pinD1!=nokey and (butstatD & (1<<1)) >  0 and (prevbutstatD & (1<<1)) == 0 ) keyreleased = pinD1;
    if ( pinD2!=nokey and (butstatD & (1<<2)) == 0 and (prevbutstatD & (1<<2)) >  0 ) keypressed  = pinD2;
    if ( pinD2!=nokey and (butstatD & (1<<2)) >  0 and (prevbutstatD & (1<<2)) == 0 ) keyreleased = pinD2;
    if ( pinD3!=nokey and (butstatD & (1<<3)) == 0 and (prevbutstatD & (1<<3)) >  0 ) keypressed  = pinD3;
    if ( pinD3!=nokey and (butstatD & (1<<3)) >  0 and (prevbutstatD & (1<<3)) == 0 ) keyreleased = pinD3;
    if ( pinD4!=nokey and (butstatD & (1<<4)) == 0 and (prevbutstatD & (1<<4)) >  0 ) keypressed  = pinD4;
    if ( pinD4!=nokey and (butstatD & (1<<4)) >  0 and (prevbutstatD & (1<<4)) == 0 ) keyreleased = pinD4;
    if ( pinD5!=nokey and (butstatD & (1<<5)) == 0 and (prevbutstatD & (1<<5)) >  0 ) keypressed  = pinD5;
    if ( pinD5!=nokey and (butstatD & (1<<5)) >  0 and (prevbutstatD & (1<<5)) == 0 ) keyreleased = pinD5;
    if ( pinD6!=nokey and (butstatD & (1<<6)) == 0 and (prevbutstatD & (1<<6)) >  0 ) keypressed  = pinD6;
    if ( pinD6!=nokey and (butstatD & (1<<6)) >  0 and (prevbutstatD & (1<<6)) == 0 ) keyreleased = pinD6;
    if ( pinD7!=nokey and (butstatD & (1<<7)) == 0 and (prevbutstatD & (1<<7)) >  0 ) keypressed  = pinD7;
    if ( pinD7!=nokey and (butstatD & (1<<7)) >  0 and (prevbutstatD & (1<<7)) == 0 ) keyreleased = pinD7;
  }
  if(butstatB!=prevbutstatB){
    if ( pinB0!=nokey and (butstatB & (1<<0)) == 0 and (prevbutstatB & (1<<0)) >  0 ) keypressed  = pinB0;
    if ( pinB0!=nokey and (butstatB & (1<<0)) >  0 and (prevbutstatB & (1<<0)) == 0 ) keyreleased = pinB0;
    if ( pinB1!=nokey and (butstatB & (1<<1)) == 0 and (prevbutstatB & (1<<1)) >  0 ) keypressed  = pinB1;
    if ( pinB1!=nokey and (butstatB & (1<<1)) >  0 and (prevbutstatB & (1<<1)) == 0 ) keyreleased = pinB1;
    if ( pinB2!=nokey and (butstatB & (1<<2)) == 0 and (prevbutstatB & (1<<2)) >  0 ) keypressed  = pinB2;
    if ( pinB2!=nokey and (butstatB & (1<<2)) >  0 and (prevbutstatB & (1<<2)) == 0 ) keyreleased = pinB2;
    if ( pinB3!=nokey and (butstatB & (1<<3)) == 0 and (prevbutstatB & (1<<3)) >  0 ) keypressed  = pinB3;
    if ( pinB3!=nokey and (butstatB & (1<<3)) >  0 and (prevbutstatB & (1<<3)) == 0 ) keyreleased = pinB3;
    if ( pinB4!=nokey and (butstatB & (1<<4)) == 0 and (prevbutstatB & (1<<4)) >  0 ) keypressed  = pinB4;
    if ( pinB4!=nokey and (butstatB & (1<<4)) >  0 and (prevbutstatB & (1<<4)) == 0 ) keyreleased = pinB4;
    if ( pinB5!=nokey and (butstatB & (1<<5)) == 0 and (prevbutstatB & (1<<5)) >  0 ) keypressed  = pinB5;
    if ( pinB5!=nokey and (butstatB & (1<<5)) >  0 and (prevbutstatB & (1<<5)) == 0 ) keyreleased = pinB5;
    if ( pinB6!=nokey and (butstatB & (1<<6)) == 0 and (prevbutstatB & (1<<6)) >  0 ) keypressed  = pinB6;
    if ( pinB6!=nokey and (butstatB & (1<<6)) >  0 and (prevbutstatB & (1<<6)) == 0 ) keyreleased = pinB6;
    if ( pinB7!=nokey and (butstatB & (1<<7)) == 0 and (prevbutstatB & (1<<7)) >  0 ) keypressed  = pinB7;
    if ( pinB7!=nokey and (butstatB & (1<<7)) >  0 and (prevbutstatB & (1<<7)) == 0 ) keyreleased = pinB7;
  }
  if(butstatC!=prevbutstatC){
    if ( pinC0!=nokey and (butstatC & (1<<0)) == 0 and (prevbutstatC & (1<<0)) >  0 ) keypressed  = pinC0;
    if ( pinC0!=nokey and (butstatC & (1<<0)) >  0 and (prevbutstatC & (1<<0)) == 0 ) keyreleased = pinC0;
    if ( pinC1!=nokey and (butstatC & (1<<1)) == 0 and (prevbutstatC & (1<<1)) >  0 ) keypressed  = pinC1;
    if ( pinC1!=nokey and (butstatC & (1<<1)) >  0 and (prevbutstatC & (1<<1)) == 0 ) keyreleased = pinC1;
    if ( pinC2!=nokey and (butstatC & (1<<2)) == 0 and (prevbutstatC & (1<<2)) >  0 ) keypressed  = pinC2;
    if ( pinC2!=nokey and (butstatC & (1<<2)) >  0 and (prevbutstatC & (1<<2)) == 0 ) keyreleased = pinC2;
    if ( pinC3!=nokey and (butstatC & (1<<3)) == 0 and (prevbutstatC & (1<<3)) >  0 ) keypressed  = pinC3;
    if ( pinC3!=nokey and (butstatC & (1<<3)) >  0 and (prevbutstatC & (1<<3)) == 0 ) keyreleased = pinC3;
    if ( pinC4!=nokey and (butstatC & (1<<4)) == 0 and (prevbutstatC & (1<<4)) >  0 ) keypressed  = pinC4;
    if ( pinC4!=nokey and (butstatC & (1<<4)) >  0 and (prevbutstatC & (1<<4)) == 0 ) keyreleased = pinC4;
    if ( pinC5!=nokey and (butstatC & (1<<5)) == 0 and (prevbutstatC & (1<<5)) >  0 ) keypressed  = pinC5;
    if ( pinC5!=nokey and (butstatC & (1<<5)) >  0 and (prevbutstatC & (1<<5)) == 0 ) keyreleased = pinC5;
    if ( pinC6!=nokey and (butstatC & (1<<6)) == 0 and (prevbutstatC & (1<<6)) >  0 ) keypressed  = pinC6;
    if ( pinC6!=nokey and (butstatC & (1<<6)) >  0 and (prevbutstatC & (1<<6)) == 0 ) keyreleased = pinC6;
    if ( pinC7!=nokey and (butstatC & (1<<7)) == 0 and (prevbutstatC & (1<<7)) >  0 ) keypressed  = pinC7;
    if ( pinC7!=nokey and (butstatC & (1<<7)) >  0 and (prevbutstatC & (1<<7)) == 0 ) keyreleased = pinC7;
  }
  
  setPWM(); //#1

  //change instrument if instrument select button is pressed
  if ( keypressed==instrkey) {
    instr++;
    if (instr>=ninstr) instr=0;
    keypressed=keyA4;
  }
  if (keyreleased==instrkey) keyreleased=keyA4;
  
  setPWM(); //#2

  //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 
  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
  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
  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

}

Сделал так.

// Arduino polyphonic FM sound 
// * 31250 Hz sampling rate
// * 9-bit resolution
// * 4-fold polyphony (4 different tones can play simulatenously)
// * FM-synthesis with time-varying modulation amplitude
// * ADSR envelopes
// * 12 preset instruments
// Through PWM with timer1, sound is generated on pin 9
// instrument-select button on A5
// 18 sound keys on the remaining i/o pins
// by Rolf Oldeman Feb 2019 
// Licence CC BY-NC-SA 2.5 https://creativecommons.org/licenses/by-nc-sa/2.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]  = {   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,   32,   16,   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 keyC4   0
#define keyC4s  1
#define keyD4   2
#define keyD4s  3
#define keyE4   4
#define keyF4   5
#define keyF4s  6
#define keyG4   7
#define keyG4s  8
#define keyA4   9
#define keyA4s 10
#define keyB4  11
#define keyC5  12
#define keyC5s 13
#define keyD5  14
#define keyD5s 15
#define keyE5  16
#define keyF5  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=0;//счётчик инструмента включённого
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
long Y=0;//переменная хранения моментов времени
int k=0;// счётчик прогресса исполнения мелодии
const int notes_times[]PROGMEM = {//массив нот и длительностей
keyC4,1000,PAUZA,2000,keyC4s,1000,keyD4,1000,keyD4s,1000,keyE4,1000,keyF4,1000,keyF4s,1000,
keyG4,1000,keyG4s,1000,keyA4,1000,keyA4s,1000,keyB4,1000,
keyC5,1000,keyC5s,1000,keyD5,1000,keyD5s,1000,keyE5,1000,keyF5,1000  
};
float temp=0.8;//задаём темп исполнения мелодии
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;

  
}


//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;
 for(int i=0;i< dlina;i=i+2){//сыграть мелодию
 if(k==i&&millis()-Y>10){Y=millis();k++;if(pgm_read_word(&notes_times[i])!=PAUZA){keypressed = pgm_read_word(&notes_times[i]);}}
 if(k==i+1&&millis()-Y>pgm_read_word(&notes_times[i+1])){Y=millis();k++;if(pgm_read_word(&notes_times[i])!=PAUZA){keyreleased = pgm_read_word(&notes_times[i]);}}
}
 if(k==dlina){k=0;instr++;if (instr>=ninstr) instr=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
 
}
///////////////////////////////////////////////////////

В массив вбиваем ноты, длительности, ставим паузы если надо и циклично играем на 12 инструментах мелодию в один голос (для примера вбил все 18 нот по секунде на каждую). Одновременное звучание нескольких нот не знаю как сделать, исполнение мелодии на нескольких инструментах - тем более. Автор запретил прерывания, пришлось запрет снять для работы миллис.

Из исходника удалил лишнее, что смог, как убрать лишние каналы (свести от 4 до 1) не знаю :-)

 

lilik
Offline
Зарегистрирован: 19.10.2017
//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(&notes_times[i])!=PAUZA){keypressed = pgm_read_word(&notes_times[i]);}}
 if(k==i+1&&millis()-Y>pgm_read_word(&notes_times[i+1])*temp){Y=millis();k++;if(pgm_read_word(&notes_times[i])!=PAUZA){keyreleased = pgm_read_word(&notes_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
 
}
///////////////////////////////////////////////////////

Подключил колонки от ПК, сделал вариант для исполнения по кнопке. Звучит потрясающе (взял ксилофон)! Автор молодец!

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

float в avr вроде 7 значащих цифр, то-есть указанная точность ПИ излишняя, знающие поправят если не так

PS я тоже оценил качество звука )))

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

float в avr вроде 7 значащих цифр, то-есть указанная точность ПИ излишняя, знающие поправят если не так

PS я тоже оценил качество звука )))

float везде одинаковая и везде 24 двоичных разряда (один из которых не нуждается в хранении).

lilik
Offline
Зарегистрирован: 19.10.2017

ua6em пишет:

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(&notes_times[i])!=PAUZA){keypressed = pgm_read_word(&notes_times[i]);}}
 if(k==i+1&&millis()-Y>pgm_read_word(&notes_times[i+1])*temp){Y=millis();k++;if(pgm_read_word(&notes_times[i])!=PAUZA){keyreleased = pgm_read_word(&notes_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 параметрам. Хочется подобрать котёнка и дудочку.

lilik
Offline
Зарегистрирован: 19.10.2017

Странно, почему такие возможности не реализованы штатно в Ардуино ИДЕ?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

lilik пишет:

Странно, почему такие возможности не реализованы штатно в Ардуино ИДЕ?

какие?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

wdrakula пишет:

какие?

Аудиопроцессор, видима, и многоголосая полифония. :))))

lilik
Offline
Зарегистрирован: 19.10.2017

Ну, типа НОТА(С4,струна,1000); два,три знаковых инструмента. Понятно, что ресурсы МК уйдут, но с другой стороны сколько библиотек не очень дружно работают. 

lilik
Offline
Зарегистрирован: 19.10.2017

DetSimen пишет:

wdrakula пишет:

какие?

Аудиопроцессор, видима, и многоголосая полифония. :))))

Нет, хотелось бы баланс сохранить. У автора "многонотие" слышно в его ролике, у меня не получилось с миллис сделать. Но вот попробовать последовательность нот мелодии сыграть на разных инструментах можно.   

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lilik пишет:

ua6em пишет:

PS я тоже оценил качество звука )))

Автор пишет, что можно самому придумать инструмент по 10 параметрам. Хочется подобрать котёнка и дудочку.

интересно, можно сделать глюкофон?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

ua6em пишет:

float в avr вроде 7 значащих цифр, то-есть указанная точность ПИ излишняя, знающие поправят если не так

PS я тоже оценил качество звука )))

float везде одинаковая и везде 24 двоичных разряда (один из которых не нуждается в хранении).

не скажите, в MYSQL не так:
TINYINT      0 - 255
SMALLINT   0 - 65535
MEDIUMINT 0 - 16777215
INT            0 - 4294967295
BIGINT      (8 байт)
FLOAT       ;-)))
 

lilik
Offline
Зарегистрирован: 19.10.2017

ua6em пишет:

lilik пишет:

ua6em пишет:

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(&notes_times[i])!=PAUZA){keypressed = pgm_read_word(&notes_times[i]);}}
 if(k==i+1&&millis()-Y>pgm_read_word(&notes_times[i+1])*temp){Y=millis();k++;if(pgm_read_word(&notes_times[i])!=PAUZA){keyreleased = pgm_read_word(&notes_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
 
}
///////////////////////////////////////////////////////

:-)

Сам сделал, но не дудочка.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lilik пишет:

Ну, не знаю, по моим скромным ушам - шендевр. Вот вариант пианино по вальсу "мой нежный и ласковый зверь". Даже захотелось найти модуль-усилитель под динамик для Ардуино с питанием 3-5 Вольт :-) 



Автор пишет, что можно самому придумать инструмент по 10 параметрам. Хочется подобрать котёнка и дудочку.

что-то на нано не заиграл (((

lilik
Offline
Зарегистрирован: 19.10.2017

А кнопку надо нажать (7 пин) и держать чтобы играла мелодия. Я на уно экспериментирую.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lilik пишет:

А кнопку надо нажать (7 пин) и держать чтобы играла мелодия. Я на уно экспериментирую.

на предыдущей работает, на этой нет, ардуино нано, компилируется и заливается без ошибок