音调播放器
根据蜂鸣器的声音频率、播放长短和声音大小,来产生设备需要的音频:比如设备启动声音、设备关机音、故障音、连接成功音、断开连接音、信号不稳定提示音、充电启动提示音、充电关闭提示音、设备插入提示音、设备拔出提示音、无操作提示音以及需要的音乐(八音盒播放的那种声音);
参考:[11-2] 蜂鸣器播放提示音&音乐_哔哩哔哩_bilibili
补充:
#表示右侧的符号转化为字符串
##表示将左右的符号拼接在一起。例如拼接变量名MUSIC_DEF(name)等同MUSIC_DEF_name
eg.
#define ADD_MUSIC(mc) {Music_##mc,(sizeof(Music_##mc) / sizeof(Music_##mc[0])), #mc}
ADD_MUSIC(Startup), // 等价 {ADD_MUSIC_Startup , 3 , "Startup" },
现在定义相关的设备启动声音、设备关机音、故障音、连接成功音、断开连接音、信号不稳定提示音、充电启动提示音、充电关闭提示音、设备插入提示音、设备拔出提示音、无操作提示音,音乐表如下:
#include "ToneMap.h"
//##表示将左右的符号拼接在一起。例如拼接变量名MUSIC_DEF(name)等同MUSIC_DEF_name
#define MUSIC_DEF(name) static const TonePlayer::MusicNode_t Music_##name[] =/*开机音 MUSIC_DEF_Startup[]={}; */
MUSIC_DEF(Startup)
{{M1, 80},{M6, 80},{M3, 80},
};/*关机音*/
MUSIC_DEF(Shutdown)
{{M3, 80},{M6, 80},{M1, 80},
};/*错误提示音*/
MUSIC_DEF(Error)
{{100, 80},{0, 80},{100, 80},
};/*连接成功音*/
MUSIC_DEF(Connect)
{{H1, 80},{H2, 80},{H3, 80},
};/*断开连接音*/
MUSIC_DEF(Disconnect)
{{H3, 80},{H2, 80},{H1, 80},
};/*信号不稳定提示音*/
MUSIC_DEF(UnstableConnect)
{{H1, 80},{0, 80},{H1, 80},
};/*充电启动提示音*/
MUSIC_DEF(BattChargeStart)
{{L1, 80},{L3, 80},
};/*充电关闭提示音*/
MUSIC_DEF(BattChargeEnd)
{{L3, 80},{L1, 80},
};/*设备插入提示音*/
MUSIC_DEF(DeviceInsert)
{/*C4,A3,F3,F4*/{M1, 180},{L6, 80},{L4, 80},{M4, 160},
};/*设备拔出提示音*/
MUSIC_DEF(DevicePullout)
{/*A4,F4,E4*/{L6, 80},{L4, 80},{L3, 80},
};/*无操作提示音*/
MUSIC_DEF(NoOperationWarning)
{{4000, 40},{0, 80},{4000, 40},{0, 80},{4000, 40},
};/*列表数据类型定义*/
typedef struct
{const TonePlayer::MusicNode_t* mc;uint16_t length;const char* name;
} MusicList_t;
//#表示右侧的符号转化为字符串
//ADD_MUSIC(mc) {ADD_MUSIC_mc , 成员数 ,"mc" }
#define ADD_MUSIC(mc) {Music_##mc,(sizeof(Music_##mc) / sizeof(Music_##mc[0])), #mc}/*提示音地址储存列表*/
static const MusicList_t MusicList[] =
{ADD_MUSIC(Startup), // 等价 {ADD_MUSIC_Startup , 3 , "Startup" },ADD_MUSIC(Shutdown),ADD_MUSIC(Error),ADD_MUSIC(Connect),ADD_MUSIC(Disconnect),ADD_MUSIC(UnstableConnect),ADD_MUSIC(BattChargeStart),ADD_MUSIC(BattChargeEnd),ADD_MUSIC(DeviceInsert),ADD_MUSIC(DevicePullout),ADD_MUSIC(NoOperationWarning),
};
音符频率列表
/*音符频率对应表*/
enum ToneMap
{L1 = 262,L1h = 277,L2 = 294,L2h = 311,L3 = 330,L4 = 349,L4h = 370,L5 = 392,L5h = 415,L6 = 440,L6h = 466,L7 = 494,M1 = 523,M1h = 554,M2 = 587,M2h = 622,M3 = 659,M4 = 698,M4h = 740,M5 = 784,M5h = 831,M6 = 880,M6h = 932,M7 = 988,H1 = 1046,H1h = 1109,H2 = 1175,H2h = 1245,H3 = 1318,H4 = 1397,H4h = 1480,H5 = 1568,H5h = 1661,H6 = 1760,H6h = 1865,H7 = 1976,
};
TonePlayer.cpp
#include "TonePlayer.h"TonePlayer::TonePlayer()
{CallbackFunction = nullptr;CurrentMusic = nullptr;Speed = SPEED_NORMAL;
}void TonePlayer::SetMusic(const MusicNode_t* music, uint16_t length)
{if (music == CurrentMusic){return;}CurrentMusic = music;Length = length;CurrentPos = length;
}void TonePlayer::SetSpeed(uint16_t speed)
{Speed = speed;
}void TonePlayer::Play()
{CurrentPos = 0;
}void TonePlayer::Stop()
{CurrentPos = Length;
}bool TonePlayer::Update(uint32_t tick)
{if (CallbackFunction == nullptr){return false;}if(CurrentPos < Length){if(tick > NextTime){CallbackFunction(CurrentMusic[CurrentPos].Freq, CurrentMusic[CurrentPos].Volume);NextTime = tick + CurrentMusic[CurrentPos].Time * Speed / SPEED_NORMAL;CurrentPos++;}return true;}else if(CurrentPos == Length && tick > NextTime){CallbackFunction(0, 0);CurrentPos++;}return false;
}
TonePlayer.h
#include <stdint.h>class TonePlayer
{typedef void(*CallbackFunction_t)(uint32_t, uint16_t);
public://音乐链表typedef struct{uint16_t Freq;//频率uint16_t Time;//时长uint16_t Volume;//音量} MusicNode_t;//速度enum Speed{SPEED_HALF = 512,SPEED_NORMAL = 256,SPEED_DOUBLE = 128};TonePlayer();~TonePlayer() {}void SetMusic(const MusicNode_t* music, uint16_t length);void SetCallback(CallbackFunction_t func){CallbackFunction = func;}void Play();void Play(const MusicNode_t* music, uint16_t length){SetMusic(music, length);Play();}void Stop();void SetSpeed(uint16_t speed);bool Update(uint32_t tick);
private:uint16_t Length;uint16_t CurrentPos;uint32_t NextTime;uint16_t Speed;const MusicNode_t* CurrentMusic;CallbackFunction_t CallbackFunction;
};
回调函数定义
沦陷更新控制蜂鸣器