MCU plays arbitrary music code through buzzer (2): Music MCU code is automatically generated
In the previous section, we have built a buzzer music playing environment based on 51 single chip microcomputer. Next, we can play different music only by manually or automatically adding music code. Of course, the second section will show you how to automatically generate these music codes.
Software used
- MuseScore 3; Used to convert mid files to musicxml files
- C/C++ IDE (this article is Visual Studio 2019)
1. Generate MID file corresponding to music
You can download music files in mid format directly, or convert a piece of music into mid files. It is best to use mid format music files directly, which can greatly save time. In this case, the ready-made mid file is used. If you need to convert any music into mid files, you can refer to the tutorials on the network. This article will not be repeated. The following figure shows the mid format file used in this article:
2. Convert MID file to MUSICXML file
Drag or add the mid file directly into MuseScore 3, and open it as shown in the following figure:
Click "file" → "export", and set the output file according to the following figure:
3. Extract the keywords of MUSICXML file and automatically generate music code
This part of the code is implemented by C language. Its main function is to find the keywords related to pitch and length in musicxml format file. This part of the code is as follows:
#include <iostream> #include<stdlib.h> int zifuchange(char x); char word[11]={0};//Note and beat array int yinfushu=0;//Statistics of the number of notes int error=0;//Error count int flag=0; int jiepai=0; int print=0; int divisions=1; int jiepaishichang=1; int main() { int i=0; int x; int j; FILE *fp; //field name pointer fp = fopen("D:\\(34 beat)Lilac(melody).musicxml", "r"); //Open file as read-only if(fp==NULL) printf("Failed to open file!\n"); else { printf("Please enter beats per minute:"); scanf("%d",&jiepai); for(i=0;;i++) { fseek(fp,i,SEEK_SET); word[0]=fgetc(fp); if(word[0]==EOF) break; //printf("%c",word[0]); fseek(fp,i+1,SEEK_SET); word[1]=fgetc(fp); if(word[1]==EOF) break; //printf("%c",word[1]); fseek(fp,i+2,SEEK_SET); word[2]=fgetc(fp); if(word[2]==EOF) break; //printf("%c",word[2]); fseek(fp,i+3,SEEK_SET); word[3]=fgetc(fp); if(word[3]==EOF) break; //printf("%c",word[3]); fseek(fp,i+4,SEEK_SET); word[4]=fgetc(fp); if(word[4]==EOF) break; //printf("%c",word[4]); fseek(fp,i+5,SEEK_SET); word[5]=fgetc(fp); if(word[5]==EOF) break; //printf("%c",word[5]); fseek(fp,i+6,SEEK_SET); word[6]=fgetc(fp); if(word[6]==EOF) break; //printf("%c",word[5]); fseek(fp,i+7,SEEK_SET); word[7]=fgetc(fp); if(word[7]==EOF) break; //printf("%c",word[5]); fseek(fp,i+8,SEEK_SET); word[8]=fgetc(fp); if(word[8]==EOF) break; //printf("%c",word[5]); fseek(fp,i+9,SEEK_SET); word[9]=fgetc(fp); if(word[9]==EOF) break; //printf("%c",word[5]); fseek(fp,i+10,SEEK_SET); word[10]=fgetc(fp); if(word[10]==EOF) break; //printf("%c",word[5]); if(word[0]=='<'&&word[1]=='d'&&word[2]=='i'&&word[3]=='v'&&word[4]=='i'&&word[5]=='s' &&word[6]=='i'&&word[7]=='o'&&word[8]=='n'&&word[9]=='s'&&word[10]=='>') //Judge whether 11 consecutive characters here are < divisions > { for(j=0;;j++) { fseek(fp,i+11+j,SEEK_SET); if(fgetc(fp)=='<') break; else { if(j==0) { fseek(fp,i+11+j,SEEK_SET); divisions=zifuchange(fgetc(fp)); } else { fseek(fp,i+11+j,SEEK_SET); divisions=10*divisions+zifuchange(fgetc(fp)); } } } printf("%d,",divisions); break; } } while(1)//Analytic note { fseek(fp,i,SEEK_SET); word[0]=fgetc(fp); if(word[0]==EOF) break; //printf("%c",word[0]); fseek(fp,i+1,SEEK_SET); word[1]=fgetc(fp); if(word[1]==EOF) break; //printf("%c",word[1]); fseek(fp,i+2,SEEK_SET); word[2]=fgetc(fp); if(word[2]==EOF) break; //printf("%c",word[2]); fseek(fp,i+3,SEEK_SET); word[3]=fgetc(fp); if(word[3]==EOF) break; //printf("%c",word[3]); fseek(fp,i+4,SEEK_SET); word[4]=fgetc(fp); if(word[4]==EOF) break; //printf("%c",word[4]); fseek(fp,i+5,SEEK_SET); word[5]=fgetc(fp); if(word[5]==EOF) break; //printf("%c",word[5]); if(word[0]=='<'&&word[1]=='s'&&word[2]=='t'&&word[3]=='e'&&word[4]=='p'&&word[5]=='>') //Judge whether six consecutive characters here are < step > { fseek(fp,i+6,SEEK_SET); word[6]=fgetc(fp); switch(word[6]) { case 'C':word[6]='1';break; case 'D':word[6]='2';break; case 'E':word[6]='3';break; case 'F':word[6]='4';break; case 'G':word[6]='5';break; case 'A':word[6]='6';break; case 'B':word[6]='7';break; default:break; } fseek(fp,i+32,SEEK_SET); word[7]=fgetc(fp); if(word[7]=='>') { fseek(fp,i+33,SEEK_SET); word[7]=fgetc(fp); for(j=0;;j++) { fseek(fp,i+81+j,SEEK_SET); if(fgetc(fp)=='<') break; else { if(j==0) { fseek(fp,i+81+j,SEEK_SET); jiepaishichang=zifuchange(fgetc(fp)); } else { fseek(fp,i+81+j,SEEK_SET); jiepaishichang=10*jiepaishichang+zifuchange(fgetc(fp)); } } } } else { fseek(fp,i+61,SEEK_SET); word[7]=fgetc(fp); if(word[7]=='<') { fseek(fp,i+60,SEEK_SET); word[7]=fgetc(fp); } for(j=0;;j++) { fseek(fp,i+109+j,SEEK_SET); if(fgetc(fp)=='<') break; else { if(j==0) { fseek(fp,i+109+j,SEEK_SET); jiepaishichang=zifuchange(fgetc(fp)); } else { fseek(fp,i+109+j,SEEK_SET); jiepaishichang=10*jiepaishichang+zifuchange(fgetc(fp)); } } } } /* if(word[7]=='4') word[7]='2'; else if(word[7]>'4') word[7]='3'; else if(word[7]<'4') word[7]='1'; */ /* if(word[8]>'9'|word[8]<'0') { error++; } switch(word[8]) { case '1':word[8]='1';break; case '2':word[8]='2';break; case '3':word[8]='3';break; case '4':word[8]='4';break; case '6':word[8]='6';break; case '8':word[8]='8';break; case '12':word[8]='12';break; default:break; } */ if(flag==0) { printf("%d,",jiepai); flag++; printf("\n"); } if(word[6]<'0'||word[6]>'9') error++; if(word[7]<'0'||word[7]>'9') error++; printf("%c,%c,%d,",word[6],word[7],jiepaishichang); yinfushu++;//Note count + 1 print++; if(print==3) { printf("\n"); print=0; } } i++; } i=0; } fclose(fp);//Close file printf("0"); printf("\n"); printf("Parsing completed, shared%d Notes,share%d Errors\n",yinfushu,error); system("pause"); return 0; } int zifuchange(char x) { switch(x) { case '0':return 0;break; case '1':return 1;break; case '2':return 2;break; case '3':return 3;break; case '4':return 4;break; case '5':return 5;break; case '6':return 6;break; case '7':return 7;break; case '8':return 8;break; case '9':return 9;break; default:return -1;break; } }
To use this part of code, you only need to change the following file path to your own file path. This part of code is as follows:
fp = fopen("D:\\(34 beat)Lilac(melody).musicxml", "r");
After adding the musicxml format file path obtained above, manually enter the beats per minute (you can customize or fill in the beats of simple music). The console will automatically generate music code, copy and paste it into the music [] array described in the previous section. The generated code is as follows:
4,89, 5,4,2,5,4,1,6,4,1, 1,5,6,6,4,2,5,4,2, 6,4,1,1,5,1,6,4,2, 5,4,2,3,4,12,3,4,2, 3,4,1,5,4,1,6,4,6, 1,5,2,5,4,2,3,5,2, 3,5,1,2,5,1,1,5,2, 2,5,12,1,5,2,2,5,2, 3,5,2,3,5,2,2,5,2, 3,5,1,2,5,1,1,5,6, 6,4,1,1,5,1,2,5,2, 2,5,2,2,5,1,1,5,1, 6,4,2,5,4,8,6,4,2, 5,4,1,6,4,1,5,4,2, 1,5,2,6,4,2,5,4,2, 3,4,2,1,4,4,2,4,12, 1,4,2,2,4,2,3,4,6, 5,4,2,5,4,2,3,4,2, 1,5,2,7,4,2,6,4,6, 6,4,2,6,4,4,1,5,2, 2,5,1,3,5,1,5,5,4, 3,5,4,2,5,2,1,5,2, 5,4,2,1,5,2,2,5,1, 3,5,1,2,5,12,3,5,1, 2,5,1,1,5,4,2,5,1, 1,5,1,6,4,4,1,5,2, 3,4,1,1,5,1,1,5,2, 6,4,2,1,5,4,6,4,1, 5,4,1,3,4,2,5,4,16, 5,4,2,6,4,2,1,5,2, 6,4,2,6,4,8,3,5,2, 3,5,2,3,5,2,3,5,1, 2,5,1,2,5,6,2,5,1, 1,5,1,6,4,6,3,5,2, 2,5,4,1,5,1,2,5,1, 1,5,1,6,4,1,1,5,16, 5,4,2,6,4,2,1,5,6, 6,4,2,5,4,2,6,4,1, 1,5,1,6,4,2,5,4,2, 3,4,12,3,4,2,3,4,1, 5,4,1,6,4,6,1,5,2, 5,4,2,3,5,2,3,5,1, 2,5,1,1,5,2,2,5,12, 1,5,2,2,5,2,3,5,2, 3,5,2,2,5,2,3,5,1, 2,5,1,1,5,6,6,4,1, 1,5,1,2,5,2,2,5,2, 2,5,1,1,5,1,6,4,2, 5,4,8,6,4,2,5,4,1, 6,4,1,5,4,2,1,5,2, 6,4,2,5,4,2,3,4,2, 1,4,4,2,4,12,1,4,2, 2,4,2,3,4,6,5,4,2, 5,4,2,3,4,2,1,5,2, 7,4,2,6,4,6,6,4,2, 6,4,4,1,5,2,2,5,1, 3,5,1,5,5,2,3,5,4, 2,5,2,1,5,2,5,4,2, 1,5,2,2,5,1,3,5,1, 2,5,12,3,5,1,2,5,1, 1,5,4,2,5,1,1,5,1, 6,4,4,1,5,2,3,4,1, 1,5,1,1,5,2,6,4,2, 1,5,4,6,4,1,5,4,1, 3,4,2,5,4,16,5,4,2, 6,4,2,1,5,2,6,4,2, 6,4,8,3,5,2,3,5,2, 3,5,2,3,5,1,2,5,1, 2,5,6,2,5,1,1,5,1, 6,4,6,3,5,2,2,5,4, 1,5,1,2,5,1,1,5,1, 6,4,1,1,5,16,1,4,2, 2,4,2,3,4,6,5,4,2, 5,4,2,3,4,2,1,5,2, 7,4,2,6,4,6,6,4,2, 6,4,4,1,5,2,2,5,1, 3,5,1,5,5,4,3,5,4, 2,5,2,1,5,2,5,4,2, 1,5,2,2,5,1,3,5,1, 2,5,12,3,5,1,2,5,1, 1,5,4,2,5,1,1,5,1, 6,4,4,1,5,2,3,4,1, 1,5,1,1,5,2,6,4,2, 1,5,4,6,4,1,5,4,1, 3,4,2,5,4,16,5,4,2, 6,4,2,1,5,2,6,4,2, 6,4,8,3,5,2,3,5,2, 3,5,2,3,5,1,2,5,1, 2,5,6,2,5,1,1,5,1, 6,4,6,3,5,2,2,5,4, 1,5,1,2,5,1,1,5,1, 6,4,1,1,5,16,0 The analysis is completed, with 275 notes in total,There are 0 errors in total
So far, you can play any music through the buzzer with the help of single chip microcomputer! Try it!