- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 C++ Win32 应用程序,它需要能够在每次触发特定事件时播放外部 .wav
文件。我目前的代码如下所示:
void CALLBACK timerCall(HWND hwnd, UINT msg, UINT timer, DWORD time)
{
if(/*some condition is met*/)
{
std::cout << "Detected event" << std::endl;
PlaySound("file.wav", NULL, SND_FILENAME | SND_ASYNC);
}
}
问题是,.wav
文件有几秒钟长,我希望每次调用该事件都能播放该声音的新实例。如果没有 SND_ASYNC
,它不会触发事件,直到声音播放完毕;这是通过添加 SND_ASYNC
解决的。但是,现在如果在声音已经播放时再次触发该事件,它会中断播放并简单地重新开始而不是重叠声音。
如何防止对 PlaySound
的新调用打断之前的调用并强制声音重叠?
最佳答案
“waveaudio”设备(由 PlaySound 使用)不支持同时播放多个文件。尝试使用 .mp3 文件。示例如下。
#include <Windows.h>
#include <stdio.h>
#include <stdexcept>
#ifdef _UNICODE
#define stprintf_s swprintf_s
#else
#define stprintf_s sprintf_s
#endif
class Player {
public:
Player(LPCTSTR lpFileName) {
MCI_OPEN_PARMS openp;
MCI_SET_PARMS setp;
openp.dwCallback = NULL;
openp.lpstrDeviceType = reinterpret_cast<LPCTSTR>(MCI_ALL_DEVICE_ID);
openp.lpstrElementName = lpFileName;
TCHAR name[32];
static int alias = 0;
stprintf_s(name, TEXT("alias%08d"), alias++);
openp.lpstrAlias = name;
checkerror(mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_ELEMENT | MCI_OPEN_SHAREABLE | MCI_OPEN_ALIAS, reinterpret_cast<DWORD_PTR>(&openp)));
_device = openp.wDeviceID;
setp.dwCallback = NULL;
setp.dwTimeFormat = 0;
if (mciSendCommand(openp.wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, reinterpret_cast<DWORD_PTR>(&setp)) == DWORD(-1)) {
close();
throw std::runtime_error("Can't open MCI device");
}
}
Player(Player const&) = delete;
Player(Player&& other) {
_device = other._device;
other._device = 0;
}
~Player() {
if (_device != 0) {
close();
}
}
void play(HWND hWndNotify) {
MCI_PLAY_PARMS params;
params.dwCallback = reinterpret_cast<DWORD_PTR>(hWndNotify);
params.dwFrom = NULL;
params.dwTo = NULL;
checkerror(mciSendCommand(_device, MCI_PLAY, (hWndNotify != 0) ? MCI_NOTIFY : 0, reinterpret_cast<DWORD_PTR>(¶ms)));
}
void rewind() {
MCI_SEEK_PARMS params;
checkerror(mciSendCommand(_device, MCI_SEEK, MCI_WAIT | MCI_SEEK_TO_START, reinterpret_cast<DWORD_PTR>(¶ms)));
}
void pause() {
MCI_GENERIC_PARMS params;
params.dwCallback = NULL;
checkerror(mciSendCommand(_device, MCI_PAUSE, MCI_WAIT, reinterpret_cast<DWORD_PTR>(¶ms)));
}
void stop() {
MCI_GENERIC_PARMS params;
params.dwCallback = NULL;
checkerror(mciSendCommand(_device, MCI_STOP, MCI_WAIT, reinterpret_cast<DWORD_PTR>(¶ms)));
}
MCIDEVICEID device() const { return _device; }
private:
MCIDEVICEID _device;
static void checkerror(MCIERROR code) {
if (code != 0) {
char buffer[260];
mciGetErrorStringA(code, buffer, sizeof(buffer) - 1);
throw std::runtime_error(buffer);
}
}
void close() {
MCI_GENERIC_PARMS params;
params.dwCallback = NULL;
checkerror(mciSendCommand(_device, MCI_CLOSE, MCI_WAIT, reinterpret_cast<DWORD_PTR>(¶ms)));
}
};
#include <map>
#include <string>
#include <mutex>
#ifdef _UNICODE
typedef std::wstring tstring;
#else
typedef std::string tstring;
#endif
class Repeater {
public:
Repeater(LPCTSTR fn) : fn(fn) {
hWnd = CreateWindowEx(0, TEXT("STATIC"), NULL, 0, 0, 0, 0, 0, HWND_DESKTOP, NULL, GetModuleHandle(NULL), 0);
if (hWnd == NULL)
throw std::runtime_error("Can't create window");
oldproc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_WNDPROC));
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG>(this));
SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG>(&myproc));
}
~Repeater() {
DestroyWindow(hWnd);
}
void play() {
Player player(fn.c_str());
std::lock_guard<std::recursive_mutex> lock(devmap_mutex);
player.play(hWnd);
devmap.insert(decltype(devmap)::value_type(player.device(), std::move(player)));
}
HWND wnd() const { return hWnd; }
void stop() {
std::lock_guard<std::recursive_mutex> lock(devmap_mutex);
devmap.clear();
}
private:
HWND hWnd;
tstring fn;
std::recursive_mutex devmap_mutex;
std::map<MCIDEVICEID, Player> devmap;
WNDPROC oldproc;
static LRESULT CALLBACK myproc(_In_ HWND hWnd, _In_ UINT Msg, _In_ WPARAM wParam, _In_ LPARAM lParam) {
auto self = reinterpret_cast<Repeater*>(GetWindowLong(hWnd, GWLP_USERDATA));
switch (Msg) {
case MM_MCINOTIFY: {
// see https://msdn.microsoft.com/ru-ru/library/windows/desktop/dd757358(v=vs.85).aspx
std::lock_guard<std::recursive_mutex> lock(self->devmap_mutex);
self->devmap.erase(static_cast<MCIDEVICEID>(lParam));
return 0;
}
case WM_DESTROY: {
SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG>(self->oldproc));
}
default:
break;
}
return CallWindowProc(self->oldproc, hWnd, Msg, wParam, lParam);
}
};
int main() {
// USE MP3. Forget about WAV.
LPCTSTR filename = TEXT("c:\\Users\\Vyacheslav\\Music\\Ori\\soundtrack\\Racing the Lava.mp3");
#if 0
// without notifications
Player dev1(filename), dev2(filename);
dev1.play();
Sleep(1000);
dev2.play();
Sleep(10000);
#else
// with notifications
{
Repeater rep(filename);
std::thread thread([&rep] {
for (int i = 0; i < 5; ++i) {
rep.play();
Sleep(1000);
}
Sleep(1000);
rep.stop(); // .stop() MUST be called from the same thread as ALL .play() !!!
PostMessage(rep.wnd(), WM_QUIT, 0, 0); // interrupt message processing queue
});
MSG msg;
while (GetMessage(&msg, 0, 0, 0)) {
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
thread.join();
}
Sleep(10000); // silence
#endif
return 0;
}
关于c++ - Win32 PlaySound 重叠音频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38597898/
我一直在寻找一页以上的Google搜索结果,试图解决此问题。 我正在尝试使PlaySound()函数正常工作,但我终生无法实现。 这是我的完整代码: #include #include using
第一个问题,对不起,如果我没有做正确的事情:S。我正在尝试在控制台窗口中创建的游戏播放时循环播放背景音轨。这是小组项目的一部分。游戏运行正常,但我无法使用PlaySound()函数来播放音轨。这是我尝
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求提供代码的问题必须表现出对所解决问题的最低限度的了解。包括尝试的解决方案、为什么它们不起作用以及预期结果
我对如何将 PlaySound() 与资源文件一起使用感到有点困惑,因为阅读此处并测试所有内容,我无法在控制台提示符 u_u 中获取 wav 文件声音。所以,如果你能帮助我,我将非常感激。$ #inc
我正在用 C 编写一个函数来播放 wav 文件。我可以播放一次声音,但我想添加一个循环选项。 我有两种工作模式: play from file name play from memory. 在两种模式
对于我的游戏,我将 Windows API 中的 PlaySound 函数用于我的音乐和声音。但是,当我在播放音乐时尝试播放声音时,音乐会停止,我只能听到声音。 我的音乐是这样播放的: PlaySou
我的程序中有以下代码: self["text"]="✖" self["bg"]="red" self["relief"] = SUNKEN self
我想就有关音乐操作的应用程序提出一个问题:我用函数 PlaySound() 编译了一个程序,但显示了以下消息:[Linker error] undefined reference到“PlaySound
我有一个俄罗斯方 block 游戏,我想给它添加背景音乐。我正在尝试使用 PlaySound(TEXT("Tetris.wav"), NULL, SND_SYNC);但是我得到的不是音乐,而是“win
我正在尝试使用 PlaySound(); C++中的函数。我想让用户输入他们想播放的文件。但是当我把变量放在 PlaySound();它给了我一个错误。这是代码, #include #include
所以我正在尝试制作一个简单的 DLL 来在另一个程序中播放声音。我正在尝试使用 playsound 功能,并且已对其进行设置,但是当我在其他程序中运行它时,我会听到默认的蜂鸣声。这是我的代码。 exp
编辑所以代码是正确的(感谢 ta.speot.is) - 底部的新问题 所以我一直在玩这个级别的控制台,我们被要求制作我们的第一个“项目”进行评估。我已经完成了基本的应用程序.. 但我想稍微提高一下并
基本上我想使用 PlaySound() ctypes 中的函数。 Yes I know winsound module is built on it and I could use that, but
我有一个 C++ Win32 应用程序,它需要能够在每次触发特定事件时播放外部 .wav 文件。我目前的代码如下所示: void CALLBACK timerCall(HWND hwnd, UINT
我的设备 WinCE 5.0 有问题。我需要从资源播放声音。 BOOL PlayResource (int lpName) { BOOL bRtn; LPTSTR lpRes; HANDL
winsound.PlaySound('1.wav', winsound.SND_FILENAME) time.sleep(0.15) winsound.PlaySound('1.wav', wins
我正在编写一个 C++ Windows 应用程序,它需要播放从数组中随机选择的歌曲,并且用户需要能够通过单击按钮播放列表中的另一首歌曲。你会如何停止第一首歌曲的声音来播放第二首歌曲? 按下我播放第一首
编辑:已解决。 Windows 不接受 .wav 文件。我提取了一个 Windows 自己的文件并将其重命名为我以前的文件的名称,并且播放没有问题。 我不知道为什么这不能播放现有文件。 Windows
我一直在测试声音,我注意到 PlaySound 是阻塞的,即它会等到声音播放完毕才返回。 #include #include #include int main() { PlaySoun
我在当前目录中使用 PlaySound() 函数播放声音时遇到问题。在以下情况下,我收到系统蜂鸣声而不是我的原始文件声音,除了第一个我有整个目录的声音。 这个很完美: PlaySound(TEXT("
我是一名优秀的程序员,十分优秀!