版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HLW0522/article/details/82141597
mci的详细使用文档如下:http://www.360doc.com/content/12/0904/09/10660072_234175177.shtml
下面给出我对它进行的一个简单的封装,调用时只需要定义一个CPlayer的对象,然后调用Open()函数即可播放。
代码如下:
//Player.h
#pragma once
#include<windows.h>
#include<mmsystem.h>
#include<string>
#pragma comment(lib,"winmm.lib")
//命令参见:http://www.360doc.com/content/12/0904/09/10660072_234175177.shtml
typedef struct _MP3INFO //MP3信息的结构
{
char Identify[3]; //TAG三个字母
//这里可以用来鉴别是不是文件信息内容
char Title[31]; //歌曲名,30个字节
char Artist[31]; //歌手名,30个字节
char Album[31]; //所属唱片,30个字节
char Year[5]; //年,4个字节
char Comment[29]; //注释,28个字节
unsigned char reserved; //保留位, 1个字节
unsigned char reserved2; //保留位,1个字节
unsigned char reserved3; //保留位,1个字节
} MP3INFO;
class CPlay
{
public:
CPlay();
CPlay(const std::string&);
~CPlay();
//对于播放新的歌曲则需要制定路径,若是暂停后需要恢复播放,则不需要添加参数
void Play( std::string f="");
void Pause();
void Close();
int GetLength();//输出音乐总长,以ms为单位
int GetCurrentPlayPos();//输出当前音乐播放位置
void Go(int); //快进or快退,int代表跳转的间隔时间
void SetFile(std::string);
void SetHwnd(HWND);
bool GetInfo(const std::string &path, MP3INFO& mp3info);
//bool GetCurrentMusicInfo(MP3INFO& mp3info);
void StartRecord();
void EndRecord();
private:
void Open();
MCI_PLAY_PARMS playParms; //播放命令消息参数
MCI_OPEN_PARMS openParms; //打开命令消息参数
MCI_STATUS_PARMS statusParms; //状态命令消息参数
MCI_SEEK_PARMS seekParms; // 定位命令消息参数
MCI_RECORD_PARMS recordParms; //录音命令消息参数
MCI_SAVE_PARMS saveParms; //保存命令消息参数
MCI_GENERIC_PARMS genericParms;
MCIDEVICEID wDeviceID; //设备ID,系统用ID来标识不同的设备,以保证命令发给正确的对象。
HWND hWnd; //窗口句柄
std::string filePath; //文件位置
};
#include"Player.h"
#include<algorithm>
using namespace std;
CPlay::CPlay() {}
CPlay::~CPlay() {}
CPlay::CPlay(const std::string &path) :filePath(path) { }
void CPlay::Open()
{
Close();
openParms.dwCallback = (DWORD)hWnd;
// openParms.lpstrDeviceType = "avivideo";
openParms.lpstrElementName = filePath.c_str();
mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_ELEMENT, (DWORD)(LPVOID)&openParms);
}
void CPlay::Play( std::string f)
{
if (f != "")
{
filePath = f;
Open();
}
mciSendCommand(wDeviceID, MCI_STOP, MCI_NOTIFY, (DWORD)(LPVOID)&playParms);
wDeviceID = openParms.wDeviceID;
mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPVOID)&playParms);
}
void CPlay::Pause()
{
mciSendCommand(wDeviceID, MCI_PAUSE, MCI_NOTIFY, (DWORD)(LPVOID)&playParms);
}
void CPlay::Close()
{
mciSendCommand(wDeviceID, MCI_CLOSE, NULL, NULL);
}
int CPlay::GetLength()
{
statusParms.dwItem = MCI_STATUS_LENGTH;
DWORD dwReturn = mciSendCommand(wDeviceID, MCI_STATUS,
MCI_STATUS_ITEM, (DWORD)(LPVOID)&statusParms);
int nTime = statusParms.dwReturn;
return nTime;
}
int CPlay::GetCurrentPlayPos()
{
statusParms.dwItem = MCI_STATUS_POSITION;
DWORD dwReturn = mciSendCommand(wDeviceID, MCI_STATUS,
MCI_STATUS_ITEM, (DWORD)(LPVOID)&statusParms);
int nTime = statusParms.dwReturn;
return nTime;
}
void CPlay::Go(int t)//跳转,t为跳转的时间,如 5 则前进5s,-5则后退5s
{
//先获得当前播放位置
int Time = GetCurrentPlayPos();
//再调整时间
seekParms.dwTo = Time + t*1000;
DWORD dwReturn = mciSendCommand(wDeviceID, MCI_SEEK, MCI_WAIT | MCI_NOTIFY | MCI_TO, (DWORD)(LPVOID)&seekParms);
mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPVOID)&playParms);
}
void CPlay::SetFile(string file)
{
filePath = file;
Open();
}
void CPlay::SetHwnd(HWND hwnd)
{
hWnd = hwnd;
}
bool CPlay::GetInfo(const std::string &path, MP3INFO& mp3info)
{
if (path.empty())
return false;
FILE * fp;
unsigned char mp3tag[128] = { 0 };
fp = fopen(path.c_str(), "rb");
if (NULL == fp)
{
// QMessageBox::information(this, "提示", "打开文件失败");
return false;
}
fseek(fp, -128, SEEK_END);
fread(&mp3tag, 1, 128, fp);
if (!((mp3tag[0] == 'T' || mp3tag[0] == 't')
&& (mp3tag[1] == 'A' || mp3tag[1] == 'a')
&& (mp3tag[2] == 'G' || mp3tag[0] == 'g')))
{
printf("mp3 file is error!!");
fclose(fp);
//QMessageBox::information(this, "提示", "解析当前文件失败");
return false;
}
//获取Mp3信息
memcpy((void *)mp3info.Identify, mp3tag, 3); //获得tag
memcpy((void *)mp3info.Title, mp3tag + 3, 30); //获得歌名
memcpy((void *)mp3info.Artist, mp3tag + 33, 30); //获得作者
memcpy((void *)mp3info.Album, mp3tag + 63, 30); //获得唱片名
memcpy((void *)mp3info.Year, mp3tag + 93, 4); //获得年
memcpy((void *)mp3info.Comment, mp3tag + 97, 28); //获得注释
memcpy((void *)&mp3info.reserved, mp3tag + 125, 1); //获得保留
memcpy((void *)&mp3info.reserved2, mp3tag + 126, 1);
memcpy((void *)&mp3info.reserved3, mp3tag + 127, 1);
fclose(fp);
}
void CPlay::StartRecord() //录音
{
//先停止当前播放
mciSendCommand(wDeviceID, MCI_STOP, MCI_WAIT,
(DWORD)(LPVOID)&playParms);
mciSendCommand(wDeviceID, MCI_CLOSE, NULL, NULL);
//再删除原来的录音文件
try
{
DeleteFile("D:\\LuYin.wav");
}
catch(...)
{
// 删除出错处理
// cout << "\nDelete Error!! Error Code: ";
// cerr << GetLastError() << endl;
return;
}
//system("del D:\\LuYin.wav");
//重新打开一个新的文件
openParms.dwCallback = 0;
openParms.wDeviceID = 0;
openParms.lpstrDeviceType = "waveaudio"; //文件类型
openParms.lpstrElementName = "";
mciSendCommand(0, MCI_OPEN,
MCI_WAIT | MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD)(LPVOID)&openParms);
//开始录音
wDeviceID = openParms.wDeviceID;
recordParms.dwFrom = 0;
recordParms.dwTo = 0;
recordParms.dwCallback = (DWORD)hWnd;
mciSendCommand(wDeviceID, MCI_RECORD, MCI_NOTIFY,
(DWORD)(LPVOID)&recordParms);
}
void CPlay::EndRecord()
{
//退出循环后暂停录音
mciSendCommand(wDeviceID, MCI_STOP, MCI_WAIT, (DWORD)(LPVOID)&genericParms);
saveParms.dwCallback = 0;
saveParms.lpfilename = "D:\\LuYin.wav";
mciSendCommand(wDeviceID, MCI_SAVE, MCI_WAIT | MCI_SAVE_FILE, (DWORD)(LPVOID)&saveParms);//保存录音
mciSendCommand(wDeviceID, MCI_CLOSE, NULL, NULL);//关闭设备
//暂停后播放录音
filePath = "D:\\LuYin.wav";
openParms.lpstrElementName = filePath.c_str();
openParms.dwCallback = (DWORD)hWnd;
mciSendCommand(wDeviceID, MCI_OPEN, MCI_WAIT | MCI_OPEN_ELEMENT, (DWORD)(LPVOID)&openParms);
wDeviceID = openParms.wDeviceID;
mciSendCommand(wDeviceID, MCI_PLAY, MCI_WAIT, (DWORD)(LPVOID)&playParms);
}