2.2 播放音乐
对照以上表格及射雕英雄传主题曲铁血丹心简谱实现树莓派播放,铁血丹心简谱如下:
上面的简谱中缺少前奏,程序中增加了从其他版本中摘录的前奏部分,主程序tiexuedanxin.c代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <bcm2835.h>
#include "pitches.h"
#define PWM_CHANNEL 0
typedef struct _TONE{
int freq;
int t_ms;
} TONE,*PTONE;
int pin = RPI_GPIO_P1_12;
int baseFreq = 600000; // BCM2835_PWM_CLOCK_DIVIDER_32 对应600KHz
typedef struct _melodyNode{
int note;
float fDuration;
}melodyNode;
melodyNode melody[]= {
// 1
{NOTE_A4, 1.5}, // 6
{NOTE_G4, 0.5}, // 5
{NOTE_A4, 1}, // 6
{NOTE_G4, 0.5}, // 5
{NOTE_E4, 0.5}, // 3
// 2
{NOTE_G4, 1}, // 5
{NOTE_D4, 3}, // 2
// 3
{NOTE_C4, 1.5}, // 1
{NOTE_A3, 0.5}, // .6
{NOTE_D4, 0.5}, // 2
{NOTE_E4, 0.5}, // 3
{NOTE_G4, 0.5}, // 5
{NOTE_F4, 0.5}, // 4
// 4
{NOTE_E4, 3}, // 3
{NOTE_E4, 0.5}, // 3
{NOTE_G4, 0.5}, // 5
// 5
{NOTE_A4, 1.5}, // 6
{NOTE_G4, 0.5}, // 5
{NOTE_A4, 1}, // 6
{NOTE_G4, 0.5}, // 5
{NOTE_E4, 0.5}, // 5
// 6
{NOTE_G4, 1}, // 5
{NOTE_D4, 3}, // 2
// 7
{NOTE_C4, 1.5}, // 1
{NOTE_A3, 0.5}, // .6
{NOTE_D4, 0.5}, // 2
{NOTE_E4, 0.5}, // 3
{NOTE_G3, 0.5}, // .5
{NOTE_B3, 0.5}, // .7
// 8
{NOTE_A3, 4}, // .6
{0, 1}, // 0
{NOTE_E4, 0.5}, // 3
{NOTE_D4, 0.5}, // 2
{NOTE_C4, 1.5}, // 1
{NOTE_B3, 0.5}, // .7
//
{NOTE_A3, 1.5}, // .6
{NOTE_E3, 0.5}, // .3
{NOTE_A3, 2}, // .6
//{NOTE_A3, 1}, // .6
{NOTE_A4, 0.5}, // 6
{NOTE_G4, 0.5}, // 5
{NOTE_E4, 1}, // 3
{NOTE_G4, 0.5}, // 5
{NOTE_D4, 0.5}, // 2
{NOTE_E4, 3}, // 3
{NOTE_E4, 0.5}, // 3
{NOTE_D4, 0.5}, // 2
{NOTE_C4, 1.5}, // 1
{NOTE_B3, 0.5}, // .7
{NOTE_A3, 1.5}, // .6
{NOTE_E3, 0.5}, // .6
{NOTE_A3, 2}, // .6
{0, 1}, // 0
{NOTE_D4, 0.5}, // 2
{NOTE_C4, 0.5}, // 1
{NOTE_A3, 1}, // .6
{NOTE_C4, 0.5}, // 1
{NOTE_D4, 0.5}, // 1
{NOTE_E4, 3}, // 3*/
{NOTE_E4, 1}, // 3 逐草四方
{NOTE_A4, 1.5}, // 6
{NOTE_G4, 0.5}, // 5
{NOTE_A4, 1}, // 6
{NOTE_G4, 0.5}, // 5
{NOTE_E4, 0.5}, // 3
{NOTE_G4, 1}, // 5
{NOTE_D4, 3}, // 2
{NOTE_C4, 1.5}, // 1
{NOTE_A3, 0.5}, // .6
{NOTE_D4, 0.5}, // 2
{NOTE_E4, 0.5}, // 3
{NOTE_G4, 0.5}, // 5
{NOTE_FS4, 0.5}, // #4
{NOTE_E4, 3}, // 3
{NOTE_E4, 0.5}, // 3
{NOTE_G4, 0.5}, // 5
{NOTE_A4, 1.5}, // 6
{NOTE_G4, 0.5}, // 5
{NOTE_A4, 1.0}, // 6
{NOTE_G4, 0.5}, // 5
{NOTE_E4, 0.5}, // 3
{NOTE_G4, 1.0}, // 5
{NOTE_D4, 3}, // 2
{NOTE_C4, 1.5}, // 1
{NOTE_A3, 0.5}, // .6
{NOTE_D4, 0.5}, // 2
{NOTE_E4, 0.5}, // 3
{NOTE_G3, 0.5}, // .5
{NOTE_B3, 0.5}, // .7
{NOTE_A3, 3}, // .6
{0, 1}, // 0
{NOTE_E4, 0.5}, // 3 应知爱意似
{NOTE_D4, 0.5}, // 2
{NOTE_C4, 1.0}, // 1
{NOTE_C4, 0.5}, // 1
{NOTE_B3, 0.5}, // .7
{NOTE_A3, 1.5}, // .6
{NOTE_E3, 0.5}, // .3
{NOTE_A3, 2.0}, // .6
{0, 1}, // 0
{NOTE_A3, 0.5}, // .6
{NOTE_G3, 0.5}, // .5
{NOTE_E3, 1.0}, // .3
{NOTE_G3, 0.5}, // .5
{NOTE_D3, 0.5}, // .2
{NOTE_E3, 3.0}, // .3
{0, 1}, // 0
{NOTE_E4, 0.5}, // 3 身经百劫也
{NOTE_D4, 0.5}, // 2
{NOTE_C4, 1.0}, // 1
{NOTE_C4, 0.5}, // 1
{NOTE_B3, 0.5}, // .7
{NOTE_A3, 1.5}, // .6
{NOTE_E4, 0.5}, // 3
{NOTE_D4, 2.0}, // 2
{0, 1}, // 0
{NOTE_D4, 0.5}, // 2
{NOTE_C4, 0.5}, // 1
{NOTE_A3, 1.0}, // .6
{NOTE_B3, 0.5}, // .7
{NOTE_G3, 0.5}, // .5
{NOTE_A3, 3.0}, // .6
};
void beep(int freq, int t_ms)
{
int range;
/*if(freq<2000||freq>5000)
{
printf("invalid freq\n");
return;
}*/
if(freq == 0)
range=1;
else
range=baseFreq/freq;
printf("will call bcm2835_pwm_set_range freq: %d range: %d\n", freq, range);
bcm2835_pwm_set_range(PWM_CHANNEL, range);
bcm2835_pwm_set_data(PWM_CHANNEL, range/2);
if(t_ms>0)
{
delay(t_ms);
}
}
void init()
{
if (!bcm2835_init())
exit (1) ;
printf("will init pin %d\n", pin);
// Set the output pin to Alt Fun 5, to allow PWM channel 0 to be output there
bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_ALT5);
bcm2835_pwm_set_clock(BCM2835_PWM_CLOCK_DIVIDER_32);
bcm2835_pwm_set_mode(PWM_CHANNEL, 1, 1);
}
int main (void)
{
int index=0;
int nLen = sizeof(melody)/sizeof(melody[0]);
init();
for ( ; index<nLen; index++)
{
int noteDuration = 600*melody[index].fDuration;
beep(melody[index].note, noteDuration);
printf("will call bcm2835_pwm_set_data 0 after beep\n");
bcm2835_pwm_set_data(PWM_CHANNEL, 0);
printf("index: %d nLen: %d@@@@@@@@@@@@\n", index, nLen);
//delay(100);
}
bcm2835_pwm_set_data(PWM_CHANNEL, 0);
bcm2835_close();
return 0 ;
}
注意代码中195行做了特殊处理,这时候频率并不是为0,只是让树莓派不再发声。