diff --git a/docs/rh-log.txt b/docs/rh-log.txt index fc5917152b..06a1773996 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,10 @@ March 26, 2008 (Changes by Graf Zahl) +- Fixed: After starting new music the music volume has to be reset so that + the song's relative volume takes effect. +- Removed the arbitrary 1024 bytes limit when the file being played is a MIDI + file. I had a D_DM2TTL that's only 990 bytes. +- Restructured I_RegisterSong so that $mididevice works again and also supports + selecting FMOD. - Added Jim' Linux fix. - Added MartinHowe's fix for mugshot display in status bars. diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 64647ca148..055f318a93 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -1261,10 +1261,11 @@ static void S_AddSNDINFO (int lump) sc.MustGetString(); FName nm = sc.String; sc.MustGetString(); - if (sc.Compare("timidity")) MidiDevices[nm] = 1; - else if (sc.Compare("standard")) MidiDevices[nm] = 0; - else if (sc.Compare("opl")) MidiDevices[nm] = 2; - else if (sc.Compare("default")) MidiDevices[nm] = -1; + if (sc.Compare("timidity")) MidiDevices[nm] = MDEV_TIMIDITY; + else if (sc.Compare("fmod")) MidiDevices[nm] = MDEV_FMOD; + else if (sc.Compare("standard")) MidiDevices[nm] = MDEV_MMAPI; + else if (sc.Compare("opl")) MidiDevices[nm] = MDEV_OPL; + else if (sc.Compare("default")) MidiDevices[nm] = MDEV_DEFAULT; else sc.ScriptError("Unknown MIDI device %s\n", sc.String); } break; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index c47b1b8c77..b54f589e23 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1307,10 +1307,10 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) { int lumpnum = -1; int offset, length; - int device = -1; + int device = MDEV_DEFAULT; - int * devp = MidiDevices.CheckKey(FName(musicname)); + int *devp = MidiDevices.CheckKey(FName(musicname)); if (devp != NULL) device = *devp; if (!FileExists (musicname)) diff --git a/src/s_sound.h b/src/s_sound.h index f05498eb7f..f5ab57e35f 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -311,6 +311,15 @@ ReverbContainer *S_FindEnvironment (const char *name); ReverbContainer *S_FindEnvironment (int id); void S_AddEnvironment (ReverbContainer *settings); +enum EMidiDevice +{ + MDEV_DEFAULT = -1, + MDEV_MMAPI = 0, + MDEV_TIMIDITY = 1, + MDEV_OPL = 2, + MDEV_FMOD = 3, +}; + typedef TMap MidiDeviceMap; extern MidiDeviceMap MidiDevices; diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp index 8c4b706d38..6f34385523 100644 --- a/src/sound/i_music.cpp +++ b/src/sound/i_music.cpp @@ -192,6 +192,9 @@ void I_PlaySong (void *handle, int _looping, float rel_vol) currSong = info; else currSong = NULL; + + // Notify the sound system of the changed relative volume + snd_musicvolume.Callback(); } @@ -275,144 +278,182 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le memcpy(&id, &musiccache[0], 4); } +#ifndef _WIN32 + // non-windows platforms don't support MDEV_MIDI so map to MDEV_FMOD + if (device == MDEV_MMAPI) device = MDEV_FMOD; +#endif + + // Check for MUS format if (id == MAKE_ID('M','U','S',0x1a)) { - if (GSnd != NULL && device != 0 && device != 1 && (opl_enable || device == 2) ) + if (GSnd != NULL) { - info = new OPLMUSSong (file, musiccache, len); + /* MUS are played as: + - OPL: + - if explicitly selected by $mididevice + - when opl_enable is true and no midi device is set for the song + + Timidity: + - if explicitly selected by $mididevice + - when snd_mididevice is -2 and no midi device is set for the song + + FMod: + - if explicitly selected by $mididevice + - when snd_mididevice is -1 and no midi device is set for the song + - as fallback when both OPL and Timidity failed unless snd_mididevice is >= 0 + + MMAPI (Win32 only): + - if explicitly selected by $mididevice (non-Win32 redirects this to FMOD) + - when snd_mididevice is >= 0 and no midi device is set for the song + - as fallback when both OPL and Timidity failed and snd_mididevice is >= 0 + */ + if ((opl_enable && device == MDEV_DEFAULT) || device == MDEV_OPL) + { + info = new OPLMUSSong (file, musiccache, len); + } + else if (device == MDEV_TIMIDITY || (device == MDEV_DEFAULT && snd_mididevice == -2)) + { + info = new TimiditySong (file, musiccache, len); + } + if (info != NULL && !info->IsValid()) + { + delete info; + info = NULL; + device = MDEV_DEFAULT; + } + if (info == NULL && (snd_mididevice == -1 || device == MDEV_FMOD) && device != MDEV_MMAPI) + { + TArray midi; + bool midi_made = false; + + if (file == NULL) + { + midi_made = ProduceMIDI((BYTE *)musiccache, midi); + } + else + { + BYTE *mus = new BYTE[len]; + size_t did_read = fread(mus, 1, len, file); + if (did_read == len) + { + midi_made = ProduceMIDI(mus, midi); + } + fseek(file, -(long)did_read, SEEK_CUR); + delete[] mus; + } + if (midi_made) + { + /* + FILE *f = fopen("latest.mid", "wb"); + fwrite(&midi[0], 1, midi.Size(), f); + fclose(f); + */ + info = new StreamSong((char *)&midi[0], -1, midi.Size()); + if (!info->IsValid()) + { + delete info; + info = NULL; + } + } + } } +#ifdef _WIN32 if (info == NULL) { -#ifdef _WIN32 - if (device == 1 && GSnd != NULL) + info = new MUSSong2 (file, musiccache, len); + } +#endif // _WIN32 + } + // Check for MIDI format + else + { + + if (id == MAKE_ID('M','T','h','d')) + { + // This is a midi file + // MIDI can't be played with OPL so use default. + if (device == MDEV_OPL) device = MDEV_DEFAULT; + + /* MIDI are played as: + Timidity: + - if explicitly selected by $mididevice + - when snd_mididevice is -2 and no midi device is set for the song + + FMod: + - if explicitly selected by $mididevice + - when snd_mididevice is -1 and no midi device is set for the song + - as fallback when Timidity failed unless snd_mididevice is >= 0 + + MMAPI (Win32 only): + - if explicitly selected by $mididevice (non-Win32 redirects this to FMOD) + - when snd_mididevice is >= 0 and no midi device is set for the song + - as fallback when Timidity failed and snd_mididevice is >= 0 + */ + + if ((device == MDEV_TIMIDITY || (snd_mididevice == -2 && device == MDEV_DEFAULT)) && GSnd != NULL) { info = new TimiditySong (file, musiccache, len); if (!info->IsValid()) { delete info; info = NULL; + device = MDEV_DEFAULT; } } - if (info == NULL && (snd_mididevice >= 0 || device == 0)) - { - info = new MUSSong2 (file, musiccache, len); - } - else if (info == NULL && GSnd != NULL) -#endif // _WIN32 - { - if (snd_mididevice == -1) - { - TArray midi; - bool midi_made = false; - - if (file == NULL) - { - midi_made = ProduceMIDI((BYTE *)musiccache, midi); - } - else - { - BYTE *mus = new BYTE[len]; - size_t did_read = fread(mus, 1, len, file); - if (did_read == len) - { - midi_made = ProduceMIDI(mus, midi); - } - fseek(file, -(long)did_read, SEEK_CUR); - delete[] mus; - } - if (midi_made) - { - FILE *f = fopen("latest.mid", "wb"); - fwrite(&midi[0], 1, midi.Size(), f); - fclose(f); - info = new StreamSong((char *)&midi[0], -1, midi.Size()); - if (!info->IsValid()) - { - delete info; - info = NULL; - } - } - } - if (info == NULL) - { - info = new TimiditySong (file, musiccache, len); - } - } - } - } - // Check for MIDI format - else if (id == MAKE_ID('M','T','h','d')) - { - // This is a midi file #ifdef _WIN32 - if (device == 1 && GSnd != NULL) - { - info = new TimiditySong (file, musiccache, len); - if (!info->IsValid()) + if (info == NULL && device != MDEV_FMOD && (snd_mididevice >= 0 || device == MDEV_MMAPI)) { - delete info; - info = NULL; + info = new MIDISong2 (file, musiccache, len); } - } - else if (info == NULL && (snd_mididevice >= 0 || device == 0)) - { - info = new MIDISong2 (file, musiccache, len); - } - else if (info == NULL && GSnd != NULL) #endif // _WIN32 + } + // Check for RDosPlay raw OPL format + else if (id == MAKE_ID('R','A','W','A') && len >= 12) { - if (snd_mididevice != -1) + DWORD fullsig[2]; + + if (file != NULL) { - info = new TimiditySong (file, musiccache, len); + if (fread (fullsig, 4, 2, file) != 2) + { + fclose (file); + return 0; + } + fseek (file, -8, SEEK_CUR); + } + else + { + memcpy(fullsig, musiccache, 8); + } + + if (fullsig[1] == MAKE_ID('D','A','T','A')) + { + info = new OPLMUSSong (file, musiccache, len); } } - } - // Check for RDosPlay raw OPL format - else if (id == MAKE_ID('R','A','W','A') && len >= 12) - { - DWORD fullsig[2]; - - if (file != NULL) + // Check for Martin Fernandez's modified IMF format + else if (id == MAKE_ID('A','D','L','I')) { - if (fread (fullsig, 4, 2, file) != 2) + char fullhead[6]; + + if (file != NULL) { - fclose (file); - return 0; + if (fread (fullhead, 1, 6, file) != 6) + { + fclose (file); + return 0; + } + fseek (file, -6, SEEK_CUR); } - fseek (file, -8, SEEK_CUR); - } - else - { - memcpy(fullsig, musiccache, 8); - } - - if (fullsig[1] == MAKE_ID('D','A','T','A')) - { - info = new OPLMUSSong (file, musiccache, len); - } - } - // Check for Martin Fernandez's modified IMF format - else if (id == MAKE_ID('A','D','L','I')) - { - char fullhead[6]; - - if (file != NULL) - { - if (fread (fullhead, 1, 6, file) != 6) + else { - fclose (file); - return 0; + memcpy(fullhead, musiccache, 6); + } + if (fullhead[4] == 'B' && fullhead[5] == 1) + { + info = new OPLMUSSong (file, musiccache, len); } - fseek (file, -6, SEEK_CUR); - } - else - { - memcpy(fullhead, musiccache, 6); - } - if (fullhead[4] == 'B' && fullhead[5] == 1) - { - info = new OPLMUSSong (file, musiccache, len); } } @@ -440,12 +481,13 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le } } } - + // no FMOD => no modules/streams // 1024 bytes is an arbitrary restriction. It's assumed that anything // smaller than this can't possibly be a valid music file if it hasn't // been identified already, so don't even bother trying to load it. - if (info == NULL && GSnd != NULL && len >= 1024) + // Of course MIDIs shorter than 1024 bytes should pass. + if (info == NULL && GSnd != NULL && (len >= 1024 || id == MAKE_ID('M','T','h','d'))) { // Let FMOD figure out what it is. if (file != NULL) @@ -457,6 +499,7 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le } } + if (info && !info->IsValid ()) { delete info;