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 f开发者_JAVA技巧or 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.
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().
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
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.
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.
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
精彩评论