|
#include "MusicPlay.h"
unsigned char *PP[]={song1,song2,song3};//指向歌曲的指针数组
unsigned char *p;//只想歌曲的指针
unsigned int Point = 0;//歌曲播放位置
bit flag_pause=1;//暂停标志位
bit flag_up=0;//上一曲标志位
bit flag_down=0;//下一曲标志位
int flag_order=0;//歌曲顺序
void Delay1ms(unsigned int count);//简单延时
void InitialSound(void);//初始化
void Play(unsigned char *sound,unsigned char Signature,unsigned Octachord,unsigned int Speed);//音乐播放函数
//******************主程序***************************************************
void main()
{
InitialSound();
while(1)
{
if(k_state==0)//有按键按下
{
if(k_pause==0)//开始/暂停键
{
while(k_pause==0);
flag_pause=~flag_pause;
}
}
while(!flag_pause)
{
Play(p+Point,0,3,360);
Delay1ms(300);
if(flag_down | flag_up)
{
if(flag_down) flag_down=0;
if(flag_up) flag_up =0;
Point = 0;
}
else flag_order++;
if(flag_pause==1) flag_order--;
if(flag_order == 3)
flag_order = 0;
p=PP[flag_order];
}
}
}
//***********************中断服务程序*************************************//
void BeepTimer0(void) interrupt 1 //音符中断程序
{
BeepIO = !BeepIO;
TH0 = Sound_Temp_TH0;
TL0 = Sound_Temp_TL0;
}
//***********************简单延时*******************************************//
void Delay1ms(unsigned int count)
{
unsigned int i,j;
for(i=0;i<count;i++)
for(j=0;j<120;j++);
}
//***********************系统初始化********************************************//
void InitialSound(void)
{
BeepIO = 0;
Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256; // 计算TL1应装入的初值 (10ms的初装值)
Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256; // 计算TH1应装入的初值
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TMOD |= 0x11;
ET0 = 1;
ET1 = 0;
TR0 = 0;
TR1 = 0;
EA = 1;
p=PP[0];
}
/****************************音乐播放函数***************************************/
/* input:歌曲名sound
调号signature
音阶octachord
速度speed
*/
void Play(unsigned char *sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)
{
unsigned int NewFreTab[12];//新的频率表
unsigned char i,j;
unsigned int LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
if(p==song1) flag_order=0;
else if (p==song2) flag_order=1;
else if (p==song3) flag_order=2;
for(i=0;i<12;i++)// 根据调号及升降八度来生成新的频率表
{
j = i + Signature;
if(j > 11)
{
j = j-12;
NewFreTab[i] = FreTab[j]*2;
}
else
NewFreTab[i] = FreTab[j];
if(Octachord == 1)
NewFreTab[i]>>=2;
else if(Octachord == 3)
NewFreTab[i]<<=2;
}
SoundLength = 0;
while(sound[SoundLength] != 0x00) //计算歌曲长度
{
SoundLength+=2;
}
// Point = 0;
Tone = sound[Point];
Length = sound[Point+1]; // 读出第一个音符和它时时值
LDiv0 = 12000/Speed; // 算出1分音符的长度(几个10ms)
LDiv4 = LDiv0/4; // 算出4分音符的长度
LDiv4 = LDiv4-LDiv4*SOUND_SPACE; // 普通音最长间隔标准
TR0 = 0;
TR1 = 1;
while(Point < SoundLength)
{
SL=Tone%10; //计算出音符
SM=Tone/10%10; //计算出高低音
SH=Tone/100; //计算出是否升半
CurrentFre = NewFreTab[SignTab[SL-1]+SH]; //查出对应音符的频率
if(SL!=0)
{
if (SM==1) CurrentFre >>= 2; //低音
if (SM==3) CurrentFre <<= 2; //高音
Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值
Sound_Temp_TH0 = Temp_T/256;
Sound_Temp_TL0 = Temp_T%256;
TH0 = Sound_Temp_TH0;
TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿
}
SLen=LengthTab[Length%10]; //算出是几分音符
XG=Length/10%10; //算出音符类型(0普通1连音2顿音)
FD=Length/100;
LDiv=LDiv0/SLen; //算出连音音符演奏的长度(多少个10ms)
if (FD==1)
LDiv=LDiv+LDiv/2;
if(XG!=1)
if(XG==0) //算出普通音符的演奏长度
if (SLen<=4)
LDiv1=LDiv-LDiv4;
else
LDiv1=LDiv*SOUND_SPACE;
else
LDiv1=LDiv/2; //算出顿音的演奏长度
else
LDiv1=LDiv;
if(SL==0) LDiv1=0;
LDiv2=LDiv-LDiv1; //算出不发音的长度
if (SL!=0)
{
TR0=1;
for(i=LDiv1;i>0;i--) //发规定长度的音
{
while(TF1==0);
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TF1=0;
}
}
if(LDiv2!=0)
{
TR0=0; BeepIO=0;
for(i=LDiv2;i>0;i--) //音符间的间隔
{
while(TF1==0);
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TF1=0;
}
}
Point+=2;
Tone=p[Point];
Length=p[Point+1];
//按键扫描
if(k_state==0)
{//扫描开始
if(k_pause==0)
{
while(k_pause==0);
flag_pause=~flag_pause;
TR1 = flag_pause;
return;
}
if(k_up==0)
{
while(k_up==0);
flag_up=~flag_up;
flag_order--;
if(flag_order < 0)
flag_order = 2;//第三首
p=PP[flag_order];
break;
}
if(k_down==0)
{
while(k_down==0);
flag_down=~flag_down;
flag_order++;
if(flag_order > 2)
flag_order=0;//第一首
p=PP[flag_order];
break;
}
}//按键扫描结束
}
BeepIO = 0;//播放结束,关闭
}#include "MusicPlay.h"
unsigned char *PP[]={song1,song2,song3};//指向歌曲的指针数组
unsigned char *p;//只想歌曲的指针
unsigned int Point = 0;//歌曲播放位置
bit flag_pause=1;//暂停标志位
bit flag_up=0;//上一曲标志位
bit flag_down=0;//下一曲标志位
int flag_order=0;//歌曲顺序
void Delay1ms(unsigned int count);//简单延时
void InitialSound(void);//初始化
void Play(unsigned char *sound,unsigned char Signature,unsigned Octachord,unsigned int Speed);//音乐播放函数
//******************主程序***************************************************
void main()
{
InitialSound();
while(1)
{
if(k_state==0)//有按键按下
{
if(k_pause==0)//开始/暂停键
{
while(k_pause==0);
flag_pause=~flag_pause;
}
}
while(!flag_pause)
{
Play(p+Point,0,3,360);
Delay1ms(300);
if(flag_down | flag_up)
{
if(flag_down) flag_down=0;
if(flag_up) flag_up =0;
Point = 0;
}
else flag_order++;
if(flag_pause==1) flag_order--;
if(flag_order == 3)
flag_order = 0;
p=PP[flag_order];
}
}
}
//***********************中断服务程序*************************************//
void BeepTimer0(void) interrupt 1 //音符中断程序
{
BeepIO = !BeepIO;
TH0 = Sound_Temp_TH0;
TL0 = Sound_Temp_TL0;
}
//***********************简单延时*******************************************//
void Delay1ms(unsigned int count)
{
unsigned int i,j;
for(i=0;i<count;i++)
for(j=0;j<120;j++);
}
//***********************系统初始化********************************************//
void InitialSound(void)
{
BeepIO = 0;
Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256; // 计算TL1应装入的初值 (10ms的初装值)
Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256; // 计算TH1应装入的初值
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TMOD |= 0x11;
ET0 = 1;
ET1 = 0;
TR0 = 0;
TR1 = 0;
EA = 1;
p=PP[0];
}
/****************************音乐播放函数***************************************/
/* input:歌曲名sound
调号signature
音阶octachord
速度speed
*/
void Play(unsigned char *sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)
{
unsigned int NewFreTab[12];//新的频率表
unsigned char i,j;
unsigned int LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
if(p==song1) flag_order=0;
else if (p==song2) flag_order=1;
else if (p==song3) flag_order=2;
for(i=0;i<12;i++)// 根据调号及升降八度来生成新的频率表
{
j = i + Signature;
if(j > 11)
{
j = j-12;
NewFreTab[i] = FreTab[j]*2;
}
else
NewFreTab[i] = FreTab[j];
if(Octachord == 1)
NewFreTab[i]>>=2;
else if(Octachord == 3)
NewFreTab[i]<<=2;
}
SoundLength = 0;
while(sound[SoundLength] != 0x00) //计算歌曲长度
{
SoundLength+=2;
}
// Point = 0;
Tone = sound[Point];
Length = sound[Point+1]; // 读出第一个音符和它时时值
LDiv0 = 12000/Speed; // 算出1分音符的长度(几个10ms)
LDiv4 = LDiv0/4; // 算出4分音符的长度
LDiv4 = LDiv4-LDiv4*SOUND_SPACE; // 普通音最长间隔标准
TR0 = 0;
TR1 = 1;
while(Point < SoundLength)
{
SL=Tone%10; //计算出音符
SM=Tone/10%10; //计算出高低音
SH=Tone/100; //计算出是否升半
CurrentFre = NewFreTab[SignTab[SL-1]+SH]; //查出对应音符的频率
if(SL!=0)
{
if (SM==1) CurrentFre >>= 2; //低音
if (SM==3) CurrentFre <<= 2; //高音
Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值
Sound_Temp_TH0 = Temp_T/256;
Sound_Temp_TL0 = Temp_T%256;
TH0 = Sound_Temp_TH0;
TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿
}
SLen=LengthTab[Length%10]; //算出是几分音符
XG=Length/10%10; //算出音符类型(0普通1连音2顿音)
FD=Length/100;
LDiv=LDiv0/SLen; //算出连音音符演奏的长度(多少个10ms)
if (FD==1)
LDiv=LDiv+LDiv/2;
if(XG!=1)
if(XG==0) //算出普通音符的演奏长度
if (SLen<=4)
LDiv1=LDiv-LDiv4;
else
LDiv1=LDiv*SOUND_SPACE;
else
LDiv1=LDiv/2; //算出顿音的演奏长度
else
LDiv1=LDiv;
if(SL==0) LDiv1=0;
LDiv2=LDiv-LDiv1; //算出不发音的长度
if (SL!=0)
{
TR0=1;
for(i=LDiv1;i>0;i--) //发规定长度的音
{
while(TF1==0);
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TF1=0;
}
}
if(LDiv2!=0)
{
TR0=0; BeepIO=0;
for(i=LDiv2;i>0;i--) //音符间的间隔
{
while(TF1==0);
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TF1=0;
}
}
Point+=2;
Tone=p[Point];
Length=p[Point+1];
//按键扫描
if(k_state==0)
{//扫描开始
if(k_pause==0)
{
while(k_pause==0);
flag_pause=~flag_pause;
TR1 = flag_pause;
return;
}
if(k_up==0)
{
while(k_up==0);
flag_up=~flag_up;
flag_order--;
if(flag_order < 0)
flag_order = 2;//第三首
p=PP[flag_order];
break;
}
if(k_down==0)
{
while(k_down==0);
flag_down=~flag_down;
flag_order++;
if(flag_order > 2)
flag_order=0;//第一首
p=PP[flag_order];
break;
}
}//按键扫描结束
}
BeepIO = 0;//播放结束,关闭
}
|
评分
-
查看全部评分
|