|
|
本帖最后由 mogo 于 2026-2-9 11:44 编辑
输入文本简谱格式(至少三个字符才算有效):
第一个字符表示唱名:1234567 或 CDEFGAB ,0为休止符。
第二个字符表示第几个八度:0123456789。
第三个字符表示节拍:
1 = 三十二分音符,(八分之一拍,3个下划线)
2 = 十六分音符,(四分之一拍,2个下划线)
3 = 八分音符,(半拍,1个下划线)
4 = 四分音符,(一拍)
5 = 二分音符(后边一个减号,两拍)
6 = 全音符(后边三个减号,四拍)
之后的字符:#*升音,/降音,.附点音符(包括双附点)
用空格表示音符结束,换行也需要先添加空格。
输出数据格式:
第1个字节为基准音,表示歌曲最低音,以半音为单位。
第2到第9个字节为节拍数组,共8个节拍,单位为4000/256=15.625ms。
其它数据如下:
高5位为音阶,加上基准音为实际音阶,最多只能表示0~30共31个半音。31表示休止符不发声。
低3位表示节拍,数值为节拍数组的索引。
尾字节为0xFF表示结束。如果需要暂停发音的时间是最长时间使用连续的空音符。
- #define CALC_TIMER_VALUE(freq) (unsigned int)(65536 - (FOSC/(float)(CRYSTAL * 2 * (freq))))
- unsigned int __code FREQ[] = { // 音阶表(完整88键)
- // A0-B0
- CALC_TIMER_VALUE(27.50), CALC_TIMER_VALUE(29.14), CALC_TIMER_VALUE(30.87),
-
- // C1-B1
- CALC_TIMER_VALUE(32.70), CALC_TIMER_VALUE(34.65), CALC_TIMER_VALUE(36.71),
- CALC_TIMER_VALUE(38.89), CALC_TIMER_VALUE(41.20), CALC_TIMER_VALUE(43.65),
- CALC_TIMER_VALUE(46.25), CALC_TIMER_VALUE(48.99), CALC_TIMER_VALUE(51.91),
- CALC_TIMER_VALUE(55.00), CALC_TIMER_VALUE(58.27), CALC_TIMER_VALUE(61.74),
-
- // C2-B2
- CALC_TIMER_VALUE(65.41), CALC_TIMER_VALUE(69.30), CALC_TIMER_VALUE(73.42),
- CALC_TIMER_VALUE(77.78), CALC_TIMER_VALUE(82.41), CALC_TIMER_VALUE(87.31),
- CALC_TIMER_VALUE(92.50), CALC_TIMER_VALUE(98.00), CALC_TIMER_VALUE(103.83),
- CALC_TIMER_VALUE(110.00), CALC_TIMER_VALUE(116.54), CALC_TIMER_VALUE(123.47),
-
- // C3-B3
- CALC_TIMER_VALUE(130.81), CALC_TIMER_VALUE(138.59), CALC_TIMER_VALUE(146.83),
- CALC_TIMER_VALUE(155.56), CALC_TIMER_VALUE(164.81), CALC_TIMER_VALUE(174.61),
- CALC_TIMER_VALUE(185.00), CALC_TIMER_VALUE(196.00), CALC_TIMER_VALUE(207.65),
- CALC_TIMER_VALUE(220.00), CALC_TIMER_VALUE(233.08), CALC_TIMER_VALUE(246.94),
-
- // C4-B4
- CALC_TIMER_VALUE(261.63), CALC_TIMER_VALUE(277.18), CALC_TIMER_VALUE(293.66),
- CALC_TIMER_VALUE(311.13), CALC_TIMER_VALUE(329.63), CALC_TIMER_VALUE(349.23),
- CALC_TIMER_VALUE(369.99), CALC_TIMER_VALUE(392.00), CALC_TIMER_VALUE(415.30),
- CALC_TIMER_VALUE(440.00), CALC_TIMER_VALUE(466.16), CALC_TIMER_VALUE(493.88),
-
- // C5-B5
- CALC_TIMER_VALUE(523.25), CALC_TIMER_VALUE(554.37), CALC_TIMER_VALUE(587.33),
- CALC_TIMER_VALUE(622.25), CALC_TIMER_VALUE(659.26), CALC_TIMER_VALUE(698.46),
- CALC_TIMER_VALUE(739.99), CALC_TIMER_VALUE(783.99), CALC_TIMER_VALUE(830.61),
- CALC_TIMER_VALUE(880.00), CALC_TIMER_VALUE(932.33), CALC_TIMER_VALUE(987.77),
-
- // C6-B6
- CALC_TIMER_VALUE(1046.50), CALC_TIMER_VALUE(1108.73), CALC_TIMER_VALUE(1174.66),
- CALC_TIMER_VALUE(1244.51), CALC_TIMER_VALUE(1318.51), CALC_TIMER_VALUE(1396.91),
- CALC_TIMER_VALUE(1479.98), CALC_TIMER_VALUE(1567.98), CALC_TIMER_VALUE(1661.22),
- CALC_TIMER_VALUE(1760.00), CALC_TIMER_VALUE(1864.66), CALC_TIMER_VALUE(1975.53),
-
- // C7-B7
- CALC_TIMER_VALUE(2093.00), CALC_TIMER_VALUE(2217.46), CALC_TIMER_VALUE(2349.32),
- CALC_TIMER_VALUE(2489.02), CALC_TIMER_VALUE(2637.02), CALC_TIMER_VALUE(2793.83),
- CALC_TIMER_VALUE(2959.96), CALC_TIMER_VALUE(3135.96), CALC_TIMER_VALUE(3322.44),
- CALC_TIMER_VALUE(3520.00), CALC_TIMER_VALUE(3729.31), CALC_TIMER_VALUE(3951.07),
-
- // C8
- CALC_TIMER_VALUE(4186.01)
- };
复制代码- volatile __bit sounding;//播放声音
- unsigned char playOffset;//基础音,调式偏移量
- unsigned char *playMeter;//节拍数组
- unsigned char *playTrack;//音乐数据指针
- __bit playEnable = 0;//是否正在播放
- void PlayStop(void) { //停止播放
- playEnable = 0;
- sounding = 0;
- SPEAKER = 0;
- }
- void PlayNote(unsigned char note){ //更改正在播放的音符
- if(note<88){
- unsigned int freq = FREQ[note];
- RCAP2H = freq >> 8;
- RCAP2L = freq & 0xFF;
- sounding = 1;
- }
- else sounding=0;
- }
- void PlayMusic(void){ //播放状态更新,每15.625ms调用一次
- static unsigned char length;
- static unsigned char meter;
- static __bit playing = 0;
- if (!playEnable)return;
- if (playing){
- if (length<meter){
- length++;
- } else {
- playing=0;
- playTrack++;
- }
- }else if(*playTrack != 0xFF){
- unsigned char noteData = *playTrack;// 获取当前音符数据
- unsigned char midiNote = (noteData >> 3) & 0x1F;//高5位为MIDI音阶
- unsigned char beatIndex = noteData & 0x07;//低3位为节拍索引
- meter = *(playMeter+beatIndex);
- length = 0;
- if(midiNote==0x1F) PlayNote(0x7F);
- else PlayNote(midiNote+playOffset);
- playing=1;
- }else PlayStop();
- }
- void PlayStart(unsigned char *track) { //开始播放
- playOffset = *track - 21;//第0字节为MIDI音阶,减去音频数组起点A0
- playMeter = track+1;//每1-8字节为节拍
- playTrack = track+9;//第9字节开始音乐数据
- playEnable = 1;
- }
- void T2Interrupt(void) __interrupt 5 __using 3{
- TF2=0;//必须软件置零
- if (sounding) SPEAKER = !SPEAKER;
- }
复制代码
main.v
(621.94 KB, 下载次数: 0)
|
|