Components and supplies
Arduino Nano R3
Max4466
Apps and platforms
Arduino IDE
Project description
Code
Note detection program
arduino
This program will print the detected note name. Refer the comment within code for clarification.
1//---------------------------------------------------------------------------// 2int in[128]; 3byte NoteV[13]={8,23,40,57,76,96,116,138,162,187,213,241,255}; //data for note detection based on frequency 4float f_peaks[5]; // top 5 frequencies peaks in descending order 5int Mic_pin; 6//---------------------------------------------------------------------------// 7 8 9void setup() { 10Serial.begin(250000); 11Mic_pin = A7; // change as per Microphone pin 12} 13 14 15void loop() 16{ 17 Tone_det(); 18 19} 20 21 22//-----------------------------Tone Detection Function----------------------------------------------// 23// Documentation on Tone_detection:https://www.instructables.com/member/abhilash_patel/instructables/ 24// Code Written By: Abhilash Patel 25// Contact: abhilashpatel121@gmail.com 26// This code written for arduino Nano board (should also work for UNO) 27// This code won't work for any board having RAM less than 2kb, 28 29 30 31void Tone_det() 32{ long unsigned int a1,b,a2; 33 float a; 34 float sum1=0,sum2=0; 35 float sampling; 36 a1=micros(); 37 for(int i=0;i<128;i++) 38 { 39 a=analogRead(Mic_pin)-500; //rough zero shift 40 //utilising time between two sample for windowing & amplitude calculation 41 sum1=sum1+a; //to average value 42 sum2=sum2+a*a; // to RMS value 43 a=a*(sin(i*3.14/128)*sin(i*3.14/128)); // Hann window 44 in[i]=10*a; // scaling for float to int conversion 45 delayMicroseconds(195); // based on operation frequency range 46 } 47b=micros(); 48 49sum1=sum1/128; // Average amplitude 50sum2=sqrt(sum2/128); // RMS 51sampling= 128000000/(b-a1); // real time sampling frequency 52 53//for very low or no amplitude, this code wont start 54//it takes very small aplitude of sound to initiate for value sum2-sum1>3, 55//change sum2-sum1 threshold based on requirement 56if(sum2-sum1>3){ 57 FFT(128,sampling); 58 //EasyFFT based optimised FFT code, 59 //this code updates f_peaks array with 5 most dominent frequency in descending order 60 61 for(int i=0;i<12;i++){in[i]=0;} // utilising in[] array for further calculation 62 63int j=0,k=0; //below loop will convert frequency value to note 64 for(int i=0; i<5;i++) 65 { 66 if(f_peaks[i]>1040){f_peaks[i]=0;} 67 if(f_peaks[i]>=65.4 && f_peaks[i]<=130.8) {f_peaks[i]=255*((f_peaks[i]/65.4)-1);} 68 if(f_peaks[i]>=130.8 && f_peaks[i]<=261.6) {f_peaks[i]=255*((f_peaks[i]/130.8)-1);} 69 if(f_peaks[i]>=261.6 && f_peaks[i]<=523.25){f_peaks[i]=255*((f_peaks[i]/261.6)-1);} 70 if(f_peaks[i]>=523.25 && f_peaks[i]<=1046) {f_peaks[i]=255*((f_peaks[i]/523.25)-1);} 71 if(f_peaks[i]>=1046 && f_peaks[i]<=2093) {f_peaks[i]=255*((f_peaks[i]/1046)-1);} 72 if(f_peaks[i]>255){f_peaks[i]=254;} 73 j=1;k=0; 74 75 while(j==1) 76 { 77 if(f_peaks[i]<NoteV[k]){f_peaks[i]=k;j=0;} 78 k++; // a note with max peaks (harmonic) with aplitude priority is selected 79 if(k>15){j=0;} 80 } 81 82 if(f_peaks[i]==12){f_peaks[i]=0;} 83 k=f_peaks[i]; 84 in[k]=in[k]+(5-i); 85 } 86 87k=0;j=0; 88 for(int i=0;i<12;i++) 89 { 90 if(k<in[i]){k=in[i];j=i;} //Max value detection 91 } 92 // Note print 93 // if you need to use note value for some application, use of note number recomendded 94 // where, 0=c;1=c#,2=D;3=D#;.. 11=B; 95 //a2=micros(); // time check 96 k=j; 97 if(k==0) {Serial.println('C');} 98 if(k==1) {Serial.print('C');Serial.println('#');} 99 if(k==2) {Serial.println('D');} 100 if(k==3) {Serial.print('D');Serial.println('#');} 101 if(k==4) {Serial.println('E');} 102 if(k==5) {Serial.println('F');} 103 if(k==6) {Serial.print('F');Serial.println('#');} 104 if(k==7) {Serial.println('G');} 105 if(k==8) {Serial.print('G');Serial.println('#');} 106 if(k==9) {Serial.println('A');} 107 if(k==10){Serial.print('A');Serial.println('#');} 108 if(k==11){Serial.println('B');} 109 } 110} 111 112//-----------------------------FFT Function----------------------------------------------// 113// Documentation on EasyFFT:https://www.instructables.com/member/abhilash_patel/instructables/ 114// EasyFFT code optimised for 128 sample size to reduce mamory consumtion 115 116float FFT(byte N,float Frequency) 117{ 118byte data[8]={1,2,4,8,16,32,64,128}; 119int a,c1,f,o,x; 120a=N; 121 122 for(int i=0;i<8;i++) //calculating the levels 123 { if(data[i]<=a){o=i;} } 124 o=7; 125byte in_ps[data[o]]={}; //input for sequencing 126float out_r[data[o]]={}; //real part of transform 127float out_im[data[o]]={}; //imaginory part of transform 128 129x=0; 130 for(int b=0;b<o;b++) // bit reversal 131 { 132 c1=data[b]; 133 f=data[o]/(c1+c1); 134 for(int j=0;j<c1;j++) 135 { 136 x=x+1; 137 in_ps[x]=in_ps[j]+f; 138 } 139 } 140 141 for(int i=0;i<data[o];i++) // update input array as per bit reverse order 142 { 143 if(in_ps[i]<a) 144 {out_r[i]=in[in_ps[i]];} 145 if(in_ps[i]>a) 146 {out_r[i]=in[in_ps[i]-a];} 147 } 148 149int i10,i11,n1; 150float e,c,s,tr,ti; 151 152 for(int i=0;i<o;i++) //fft 153 { 154 i10=data[i]; // overall values of sine cosine 155 i11=data[o]/data[i+1]; // loop with similar sine cosine 156 e=6.283/data[i+1]; 157 e=0-e; 158 n1=0; 159 160 for(int j=0;j<i10;j++) 161 { 162 c=cos(e*j); 163 s=sin(e*j); 164 n1=j; 165 166 for(int k=0;k<i11;k++) 167 { 168 tr=c*out_r[i10+n1]-s*out_im[i10+n1]; 169 ti=s*out_r[i10+n1]+c*out_im[i10+n1]; 170 171 out_r[n1+i10]=out_r[n1]-tr; 172 out_r[n1]=out_r[n1]+tr; 173 174 out_im[n1+i10]=out_im[n1]-ti; 175 out_im[n1]=out_im[n1]+ti; 176 177 n1=n1+i10+i10; 178 } 179 } 180 } 181 182//---> here onward out_r contains amplitude and our_in conntains frequency (Hz) 183 for(int i=0;i<data[o-1];i++) // getting amplitude from compex number 184 { 185 out_r[i]=sqrt((out_r[i]*out_r[i])+(out_im[i]*out_im[i])); // to increase the speed delete sqrt 186 out_im[i]=(i*Frequency)/data[o]; 187 /* 188 Serial.print(out_im[i],2); Serial.print("Hz"); 189 Serial.print("\ "); // uncomment to print freuency bin 190 Serial.println(out_r[i]); 191 */ 192 } 193 194x=0; // peak detection 195 for(int i=1;i<data[o-1]-1;i++) 196 { 197 if(out_r[i]>out_r[i-1] && out_r[i]>out_r[i+1]) 198 {in_ps[x]=i; //in_ps array used for storage of peak number 199 x=x+1;} 200 } 201 202s=0; 203c=0; 204 for(int i=0;i<x;i++) // re arraange as per magnitude 205 { 206 for(int j=c;j<x;j++) 207 { 208 if(out_r[in_ps[i]]<out_r[in_ps[j]]) 209 {s=in_ps[i]; 210 in_ps[i]=in_ps[j]; 211 in_ps[j]=s;} 212 } 213 c=c+1; 214 } 215 216 for(int i=0;i<5;i++) // updating f_peak array (global variable)with descending order 217 { 218 f_peaks[i]=(out_im[in_ps[i]-1]*out_r[in_ps[i]-1]+out_im[in_ps[i]]*out_r[in_ps[i]]+out_im[in_ps[i]+1]*out_r[in_ps[i]+1]) 219 /(out_r[in_ps[i]-1]+out_r[in_ps[i]]+out_r[in_ps[i]+1]); 220 } 221} 222 223//------------------------------------------------------------------------------------//
Chord detection program
arduino
1//---------------------------------------------------------------------------// 2int in[128]; 3byte NoteV[13]={8,23,40,57,76,96,116,138,162,187,213,241,255}; 4float f_peaks[8]; // top 8 frequencies peaks in descending order 5//---------------------------------------------------------------------------// 6 7 8void setup() { 9Serial.begin(250000); 10} 11 12 13void loop() 14{ 15 Chord_det(); 16 17} 18 19 20//-----------------------------Chord Detection Function----------------------------------------------// 21// Documentation on Chord_detection:https://www.instructables.com/member/abhilash_patel/instructables/ 22// Code Written By: Abhilash Patel 23// Contact: abhilashpatel121@gmail.com 24// this code written for arduino Nano board (should also work for UNO) or better board 25// this code won't work for any board having RAM less than 2kb, 26// More accurate detection can be carried out on more powerful borad by increasing sample size 27 28 29 30void Chord_det() 31{ 32 long unsigned int a1,b,a2; 33 float a; 34 float sum1=0,sum2=0; 35 float sampling; 36 a1=micros(); 37 for(int i=0;i<128;i++) 38 { 39 a=analogRead(A7)-500; //rough zero shift 40 //utilising time between two sample for windowing & amplitude calculation 41 sum1=sum1+a; //to average value 42 sum2=sum2+a*a; // to RMS value 43 a=a*(sin(i*3.14/128)*sin(i*3.14/128)); // Hann window 44 in[i]=4*a; // scaling for float to int conversion 45 delayMicroseconds(195); // based on operation frequency range 46 } 47b=micros(); 48sum1=sum1/128; //average amplitude 49sum2=sqrt(sum2/128); //RMS amplitude 50sampling= 128000000/(b-a1); // real time sampling frequency 51 52//for very low or no amplitude, this code wont start 53//it takes very small aplitude of sound to initiate for value sum2-sum1>3, 54//change sum2-sum1 threshold based on requirement 55if(sum2-sum1>3){ 56 FFT(128,sampling); //EasyFFT based optimised FFT code 57 58 59 for(int i=0;i<12;i++){in[i]=0;} 60 61int j=0,k=0; //below loop will convert frequency value to note 62 for(int i=0; i<8;i++) 63 { 64 if(f_peaks[i]>1040){f_peaks[i]=0;} 65 if(f_peaks[i]>=65.4 && f_peaks[i]<=130.8) {f_peaks[i]=255*((f_peaks[i]/65.4)-1);} 66 if(f_peaks[i]>=130.8 && f_peaks[i]<=261.6) {f_peaks[i]=255*((f_peaks[i]/130.8)-1);} 67 if(f_peaks[i]>=261.6 && f_peaks[i]<=523.25){f_peaks[i]=255*((f_peaks[i]/261.6)-1);} 68 if(f_peaks[i]>=523.25 && f_peaks[i]<=1046) {f_peaks[i]=255*((f_peaks[i]/523.25)-1);} 69 if(f_peaks[i]>=1046 && f_peaks[i]<=2093) {f_peaks[i]=255*((f_peaks[i]/1046)-1);} 70 if(f_peaks[i]>255){f_peaks[i]=254;} 71 j=1;k=0; 72 while(j==1) 73 { 74 if(f_peaks[i]<=NoteV[k]){f_peaks[i]=k;j=0;} 75 k++; // a note with max peaks (harmonic) with aplitude priority is selected 76 if(k>15){j=0;} 77 } 78 79 if(f_peaks[i]==12){f_peaks[i]=0;} 80 k=f_peaks[i]; 81 in[k]=in[k]+(8-i); 82 } 83 84k=0;j=0; 85 for(int i=0;i<12;i++) 86 { 87 if(k<in[i]){k=in[i];j=i;} //Max value detection 88 } 89 90 for(int i=0;i<8;i++) 91 { 92 in[12+i]=in[i]; 93 } 94 95for (int i=0;i<12;i++) 96{ 97 in[20+i]=in[i]*in[i+4]*in[i+7]; 98 in[32+i]=in[i]*in[i+3]*in[i+7]; //all chord check 99} 100 101 102for (int i=0;i<24;i++) 103{ 104in[i]=in[i+20]; 105if(k<in[i]){k=in[i];j=i;} // picking chord with max possiblity 106} 107char chord_out; 108int chord=j; 109if(chord>11){chord=chord-12;chord_out='m';} //Mojor-minor check 110else{chord_out=' ';} 111 112// Here "chord" variable has value of detected chord, 113// 0-11 defines all majot chord from C,C#,D,D#,.. B 114//12-23 defines all minor chord from Cm,C#m,Dm,D#m,.. Bm 115 116 117 a2=micros(); 118 k=chord; 119 if(k==0){Serial.print('C');Serial.println(chord_out);} 120 if(k==1){Serial.print('C');Serial.print('#');Serial.println(chord_out);} 121 if(k==2){Serial.print('D');Serial.println(chord_out);} 122 if(k==3){Serial.print('D');Serial.print('#');Serial.println(chord_out);} 123 if(k==4){Serial.print('E');Serial.println(chord_out);} 124 if(k==5){Serial.print('F');Serial.println(chord_out);} 125 if(k==6){Serial.print('F');Serial.print('#');Serial.println(chord_out);} 126 if(k==7){Serial.print('G');Serial.println(chord_out);} 127 if(k==8){Serial.print('G');Serial.print('#');Serial.println(chord_out);} 128 if(k==9){Serial.print('A');Serial.println(chord_out);} 129 if(k==10){Serial.print('A');Serial.print('#');Serial.println(chord_out);} 130 if(k==11){Serial.print('B');Serial.println(chord_out);} 131 } 132 133} 134 135//-----------------------------FFT Function----------------------------------------------// 136// Documentation on EasyFFT:https://www.instructables.com/member/abhilash_patel/instructables/ 137// EasyFFT code optimised for 128 sample size to reduce mamory consumtion 138 139float FFT(byte N,float Frequency) 140{ 141byte data[8]={1,2,4,8,16,32,64,128}; 142int a,c1,f,o,x; 143a=N; 144 145 for(int i=0;i<8;i++) //calculating the levels 146 { if(data[i]<=a){o=i;} } 147 o=7; 148byte in_ps[data[o]]={}; //input for sequencing 149float out_r[data[o]]={}; //real part of transform 150float out_im[data[o]]={}; //imaginory part of transform 151 152x=0; 153 for(int b=0;b<o;b++) // bit reversal 154 { 155 c1=data[b]; 156 f=data[o]/(c1+c1); 157 for(int j=0;j<c1;j++) 158 { 159 x=x+1; 160 in_ps[x]=in_ps[j]+f; 161 } 162 } 163 164 for(int i=0;i<data[o];i++) // update input array as per bit reverse order 165 { 166 if(in_ps[i]<a) 167 {out_r[i]=in[in_ps[i]];} 168 if(in_ps[i]>a) 169 {out_r[i]=in[in_ps[i]-a];} 170 } 171 172 173int i10,i11,n1; 174float e,c,s,tr,ti; 175 176 for(int i=0;i<o;i++) //fft 177 { 178 i10=data[i]; // overall values of sine cosine 179 i11=data[o]/data[i+1]; // loop with similar sine cosine 180 e=6.283/data[i+1]; 181 e=0-e; 182 n1=0; 183 184 for(int j=0;j<i10;j++) 185 { 186 c=cos(e*j); 187 s=sin(e*j); 188 n1=j; 189 190 for(int k=0;k<i11;k++) 191 { 192 tr=c*out_r[i10+n1]-s*out_im[i10+n1]; 193 ti=s*out_r[i10+n1]+c*out_im[i10+n1]; 194 195 out_r[n1+i10]=out_r[n1]-tr; 196 out_r[n1]=out_r[n1]+tr; 197 198 out_im[n1+i10]=out_im[n1]-ti; 199 out_im[n1]=out_im[n1]+ti; 200 201 n1=n1+i10+i10; 202 } 203 } 204 } 205 206/* 207for(int i=0;i<data[o];i++) 208{ 209Serial.print(out_r[i]); 210Serial.print("\ "); // uncomment to print RAW o/p 211Serial.print(out_im[i]); Serial.println("i"); 212} 213*/ 214 215//---> here onward out_r contains amplitude and our_in conntains frequency (Hz) 216 for(int i=0;i<data[o-1];i++) // getting amplitude from compex number 217 { 218 out_r[i]=sqrt((out_r[i]*out_r[i])+(out_im[i]*out_im[i])); // to increase the speed delete sqrt 219 out_im[i]=(i*Frequency)/data[o]; 220 /* 221 Serial.print(out_im[i],2); Serial.print("Hz"); 222 Serial.print("\ "); // uncomment to print freuency bin 223 Serial.println(out_r[i]); 224 */ 225 } 226 227x=0; // peak detection 228 for(int i=1;i<data[o-1]-1;i++) 229 { 230 if(out_r[i]>out_r[i-1] && out_r[i]>out_r[i+1]) 231 {in_ps[x]=i; //in_ps array used for storage of peak number 232 x=x+1;} 233 } 234 235s=0; 236c=0; 237 for(int i=0;i<x;i++) // re arraange as per magnitude 238 { 239 for(int j=c;j<x;j++) 240 { 241 if(out_r[in_ps[i]]<out_r[in_ps[j]]) 242 {s=in_ps[i]; 243 in_ps[i]=in_ps[j]; 244 in_ps[j]=s;} 245 } 246 c=c+1; 247 } 248 249 for(int i=0;i<8;i++) // updating f_peak array (global variable)with descending order 250 { 251 // f_peaks[i]=out_im[in_ps[i]];Serial.println(f_peaks[i]); 252 f_peaks[i]=(out_im[in_ps[i]-1]*out_r[in_ps[i]-1]+out_im[in_ps[i]]*out_r[in_ps[i]]+out_im[in_ps[i]+1]*out_r[in_ps[i]+1]) 253 /(out_r[in_ps[i]-1]+out_r[in_ps[i]]+out_r[in_ps[i]+1]); 254 // Serial.println(f_peaks[i]); 255 } 256} 257 258//------------------------------------------------------------------------------------//
Note detection program
arduino
This program will print the detected note name. Refer the comment within code for clarification.
1//---------------------------------------------------------------------------// 2int in[128]; 3byte NoteV[13]={8,23,40,57,76,96,116,138,162,187,213,241,255}; //data for note detection based on frequency 4float f_peaks[5]; // top 5 frequencies peaks in descending order 5int Mic_pin; 6//---------------------------------------------------------------------------// 7 8 9void setup() { 10Serial.begin(250000); 11Mic_pin = A7; // change as per Microphone pin 12} 13 14 15void loop() 16{ 17 Tone_det(); 18 19} 20 21 22//-----------------------------Tone Detection Function----------------------------------------------// 23// Documentation on Tone_detection:https://www.instructables.com/member/abhilash_patel/instructables/ 24// Code Written By: Abhilash Patel 25// Contact: abhilashpatel121@gmail.com 26// This code written for arduino Nano board (should also work for UNO) 27// This code won't work for any board having RAM less than 2kb, 28 29 30 31void Tone_det() 32{ long unsigned int a1,b,a2; 33 float a; 34 float sum1=0,sum2=0; 35 float sampling; 36 a1=micros(); 37 for(int i=0;i<128;i++) 38 { 39 a=analogRead(Mic_pin)-500; //rough zero shift 40 //utilising time between two sample for windowing & amplitude calculation 41 sum1=sum1+a; //to average value 42 sum2=sum2+a*a; // to RMS value 43 a=a*(sin(i*3.14/128)*sin(i*3.14/128)); // Hann window 44 in[i]=10*a; // scaling for float to int conversion 45 delayMicroseconds(195); // based on operation frequency range 46 } 47b=micros(); 48 49sum1=sum1/128; // Average amplitude 50sum2=sqrt(sum2/128); // RMS 51sampling= 128000000/(b-a1); // real time sampling frequency 52 53//for very low or no amplitude, this code wont start 54//it takes very small aplitude of sound to initiate for value sum2-sum1>3, 55//change sum2-sum1 threshold based on requirement 56if(sum2-sum1>3){ 57 FFT(128,sampling); 58 //EasyFFT based optimised FFT code, 59 //this code updates f_peaks array with 5 most dominent frequency in descending order 60 61 for(int i=0;i<12;i++){in[i]=0;} // utilising in[] array for further calculation 62 63int j=0,k=0; //below loop will convert frequency value to note 64 for(int i=0; i<5;i++) 65 { 66 if(f_peaks[i]>1040){f_peaks[i]=0;} 67 if(f_peaks[i]>=65.4 && f_peaks[i]<=130.8) {f_peaks[i]=255*((f_peaks[i]/65.4)-1);} 68 if(f_peaks[i]>=130.8 && f_peaks[i]<=261.6) {f_peaks[i]=255*((f_peaks[i]/130.8)-1);} 69 if(f_peaks[i]>=261.6 && f_peaks[i]<=523.25){f_peaks[i]=255*((f_peaks[i]/261.6)-1);} 70 if(f_peaks[i]>=523.25 && f_peaks[i]<=1046) {f_peaks[i]=255*((f_peaks[i]/523.25)-1);} 71 if(f_peaks[i]>=1046 && f_peaks[i]<=2093) {f_peaks[i]=255*((f_peaks[i]/1046)-1);} 72 if(f_peaks[i]>255){f_peaks[i]=254;} 73 j=1;k=0; 74 75 while(j==1) 76 { 77 if(f_peaks[i]<NoteV[k]){f_peaks[i]=k;j=0;} 78 k++; // a note with max peaks (harmonic) with aplitude priority is selected 79 if(k>15){j=0;} 80 } 81 82 if(f_peaks[i]==12){f_peaks[i]=0;} 83 k=f_peaks[i]; 84 in[k]=in[k]+(5-i); 85 } 86 87k=0;j=0; 88 for(int i=0;i<12;i++) 89 { 90 if(k<in[i]){k=in[i];j=i;} //Max value detection 91 } 92 // Note print 93 // if you need to use note value for some application, use of note number recomendded 94 // where, 0=c;1=c#,2=D;3=D#;.. 11=B; 95 //a2=micros(); // time check 96 k=j; 97 if(k==0) {Serial.println('C');} 98 if(k==1) {Serial.print('C');Serial.println('#');} 99 if(k==2) {Serial.println('D');} 100 if(k==3) {Serial.print('D');Serial.println('#');} 101 if(k==4) {Serial.println('E');} 102 if(k==5) {Serial.println('F');} 103 if(k==6) {Serial.print('F');Serial.println('#');} 104 if(k==7) {Serial.println('G');} 105 if(k==8) {Serial.print('G');Serial.println('#');} 106 if(k==9) {Serial.println('A');} 107 if(k==10){Serial.print('A');Serial.println('#');} 108 if(k==11){Serial.println('B');} 109 } 110} 111 112//-----------------------------FFT Function----------------------------------------------// 113// Documentation on EasyFFT:https://www.instructables.com/member/abhilash_patel/instructables/ 114// EasyFFT code optimised for 128 sample size to reduce mamory consumtion 115 116float FFT(byte N,float Frequency) 117{ 118byte data[8]={1,2,4,8,16,32,64,128}; 119int a,c1,f,o,x; 120a=N; 121 122 for(int i=0;i<8;i++) //calculating the levels 123 { if(data[i]<=a){o=i;} } 124 o=7; 125byte in_ps[data[o]]={}; //input for sequencing 126float out_r[data[o]]={}; //real part of transform 127float out_im[data[o]]={}; //imaginory part of transform 128 129x=0; 130 for(int b=0;b<o;b++) // bit reversal 131 { 132 c1=data[b]; 133 f=data[o]/(c1+c1); 134 for(int j=0;j<c1;j++) 135 { 136 x=x+1; 137 in_ps[x]=in_ps[j]+f; 138 } 139 } 140 141 for(int i=0;i<data[o];i++) // update input array as per bit reverse order 142 { 143 if(in_ps[i]<a) 144 {out_r[i]=in[in_ps[i]];} 145 if(in_ps[i]>a) 146 {out_r[i]=in[in_ps[i]-a];} 147 } 148 149int i10,i11,n1; 150float e,c,s,tr,ti; 151 152 for(int i=0;i<o;i++) //fft 153 { 154 i10=data[i]; // overall values of sine cosine 155 i11=data[o]/data[i+1]; // loop with similar sine cosine 156 e=6.283/data[i+1]; 157 e=0-e; 158 n1=0; 159 160 for(int j=0;j<i10;j++) 161 { 162 c=cos(e*j); 163 s=sin(e*j); 164 n1=j; 165 166 for(int k=0;k<i11;k++) 167 { 168 tr=c*out_r[i10+n1]-s*out_im[i10+n1]; 169 ti=s*out_r[i10+n1]+c*out_im[i10+n1]; 170 171 out_r[n1+i10]=out_r[n1]-tr; 172 out_r[n1]=out_r[n1]+tr; 173 174 out_im[n1+i10]=out_im[n1]-ti; 175 out_im[n1]=out_im[n1]+ti; 176 177 n1=n1+i10+i10; 178 } 179 } 180 } 181 182//---> here onward out_r contains amplitude and our_in conntains frequency (Hz) 183 for(int i=0;i<data[o-1];i++) // getting amplitude from compex number 184 { 185 out_r[i]=sqrt((out_r[i]*out_r[i])+(out_im[i]*out_im[i])); // to increase the speed delete sqrt 186 out_im[i]=(i*Frequency)/data[o]; 187 /* 188 Serial.print(out_im[i],2); Serial.print("Hz"); 189 Serial.print("\ "); // uncomment to print freuency bin 190 Serial.println(out_r[i]); 191 */ 192 } 193 194x=0; // peak detection 195 for(int i=1;i<data[o-1]-1;i++) 196 { 197 if(out_r[i]>out_r[i-1] && out_r[i]>out_r[i+1]) 198 {in_ps[x]=i; //in_ps array used for storage of peak number 199 x=x+1;} 200 } 201 202s=0; 203c=0; 204 for(int i=0;i<x;i++) // re arraange as per magnitude 205 { 206 for(int j=c;j<x;j++) 207 { 208 if(out_r[in_ps[i]]<out_r[in_ps[j]]) 209 {s=in_ps[i]; 210 in_ps[i]=in_ps[j]; 211 in_ps[j]=s;} 212 } 213 c=c+1; 214 } 215 216 for(int i=0;i<5;i++) // updating f_peak array (global variable)with descending order 217 { 218 f_peaks[i]=(out_im[in_ps[i]-1]*out_r[in_ps[i]-1]+out_im[in_ps[i]]*out_r[in_ps[i]]+out_im[in_ps[i]+1]*out_r[in_ps[i]+1]) 219 /(out_r[in_ps[i]-1]+out_r[in_ps[i]]+out_r[in_ps[i]+1]); 220 } 221} 222 223//------------------------------------------------------------------------------------//
Chord detection program
arduino
1//---------------------------------------------------------------------------// 2int in[128]; 3byte NoteV[13]={8,23,40,57,76,96,116,138,162,187,213,241,255}; 4float f_peaks[8]; // top 8 frequencies peaks in descending order 5//---------------------------------------------------------------------------// 6 7 8void setup() { 9Serial.begin(250000); 10} 11 12 13void loop() 14{ 15 Chord_det(); 16 17} 18 19 20//-----------------------------Chord Detection Function----------------------------------------------// 21// Documentation on Chord_detection:https://www.instructables.com/member/abhilash_patel/instructables/ 22// Code Written By: Abhilash Patel 23// Contact: abhilashpatel121@gmail.com 24// this code written for arduino Nano board (should also work for UNO) or better board 25// this code won't work for any board having RAM less than 2kb, 26// More accurate detection can be carried out on more powerful borad by increasing sample size 27 28 29 30void Chord_det() 31{ 32 long unsigned int a1,b,a2; 33 float a; 34 float sum1=0,sum2=0; 35 float sampling; 36 a1=micros(); 37 for(int i=0;i<128;i++) 38 { 39 a=analogRead(A7)-500; //rough zero shift 40 //utilising time between two sample for windowing & amplitude calculation 41 sum1=sum1+a; //to average value 42 sum2=sum2+a*a; // to RMS value 43 a=a*(sin(i*3.14/128)*sin(i*3.14/128)); // Hann window 44 in[i]=4*a; // scaling for float to int conversion 45 delayMicroseconds(195); // based on operation frequency range 46 } 47b=micros(); 48sum1=sum1/128; //average amplitude 49sum2=sqrt(sum2/128); //RMS amplitude 50sampling= 128000000/(b-a1); // real time sampling frequency 51 52//for very low or no amplitude, this code wont start 53//it takes very small aplitude of sound to initiate for value sum2-sum1>3, 54//change sum2-sum1 threshold based on requirement 55if(sum2-sum1>3){ 56 FFT(128,sampling); //EasyFFT based optimised FFT code 57 58 59 for(int i=0;i<12;i++){in[i]=0;} 60 61int j=0,k=0; //below loop will convert frequency value to note 62 for(int i=0; i<8;i++) 63 { 64 if(f_peaks[i]>1040){f_peaks[i]=0;} 65 if(f_peaks[i]>=65.4 && f_peaks[i]<=130.8) {f_peaks[i]=255*((f_peaks[i]/65.4)-1);} 66 if(f_peaks[i]>=130.8 && f_peaks[i]<=261.6) {f_peaks[i]=255*((f_peaks[i]/130.8)-1);} 67 if(f_peaks[i]>=261.6 && f_peaks[i]<=523.25){f_peaks[i]=255*((f_peaks[i]/261.6)-1);} 68 if(f_peaks[i]>=523.25 && f_peaks[i]<=1046) {f_peaks[i]=255*((f_peaks[i]/523.25)-1);} 69 if(f_peaks[i]>=1046 && f_peaks[i]<=2093) {f_peaks[i]=255*((f_peaks[i]/1046)-1);} 70 if(f_peaks[i]>255){f_peaks[i]=254;} 71 j=1;k=0; 72 while(j==1) 73 { 74 if(f_peaks[i]<=NoteV[k]){f_peaks[i]=k;j=0;} 75 k++; // a note with max peaks (harmonic) with aplitude priority is selected 76 if(k>15){j=0;} 77 } 78 79 if(f_peaks[i]==12){f_peaks[i]=0;} 80 k=f_peaks[i]; 81 in[k]=in[k]+(8-i); 82 } 83 84k=0;j=0; 85 for(int i=0;i<12;i++) 86 { 87 if(k<in[i]){k=in[i];j=i;} //Max value detection 88 } 89 90 for(int i=0;i<8;i++) 91 { 92 in[12+i]=in[i]; 93 } 94 95for (int i=0;i<12;i++) 96{ 97 in[20+i]=in[i]*in[i+4]*in[i+7]; 98 in[32+i]=in[i]*in[i+3]*in[i+7]; //all chord check 99} 100 101 102for (int i=0;i<24;i++) 103{ 104in[i]=in[i+20]; 105if(k<in[i]){k=in[i];j=i;} // picking chord with max possiblity 106} 107char chord_out; 108int chord=j; 109if(chord>11){chord=chord-12;chord_out='m';} //Mojor-minor check 110else{chord_out=' ';} 111 112// Here "chord" variable has value of detected chord, 113// 0-11 defines all majot chord from C,C#,D,D#,.. B 114//12-23 defines all minor chord from Cm,C#m,Dm,D#m,.. Bm 115 116 117 a2=micros(); 118 k=chord; 119 if(k==0){Serial.print('C');Serial.println(chord_out);} 120 if(k==1){Serial.print('C');Serial.print('#');Serial.println(chord_out);} 121 if(k==2){Serial.print('D');Serial.println(chord_out);} 122 if(k==3){Serial.print('D');Serial.print('#');Serial.println(chord_out);} 123 if(k==4){Serial.print('E');Serial.println(chord_out);} 124 if(k==5){Serial.print('F');Serial.println(chord_out);} 125 if(k==6){Serial.print('F');Serial.print('#');Serial.println(chord_out);} 126 if(k==7){Serial.print('G');Serial.println(chord_out);} 127 if(k==8){Serial.print('G');Serial.print('#');Serial.println(chord_out);} 128 if(k==9){Serial.print('A');Serial.println(chord_out);} 129 if(k==10){Serial.print('A');Serial.print('#');Serial.println(chord_out);} 130 if(k==11){Serial.print('B');Serial.println(chord_out);} 131 } 132 133} 134 135//-----------------------------FFT Function----------------------------------------------// 136// Documentation on EasyFFT:https://www.instructables.com/member/abhilash_patel/instructables/ 137// EasyFFT code optimised for 128 sample size to reduce mamory consumtion 138 139float FFT(byte N,float Frequency) 140{ 141byte data[8]={1,2,4,8,16,32,64,128}; 142int a,c1,f,o,x; 143a=N; 144 145 for(int i=0;i<8;i++) //calculating the levels 146 { if(data[i]<=a){o=i;} } 147 o=7; 148byte in_ps[data[o]]={}; //input for sequencing 149float out_r[data[o]]={}; //real part of transform 150float out_im[data[o]]={}; //imaginory part of transform 151 152x=0; 153 for(int b=0;b<o;b++) // bit reversal 154 { 155 c1=data[b]; 156 f=data[o]/(c1+c1); 157 for(int j=0;j<c1;j++) 158 { 159 x=x+1; 160 in_ps[x]=in_ps[j]+f; 161 } 162 } 163 164 for(int i=0;i<data[o];i++) // update input array as per bit reverse order 165 { 166 if(in_ps[i]<a) 167 {out_r[i]=in[in_ps[i]];} 168 if(in_ps[i]>a) 169 {out_r[i]=in[in_ps[i]-a];} 170 } 171 172 173int i10,i11,n1; 174float e,c,s,tr,ti; 175 176 for(int i=0;i<o;i++) //fft 177 { 178 i10=data[i]; // overall values of sine cosine 179 i11=data[o]/data[i+1]; // loop with similar sine cosine 180 e=6.283/data[i+1]; 181 e=0-e; 182 n1=0; 183 184 for(int j=0;j<i10;j++) 185 { 186 c=cos(e*j); 187 s=sin(e*j); 188 n1=j; 189 190 for(int k=0;k<i11;k++) 191 { 192 tr=c*out_r[i10+n1]-s*out_im[i10+n1]; 193 ti=s*out_r[i10+n1]+c*out_im[i10+n1]; 194 195 out_r[n1+i10]=out_r[n1]-tr; 196 out_r[n1]=out_r[n1]+tr; 197 198 out_im[n1+i10]=out_im[n1]-ti; 199 out_im[n1]=out_im[n1]+ti; 200 201 n1=n1+i10+i10; 202 } 203 } 204 } 205 206/* 207for(int i=0;i<data[o];i++) 208{ 209Serial.print(out_r[i]); 210Serial.print("\ "); // uncomment to print RAW o/p 211Serial.print(out_im[i]); Serial.println("i"); 212} 213*/ 214 215//---> here onward out_r contains amplitude and our_in conntains frequency (Hz) 216 for(int i=0;i<data[o-1];i++) // getting amplitude from compex number 217 { 218 out_r[i]=sqrt((out_r[i]*out_r[i])+(out_im[i]*out_im[i])); // to increase the speed delete sqrt 219 out_im[i]=(i*Frequency)/data[o]; 220 /* 221 Serial.print(out_im[i],2); Serial.print("Hz"); 222 Serial.print("\ "); // uncomment to print freuency bin 223 Serial.println(out_r[i]); 224 */ 225 } 226 227x=0; // peak detection 228 for(int i=1;i<data[o-1]-1;i++) 229 { 230 if(out_r[i]>out_r[i-1] && out_r[i]>out_r[i+1]) 231 {in_ps[x]=i; //in_ps array used for storage of peak number 232 x=x+1;} 233 } 234 235s=0; 236c=0; 237 for(int i=0;i<x;i++) // re arraange as per magnitude 238 { 239 for(int j=c;j<x;j++) 240 { 241 if(out_r[in_ps[i]]<out_r[in_ps[j]]) 242 {s=in_ps[i]; 243 in_ps[i]=in_ps[j]; 244 in_ps[j]=s;} 245 } 246 c=c+1; 247 } 248 249 for(int i=0;i<8;i++) // updating f_peak array (global variable)with descending order 250 { 251 // f_peaks[i]=out_im[in_ps[i]];Serial.println(f_peaks[i]); 252 f_peaks[i]=(out_im[in_ps[i]-1]*out_r[in_ps[i]-1]+out_im[in_ps[i]]*out_r[in_ps[i]]+out_im[in_ps[i]+1]*out_r[in_ps[i]+1]) 253 /(out_r[in_ps[i]-1]+out_r[in_ps[i]]+out_r[in_ps[i]+1]); 254 // Serial.println(f_peaks[i]); 255 } 256} 257 258//------------------------------------------------------------------------------------//
Downloadable files
Connection
signal pin from module need to be connected to any analog pin of arduino. required change to be made on code accordingly.
Connection
Comments
Only logged in users can leave comments