📄 soundplay.lst
字号:
C51 COMPILER V7.07 SOUNDPLAY 05/26/2008 19:51:42 PAGE 1
C51 COMPILER V7.07, COMPILATION OF MODULE SOUNDPLAY
OBJECT MODULE PLACED IN SOUNDPLAY.OBJ
COMPILER INVOKED BY: D:\Program Files\keil\C51\BIN\C51.EXE SOUNDPLAY.C BROWSE DEBUG OBJECTEXTEND
stmt level source
1 #include <reg52.h>
2 #include "MusicBox.h"
3
4
5 /*说明**************************************************************************
6 曲谱存贮格式 unsigned char code MusicName{音高,音长,音高,音长...., 0,0}; 末尾:0,0 表示结束(Important)
7
8 音高由三位数字组成:
9 个位是表示 1~7 这七个音符
10 十位是表示音符所在的音区:1-低音,2-中音,3-高音;
11 百位表示这个音符是否要升半音: 0-不升,1-升半音。
12
13 音长最多由三位数字组成:
14 个位表示音符的时值,其对应关系是:
15 |数值(n): |0 |1 |2 |3 | 4 | 5 | 6
16 |几分音符: |1 |2 |4 |8 |16 |32 |64 音符=2^n
17 十位表示音符的演奏效果(0-2): 0-普通,1-连音,2-顿音
18 百位是符点位: 0-无符点,1-有符点
19
20 调用演奏子程序的格式
21 Play(乐曲名,调号,升降八度,演奏速度);
22 |乐曲名 : 要播放的乐曲指针,结尾以(0,0)结束;
23 |调号(0-11) : 是指乐曲升多少个半音演奏;
24 |升降八度(1-3) : 1:降八度, 2:不升不降, 3:升八度;
25 |演奏速度(1-12000): 值越大速度越快;
26
27 ***************************************************************************/
28
29
30 #define SYSTEM_OSC 12000000 //定义晶振频率12000000HZ
31 #define SOUND_SPACE 4/5 //定义普通音符演奏的长度分率,//每4分音符间隔
32 sbit BeepIO = P1^0; //定义输出管脚,连接翁鸣器
33
34 unsigned int code FreTab[12] = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率表
35 unsigned char code SignTab[7] = { 0,2,4,5,7,9,11 }; //1~7在频率表中的位置
36 unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };
37 unsigned char Sound_Temp_TH0, Sound_Temp_TL0; //音符定时器初值暂存
38 unsigned char Sound_Temp_TH1, Sound_Temp_TL1; //音长定时器初值暂存
39
40 extern unsigned char play_state; //播放状态标识,0为不播放,1为播放
41
42 void InitialSound(void)
43 {
44 1 //禁止中断
45 1 EA = 0;
46 1
47 1 //设置INT1为高优先级
48 1 PX1 = 1;
49 1
50 1 /****INT1中断初始化******/
51 1 //设为电平触发方式
52 1 IT1 = 1;
53 1
54 1 //允许INT1中断
55 1 EX1 = 1;
C51 COMPILER V7.07 SOUNDPLAY 05/26/2008 19:51:42 PAGE 2
56 1
57 1 /*****TR0,TR1初始化******/
58 1 BeepIO = 0;
59 1 Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256; // 计算TL1应装入的初值 (10ms的初装值)
60 1 Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256; // 计算TH1应装入的初值
61 1 TH1 = Sound_Temp_TH1;
62 1 TL1 = Sound_Temp_TL1;
63 1 TMOD |= 0x11;
64 1 ET0 = 1;
65 1 ET1 = 0;
66 1 TR0 = 0;
67 1 TR1 = 0;
68 1
69 1 //开全局中断
70 1 EA = 1;
71 1 }
72
73 void BeepTimer0(void) interrupt 1 //音符发生中断
74 {
75 1 EA = 0;
76 1 BeepIO = !BeepIO;
77 1 TH0 = Sound_Temp_TH0;
78 1 TL0 = Sound_Temp_TL0;
79 1 EA = 1;
80 1 }
81 //**************************************************************************
82 void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)
83 {
84 1 unsigned int NewFreTab[12]; //新的频率表
85 1 unsigned char i,j;
86 1 unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
87 1 unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
88 1
89 1 if(play_state){ //如果为播放态
90 2 for(i=0;i<12;i++) // 根据调号及升降八度来生成新的频率表
91 2 {
92 3 j = i + Signature;
93 3
94 3 if(j > 11)
95 3 {
96 4 j = j-12;
97 4 NewFreTab[i] = FreTab[j]*2;
98 4 }
99 3 else
100 3 NewFreTab[i] = FreTab[j];
101 3
102 3 if(Octachord == 1)
103 3 NewFreTab[i]>>=2;
104 3 else if(Octachord == 3)
105 3 NewFreTab[i]<<=2;
106 3 }//end of for
107 2
108 2 SoundLength = 0;
109 2 while(Sound[SoundLength] != 0x00) //计算歌曲长度
110 2 {
111 3 SoundLength+=2;
112 3 }
113 2
114 2 Point = 0;
115 2 Tone = Sound[Point];
116 2 Length = Sound[Point+1]; // 读出第一个音符和它时时值
117 2
C51 COMPILER V7.07 SOUNDPLAY 05/26/2008 19:51:42 PAGE 3
118 2 LDiv0 = 12000/Speed; // 算出1分音符的长度(几个10ms)
119 2 LDiv4 = LDiv0/4; // 算出4分音符的长度
120 2 LDiv4 = LDiv4-LDiv4*SOUND_SPACE; // 普通音最长间隔标准
121 2 TR0 = 0;
122 2 TR1 = 1;
123 2
124 2 while(Point < SoundLength)
125 2 {
126 3 if(play_state){ //如果为播放态
127 4 SL=Tone%10; //计算出音符
128 4 SM=Tone/10%10; //计算出高低音
129 4 SH=Tone/100; //计算出是否升半
130 4 CurrentFre = NewFreTab[SignTab[SL-1]+SH]; //查出对应音符的频率
131 4
132 4 if(SL!=0)
133 4 {
134 5 if (SM==1) CurrentFre >>= 2; //低音
135 5 if (SM==3) CurrentFre <<= 2; //高音
136 5 Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值
137 5 Sound_Temp_TH0 = Temp_T/256;
138 5 Sound_Temp_TL0 = Temp_T%256;
139 5 TH0 = Sound_Temp_TH0;
140 5 TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿
141 5 }
142 4
143 4 SLen=LengthTab[Length%10]; //算出是几分音符
144 4 XG=Length/10%10; //算出音符类型(0普通1连音2顿音)
145 4 FD=Length/100;
146 4 LDiv=LDiv0/SLen; //算出连音音符演奏的长度(多少个10ms)
147 4
148 4 if (FD==1)
149 4 LDiv=LDiv+LDiv/2;
150 4 if(XG!=1)
151 4 if(XG==0) //算出普通音符的演奏长度
152 4 if (SLen<=4)
153 4 LDiv1=LDiv-LDiv4;
154 4 else
155 4 LDiv1=LDiv*SOUND_SPACE;
156 4 else
157 4 LDiv1=LDiv/2; //算出顿音的演奏长度
158 4 else
159 4 LDiv1=LDiv;
160 4 if(SL==0) LDiv1=0;
161 4 LDiv2=LDiv-LDiv1; //算出不发音的长度
162 4
163 4 if (SL!=0)
164 4 {
165 5 TR0=1;
166 5 for(i=LDiv1;i>0;i--) //发规定长度的音
167 5 {
168 6 while(TF1==0);
169 6 TH1 = Sound_Temp_TH1;
170 6 TL1 = Sound_Temp_TL1;
171 6 TF1=0;
172 6 }//end of for
173 5 }//end of if
174 4
175 4 if(LDiv2!=0)
176 4 {
177 5 TR0=0; BeepIO=0;
178 5 for(i=LDiv2;i>0;i--) //音符间的间隔
179 5 {
C51 COMPILER V7.07 SOUNDPLAY 05/26/2008 19:51:42 PAGE 4
180 6 while(TF1==0);
181 6 TH1 = Sound_Temp_TH1;
182 6 TL1 = Sound_Temp_TL1;
183 6 TF1=0;
184 6 }//end of for
185 5 }//end of if
186 4
187 4 Point+=2;
188 4 Tone=Sound[Point];
189 4 Length=Sound[Point+1];
190 4 }
191 3 else{
192 4 return;
193 4 }
194 3 }//end of while
195 2 BeepIO = 0;
196 2 }
197 1 else{ //若不为播放态,则返回
198 2 return;
199 2 }
200 1 }
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 763 ----
CONSTANT SIZE = 38 ----
XDATA SIZE = ---- ----
PDATA SIZE = ---- ----
DATA SIZE = 4 51
IDATA SIZE = ---- ----
BIT SIZE = ---- ----
END OF MODULE INFORMATION.
C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -