我希望能够在我的程序中的某个特定时间(例如,进入歌曲的30秒)开始播放一首歌曲,该程序复制了一个广播电台,当您更改频道时,歌曲已经在播放或几乎在播放完成。
目前,我使用PlaySound,并将26首歌曲另存为wav文件和程序中的资源。我已经看到mciSendString是一个选项,但是我不明白在使用Windows API和C ++进行编码时如何设法使其工作。
这是我当前的PlayWavFile函数(其中资源整数是从0到25的随机生成的数字,强制转换为该函数以播放随机歌曲):
void PlayWavFile(int resource) {
PlaySound(MAKEINTRESOURCE(resource), hInst, SND_RESOURCE | SND_ASYNC);
}
我希望能够使用我预先确定的整数值(例如持续时间)以某种方式播放歌曲。
答案 0 :(得分:2)
我已经将mciSendString作为选项,但是我不知道如何 使用Windows API和C ++进行编码时,我可以设法使其正常工作。
您可以阅读Multimedia Command Strings之类的MSDN文档来了解命令的语法
从1秒钟读取wav文件的基本示例=>
int rc = mciSendString(L"open E:\\test.wav alias wav1", NULL, 0, 0);
if (rc == 0)
{
rc = mciSendString(L"set wav1 time format ms", NULL, 0, 0);
rc = mciSendString(L"seek wav1 to 1000", NULL, 0, 0);
if (rc == 0)
{
rc = mciSendString(L"play wav1", NULL, 0, 0);
}
else
{
// handle error (like MCIERR_OUTOFRANGE for example)
}
}
else
{
// handle error
}
答案 1 :(得分:2)
要将MCI与mciSendCommand
一起使用,您应该
或
示例:
#include <windows.h>
#pragma comment(lib, "winmm.lib")
MCIDEVICEID MCIOpen(LPCTSTR strPath)
{
MCI_OPEN_PARMS mciOP;
DWORD opReturn;
mciOP.lpstrDeviceType = NULL;
mciOP.lpstrElementName = strPath; //Set the .wav file name to open
opReturn = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_ELEMENT, (DWORD)(LPVOID)&mciOP);
if (!opReturn)
return mciOP.wDeviceID;
return -1;
}
DWORD MCISeek(MCIDEVICEID wDeviceID,int sec)
{
MCI_SEEK_PARMS SeekParms;
SeekParms.dwTo = (sec) * 1000;
return mciSendCommand(wDeviceID, MCI_SEEK, MCI_TO, (DWORD)(LPVOID)&SeekParms);
}
DWORD MCIPlay(MCIDEVICEID wDeviceID)
{
MCI_PLAY_PARMS mciPP;
return mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY| MCI_WAIT, (DWORD)&mciPP);
}
DWORD MCIPlayFrom(MCIDEVICEID wDeviceID,int sec)
{
MCI_PLAY_PARMS play;
play.dwFrom = sec*1000;//Play From sec*1000 ms
return mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM| MCI_WAIT, (DWORD)&play);
}
int main()
{
//open device
MCIDEVICEID wDeviceID = MCIOpen("test.wav"); //Save DeviceID
DWORD opReturn;
if (wDeviceID != -1)
{
//MCI_SET_PARMS mciSet;
//mciSet.dwTimeFormat = MCI_FORMAT_MILLISECONDS;//set time format to milliseconds
//opReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID)&mciSet);
////set the position at 30s.
//opReturn = MCISeek(wDeviceID, 30);
////play
//opReturn = MCIPlay(wDeviceID);
opReturn = MCIPlayFrom(wDeviceID,30);
}
return opReturn;
}
请注意,如果要获取声音,则在使用MCI_WAIT
时需要MCI_PLAY
标志。
编辑:
您无法听到声音,因为开始播放后运行时间很短。它将启动播放并立即将其关闭(可以在播放开始后通过添加Sleep()
进行验证)。请参见related issue。如果您不想等待播放,则需要处理MCI_NOTIFY
,设置回调窗口句柄,并在播放结束后处理MM_MCINOTIFY
。
#include <windows.h>
#pragma comment(lib, "winmm.lib")
HWND hwnd;
MCIDEVICEID MCIOpen(LPCTSTR strPath)
{
MCI_OPEN_PARMS mciOP;
DWORD opReturn;
mciOP.lpstrDeviceType = NULL;
mciOP.lpstrElementName = strPath; //Set the .wav file name to open
opReturn = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_ELEMENT, (DWORD)(LPVOID)&mciOP);
if (!opReturn)
return mciOP.wDeviceID;
return -1;
}
DWORD MCISeek(MCIDEVICEID wDeviceID,int sec)
{
MCI_SEEK_PARMS SeekParms;
SeekParms.dwTo = (sec) * 1000;
return mciSendCommand(wDeviceID, MCI_SEEK, MCI_TO, (DWORD)(LPVOID)&SeekParms);
}
DWORD MCIPlay(MCIDEVICEID wDeviceID)
{
MCI_PLAY_PARMS mciPP;
mciPP.dwCallback = (DWORD_PTR)hwnd;
return mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)&mciPP);
}
DWORD MCIPlayFrom(MCIDEVICEID wDeviceID,int sec)
{
MCI_PLAY_PARMS play;
play.dwFrom = sec*1000;//Play From sec*1000 ms
return mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM, (DWORD)&play);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case MM_MCINOTIFY:
{
if (MCI_NOTIFY_SUCCESSFUL == wParam) //MCI_NOTIFY_SUCCESSFUL means that the song has been played successfully.
{
//To Do
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int main()
{
static const char* class_name = "DUMMY_CLASS";
WNDCLASSEX wx = {};
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = WndProc; // function which will handle messages
wx.hInstance = GetModuleHandleA(NULL);
wx.lpszClassName = class_name;
if (RegisterClassEx(&wx)) {
hwnd = CreateWindowEx(0, class_name, "dummy_name", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
}
//open device
MCIDEVICEID wDeviceID = MCIOpen("test.wav"); //Save DeviceID
DWORD opReturn;
if (wDeviceID != -1)
{
//MCI_SET_PARMS mciSet;
//mciSet.dwTimeFormat = MCI_FORMAT_MILLISECONDS;//set time format to milliseconds
//opReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID)&mciSet);
////set the position at 30s.
//opReturn = MCISeek(wDeviceID, 30);
////play
//opReturn = MCIPlay(wDeviceID);
opReturn = MCIPlayFrom(wDeviceID,30);
}
HACCEL hAccelTable = LoadAccelerators(wx.hInstance, class_name);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
答案 2 :(得分:0)
有很多可以播放声音的库,但是如果您想继续使用PlaySound()
,可以使用以下方法:
因此,尽管这可能不是最简单的方法,但是您可以打开原始声音,跳过前N秒(使用.wav文件非常容易,因为它们是恒定比特率并且没有关键帧),请存储该声音作为一种新资源,最后使用它。