From 98bf10106098f50b5168f69067882b75982da1d7 Mon Sep 17 00:00:00 2001 From: RedGuy Date: Tue, 20 Jun 2023 17:06:51 +0300 Subject: [PATCH] Music Box --- Music Box/Music_box.ino | 67 ++++++++++ Music Box/QB.h | 262 ++++++++++++++++++++++++++++++++++++++++ Music Box/QBmusics.h | 10 ++ Music Box/musics.h | 4 + 4 files changed, 343 insertions(+) create mode 100644 Music Box/Music_box.ino create mode 100644 Music Box/QB.h create mode 100644 Music Box/QBmusics.h create mode 100644 Music Box/musics.h diff --git a/Music Box/Music_box.ino b/Music Box/Music_box.ino new file mode 100644 index 0000000..8c7beea --- /dev/null +++ b/Music Box/Music_box.ino @@ -0,0 +1,67 @@ +#define SizeRegisterModules 20 +#include "musics.h" +#include "QB.h" +#include "QBmusics.h" + +int IDarg = 0; +String ParsedCommand[SizeRegisterModules]; + +int adding; + +void ShowError(String errorMessage){ + Serial.println("Error: \n "+errorMessage); +} + +void ShowMessage(String type, String Message){ + Serial.println("["+type+"] "+Message); +} + +char getCharCommand(){ + if (Serial.available() > 0) { + char cmdraw = Serial.read(); + if (cmdraw > 0) return cmdraw; + } + return '?'; +} + +void mainL(String *args){ + if(args[0] == "play") { + String prom = args[2]; + int data = prom.toInt(); + if(args[2] == "") { + Serial.println("Введите пин!"); + return 1; + } + if(args[1] == "mario") { + mario(data,false); + } + if(args[1] == "Bells") { + bell(data,false); + } + } + } +} + +void setup() { + Serial.begin(9600); + ShowMessage("Note","Type ';' to indicate the end of command, and then press 'Enter'"); + Serial.print("\n \n \n \n>"); +} + +void loop() { + char CharCommand = getCharCommand(); + if (CharCommand != ';' && CharCommand != '?'){ + Serial.print(CharCommand); + if (CharCommand == ' '){ + IDarg++; + }else{ + ParsedCommand[IDarg] += CharCommand; + } + }else if(CharCommand == ';'){ + Serial.println(" "); + mainL(ParsedCommand); + IDarg = 0; + for (int i = 0;i<=20;i++) {ParsedCommand[i]="";} + Serial.print(">"); + } +} diff --git a/Music Box/QB.h b/Music Box/QB.h new file mode 100644 index 0000000..3a42a50 --- /dev/null +++ b/Music Box/QB.h @@ -0,0 +1,262 @@ +#include "QBmusics.h" +int freq[7][12] = { + {65, 69, 73, 78, 82, 87, 92, 98, 104, 110, 117, 123}, //0 = Большая октава + {131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247}, //1 = Малая октава + {262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494}, //2 = 1-я октава + {523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988}, //3 = 2-я октава + {1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976}, //4 = 3-я октава + {2093, 2218, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951}, //5 = 4-я октава + {4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902}, //6 = 5-я октава +}; +int extractNumber(int& myNumber, char Muz[], int& curPosition) +{ + int digitsNumber=0; + int curDigit=0; + myNumber=0; + do + { + if ((Muz[curPosition]> 47) && (Muz[curPosition]<58)) // Коды ASCII цифр '0' == 48 , "9' == 57 + { + curDigit=Muz[curPosition]-48; + digitsNumber++; + myNumber=myNumber*10+curDigit; + } + else + { + return digitsNumber; + } + curPosition++; + }while(Muz[curPosition]!= '\0'); + return digitsNumber; +} + +int pointsCount(char Muz[], int& curPosition) +{ + int pointsNumber=0; + do + { + if (Muz[curPosition]== '.') + { + pointsNumber++; + } + else + { + return pointsNumber; + } + curPosition++; + }while(Muz[curPosition]!= '\0'); + return pointsNumber; +} + +void Qb_PLAY(int SoundPin,char Muz[]) +{ + static int generalOktava; + int oktava; + static int tempo=120; // Задание темпа или четвертных нот, которые исполняются в минуту. n от 32 до 255. По умолчанию 120 + int Nota=0; + int curPosition, curNota4; + unsigned long currentNotaPauseDuration; + unsigned long currentNotaDuration; + unsigned long pauseDuration; + int takt=240000/tempo; + bool isNota; + bool isPause; + int pointsNum=0; + float generalNotaMultipl=0.875; + static float NotaLong; + float curMultipl; + float tempFlo; + float curPause; + unsigned long tempLong; + int i=0; + do + { + isNota=false; + isPause=false; + oktava=generalOktava; + switch(Muz[i]){ + case '\0':{ + return; + } + break; + case 'C':{ + Nota=0; + isNota=true; + } + break; + case 'D':{ + Nota=2; + isNota=true; + } + break; + case 'E':{ + Nota=4; + isNota=true; + } + break; + case 'F':{ + Nota=5; + isNota=true; + } + break; + case 'G':{ + Nota=7; + isNota=true; + } + break; + case 'A':{ + Nota=9; + isNota=true; + } + break; + case 'B':{ + Nota=11; + isNota=true; + } + break; + case 'N':{// Nнота Играет определенную ноту (0 - 84) в диапазоне семи октав (0 - пауза). + curPosition=i+1; + if (extractNumber(curNota4, Muz, curPosition)){ + i=curPosition-1; + if (curNota4){ + curNota4--; + oktava=curNota4 / 12; + Nota=curNota4 % 12; + isNota=true; + } + else{ + isPause=true; + } + } + } + break; + case 'O':{ //Oоктава Задает текущую октаву (0 - 6). + curPosition=i+1; + if (extractNumber(oktava, Muz, curPosition)){ + i=curPosition-1; + generalOktava=oktava; + } + } + break; + case '>':{ + generalOktava++; + } + break; + case '<':{ + generalOktava--; + } + break; + case 'M':{ + switch(Muz[i+1]){ + case 'N':{ //MN Нормаль. Каждая нота звучит 7/8 времени, заданного в команде L + generalNotaMultipl=0.875; // =7/8 + i++; + } + break; + case 'L':{ //ML Легато. Каждая нота звучит полный интервал времени, заданного в команде L + generalNotaMultipl=1.0; + i++; + } + break; + case 'S':{ //MS Стаккато. Каждая нота звучит 3/4 времени, заданного в команде L + generalNotaMultipl=0.75; // =3/4 + i++; + } + break; + case 'F':{ //MF Режим непосредственного исполнения. Т.е. на время проигрывания ноты программа приостанавливается. Используется по умолчанию + i++; //Сдвигаем точку чтения и ничего не делаем. + } + break; + + case 'B':{ //MB проигрывние в буффер + i++; //Сдвигаем точку чтения и ничего не делаем. + } + break; + } + } + break; + case 'L':{ //Lразмер Задает длительность каждой ноты (1 - 64). L1 - целая нота, L2 - 1/2 ноты и т.д. + curPosition=i+1; + if (extractNumber(curNota4, Muz, curPosition)){ + i=curPosition-1; + tempFlo=float(curNota4); + NotaLong=1/tempFlo; + } + } + break; + case 'T':{ //Tтемп Задает темп исполнения в четвертях в минуту (32-255).По умолчанию 120 + curPosition=i+1; + if (extractNumber(tempo, Muz, curPosition)){ + i=curPosition-1; + takt=240000/tempo; // миллисекунд на 1 целую ноту. 240000= 60 сек * 1000 мсек/сек *4 четвертей в ноте + } + } + break; + case 'P':{ //Pпауза Задает паузу (1 - 64). P1 - пауза в целую ноту, P2 - пауза в 1/2 ноты и т.д. + curPosition=i+1; + if (extractNumber(curNota4, Muz, curPosition)){ + tempFlo=float(curNota4); + curPause=1/tempFlo; + i=curPosition-1; + isPause=true; + } + } + break; + case ' ':{ //Есть в некоторых текстах. Вероятно это пауза длительностью в текущую ноту + curPause= NotaLong; + isPause=true; + } + break; + } + if (isNota){ + switch(Muz[i+1]){ + case '#':{ // диез + Nota++; + i++; + } + break; + case '+':{ // диез + Nota++; + i++; + } + break; + case '-':{ // бемоль + Nota--; + i++; + } + break; + } + curPosition=i+1; + if (extractNumber(curNota4, Muz, curPosition)){ + currentNotaDuration=takt/curNota4; + i=curPosition-1; + } + } + if (oktava<0) oktava=0; + if (oktava>6) oktava=6; + if (isNota || isPause){ + curPosition=i+1; + pointsNum=pointsCount(Muz, curPosition); + if (pointsNum) i=curPosition-1; + curMultipl=1.0; + for (int j=1; j<=pointsNum; j++) { + curMultipl= curMultipl * 1.5; + } + currentNotaPauseDuration=(takt*NotaLong); + } + if (isNota){ + curMultipl=curMultipl*generalNotaMultipl; + currentNotaDuration= (currentNotaPauseDuration*curMultipl); + if (Nota<0) Nota=0; + if (Nota>11) Nota=11; + tempLong= freq[oktava][Nota]; + tone(SoundPin,tempLong,currentNotaDuration); + delay(currentNotaPauseDuration); + } + if (isPause){ + pauseDuration=takt*curPause*curMultipl; + delay(pauseDuration); + } + i++; + } while (Muz[i]!= '\0'); +} diff --git a/Music Box/QBmusics.h b/Music Box/QBmusics.h new file mode 100644 index 0000000..4d3f234 --- /dev/null +++ b/Music Box/QBmusics.h @@ -0,0 +1,10 @@ +#include "QB.h" +#include "musics.h" +void bell(int pin, boolean next){ + Qb_PLAY (pin,"MNT255L4O2DBAGL2D.L8DDL4DBAGL2E.L4EE>CDDCCDDDDEDCDCCC.L8CL4CDL4DCCC.L8CL4CD"); + Qb_PLAY (pin,"DC