// debug #define DEBUG #ifdef DEBUG #define db(t,x) if(t) { Serial.print(x); } #define dbln(t,x) if(t) { Serial.println(x); } #else #define db(t,x) // define empty, so macro does nothing #define dbln(t,x) #endif boolean debug = true; boolean debugt = true; // call: db(debug,"blabla"); dbln(debug,"blabla"); //________________________________________________________________________________ int beats = 100; int vol = 127; int speakerOut = 9; // pin D9 is PWM, on Arduino MICRO also A9 // get some basics for Notes. float Fs[89]; // freq array 0, piano key 1 .. 88 int Tf[89]; // Ontime for square wave String Nname[13]={" ","C_","C#","D_","D#","E_","F_","F#","G_","G#","A_","A#","B_"}; String Fsname[90]; // Notelist from Note name + oktave // MIDI // kll 30.01.2015 incl. MIDI ( 3 unreadable bytes ) to USB ( for RPI PYTHON MIDI device to play parallel or without arduino speaker ) #define MIDI // uncomment = enable byte Mbasis = 127; byte Mchannel = 1; byte MON =16; byte Mpkey = 20; // midi note = piano note + 20 //________________________________________________________________________________ void Notelist() { // calc 88 keys of piano // 1 = A0 == 27.5Hz == MIDI 21 int oktave=0; int Nnamep=9; // 9 + 1 = 10 --> Nname[10] = A String temp=""; Fsname[0]="pau"; Fs[0]=20000; Tf[0]=25; // init for (int N=1; N < 89; N++) { Nnamep = Nnamep+1; if ( Nnamep == 13 ) { Nnamep = 1; oktave = oktave+1; } // next oktave Fsname[N] = Nname[Nnamep]; //db(debug,"Nnamep "); db(debug,Nnamep); db(debug," ");dbln(debug,Fsname[N]); Fsname[N].concat(char(48+oktave)); float Freq = 440.0 * pow(2,((N-49)/12.0)); Fs[N]=Freq; // fill array float Halfwave=500000.0/Freq; // like ON time Tf[N] = int(Halfwave); // fill array db(debug,"N "); db(debug,N); if ( N <10 ) {db(debugt," "); } db(debug," F "); if (Fs[N] < 100.0 ) {db(debugt," "); } if (Fs[N] < 1000.0 ) {db(debugt," "); } db(debug,Fs[N]); db(debug," ");db(debug,Fsname[N]); db(debug," onT "); dbln(debug,Tf[N]); } } //________________________________________________________________________________ void tone(int pnote,int plong=1,int pvol =127) { int delayus = Tf[pnote]; digitalWrite(speakerOut, LOW); if ( delayus <=25 ){ delayus =25; } // 20.000 waves / sec = 20kHz // cutoff for usec problem and int limit int waves= int(1.0*plong*Fs[pnote]*60.0/beats); // needed waves to fill time must force float calc int volon = int(delayus * ( 1.0*pvol/127.0 )); int voloff = int(delayus * ( 2.0 - 1.0*pvol/127.0)); // pvol 0 .. 127 //not work too well, what it does? // 1111000011110000 to 1100000011000000 == half ONTIME but same freq db(debugt," Pkey: ");db(debugt,pnote); if ( pnote <10 ) {db(debugt," "); } db(debugt," Note: ");db(debugt,Fsname[pnote]); db(debugt," long: ");db(debugt,plong); if ( pnote > 0 ) { //db(debugt," ONtime: ");db(debugt,delayus); db(debugt," waves: ");db(debugt,waves); db(debugt," Hz: ");db(debugt,Fs[pnote]); db(debugt," onT: "); db(debugt,volon); db(debugt," offT: ");db(debugt,voloff); db(debugt," vol: ");db(debugt,pvol); } dbln(debugt,""); if ( pnote > 0 ) MIDImessage(byte(Mbasis + Mchannel + MON),byte(pnote+Mpkey),byte(pvol)); //note ON for (int i=0 ; i < waves; i++) { if ( delayus > 25) { digitalWrite(speakerOut, HIGH); delayMicroseconds(volon); digitalWrite(speakerOut, LOW); delayMicroseconds(voloff); } else {delayMicroseconds(2*delayus);} // >20kHz not play / only pause digitalWrite(speakerOut, LOW); } if ( pnote > 0 ) MIDImessage(byte(Mbasis + Mchannel),byte(pnote+Mpkey),byte(pvol)); // note OFF } //________________________________________________________________________________ // send MIDI message ( USB ) void MIDImessage(byte Mcommand, byte Mnote, byte Mvelocity) { #if defined MIDI Serial.write(Mcommand); //send note on or note off command Serial.write(Mnote); //send pitch data Serial.write(Mvelocity); //send velocity data Serial.println(); // only pseudo MIDI, use NL to USB #endif } //________________________________________________________________________________ // note, pianokey // frequency. #define c 40 // 261 Hz #define d 42 // 294 Hz #define e 44 // 329 Hz #define f 45 // 349 Hz #define g 47 // 392 Hz #define a 49 // 440 Hz #define b 51 // 493 Hz #define C 52 // 523 Hz #define R 0 // 20000 Hz not play, rest String msg = "ONE LOVE, ONE HEART, // BOB MARLEY for ever"; //__________________0__1__2__3__4__5__6__7__8__9__0__1__2__3__4__5__6__7__8__9__0__1__2__3__4__5__6__7__8__9__0 int melody[] = { e, R, e, d, R, d, R, f, e, d, c, c, c, d, e, d, c, R, e, R, e, d, R, d }; int melodyT[] = { 1, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 1, 1, 2 }; int melodylong=23; //________________________________________________________________________________ void setup() { Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } pinMode(speakerOut, OUTPUT); // KLL delay(3000); Serial.println("make all notes"); Notelist(); } //________________________________________________________________________________ void loop() { Serial.println("play all notes"); for (int N=1; N <=88; N++) { tone(N,1,127); tone(0,1,127); } delay(2000); // pause Serial.println(msg); for (int j = 0; j <= melodylong; j++) { tone(melody[j],melodyT[j],vol); } delay(2000); // pause } //________________________________________________________________________________