VOGONS


First post, by Kneesnap

User metadata
Rank Newbie
Rank
Newbie

Hi all,

Many old PC games stored their music as redbook CD audio tracks, and sometime in the early 2000s (Windows XP) this broke due to some change in Windows, or at least that's what I remember reading at some point. Programs like inmm.dll, DxWnd, and probably more are able to fix this problem, but I have a different situation.

I have the source code to the game I'm trying to fix (will be available publicly soon), and am using it to make a better PC port. One of the things we want to add is a fix to CD audio so that without needing to install anything like dgVoodoo or DxWnd, CD audio can just work. Unfortunately, I'm having trouble finding any information online about the technical reasons that CD audio stopped working. If anyone here has any information, documentation, or anything else which could be helpful, it would be much appreciated.

Thanks!

Reply 1 of 6, by jakethompson1

User metadata
Rank Oldbie
Rank
Oldbie

Around that time the default shifted from "analog" CD playback (where the computer just sends brief commands to the drive saying play track 2, etc., and the audio goes directly from the drive to the sound card via a cable) to "digital" CD playback (where the computer "rips" the digital audio from the CD into memory, sends it to the sound card, then throws it away).

If that isn't the issue, perhaps modern sound cards want 48000 Hz audio and not 44100 and it needs resampled on the fly?

I'm not familiar with those third-party DLLs you mention and how they function. Do they fix audio CD playback or simply redirect it to play .MP3 files from the file system instead? (Since so many people don't want physical CDs nowadays) And what is it that you want to do?

Reply 2 of 6, by Kneesnap

User metadata
Rank Newbie
Rank
Newbie
jakethompson1 wrote on 2023-07-31, 22:28:

Around that time the default shifted from "analog" CD playback (where the computer just sends brief commands to the drive saying play track 2, etc., and the audio goes directly from the drive to the sound card via a cable) to "digital" CD playback (where the computer "rips" the digital audio from the CD into memory, sends it to the sound card, then throws it away).

If that isn't the issue, perhaps modern sound cards want 48000 Hz audio and not 44100 and it needs resampled on the fly?

Hmm, looking at the code it does appear to be sending a command that says "play track", I don't see anything related to audio buffering though I've only skimmed it. The game was made in 2000 though, and I saw "Frogger (1997)", a game 3 years prior get a fix posted here on Vogons (all the way back in 2004) which fixed audio playback from the CD as well, and if I recall it didn't do anything like a complete rewrite of reading audio.

Audio Source Code
// Plays a specified audio track using MCI_OPEN, MCI_PLAY. Returns as 
// soon as playback begins. The window procedure function for the
// specified window will be notified when playback is complete.
// Returns 0L on success; otherwise, returns an MCI error code.
DWORD playCDTrack ( HWND hWndNotify, BYTE bTrack )
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_SET_PARMS mciSetParms;
MCI_PLAY_PARMS mciPlayParms;
DWORD flags;

if( !mciDevice )
{
// Open the CD audio device by specifying the device name.
mciOpenParms.lpstrDeviceType = "cdaudio";

if ( dwReturn = mciSendCommand( 0, MCI_OPEN, MCI_OPEN_TYPE, ( DWORD ) ( LPVOID ) &mciOpenParms ) )
{
if( dwReturn == MCIERR_MUST_USE_SHAREABLE )
{
utilPrintf("Failed to open device %s, trying shareable...\n", mciOpenParms.lpstrDeviceType );
if ( dwReturn = mciSendCommand( 0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, ( DWORD ) ( LPVOID ) &mciOpenParms ) )
{
utilPrintf("Failed to open device %s\n",mciOpenParms.lpstrDeviceType);
// Failed to open device. Don't close it; just return error.
return dwReturn;
}
}
}

// The device opened successfully; get the device ID.
wDeviceID = mciOpenParms.wDeviceID;

// Set the time format to track/minute/second/frame (TMSF).
mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;

if (dwReturn = mciSendCommand ( wDeviceID, MCI_SET,MCI_SET_TIME_FORMAT, ( DWORD ) ( LPVOID ) &mciSetParms ) )
{
utilPrintf("Failed to set time format for cd device\n");

mciSendCommand( wDeviceID, MCI_CLOSE, 0, 0 );
return dwReturn;
}
}
else // Repeat performance
{
wDeviceID = mciDevice;
}

