1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 单片机通过蜂鸣器播放任意音乐代码实现(2):音乐单片机代码自动生成

单片机通过蜂鸣器播放任意音乐代码实现(2):音乐单片机代码自动生成

时间:2020-11-18 20:07:47

相关推荐

单片机通过蜂鸣器播放任意音乐代码实现(2):音乐单片机代码自动生成

单片机通过蜂鸣器播放任意音乐代码实现(2):音乐的单片机代码自动生成

上一节我们已经构建了基于51单片机的蜂鸣器音乐播放环境,接下来只需要手动或者自动添加音乐代码便能实现不同音乐的播放。当然,第二节将告诉你如何自动生成这些音乐代码。

所用软件

MuseScore 3;用于转换mid文件为musicxml文件C/C++ IDE(本文为Visual Studio )

1.生成音乐对应的MID文件

可以直接下载mid格式音乐文件,也可以将某段音乐转换为mid文件。最好是直接使用mid格式音乐文件,可以大大节省时间。在本例中使用的便是现成的mid文件。如果你需要将任意音乐转为mid文件,可以参考网络上的教程,本文不再赘诉。下图为本文所用的mid格式文件:

2.将MID文件转为MUSICXML文件

直接将mid文件拖拽进或是添加进MuseScore 3,打开后如下图所示:

点击“文件”→“导出”,按照下图设置输出文件:

3.提取MUSICXML文件关键字,自动生成音乐代码

该部分代码由C语言实现,主要功能是寻找musicxml格式文件中有关音高、音长的关键字,该部分代码如下:

#include <iostream> #include<stdlib.h>int zifuchange(char x);char word[11]={0};//音符、节拍数组int yinfushu=0;//音符个数统计int error=0;//错误计数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; //文件指针fp = fopen("D:\\(34拍)丁香花(旋律).musicxml", "r"); //以只读方式打开文件if(fp==NULL)printf("打开文件失败!\n");else{printf("请输入每分钟节拍数:");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]=='>') //判断此处连续11个字符是否为<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)//解析音符{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]=='>') //判断此处连续六个字符是否为<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++;//音符计数+1print++;if(print==3){printf("\n");print=0;}}i++;}i=0;}fclose(fp);//关闭文件printf("0");printf("\n");printf("解析完成,共有%d个音符,共有%d个错误\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;}}

使用该部分代码只需要更改以下文件路径为自己的文件路径即可,该部分代码如下:

fp = fopen("D:\\(34拍)丁香花(旋律).musicxml", "r");

将上面获取到的爱拼才会赢的musicxml格式文件路径添加进去后,手动输入每分钟节拍数(可自定义,也可填简谱节拍数)控制台会自动生成音乐代码,复制并粘贴进上一节所述的music[]数组即可。本次生成的代码如下:

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解析完成,共有275个音符,共有0个错误

至此,你便可以利用借助单片机通过蜂鸣器播放任意音乐!试试吧!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。