I_FadeOutStopMusic, I_FadeInStartDigSong, S_ChangeMusicWithFade implementation

* First attempt, a little messy but works fine
This commit is contained in:
mazmazz 2018-08-19 22:05:23 -04:00
parent 783ccf8c67
commit 87df31a685
4 changed files with 162 additions and 18 deletions

View file

@ -251,10 +251,15 @@ void I_SetInternalMusicVolume(UINT8 volume);
void I_StopFadingMusic(void); void I_StopFadingMusic(void);
boolean I_FadeMusicFromLevel(UINT8 target_volume, UINT16 source_volume, UINT32 ms); boolean I_FadeMusicFromLevel(UINT8 target_volume, UINT8 source_volume, UINT32 ms, boolean stopafterfade);
boolean I_FadeMusic(UINT8 target_volume, UINT32 ms); boolean I_FadeMusic(UINT8 target_volume, UINT32 ms);
boolean I_FadeOutStopMusic(UINT32 ms);
boolean I_FadeInStartDigSong(const char *musicname, UINT16 track, boolean looping, UINT32 position, UINT32 fadeinms, boolean queuepostfade);
#define I_QueueDigSongPostFade(a,b,c,d,e) I_FadeInStartDigSong(a,b,c,d,e,1)
/** \brief The I_StartDigSong function /** \brief The I_StartDigSong function
\param musicname music lump name \param musicname music lump name

View file

@ -1379,7 +1379,7 @@ static boolean S_DigMusic(const char *mname, boolean looping)
return true; return true;
} }
void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) void S_ChangeMusicWithFade(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms)
{ {
if ((nomidimusic || music_disabled) && (nodigimusic || digital_disabled)) if ((nomidimusic || music_disabled) && (nodigimusic || digital_disabled))
return; return;
@ -1402,13 +1402,47 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
if (strncmp(music_name, newmusic, 6)) if (strncmp(music_name, newmusic, 6))
{ {
S_StopMusic(); // shutdown old music if (S_MusicExists(newmusic, false, true) && !nodigimusic && !digital_disabled) // digmusic?
if (!S_DigMusic(newmusic, looping) && !S_MIDIMusic(newmusic, looping))
{ {
CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), newmusic); if (prefadems) //have to queue post-fade
return; {
I_FadeOutStopMusic(prefadems);
I_QueueDigSongPostFade(newmusic, mflags & MUSIC_TRACKMASK, looping, position, fadeinms);
// HACK: set the vars now and hope everything works out
strncpy(music_name, newmusic, 7);
music_name[6] = 0;
music_lumpnum = LUMPERROR;
music_data = NULL;
music_handle = 0;
return;
}
else
{
S_StopMusic();
if (!S_DigMusic(newmusic, looping))
{
CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), newmusic);
return;
}
}
}
else if (S_MusicExists(newmusic, true, false) && !nomidimusic && !music_disabled) // midimusic?
{
// HACK: We don't support fade for MIDI right now, so
// just fall to old behavior verbatim. This technically should be implemented in
// the interfaces, even as a stub.
S_StopMusic();
if (!S_MIDIMusic(newmusic, looping))
{
CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), newmusic);
return;
}
} }
} }
I_SetSongTrack(mflags & MUSIC_TRACKMASK); I_SetSongTrack(mflags & MUSIC_TRACKMASK);
} }
@ -1491,7 +1525,12 @@ boolean S_FadeMusicFromLevel(UINT8 target_volume, INT16 source_volume, UINT32 ms
if (source_volume < 0) if (source_volume < 0)
return I_FadeMusic(target_volume, ms); return I_FadeMusic(target_volume, ms);
else else
return I_FadeMusicFromLevel(target_volume, source_volume, ms); return I_FadeMusicFromLevel(target_volume, source_volume, ms, false);
}
boolean S_FadeOutStopMusic(UINT32 ms)
{
return I_FadeOutStopMusic(ms);
} }
void S_SetDigMusicVolume(INT32 volume) void S_SetDigMusicVolume(INT32 volume)

View file

@ -130,8 +130,10 @@ void S_StopSound(void *origin);
// note: music flags 12 bits for tracknum (gme, other formats with more than one track) // note: music flags 12 bits for tracknum (gme, other formats with more than one track)
// 13-15 aren't used yet // 13-15 aren't used yet
// and the last bit we ignore (internal game flag for resetting music on reload) // and the last bit we ignore (internal game flag for resetting music on reload)
#define S_ChangeMusicInternal(a,b) S_ChangeMusic(a,0,b) void S_ChangeMusicWithFade(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms);
void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping); #define S_FadeInChangeMusic(a,b,c,d) S_ChangeMusicWithFade(a,b,c,0,0,d)
#define S_ChangeMusicInternal(a,b) S_ChangeMusicWithFade(a,0,b,0,0,0)
#define S_ChangeMusic(a,b,c) S_ChangeMusicWithFade(a,b,c,0,0,0)
// Get music type // Get music type
musictype_t S_MusicType(); musictype_t S_MusicType();
@ -176,6 +178,7 @@ boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi);
void S_StopFadingMusic(void); void S_StopFadingMusic(void);
boolean S_FadeMusicFromLevel(UINT8 target_volume, INT16 source_volume, UINT32 ms); boolean S_FadeMusicFromLevel(UINT8 target_volume, INT16 source_volume, UINT32 ms);
#define S_FadeMusic(a, b) S_FadeMusicFromLevel(a, -1, b) #define S_FadeMusic(a, b) S_FadeMusicFromLevel(a, -1, b)
boolean S_FadeOutStopMusic(UINT32 ms);
// //
// Updates music & sounds // Updates music & sounds

View file

@ -75,6 +75,12 @@ static UINT8 fading_target;
static UINT32 fading_steps; static UINT32 fading_steps;
static INT16 fading_volume_step; static INT16 fading_volume_step;
static INT32 fading_id; static INT32 fading_id;
static char queue_music_name[7]; // up to 6-character name
static UINT16 queue_track;
static boolean queue_looping;
static UINT32 queue_position;
static UINT32 queue_fadeinms;
static boolean queue_stopafterfade;
#ifdef HAVE_LIBGME #ifdef HAVE_LIBGME
static Music_Emu *gme; static Music_Emu *gme;
@ -93,6 +99,14 @@ static void varcleanup(void)
internal_volume = 100; internal_volume = 100;
} }
static void queuecleanup(void)
{
queue_track = queue_looping =\
queue_position = queue_fadeinms =\
queue_stopafterfade = 0;
queue_music_name[0] = 0;
}
static UINT32 get_real_volume(UINT8 volume) static UINT32 get_real_volume(UINT8 volume)
{ {
// convert volume to mixer's 128 scale // convert volume to mixer's 128 scale
@ -115,6 +129,7 @@ void I_StartupSound(void)
} }
varcleanup(); varcleanup();
queuecleanup();
music = NULL; music = NULL;
music_volume = midi_volume = sfx_volume = 0; music_volume = midi_volume = sfx_volume = 0;
@ -508,14 +523,31 @@ static void music_loop(void)
I_StopDigSong(); I_StopDigSong();
} }
static void run_queue()
{
if (queue_stopafterfade)
I_StopDigSong();
else if (queue_music_name[0] && I_StartDigSong(queue_music_name, queue_looping))
{
I_SetSongTrack(queue_track);
if (queue_fadeinms)
I_FadeMusicFromLevel(100, 0, queue_fadeinms, false);
if (queue_position)
I_SetMusicPosition(queue_position);
}
queuecleanup();
}
static UINT32 music_fade(UINT32 interval, void *param) static UINT32 music_fade(UINT32 interval, void *param)
{ {
if (!is_fading || if (!is_fading ||
midimode || // stub out MIDI, see bug in I_SetMIDIMusicVolume
internal_volume == fading_target || internal_volume == fading_target ||
fading_steps == 0 || fading_steps == 0 ||
fading_volume_step == 0) fading_volume_step == 0)
{ {
I_StopFadingMusic(); I_StopFadingMusic();
queuecleanup();
return 0; return 0;
} }
else if ( else if (
@ -524,6 +556,7 @@ static UINT32 music_fade(UINT32 interval, void *param)
{ {
internal_volume = fading_target; internal_volume = fading_target;
Mix_VolumeMusic(get_real_volume(midimode ? midi_volume : music_volume)); Mix_VolumeMusic(get_real_volume(midimode ? midi_volume : music_volume));
run_queue();
return 0; return 0;
} }
else else
@ -644,6 +677,7 @@ void I_ShutdownDigMusic(void)
if (!music) if (!music)
return; return;
varcleanup(); varcleanup();
queuecleanup();
SDL_RemoveTimer(fading_id); SDL_RemoveTimer(fading_id);
Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes);
Mix_HookMusicFinished(NULL); Mix_HookMusicFinished(NULL);
@ -1176,7 +1210,7 @@ boolean I_SetSongTrack(int track)
void I_SetInternalMusicVolume(UINT8 volume) void I_SetInternalMusicVolume(UINT8 volume)
{ {
internal_volume = volume; internal_volume = volume;
if (!music) if (midimode || !music) // stub out MIDI, see bug in I_SetMIDIMusicVolume
return; return;
Mix_VolumeMusic(get_real_volume(midimode ? midi_volume : music_volume)); Mix_VolumeMusic(get_real_volume(midimode ? midi_volume : music_volume));
} }
@ -1189,23 +1223,39 @@ void I_StopFadingMusic(void)
fading_target = fading_steps = fading_volume_step = fading_id = 0; fading_target = fading_steps = fading_volume_step = fading_id = 0;
} }
boolean I_FadeMusicFromLevel(UINT8 target_volume, UINT8 source_volume, UINT32 ms) boolean I_FadeMusicFromLevel(UINT8 target_volume, UINT8 source_volume, UINT32 ms, boolean stopafterfade)
{ {
UINT32 target_steps, ms_per_step; UINT32 target_steps, ms_per_step;
INT16 target_volume_step, volume_delta; INT16 target_volume_step, volume_delta;
source_volume = min(source_volume, 100); source_volume = min(source_volume, 100);
volume_delta = (INT16)(target_volume - source_volume)); volume_delta = (INT16)(target_volume - source_volume);
I_StopFadingMusic(); I_StopFadingMusic();
if (!ms && volume_delta) if (!ms && volume_delta)
{ {
I_SetInternalMusicVolume(target_volume); if (stopafterfade)
return true; {
I_StopDigSong();
return true;
}
else
{
I_SetInternalMusicVolume(target_volume);
return true;
}
} }
else if (!volume_delta) else if (!volume_delta)
return true; {
if (stopafterfade)
{
I_StopDigSong();
return true;
}
else
return true;
}
// Round MS to nearest 10 // Round MS to nearest 10
// If n - lower > higher - n, then round up // If n - lower > higher - n, then round up
@ -1229,6 +1279,7 @@ boolean I_FadeMusicFromLevel(UINT8 target_volume, UINT8 source_volume, UINT32 ms
fading_target = target_volume; fading_target = target_volume;
fading_steps = target_steps; fading_steps = target_steps;
fading_volume_step = target_volume_step; fading_volume_step = target_volume_step;
queue_stopafterfade = stopafterfade;
if (internal_volume != source_volume) if (internal_volume != source_volume)
I_SetInternalMusicVolume(source_volume); I_SetInternalMusicVolume(source_volume);
@ -1240,7 +1291,45 @@ boolean I_FadeMusicFromLevel(UINT8 target_volume, UINT8 source_volume, UINT32 ms
boolean I_FadeMusic(UINT8 target_volume, UINT32 ms) boolean I_FadeMusic(UINT8 target_volume, UINT32 ms)
{ {
return I_FadeMusicFromLevel(target_volume, internal_volume, ms); return I_FadeMusicFromLevel(target_volume, internal_volume, ms, false);
}
boolean I_FadeOutStopMusic(UINT32 ms)
{
return I_FadeMusicFromLevel(0, internal_volume, ms, true);
}
boolean I_FadeInStartDigSong(const char *musicname, UINT16 track, boolean looping, UINT32 position, UINT32 fadeinms, boolean queuepostfade)
{
if (musicname[0] == 0)
return true; // nothing to play
else if (queuepostfade && is_fading)
{
strncpy(queue_music_name, musicname, 7);
queue_music_name[6] = 0;
queue_track = track;
queue_looping = looping;
queue_position = position;
queue_fadeinms = fadeinms;
queue_stopafterfade = false;
return true;
}
else
{
if (I_StartDigSong(musicname, looping))
{
I_SetSongTrack(track);
if (fadeinms)
I_FadeMusicFromLevel(100, 0, fadeinms, false);
if (position)
I_SetMusicPosition(position);
return true;
}
else
return false;
}
} }
// //
@ -1264,10 +1353,18 @@ void I_ShutdownMIDIMusic(void)
void I_SetMIDIMusicVolume(UINT8 volume) void I_SetMIDIMusicVolume(UINT8 volume)
{ {
midi_volume = volume; // HACK: Until we stop using native MIDI,
// disable volume changes
// Why: In Windows, MIDI volume messes with the executable's volume setting
// in the OS volume mixer. So any EXE sharing that same filename and directory
// will be affected by this volume bug.
(void)volume;
midi_volume = 31;
//midi_volume = volume;
if (!midimode || !music) if (!midimode || !music)
return; return;
Mix_VolumeMusic(get_real_volume(volume)); Mix_VolumeMusic((UINT32)midi_volume*128/31);
} }
INT32 I_RegisterSong(void *data, size_t len) INT32 I_RegisterSong(void *data, size_t len)