// Begin playback from the given track and play until the beginning
// of the next track.
mciPlayParms.dwTo = 0L;
mciPlayParms.dwFrom = MCI_MAKE_TMSF ( bTrack, 0, 0, 0 );
mciPlayParms.dwTo = MCI_MAKE_TMSF ( bTrack + 1, 0, 0, 0 );
mciPlayParms.dwCallback = ( DWORD ) hWndNotify;

if( bTrack != LEVELCOMPLETELOOP_CDAUDIO )
flags = MCI_FROM | MCI_TO | MCI_NOTIFY;
Show last 16 lines
	else
flags = MCI_FROM | MCI_NOTIFY;

if ( dwReturn = mciSendCommand ( wDeviceID, MCI_PLAY, flags, (DWORD)(LPVOID) &mciPlayParms ) )
{
utilPrintf("Couldn't play cd track %i\n",bTrack);

mciSendCommand ( wDeviceID, MCI_CLOSE, 0, 0 );
return dwReturn;
}

mciDevice = wDeviceID;

return 0L;
}
jakethompson1 wrote on 2023-07-31, 22:28:

I'm not familiar with those third-party DLLs you mention and how they function. Do they fix audio CD playback or simply redirect it to play .MP3 files from the file system instead? (Since so many people don't want physical CDs nowadays) And what is it that you want to do?

Some of them play audios from the filesystem, but I've seen at least one which was able to fix it to play audio directly from the CD again. I plan to support both, but reading from the filesystem shouldn't be too hard. The original game is very finnicky with a lot of things so I'm trying to make the modern version as seamless as possible.

Reply 3 of 6, by jakethompson1

User metadata
Rank Oldbie
Rank
Oldbie

For troubleshooting purposes I would (temporarily) break out the audio CD-playing code into a separate program--essentially write your own audio CD player. It would be better if the above code logged the error code if the mci functions fail, and also it would be better if those MCI_*_PARMS structs were zeroed out before using them since they are only partially initialized.

Reply 4 of 6, by Kneesnap

User metadata
Rank Newbie
Rank
Newbie
jakethompson1 wrote on 2023-07-31, 22:50:

For troubleshooting purposes I would (temporarily) break out the audio CD-playing code into a separate program--essentially write your own audio CD player. It would be better if the above code logged the error code if the mci functions fail, and also it would be better if those MCI_*_PARMS structs were zeroed out before using them since they are only partially initialized.

The error code is not logged, but that can be changed. Good idea about clearing the uninitialized data too.

I like your idea of breaking it out into a standalone program too, should make it easier to debug, gonna give it a go soon.

Reply 5 of 6, by Falcosoft

User metadata
Rank Oldbie
Rank
Oldbie

The biggest MCI CD audio related breaking change happened with Windows Vista. More info about the problem that caused tracks do not repeat issues:
https://social.msdn.microsoft.com/Forums/wind … udiodevelopment

MCI cdaudio not repeating (looping) on modern Windows systems

Website, Facebook, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper

Reply 6 of 6, by BEEN_Nath_58

User metadata
Rank l33t
Rank
l33t

DxWnd uses their own tool MCITool to analyse behaviour of MCI functions (video, CD audio, other audio...) on Win9x to Win11. There is "no complete change documentation" as to what changed that broke CD audio in Window Vista (not XP). XP had a modified CD audio plan, not a broken one; a good example to test it is to use the game Frogger 2 and analyse the CD audio behaviour in the 1st level.

CDaudio didn't break specifically. It was MCI. Games like Half Life, which have skippable intros, don't skip anymore because the "BREAK" command doesn't work. It's a part of MCI so the entire MCI system is at fault.

previously known as Discrete_BOB_058