Windows Vista/7 上的 SDL_Mixer MIDI 音量问题
我实际上并不精通 C++ 或 SDL_Mixer,但无论如何我代表 Doom 社区提出这个问题。简而言之,编写 Doom 源端口的人似乎无法弄清楚如何在 Windows Vista 或 7 上使用 SDL_Mixer 独立控制正常音量和 MIDI 音量。我会让 Eternity Engine 的作者 James Haley 用他自己的话说:
Windows Vista 或 7 中似乎不存在本机 MIDI 的独立音量概念,因为在任何具有 MIDI 音量滑块的应用程序(包括大多数使用 SDL_mixer 的游戏)中使用 MIDI 音量滑块也会影响数字声音输出的音量。这使得尝试调整音乐的相对音量以获得舒适感是不可能的。
有人找到解决方法吗?我猜这不太可能,因为微软似乎在整个操作系统中不遗余力地单独控制各个声音设备的音量。
我听说过各种涉及 Timidity 驱动程序的解决方法,但这需要用户不仅仅只是在系统上安装游戏。据我所知,唯一能明确解决此问题的端口是 ZDoom,但它使用与 GPL 不兼容的 FModEx,因此不是合适的解决方案。
如果您想查看一些代码,Chocolate Doom 可能是最容易理解的 Doom 源代码移植,您可以获取其源代码 这里。
任何有关其他开源声音和音乐库的建议也将受到欢迎。
I'm not actually well versed in C++ or SDL_Mixer, but I'm asking this question anyway on behalf on the Doom community. Put simply, nobody writing Doom source ports can seem to figure out how to control normal sound volume and MIDI sound volume independently using SDL_Mixer on Windows Vista or 7. I'll let James Haley, author of Eternity Engine, put it in his own words:
Seems the concept of independent volume for native MIDI doesn't exist under Windows Vista or 7, as using MIDI volume sliders in any application that has them (including most games that use SDL_mixer) also affects the volume of digital sound output. This makes attempting to adjust the relative volume of music for comfort impossible.
Has anybody found any workarounds for this? I'm guessing it's unlikely given how Microsoft seems to have skimped throughout the OS on any way to control the volume of individual sound devices separately.
I've heard of various workarounds all involving a Timidity driver, but this requires the user go above and beyond simply installing the game on his system. The only port that I know of that definitively fixes this issue is ZDoom, but it uses the GPL-incompatible FModEx and is thus not a suitable solution.
If you want some code to look at, Chocolate Doom is perhaps the easiest Doom source port to grok and you can grab its source here.
Any suggestions on other open-source sound and music libraries would be welcome as well.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
解决方案是附带支持 FluidSynth 的 SDL_mixer。您还需要附带一个 SoundFont2 文件。幸运的是,有免费的 SF2,有些甚至针对 Doom 的 MIDI 文件进行了优化。许可证不应该是问题,因为 SoundFont 是资产,而不是代码。
然后使用 Mix_SetSoundFonts() 加载 SF2。
A solution would be to ship with a FluidSynth-enabled SDL_mixer. You would also need to ship a SoundFont2 file to go with it. Fortunately, there are free SF2's out there, and some are even optimized for Doom's MIDI files. Licenses shouldn't be a problem, since SoundFonts are assets, not code.
You then load the SF2 using Mix_SetSoundFonts().
您可能想查看 SDL 之外的不同 MIDI 库。
http://wildmidi.sourceforge.net/
http://sourceforge.net/apps/trac/fluidsynth/
http://timidity.sourceforge.net
You may want to look at different MIDI libraries outside of SDL.
http://wildmidi.sourceforge.net/
http://sourceforge.net/apps/trac/fluidsynth/
http://timidity.sourceforge.net
我正在维护一个类似的游戏端口(Descent 2),并且遇到了同样的问题。据我所知,使用 SDL_mixer 时没有解决方案。我发现,在关闭 MIDI 音乐时避免声音静音的解决方法是检索临时 MIDI 设备的句柄,将 MIDI 音量设置为最大,然后再次关闭临时设备。
I am maintaining a similar game port (Descent 2), and I have come across the same problem. Afaik there is no solution for it when using SDL_mixer. A cure to avoid sound being muted when turning off midi music I have found is to retrieve a handle to a temporary midi device, set the midi volume to max and then close the temporary device again.
很长一段时间以来,我们找到的唯一解决方案就是使用 PortMIDI 之类的东西。然而,永恒引擎的 Quasar 找到了一个巧妙的解决方案:
http://www.doomworld.com/vb/showthread.php?s=&postid=1124981#post1124981
他本质上是将SDL_Mixer放入自己的进程中并通过RPC对其进行控制。非常聪明。
For the longest time, the only solution we found was to use something like PortMIDI. However, Quasar of Eternity Engine fame has come across a neat solution:
http://www.doomworld.com/vb/showthread.php?s=&postid=1124981#post1124981
He essentially puts SDL_Mixer into its own process and controls it with RPC. Very clever.
因此,我之前给出的答案的一个问题是,有时 MIDI 子进程无法正常工作,并且会以奇怪的方式中断或停止工作。 Eternity的具体实现使用了IDL,我个人使用管道重新实现了它,但子进程本身就是一个bug磁铁。
值得庆幸的是,最近找到了另一个答案。您可以完全绕过 SDL_Mixer 并直接处理 Windows 的本机 MIDI 支持,一旦您知道自己在做什么,就不需要大量代码。
https://github.com/chocolate-doom/ Chocolate-doom/blob/master/src/i_winmusic.c
您还可以使用 PortMIDI 实现这种想法,并获得能够与外部 MIDI 设备通信的好处,如下所示 出色地。
https://github.com/odamex/odamex/blob/稳定/客户端/sdl/i_musicsystem_portmidi.cpp
So one problem with the previous answer I gave was that sometimes the MIDI subprocess did not behave itself, and would break or stop working in strange ways. Eternity's specific implementation used IDL, and I personally re-implemented it using pipes, but the subprocess itself was a bug magnet.
Thankfully, another answer was figured out rather recently. You can simply bypass SDL_Mixer entirely and deal with Windows' native MIDI support directly, which turns out to not require a ton of code once you know what you're doing.
https://github.com/chocolate-doom/chocolate-doom/blob/master/src/i_winmusic.c
You can also implement this sort of idea with PortMIDI and get the benefit of being able to communicate with external MIDI devices as well.
https://github.com/odamex/odamex/blob/stable/client/sdl/i_musicsystem_portmidi.cpp