MP3 Support
Posted: Wed Nov 18, 2009 2:42 pm
The following tutorial adds MP3 playback support to an engine under Windows with, presumably, DirectX 8 or later installed.
Credit: MH and Reckless
Requires: DX8.1 SDK "dx81sdk_full.exe" to compile (NOT needed to run the engine)
Sample implementation with binary and source: FitzQuake 0.85 MP3
Limitations:
1. Download cd_win_mp3.c (file)and add to your project.
2. Download qmp3.cpp (file) and add to your project.
3. Remove cd_win.c from your project.
Step 4.
In sound.h, add below "extern vec_t sound_nominal_clip_dist;":
Open common.h and above "void Q_memset (void *dest, int fill, int count);" add:
Open common.c and add this where you'd like. It can go to the botton of the file if you want but it'd be better to include somewhere in the vicinity of the string functions.
The MP3 playback needs to pause if the Quake window loses focus and then resume if it gets it back. At least that's what I think. And I was lazy and didn't make proper functions and just tossed commands on the command buffer.
Mostly because I have no time and would like to get this done.
Open gl_vidnt.c and locate this:
And replace it with ...
Still in gl_vidnt.c
Find this:
And add above it:
This next part, I could Google up what this is doing, but I'm low on time and don't want to. Sorry.
Done is better than not done in this one instance and I have not so much time and so many things I want to get done.
Find this:
And replace with ...
Now MH wrote this very modularly, so it is easy to implement. In the project, you need to define MP3_VERSION. In MSVC6, do Projects -> Settings. And likewise you need to add references to 2 libraries: dsound.lib strmiids.lib
Then compile!
Credit: MH and Reckless
Requires: DX8.1 SDK "dx81sdk_full.exe" to compile (NOT needed to run the engine)
Sample implementation with binary and source: FitzQuake 0.85 MP3
Limitations:
Instructions:1. No volume control for mp3 playback volume
2. No support for mp3s to be in pak files
3. Music goes in quake\<gamedir>\music or quake\id1\music folder
4. CD tracks are named track01.mp3, track02.mp3, etc.
5. Can directly play MP3s via "mp3 play track03"
6. Doing this tutorial adds MP3 support but removes CD support
1. Download cd_win_mp3.c (file)and add to your project.
2. Download qmp3.cpp (file) and add to your project.
3. Remove cd_win.c from your project.
Step 4.
In sound.h, add below "extern vec_t sound_nominal_clip_dist;":
Step 5.Code: Select all
#ifdef MP3_VERSION extern int sound_started; #endif
Open common.h and above "void Q_memset (void *dest, int fill, int count);" add:
Step 6.Code: Select all
#ifdef MP3_VERSION #undef snprintf #undef vsnprintf #ifdef WIN32 # define snprintf _snprintf # define vsnprintf _vsnprintf #endif int va_snprintf (char *function, char *buffer, size_t buffersize, const char *format, ...); int va_vsnprintf (char *function, char *buffer, size_t buffersize, const char *format, va_list args); #endif
Open common.c and add this where you'd like. It can go to the botton of the file if you want but it'd be better to include somewhere in the vicinity of the string functions.
Step #7.1Code: Select all
#ifdef MP3_VERSION // fast safe printbuffers courtesy of lord havoc. int va_snprintf (char *function, char *buffer, size_t buffersize, const char *format, ...) { va_list args; int result; va_start (args, format); result = va_vsnprintf (function, buffer, buffersize, format, args); va_end (args); return result; } int va_vsnprintf (char *function, char *buffer, size_t buffersize, const char *format, va_list args) { size_t result; result = vsnprintf (buffer, buffersize, format, args); if (result < 0 || result >= buffersize) { static qboolean inside; // Beware recursion here if (!inside) { inside = true; Con_SafePrintf ("%s: excessive string length, max = %d\n", function, buffersize); } inside = false; buffer[buffersize - 1] = '\0'; return -1; } return result; } #endif
The MP3 playback needs to pause if the Quake window loses focus and then resume if it gets it back. At least that's what I think. And I was lazy and didn't make proper functions and just tossed commands on the command buffer.
Mostly because I have no time and would like to get this done.
Open gl_vidnt.c and locate this:
Code: Select all
// enable/disable sound on focus gain/loss
if (!ActiveApp && sound_active)
{
S_BlockSound ();
sound_active = false;
}
else if (ActiveApp && !sound_active)
{
S_UnblockSound ();
sound_active = true;
}
Step #7.2Code: Select all
// enable/disable sound on focus gain/loss if (!ActiveApp && sound_active) { S_BlockSound (); #ifdef MP3_VERSION // Need to pause CD music here if is playing if (sound_started) { Cbuf_InsertText ("mp3 pause\n"); Cbuf_Execute (); } #endif sound_active = false; } else if (ActiveApp && !sound_active) { S_UnblockSound (); #ifdef MP3_VERSION // Need to unpause CD music here if was playing if (sound_started) { Cbuf_InsertText ("mp3 resume\n"); Cbuf_Execute (); } #endif sound_active = true; }
Still in gl_vidnt.c
Find this:
Code: Select all
/* main window procedure */
LONG WINAPI MainWndProc ...
Step #7.3Code: Select all
#ifdef MP3_VERSION #ifndef WM_GRAPHNOTIFY #define WM_GRAPHNOTIFY WM_USER + 13 #endif #endif
This next part, I could Google up what this is doing, but I'm low on time and don't want to. Sorry.
Done is better than not done in this one instance and I have not so much time and so many things I want to get done.
Find this:
Code: Select all
case MM_MCINOTIFY:
lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
break;
Step 8.Code: Select all
#ifdef MP3_VERSION case WM_GRAPHNOTIFY: #else case MM_MCINOTIFY: #endif lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); break;
Now MH wrote this very modularly, so it is easy to implement. In the project, you need to define MP3_VERSION. In MSVC6, do Projects -> Settings. And likewise you need to add references to 2 libraries: dsound.lib strmiids.lib
Then compile!