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 87b6fc613b
commit 2cf49f9361
4 changed files with 162 additions and 18 deletions

View File

@ -251,10 +251,15 @@ void I_SetInternalMusicVolume(UINT8 volume);
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_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
\param musicname music lump name

View File

@ -1379,7 +1379,7 @@ static boolean S_DigMusic(const char *mname, boolean looping)
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))
return;
@ -1402,13 +1402,47 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
if (strncmp(music_name, newmusic, 6))
{
S_StopMusic(); // shutdown old music
if (!S_DigMusic(newmusic, looping) && !S_MIDIMusic(newmusic, looping))
if (S_MusicExists(newmusic, false, true) && !nodigimusic && !digital_disabled) // digmusic?
{
CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), newmusic);
return;
if (prefadems) //have to queue post-fade
{
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);
}
@ -1491,7 +1525,12 @@ boolean S_FadeMusicFromLevel(UINT8 target_volume, INT16 source_volume, UINT32 ms
if (source_volume < 0)
return I_FadeMusic(target_volume, ms);
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)

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)
// 13-15 aren't used yet
// 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_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping);
void S_ChangeMusicWithFade(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms);
#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
musictype_t S_MusicType();
@ -176,6 +178,7 @@ boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi);
void S_StopFadingMusic(void);
boolean S_FadeMusicFromLevel(UINT8 target_volume, INT16 source_volume, UINT32 ms);
#define S_FadeMusic(a, b) S_FadeMusicFromLevel(a, -1, b)
boolean S_FadeOutStopMusic(UINT32 ms);
//
// Updates music & sounds

View File

@ -75,6 +75,12 @@ static UINT8 fading_target;
static UINT32 fading_steps;
static INT16 fading_volume_step;
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
static Music_Emu *gme;
@ -93,6 +99,14 @@ static void varcleanup(void)
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)
{
// convert volume to mixer's 128 scale
@ -115,6 +129,7 @@ void I_StartupSound(void)
}
varcleanup();
queuecleanup();
music = NULL;
music_volume = midi_volume = sfx_volume = 0;
@ -508,14 +523,31 @@ static void music_loop(void)
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)
{
if (!is_fading ||
midimode || // stub out MIDI, see bug in I_SetMIDIMusicVolume
internal_volume == fading_target ||
fading_steps == 0 ||
fading_volume_step == 0)
{
I_StopFadingMusic();
queuecleanup();
return 0;
}
else if (
@ -524,6 +556,7 @@ static UINT32 music_fade(UINT32 interval, void *param)
{
internal_volume = fading_target;
Mix_VolumeMusic(get_real_volume(midimode ? midi_volume : music_volume));
run_queue();
return 0;
}
else
@ -644,6 +677,7 @@ void I_ShutdownDigMusic(void)
if (!music)
return;
varcleanup();
queuecleanup();
SDL_RemoveTimer(fading_id);
Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes);
Mix_HookMusicFinished(NULL);
@ -1176,7 +1210,7 @@ boolean I_SetSongTrack(int track)
void I_SetInternalMusicVolume(UINT8 volume)
{
internal_volume = volume;
if (!music)
if (midimode || !music) // stub out MIDI, see bug in I_SetMIDIMusicVolume
return;
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;
}
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;
INT16 target_volume_step, volume_delta;
source_volume = min(source_volume, 100);
volume_delta = (INT16)(target_volume - source_volume));
volume_delta = (INT16)(target_volume - source_volume);
I_StopFadingMusic();
if (!ms && volume_delta)
{
I_SetInternalMusicVolume(target_volume);
return true;
if (stopafterfade)
{
I_StopDigSong();
return true;
}
else
{
I_SetInternalMusicVolume(target_volume);
return true;
}
}
else if (!volume_delta)
return true;
{
if (stopafterfade)
{
I_StopDigSong();
return true;
}
else
return true;
}
// Round MS to nearest 10
// 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_steps = target_steps;
fading_volume_step = target_volume_step;
queue_stopafterfade = stopafterfade;
if (internal_volume != 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)
{
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)
{
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)
return;
Mix_VolumeMusic(get_real_volume(volume));
Mix_VolumeMusic((UINT32)midi_volume*128/31);
}
INT32 I_RegisterSong(void *data, size_t len)