打印

音频编程

[复制链接]
1481|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wyg0504|  楼主 | 2007-11-27 19:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请各位帮我讲解一下下面的程序.
#ifndef __SOUNDPLAY_H_REVISION_FIRST__
#define __SOUNDPLAY_H_REVISION_FIRST__

//**************************************************************************

#define SYSTEM_OSC         12000000    //定义晶振频率12000000HZ
#define SOUND_SPACE     4/5         //定义普通音符演奏的长度分率,//每4分音符间隔
sbit    BeepIO    =       P3^7;        //定义输出管脚

unsigned int  code FreTab[12]  = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率表
unsigned char code SignTab[7]  = { 0,2,4,5,7,9,11 };                                   //1~7在频率表中的位置
unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };                        
unsigned char Sound_Temp_TH0,Sound_Temp_TL0;    //音符定时器初值暂存 
unsigned char Sound_Temp_TH1,Sound_Temp_TL1;    //音长定时器初值暂存
//**************************************************************************
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;
}

void BeepTimer0(void) interrupt 1    //音符发生中断
{
    BeepIO = !BeepIO;
    TH0    = Sound_Temp_TH0;
     TL0    = Sound_Temp_TL0;
}
//**************************************************************************
void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)
{
    unsigned int NewFreTab[12];        //新的频率表
    unsigned char i,j;
    unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
    unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
    for(i=0;i<12;i++)                 // 根据调号及升降八度来生成新的频率表 
    {
        j = i + Signature;
        if(j > 11)
        {
            j = j-12;
            NewFreTab = FreTab[j]*2;
        }
        else
            NewFreTab = FreTab[j];

        if(Octachord == 1)
            NewFreTab>>=2;
        else if(Octachord == 3)
            NewFreTab<<=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=Sound[Point];
        Length=Sound[Point+1];
    }
    BeepIO = 0;
}
//**************************************************************************
#endif

相关帖子

沙发
computer00| | 2007-11-27 19:27 | 只看该作者

哈哈~~~楼主这个出来的是C大调或者A小调的~~~

使用特权

评论回复
板凳
hellomcu| | 2007-11-27 20:44 | 只看该作者

呵呵,有歌仔听呀,不会是贝多芬的交响乐吧

   呵呵,有歌仔听呀,不会是贝多芬的交响乐吧

   蜂鸣器也称喇叭,是广泛应用于各种电子产品的一种元器件,它用于提示、报警、音乐等许多应用场合。蜂鸣器通常工作电流较大,电路上的TTL 电平基本上驱动不了蜂鸣器,需要增加驱动电路,驱动电流的大小会影响声音的大小。
    蜂鸣器有两种,一种是有源蜂鸣器,一种是无源蜂鸣器。有源的蜂鸣器使用很方便,电流通过时蜂鸣器就发出响声。可以说通电就响。
无源的蜂鸣器通电不会响,需要给它送一定频率的信号才会响。因此,不同的频率可以产生不同的响声。可以据此产生一些音乐或不同的单音,这依靠单片机的程序控制。

   看一下吧,看你的程序是如何控制时间(即频率)的。
相关链接:http://shop35088126.taobao.com

使用特权

评论回复
地板
ddaitt99| | 2007-11-27 21:42 | 只看该作者

好听的音乐!!

LS说蜂鸣器要个驱动电路!!LM386可以搭个驱动电路,驱动4W的喇叭没得问题

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

22

帖子

0

粉丝