目录
Let'sDo第2期任务——《彩屏贪吃蛇》背景音乐及音效-个性化
通过PICO的PWM输出通过数字控制模拟信号,直接驱动扬声器,高效且功耗低。本次通过DECK2插针用来扩展音频,27管脚作为PWM输出接到蜂鸣上。

初始化代码中加入以下代码将27管脚设置为PWM输出,并 设置一个定时触发的中断函数on_pwm_wrap来改变PWM输出频率及幅值。
gpio_set_function(27, GPIO_FUNC_PWM); // Figure out which slice we just connected to the LED pin uint slice_num = pwm_gpio_to_slice_num(27); // Mask our slice's IRQ output into the PWM block's single interrupt line, // and register our interrupt handler pwm_clear_irq(slice_num); pwm_set_irq_enabled(slice_num, true); irq_set_exclusive_handler(PWM_IRQ_WRAP, on_pwm_wrap); irq_set_enabled(PWM_IRQ_WRAP, true); // Get some sensible defaults for the slice configuration. By default, the // counter is allowed to wrap over its maximum range (0 to 2**16-1) pwm_config config = pwm_get_default_config(); // Set divider, reduces counter clock to sysclock/this value pwm_config_set_clkdiv(&config, 1.f); pwm_config_set_wrap(&config, 20000); // Load the configuration into our PWM slice, and set it running. pwm_init(slice_num, &config, true);
在定时中断on_pwm_wrap函数中播放乐曲的音符,乐曲的每一个音符包含的信息有“频率”和“时长”两个信息,我们可以定义一个二维数组,数组的元素表示音符的频率和时长,整个数组表示一段音符,使用for循环即可播放这段音符。定义音符频率:根据音乐理论中的音阶频率表,为每个音符定义其对应的频率值。例如,C4=262Hz, D4=294Hz等。定义音符与频率之间的对应关系:
#define LC 262
#define LD 294
#define LE 330
#define LF 349
#define LG 392
#define LA 440
#define LAP_LBN 466
#define LB 494
#define MC 523
#define MD 587
#define ME 659
#define MEP 740
#define MF 698
#define MG 784
#define MA 880
#define MAP_MBN 932
#define MB 988
#define HC 1046
#define HD 1175
#define HE 1318
#define HF 1397
#define HG 1568
#define HA 1760
#define HB 1976
//定义一首乐曲数组
const unsigned int notes[] = { //音符库,四个八度
ME,ME,ME, ME,MD,MC, MC,LB,LA, LA,MC,ME, MA,MA,MA,
MA,MG,MD, MF,ME,MD, MD,ME,MF, ME,MF,ME, MEP,MF,ME,
ME,MD,MC, MC,LB,LA, LB,LB,LB, LB,MC,LB, LA,LA,LA, LA,
ME,ME,ME, ME,MD,MC, MC,LB,LB, LB,LAP_LBN,LB, MA,MA,MA,
MA,MB,MA, MA,MG,MG, MG,MA,MB, HC,HC,HC, HC,MB,MAP_MBN,
MA,MA,MA, MA,ME,MD, ME,ME,ME, ME,MF,MD, MC,MC,MC, MC,
};在中断函数中实现乐曲的播放。设置一个全局变量数组sound_state[2],游戏进行时修改sound_state[0]为1,播放背景音乐,其他界面sound_state[0]为0不播放背景音乐。在游戏函数snake_move中吃到食物时设置sound_state[1]为1、过关时sound_state[1]为2,游戏结束时sound_state[1]为2, on_pwm_wrap()函数中根据sound_state变量内容播放不同的效果音效。
void on_pwm_wrap() {
static int going_up = 0;
static int sound_level;
static int sound_f;
// Clear the interrupt flag that brought us here
pwm_clear_irq(pwm_gpio_to_slice_num(27));
if((sound_state[0])||(sound_state[1]))
{
going_up++;
if(going_up>300)
{
going_up = 0 ;
fade++;
if (fade > 90) {
fade = 0;
}
}
sound_level = 1000;
sound_f = 6000/notes[fade];
if(sound_state[1]==1)
{
sound_f = 10000;
sound_level = 10000;
sound_state[1]=0;
}
else if(sound_state[1]==2)
{
sound_f = 15000;
sound_level = 10000;
sound_state[1]--;
}
else if(sound_state[1]>2)
{
sound_f = 25000;
sound_level = 10000;
sound_state[1]--;
}
}
else
{
going_up=0;fade=0;sound_level=0;
}
// Square the fade value to make the LED's brightness appear more linear
// Note this range matches with the wrap value
pwm_set_gpio_level(27, sound_level);
// pwm_config config = pwm_get_default_config();
pwm_set_clkdiv(pwm_gpio_to_slice_num(27), sound_f);
}音效可参考视频,蜂鸣器音质太差,凑合听一下,后面有时间再优化。
https://www.bilibili.com/video/BV1GPpyebEko/?share_source=copy_web&vd_source=771c5bc0a24f31639a426bf66cb9e6c1
https://minkai-shi.github.io/
我要赚赏金
