From e7a4f6d78fbb4d733a80c8d0e9b1740c96c3e92d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 14:18:29 -0400 Subject: [PATCH 01/19] I_GetMusicLength implementation --- src/i_sound.h | 2 ++ src/s_sound.c | 7 ++++- src/s_sound.h | 3 ++ src/sdl/mixer_sound.c | 69 ++++++++++++++++++++++++++++++++----------- 4 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/i_sound.h b/src/i_sound.h index ff9a9f196..98cc7523c 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -224,6 +224,8 @@ void I_ShutdownDigMusic(void); boolean I_SetSongSpeed(float speed); +UINT32 I_GetMusicLength(void); + boolean I_SetMusicPosition(UINT32 position); UINT32 I_GetMusicPosition(void); diff --git a/src/s_sound.c b/src/s_sound.c index bd27e4da2..16d808f63 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1389,7 +1389,7 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) if(LUAh_MusicChange(music_name, mmusic, newmusic, &mflags, &looping)) return; #else - strncpy(newmusic, mmusic, 7); + strncpy(newmusic, mmusic, 7); #endif newmusic[6] = 0; @@ -1417,6 +1417,11 @@ boolean S_SpeedMusic(float speed) return I_SetSongSpeed(speed); } +UINT32 S_GetMusicLength(void) +{ + return I_GetMusicLength(); +} + boolean S_SetMusicPosition(UINT32 position) { return I_SetMusicPosition(position); diff --git a/src/s_sound.h b/src/s_sound.h index bb33233db..94b12ba0b 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -135,6 +135,9 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping); // Set Speed of Music boolean S_SpeedMusic(float speed); +// Get Length of Music +UINT32 S_GetMusicLength(void); + // Set Position of Music boolean S_SetMusicPosition(UINT32 position); diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 2b3653fe7..9b9887103 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -66,6 +66,7 @@ static boolean midimode; static Mix_Music *music; static UINT8 music_volume, midi_volume, sfx_volume; static float loop_point; +static float music_length; // length in seconds static boolean songpaused; static UINT32 music_bytes; static boolean is_looping; @@ -693,36 +694,49 @@ boolean I_StartDigSong(const char *musicname, boolean looping) // Find the OGG loop point. is_looping = looping; loop_point = 0.0f; + music_length = 0.0f; if (looping) { const char *key1 = "LOOP"; const char *key2 = "POINT="; const char *key3 = "MS="; + const char *key4 = "LENGTHMS="; const size_t key1len = strlen(key1); const size_t key2len = strlen(key2); const size_t key3len = strlen(key3); + const size_t key4len = strlen(key4); char *p = data; while ((UINT32)(p - data) < len) { - if (strncmp(p++, key1, key1len)) - continue; - p += key1len-1; // skip OOP (the L was skipped in strncmp) - if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=? + if (!loop_point && !strncmp(p, key1, key1len)) { - p += key2len; // skip POINT= - loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count. - // because SDL_Mixer is USELESS and can't even tell us - // something simple like the frequency of the streaming music, - // we are unfortunately forced to assume that ALL MUSIC is 44100hz. - // This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly. + p += key1len; // skip LOOP + if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=? + { + p += key2len; // skip POINT= + loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count. + // because SDL_Mixer is USELESS and can't even tell us + // something simple like the frequency of the streaming music, + // we are unfortunately forced to assume that ALL MUSIC is 44100hz. + // This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly. + } + else if (!strncmp(p, key3, key3len)) // is it LOOPMS=? + { + p += key3len; // skip MS= + loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds. + // Everything that uses LOOPMS will work perfectly with SDL_Mixer. + } } - else if (!strncmp(p, key3, key3len)) // is it LOOPMS=? + else if (!music_length && !strncmp(p, key4, key4len)) // is it LENGTHMS=? { - p += key3len; // skip MS= - loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds. - // Everything that uses LOOPMS will work perfectly with SDL_Mixer. + p += key4len; // skip LENGTHMS + music_length = (float)(atoi(p) / 1000.0L); } - // Neither?! Continue searching. + + if (loop_point && music_length) // Got what we needed + break; + else // continue searching + p++; } } @@ -792,18 +806,37 @@ boolean I_SetSongSpeed(float speed) return false; } +UINT32 I_GetMusicLength(void) +{ + // VERY IMPORTANT to set your LENGTHMS= in your song files, folks! + // SDL mixer can't read music length itself. + + if (midimode) + return 0; + UINT32 length = (UINT32)(music_length*1000); + if (!length) + CONS_Debug(DBG_BASIC, "Getting music length: music is missing LENGTHMS= in music tag.\n"); + return length; +} + boolean I_SetMusicPosition(UINT32 position) { if(midimode || !music) return false; + + // Because SDL mixer can't identify song length, if you have + // a position input greater than the real length, then + // music_bytes becomes inaccurate. + UINT32 length = I_GetMusicLength(); // get it in MS + if (length) + position %= length; + Mix_RewindMusic(); // needed for mp3 if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0) - music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPositon) + music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) else // NOTE: This block fires on incorrect song format, // NOT if position input is greater than song length. - // This means music_bytes will be inaccurate because we can't compare to - // max song length. So, don't write your scripts to seek beyond the song. music_bytes = 0; return true; } From 7328f47b53b6d12f6dbe3be7fb28ea9d0fdc3c7e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 14:18:49 -0400 Subject: [PATCH 02/19] I_GetMusicLength declarations for other interfaces --- src/android/i_sound.c | 7 ++++++- src/djgppdos/i_sound.c | 7 ++++++- src/dummy/i_sound.c | 5 +++++ src/sdl/sdl_sound.c | 5 +++++ src/win32/win_snd.c | 9 +++++++++ 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index fa9e326c0..a6e12c32d 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -158,6 +158,11 @@ boolean I_SetSongSpeed(float speed) return false; } +UINT32 I_GetMusicLength(void) +{ + return 0; +} + boolean I_SetMusicPosition(UINT32 position) { (void)position; @@ -167,4 +172,4 @@ boolean I_SetMusicPosition(UINT32 position) UINT32 I_GetMusicPosition(void) { return 0; -} +} \ No newline at end of file diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index 4a1afa301..f0c8fd3e0 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -551,6 +551,11 @@ boolean I_SetSongSpeed(float speed) return false; } +UINT32 I_GetMusicLength(void) +{ + return 0; +} + boolean I_SetMusicPosition(UINT32 position) { (void)position; @@ -559,7 +564,7 @@ boolean I_SetMusicPosition(UINT32 position) UINT32 I_GetMusicPosition(void) { - return 0.; + return 0; } boolean I_MIDIPlaying(void) diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index 26d782709..5c1847b2e 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -146,6 +146,11 @@ boolean I_SetSongTrack(int track) return false; } +UINT32 I_GetMusicLength(void) +{ + return 0; +} + boolean I_SetMusicPosition(UINT32 position) { (void)position; diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 42b45c563..25c561860 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1989,6 +1989,11 @@ boolean I_SetSongSpeed(float speed) return false; } +UINT32 I_GetMusicLength(void) +{ + return 0; +} + boolean I_SetMusicPosition(UINT32 position) { (void)position; diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index f86686945..3e88451d7 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -774,6 +774,15 @@ boolean I_SetSongSpeed(float speed) return true; } +UINT32 I_GetMusicLength() +{ + if (midimode) + return 0; + UINT32 length; + e = FMOD_Sound_GetLength(music_stream, length, FMOD_TIMEUNIT_MS); + return length; +} + boolean I_SetMusicPosition(UINT32 position) { if(midimode) From 2319a2ba536eb46f5f5638eb537327227c4a1c9c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 14:18:58 -0400 Subject: [PATCH 03/19] Lua for I_GetMusicLength --- src/lua_baselib.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index d6aeb9a31..1f88be24e 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2266,9 +2266,16 @@ static int lib_sSpeedMusic(lua_State *L) } #ifdef HAVE_LUA_MUSICPLUS +static int lib_sGetMusicLength(lua_State *L) +{ + NOHUD + lua_pushinteger(L, (UINT32)S_GetMusicLength()); + return 1; +} + static int lib_sSetMusicPosition(lua_State *L) { - UINT32 position = 0; + UINT32 position = (UINT32)luaL_checkinteger(L, 1); player_t *player = NULL; NOHUD if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) @@ -2850,6 +2857,7 @@ static luaL_Reg lib[] = { {"S_ChangeMusic",lib_sChangeMusic}, {"S_SpeedMusic",lib_sSpeedMusic}, #ifdef HAVE_LUA_MUSICPLUS + {"S_GetMusicLength",lib_sGetMusicLength}, {"S_SetMusicPosition",lib_sSetMusicPosition}, {"S_GetMusicPosition",lib_sGetMusicPosition}, {"S_PauseMusic",lib_sPauseMusic}, From 8db0d04cb8b2d9348ceeb9114f03dd1f7d0d1baf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 15:22:15 -0400 Subject: [PATCH 04/19] Support wide chars when searching for music tags (MP3) --- src/sdl/mixer_sound.c | 57 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 9b9887103..0b23ba6ae 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -701,10 +701,17 @@ boolean I_StartDigSong(const char *musicname, boolean looping) const char *key2 = "POINT="; const char *key3 = "MS="; const char *key4 = "LENGTHMS="; + const char *key1w = "L\0O\0O\0P\0"; + const char *key2w = "P\0O\0I\0N\0T\0=\0"; + const char *key3w = "M\0S\0=\0"; + const char *key4w = "L\0E\0N\0G\0T\0H\0M\0S\0=\0"; + const char *wterm = "\0\0"; const size_t key1len = strlen(key1); const size_t key2len = strlen(key2); const size_t key3len = strlen(key3); const size_t key4len = strlen(key4); + char wval[10]; // millisecond range up to 30 hours! + size_t wstart, wp; char *p = data; while ((UINT32)(p - data) < len) { @@ -732,8 +739,56 @@ boolean I_StartDigSong(const char *musicname, boolean looping) p += key4len; // skip LENGTHMS music_length = (float)(atoi(p) / 1000.0L); } + // below: search MP3 or other tags that use wide char encoding + else if (!loop_point && !strncmp(p, key1w, key1len*2)) // LOOP wide char + { + p += key1len*2; + if (!strncmp(p, key2w, key2len*2)) // POINT= wide char + { + p += key2len*2+2; + wstart = (size_t)p; + wp = 0; + while (wp < 9 && strncmp(p, wterm, 2)) + { + wval[wp] = *p; + p += 2; + wp = ((size_t)(p-wstart))/2; + } + wval[min(wp, 9)] = 0; + loop_point = (float)((44.1L+atoi(wval) / 44100.0L)); + } + else if (!strncmp(p, key3w, key3len*2)) // MS= wide char + { + p += key3len*2+2; + wstart = (size_t)p; + wp = 0; + while (wp < 9 && strncmp(p, wterm, 2)) + { + wval[wp] = *p; + p += 2; + wp = ((size_t)(p-wstart))/2; + } + wval[min(wp, 9)] = 0; + loop_point = (float)(atoi(wval) / 1000.0L); + } + } + else if (!music_length && !strncmp(p, key4w, key4len*2)) // LENGTHMS= wide char + { + p += key4len*2+2; + wstart = (size_t)p; + wp = 0; + while (wp < 9 && strncmp(p, wterm, 2)) + { + wval[wp] = *p; + p += 2; + wp = ((size_t)(p-wstart))/2; + } + wval[min(wp, 9)] = 0; + music_length = (float)(atoi(wval) / 1000.0L); + } - if (loop_point && music_length) // Got what we needed + if (loop_point && music_length && music_length > loop_point) // Got what we needed + // the last case is a sanity check, in case the wide char searches were false matches. break; else // continue searching p++; From 7080c93576e4340b074428bd1c33cc5a07dc4782 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 16:21:28 -0400 Subject: [PATCH 05/19] Added GME for GetMusicLength, SetMusicPosition, GetMusicPosition * Misc fixes --- src/sdl/mixer_sound.c | 92 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 7 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 0b23ba6ae..012c3fffb 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -311,6 +311,7 @@ void *I_GetSfx(sfxinfo_t *sfx) len = (info->play_length * 441 / 10) << 2; mem = Z_Malloc(len, PU_SOUND, NULL); gme_play(emu, len >> 1, mem); + gme_free_info(info); gme_delete(emu); return Mix_QuickLoad_RAW((Uint8 *)mem, len); @@ -383,6 +384,7 @@ void *I_GetSfx(sfxinfo_t *sfx) len = (info->play_length * 441 / 10) << 2; mem = Z_Malloc(len, PU_SOUND, NULL); gme_play(emu, len >> 1, mem); + gme_free_info(info); gme_delete(emu); return Mix_QuickLoad_RAW((Uint8 *)mem, len); @@ -863,12 +865,40 @@ boolean I_SetSongSpeed(float speed) UINT32 I_GetMusicLength(void) { + INT32 length; + + if (gme) + { + gme_info_t *info; + gme_err_t gme_e = gme_track_info(gme, &info, current_track); + + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + length = 0; + } + else + { + // reconstruct info->play_length, from GME source + // we only want intro + 1 loop, not 2 + length = info->length; + if (length <= 0) + { + length = info->intro_length + info->loop_length; // intro + 1 loop + if (length <= 0) + length = 150 * 1000; // 2.5 minutes + } + } + + gme_free_info(info); + return max(length, 0); + } + else if (midimode || !music) + return 0; + // VERY IMPORTANT to set your LENGTHMS= in your song files, folks! // SDL mixer can't read music length itself. - - if (midimode) - return 0; - UINT32 length = (UINT32)(music_length*1000); + length = (UINT32)(music_length*1000); if (!length) CONS_Debug(DBG_BASIC, "Getting music length: music is missing LENGTHMS= in music tag.\n"); return length; @@ -876,13 +906,34 @@ UINT32 I_GetMusicLength(void) boolean I_SetMusicPosition(UINT32 position) { - if(midimode || !music) + UINT32 length; + + if (gme) + { + // this isn't required technically, but GME thread-locks for a second + // if you seek too high from the counter + length = I_GetMusicLength(); + if (length) + position %= length; + + SDL_LockAudio(); + gme_err_t gme_e = gme_seek(gme, position); + SDL_UnlockAudio(); + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + return false; + } + else + return true; + } + else if (midimode || !music) return false; // Because SDL mixer can't identify song length, if you have // a position input greater than the real length, then // music_bytes becomes inaccurate. - UINT32 length = I_GetMusicLength(); // get it in MS + length = I_GetMusicLength(); // get it in MS if (length) position %= length; @@ -898,8 +949,35 @@ boolean I_SetMusicPosition(UINT32 position) UINT32 I_GetMusicPosition(void) { - if(midimode) + if (gme) + { + INT32 position = gme_tell(gme); + + gme_info_t *info; + gme_err_t gme_e = gme_track_info(gme, &info, current_track); + + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + return position; + } + else + { + // adjust position, since GME's counter keeps going past loop + if (info->length > 0) + position %= info->length; + else if (info->intro_length + info->loop_length > 0) + position = ((position - info->intro_length) % info->loop_length) + info->intro_length; + else + position %= 150 * 1000; // 2.5 minutes + } + + gme_free_info(info); + return max(position, 0); + } + else if (midimode || !music) return 0; + return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz // 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel) // This is hardcoded in I_StartupSound. Other formats for factor: From c9c1b24ad664ab9601f16a664abec4a246cd56d1 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 17:17:53 -0400 Subject: [PATCH 06/19] S_MusicType implementation; MOD support for Get/SetMusicPosition and MusicLength * Misc MOD fixes --- src/i_sound.h | 17 ++++++++ src/s_sound.c | 5 +++ src/s_sound.h | 4 ++ src/sdl/mixer_sound.c | 97 +++++++++++++++++++++++++++++-------------- 4 files changed, 91 insertions(+), 32 deletions(-) diff --git a/src/i_sound.h b/src/i_sound.h index 98cc7523c..71d3a8c24 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -18,6 +18,21 @@ #include "sounds.h" #include "command.h" +// copied from SDL mixer, plus GME +typedef enum { + MU_NONE, + MU_CMD, + MU_WAV, + MU_MOD, + MU_MID, + MU_OGG, + MU_MP3, + MU_MP3_MAD_UNUSED, // use MU_MP3 instead + MU_FLAC, + MU_MODPLUG_UNUSED, // use MU_MOD instead + MU_GME +} musictype_t; + /** \brief Sound subsystem runing and waiting */ extern UINT8 sound_started; @@ -150,6 +165,8 @@ boolean I_MusicPlaying(void); */ boolean I_MusicPaused(void); +musictype_t I_MusicType(void); + // // MIDI I/O // diff --git a/src/s_sound.c b/src/s_sound.c index 16d808f63..f28881986 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1412,6 +1412,11 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) I_SetSongTrack(mflags & MUSIC_TRACKMASK); } +musictype_t S_MusicType() +{ + return I_MusicType(); +} + boolean S_SpeedMusic(float speed) { return I_SetSongSpeed(speed); diff --git a/src/s_sound.h b/src/s_sound.h index 94b12ba0b..e73e8c909 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -14,6 +14,7 @@ #ifndef __S_SOUND__ #define __S_SOUND__ +#include "i_sound.h" #include "sounds.h" #include "m_fixed.h" #include "command.h" @@ -132,6 +133,9 @@ void S_StopSound(void *origin); #define S_ChangeMusicInternal(a,b) S_ChangeMusic(a,0,b) void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping); +// Get music type +musictype_t S_MusicType(); + // Set Speed of Music boolean S_SpeedMusic(float speed); diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 012c3fffb..43060db88 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -441,9 +441,25 @@ void I_SetSfxVolume(UINT8 volume) // Music // +musictype_t I_MusicType(void) +{ + if (gme) + return MU_GME; + else if (midimode) + return MU_MID; + else if (!music) + return MU_NONE; + else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG_UNUSED) + return MU_MOD; + else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD_UNUSED) + return MU_MP3; + else + return (musictype_t)Mix_GetMusicType(music); +} + static void count_music_bytes(int chan, void *stream, int len, void *udata) { - if(midimode || !music) + if (gme || midimode || !music || I_MusicType() == MU_MOD) return; music_bytes += len; } @@ -797,17 +813,24 @@ boolean I_StartDigSong(const char *musicname, boolean looping) } } - if (Mix_PlayMusic(music, 0) == -1) + if (I_MusicType() != MU_MOD && Mix_PlayMusic(music, 0) == -1) { CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); return true; } + else if ((I_MusicType() == MU_MOD) && Mix_PlayMusic(music, -1) == -1) // if MOD, loop forever + { + CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); + return true; + } + Mix_VolumeMusic((UINT32)music_volume*128/31); - Mix_HookMusicFinished(music_loop); + if (I_MusicType() != MU_MOD) + Mix_HookMusicFinished(music_loop); // don't bother counting if MOD music_bytes = 0; - if(!Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) + if(I_MusicType() != MU_MOD && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); return true; @@ -893,15 +916,17 @@ UINT32 I_GetMusicLength(void) gme_free_info(info); return max(length, 0); } - else if (midimode || !music) + else if (midimode || !music || I_MusicType() == MU_MOD) return 0; - - // VERY IMPORTANT to set your LENGTHMS= in your song files, folks! - // SDL mixer can't read music length itself. - length = (UINT32)(music_length*1000); - if (!length) - CONS_Debug(DBG_BASIC, "Getting music length: music is missing LENGTHMS= in music tag.\n"); - return length; + else + { + // VERY IMPORTANT to set your LENGTHMS= in your song files, folks! + // SDL mixer can't read music length itself. + length = (UINT32)(music_length*1000); + if (!length) + CONS_Debug(DBG_BASIC, "Getting music length: music is missing LENGTHMS= in music tag.\n"); + return length; + } } boolean I_SetMusicPosition(UINT32 position) @@ -929,22 +954,27 @@ boolean I_SetMusicPosition(UINT32 position) } else if (midimode || !music) return false; - - // Because SDL mixer can't identify song length, if you have - // a position input greater than the real length, then - // music_bytes becomes inaccurate. - length = I_GetMusicLength(); // get it in MS - if (length) - position %= length; - - Mix_RewindMusic(); // needed for mp3 - if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0) - music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) + else if (I_MusicType() == MU_MOD) + // Goes by channels + return Mix_SetMusicPosition(position); else - // NOTE: This block fires on incorrect song format, - // NOT if position input is greater than song length. - music_bytes = 0; - return true; + { + // Because SDL mixer can't identify song length, if you have + // a position input greater than the real length, then + // music_bytes becomes inaccurate. + length = I_GetMusicLength(); // get it in MS + if (length) + position %= length; + + Mix_RewindMusic(); // needed for mp3 + if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0) + music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) + else + // NOTE: This block fires on incorrect song format, + // NOT if position input is greater than song length. + music_bytes = 0; + return true; + } } UINT32 I_GetMusicPosition(void) @@ -977,11 +1007,11 @@ UINT32 I_GetMusicPosition(void) } else if (midimode || !music) return 0; - - return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz - // 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel) - // This is hardcoded in I_StartupSound. Other formats for factor: - // 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4 + else + return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz + // 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel) + // This is hardcoded in I_StartupSound. Other formats for factor: + // 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4 } boolean I_SetSongTrack(int track) @@ -1010,7 +1040,10 @@ boolean I_SetSongTrack(int track) SDL_UnlockAudio(); return false; } + else #endif + if (I_MusicType() == MU_MOD) + Mix_SetMusicPosition(track); (void)track; return false; } From 14336ea1ae5995beffa8c96305d30762287cbae6 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 17:18:13 -0400 Subject: [PATCH 07/19] Other interfaces for I_MusicType --- src/android/i_sound.c | 7 ++++++- src/djgppdos/i_sound.c | 5 +++++ src/dummy/i_sound.c | 5 +++++ src/sdl/sdl_sound.c | 5 +++++ src/win32/win_snd.c | 5 +++++ 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index a6e12c32d..869cc1f8d 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -89,6 +89,11 @@ boolean I_MusicPaused(void) return false; } +musictype_t I_MusicType(void) +{ + return MU_NONE; +} + // // MIDI I/O // @@ -172,4 +177,4 @@ boolean I_SetMusicPosition(UINT32 position) UINT32 I_GetMusicPosition(void) { return 0; -} \ No newline at end of file +} diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index f0c8fd3e0..d3d827a12 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -581,3 +581,8 @@ boolean I_MusicPaused(void) { return false; } + +musictype_t I_MusicType(void) +{ + return MU_NONE; +} diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index 5c1847b2e..c362f7980 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -176,3 +176,8 @@ boolean I_MusicPaused(void) { return false; } + +musictype_t I_MusicType(void) +{ + return MU_NONE; +} diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 25c561860..3b370c988 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1665,6 +1665,11 @@ boolean I_MusicPaused(void) return Mix_PausedMusic(); } +musictype_t I_MusicType(void) +{ + return MU_NONE; +} + void I_UnRegisterSong(INT32 handle) { #ifdef HAVE_MIXER diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 3e88451d7..45fda7edf 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -486,6 +486,11 @@ boolean I_MusicPaused(void) return fmpaused; } +musictype_t I_MusicType(void) +{ + return MU_NONE; +} + void I_InitDigMusic(void) { } From ec2b368c6d0d975fe0a3e8df98b0604e97c2d5de Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 17:18:22 -0400 Subject: [PATCH 08/19] Lua for MusicType --- src/lua_baselib.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 1f88be24e..45597260d 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2426,6 +2426,23 @@ static int lib_sMusicPaused(lua_State *L) return 1; } +static int lib_sMusicType(lua_State *L) +{ + player_t *player = NULL; + NOHUD + if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) + { + player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (!player || P_IsLocalPlayer(player)) + lua_pushinteger(L, S_MusicType()); + else + lua_pushnil(L); + return 1; +} + static int lib_sMusicName(lua_State *L) { player_t *player = NULL; @@ -2867,6 +2884,7 @@ static luaL_Reg lib[] = { {"S_MidiPlaying",lib_sMidiPlaying}, {"S_MusicPlaying",lib_sMusicPlaying}, {"S_MusicPaused",lib_sMusicPaused}, + {"S_MusicType",lib_sMusicType}, {"S_MusicName",lib_sMusicName}, {"S_MusicExists",lib_sMusicExists}, #endif From 22b2ef44b9fd2d212ea12fb3f9bac79c15af10f5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 17:45:57 -0400 Subject: [PATCH 09/19] Remove I_MIDIPlaying --- src/i_sound.h | 6 ------ src/s_sound.c | 5 ----- src/s_sound.h | 3 --- src/sdl/mixer_sound.c | 5 ----- 4 files changed, 19 deletions(-) diff --git a/src/i_sound.h b/src/i_sound.h index 71d3a8c24..fce94a26d 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -147,12 +147,6 @@ void I_PauseSong(INT32 handle); */ void I_ResumeSong(INT32 handle); -/** \brief Get MIDI music status - - \return boolean -*/ -boolean I_MIDIPlaying(void); - /** \brief Get general music status \return boolean diff --git a/src/s_sound.c b/src/s_sound.c index f28881986..a9980acda 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1599,11 +1599,6 @@ void S_ResumeAudio(void) I_ResumeCD(); } -boolean S_MIDIPlaying(void) -{ - return I_MIDIPlaying(); -} - boolean S_MusicPlaying(void) { return I_MusicPlaying(); diff --git a/src/s_sound.h b/src/s_sound.h index e73e8c909..42f3a1433 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -155,9 +155,6 @@ void S_StopMusic(void); void S_PauseAudio(void); void S_ResumeAudio(void); -// Gets MIDI music status -boolean S_MIDIPlaying(void); - // Gets general music status boolean S_MusicPlaying(void); diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 43060db88..33ffb5510 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -537,11 +537,6 @@ void I_ResumeSong(INT32 handle) songpaused = false; } -boolean I_MIDIPlaying(void) -{ - return midimode && music; -} - boolean I_MusicPlaying(void) { return (boolean)music; From 4659bc241a2e52e58b93609a84a5165bdb13f6af Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 17:46:06 -0400 Subject: [PATCH 10/19] Remove I_MIDIPlaying from other targets --- src/android/i_sound.c | 5 ----- src/djgppdos/i_sound.c | 5 ----- src/dummy/i_sound.c | 5 ----- src/sdl/sdl_sound.c | 6 ------ src/win32/win_snd.c | 5 ----- 5 files changed, 26 deletions(-) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index 869cc1f8d..08721c6a3 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -74,11 +74,6 @@ void I_ResumeSong(INT32 handle) (void)handle; } -boolean I_MIDIPlaying(void) -{ - return false; -} - boolean I_MusicPlaying(void) { return false; diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index d3d827a12..8f4e560a8 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -567,11 +567,6 @@ UINT32 I_GetMusicPosition(void) return 0; } -boolean I_MIDIPlaying(void) -{ - return (boolean)currsong && music_started; -} - boolean I_MusicPlaying(void) { return (boolean)currsong && music_started; diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index c362f7980..c16dd8a3f 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -162,11 +162,6 @@ UINT32 I_GetMusicPosition(void) return 0; } -boolean I_MIDIPlaying(void) -{ - return false; -} - boolean I_MusicPlaying(void) { return false; diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 3b370c988..748eb4427 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1649,12 +1649,6 @@ void I_StopSong(INT32 handle) #endif } -boolean I_MIDIPlaying(void) -{ - // todo: no way to tell specifically if MIDI is playing, implement midimode - return !nomidimusic && nodigimusic && musicStarted; -} - boolean I_MusicPlaying(void) { return musicStarted; diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 45fda7edf..987e3498d 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -468,11 +468,6 @@ void I_ResumeSong(INT32 handle) FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, false)); } -boolean I_MIDIPlaying(void) -{ - return midimode && music_stream; -} - boolean I_MusicPlaying(void) { return (boolean)music_stream; From e68187edfe2723b18b43fb1856be5923ffc774cf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 17:46:14 -0400 Subject: [PATCH 11/19] Remove I_MIDIPlaying from Lua --- src/lua_baselib.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 45597260d..3a89aae27 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2358,40 +2358,6 @@ static int lib_sStopMusic(lua_State *L) return 1; } -static int lib_sDigitalPlaying(lua_State *L) -{ - player_t *player = NULL; - NOHUD - if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) - { - player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - if (!player) - return LUA_ErrInvalid(L, "player_t"); - } - if (!player || P_IsLocalPlayer(player)) - lua_pushboolean(L, !S_MIDIPlaying() && S_MusicPlaying()); - else - lua_pushnil(L); - return 1; -} - -static int lib_sMidiPlaying(lua_State *L) -{ - player_t *player = NULL; - NOHUD - if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) - { - player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - if (!player) - return LUA_ErrInvalid(L, "player_t"); - } - if (!player || P_IsLocalPlayer(player)) - lua_pushboolean(L, S_MIDIPlaying()); - else - lua_pushnil(L); - return 1; -} - static int lib_sMusicPlaying(lua_State *L) { player_t *player = NULL; @@ -2880,8 +2846,6 @@ static luaL_Reg lib[] = { {"S_PauseMusic",lib_sPauseMusic}, {"S_ResumeMusic",lib_sResumeMusic}, {"S_StopMusic",lib_sStopMusic}, - {"S_DigitalPlaying",lib_sDigitalPlaying}, - {"S_MidiPlaying",lib_sMidiPlaying}, {"S_MusicPlaying",lib_sMusicPlaying}, {"S_MusicPaused",lib_sMusicPaused}, {"S_MusicType",lib_sMusicType}, From 24270b4998b64eb2414ba6e27737f201431df832 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 18:57:53 -0400 Subject: [PATCH 12/19] Lua merge fixes --- src/lua_baselib.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 3a89aae27..e7cd69689 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2293,8 +2293,18 @@ static int lib_sSetMusicPosition(lua_State *L) static int lib_sGetMusicPosition(lua_State *L) { + player_t *player = NULL; NOHUD - lua_pushinteger(L, (UINT32)S_GetMusicPosition()); + if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) + { + player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (!player || P_IsLocalPlayer(player)) + lua_pushinteger(L, (int)S_GetMusicPosition()); + else + lua_pushnil(L); return 1; } @@ -2322,9 +2332,9 @@ static int lib_sResumeMusic(lua_State *L) { player_t *player = NULL; NOHUD - if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) + if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) { - player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); + player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); if (!player) return LUA_ErrInvalid(L, "player_t"); } From 1629a8cfd0d95a2b08d092b099c29645f22b9439 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 20:19:44 -0400 Subject: [PATCH 13/19] I_GetMusicLoopPoint and I_SetMusicLoopPoint implementation * Stub pause for MIDI * Fix MP3 tag wide char search * Reset songpaused bool where appropriate --- src/i_sound.h | 4 ++ src/s_sound.c | 10 +++++ src/s_sound.h | 6 +++ src/sdl/mixer_sound.c | 100 ++++++++++++++++++++++++++++++++---------- 4 files changed, 97 insertions(+), 23 deletions(-) diff --git a/src/i_sound.h b/src/i_sound.h index fce94a26d..a88038b39 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -237,6 +237,10 @@ boolean I_SetSongSpeed(float speed); UINT32 I_GetMusicLength(void); +boolean I_SetMusicLoopPoint(UINT32 looppoint); + +UINT32 I_GetMusicLoopPoint(void); + boolean I_SetMusicPosition(UINT32 position); UINT32 I_GetMusicPosition(void); diff --git a/src/s_sound.c b/src/s_sound.c index a9980acda..af1425abf 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1427,6 +1427,16 @@ UINT32 S_GetMusicLength(void) return I_GetMusicLength(); } +boolean S_SetMusicLoopPoint(UINT32 looppoint) +{ + return I_SetMusicPosition(looppoint); +} + +UINT32 S_GetMusicLoopPoint(void) +{ + return I_GetMusicLoopPoint(); +} + boolean S_SetMusicPosition(UINT32 position) { return I_SetMusicPosition(position); diff --git a/src/s_sound.h b/src/s_sound.h index 42f3a1433..096a03f1f 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -142,6 +142,12 @@ boolean S_SpeedMusic(float speed); // Get Length of Music UINT32 S_GetMusicLength(void); +// Set LoopPoint of Music +boolean S_SetMusicLoopPoint(UINT32 looppoint); + +// Get LoopPoint of Music +UINT32 S_GetMusicLoopPoint(void); + // Set Position of Music boolean S_SetMusicPosition(UINT32 position); diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 33ffb5510..46230e31a 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -477,6 +477,7 @@ static void music_loop(void) { Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); music_bytes = 0; + songpaused = false; // be consistent with FMOD, otherwise I'd prefer to freeze music_bytes // since the other flags indicate music is still playing. } @@ -516,8 +517,13 @@ void I_ShutdownMusic(void) void I_PauseSong(INT32 handle) { (void)handle; - if(!midimode) + + if(midimode) // really, SDL Mixer? why can't you pause MIDI??? + return; + + if(!gme && I_MusicType() != MU_MOD) Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); + Mix_PauseMusic(); songpaused = true; } @@ -525,14 +531,19 @@ void I_PauseSong(INT32 handle) void I_ResumeSong(INT32 handle) { (void)handle; - if(!midimode) + + if (midimode) + return; + + if (!gme && I_MusicType() != MU_MOD) { while(Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes) != 0) { } // HACK: fixes issue of multiple effect callbacks being registered + if(music && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) - // midimode and music must be checked in case nothing is actually playing CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); } + Mix_ResumeMusic(); songpaused = false; } @@ -544,7 +555,7 @@ boolean I_MusicPlaying(void) boolean I_MusicPaused(void) { - return Mix_PausedMusic(); + return songpaused; } // @@ -574,6 +585,7 @@ void I_ShutdownDigMusic(void) if (!music) return; is_looping = false; + songpaused = false; music_bytes = 0; Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_HookMusicFinished(NULL); @@ -714,16 +726,19 @@ boolean I_StartDigSong(const char *musicname, boolean looping) const char *key2 = "POINT="; const char *key3 = "MS="; const char *key4 = "LENGTHMS="; - const char *key1w = "L\0O\0O\0P\0"; - const char *key2w = "P\0O\0I\0N\0T\0=\0"; - const char *key3w = "M\0S\0=\0"; - const char *key4w = "L\0E\0N\0G\0T\0H\0M\0S\0=\0"; - const char *wterm = "\0\0"; const size_t key1len = strlen(key1); const size_t key2len = strlen(key2); const size_t key3len = strlen(key3); const size_t key4len = strlen(key4); - char wval[10]; // millisecond range up to 30 hours! + + // for mp3 wide chars + const char *key1w = "L\0O\0O\0P\0"; + const char *key2w = "P\0O\0I\0N\0T\0\0\0\xFF\xFE"; + const char *key3w = "M\0S\0\0\0\xFF\xFE"; + const char *key4w = "L\0E\0N\0G\0T\0H\0M\0S\0\0\0\xFF\xFE"; + const char *wterm = "\0\0"; + char wval[10]; + size_t wstart, wp; char *p = data; while ((UINT32)(p - data) < len) @@ -753,15 +768,15 @@ boolean I_StartDigSong(const char *musicname, boolean looping) music_length = (float)(atoi(p) / 1000.0L); } // below: search MP3 or other tags that use wide char encoding - else if (!loop_point && !strncmp(p, key1w, key1len*2)) // LOOP wide char + else if (!loop_point && !memcmp(p, key1w, key1len*2)) // LOOP wide char { p += key1len*2; - if (!strncmp(p, key2w, key2len*2)) // POINT= wide char + if (!memcmp(p, key2w, (key2len+1)*2)) // POINT= wide char { - p += key2len*2+2; + p += (key2len+1)*2; wstart = (size_t)p; wp = 0; - while (wp < 9 && strncmp(p, wterm, 2)) + while (wp < 9 && memcmp(p, wterm, 2)) { wval[wp] = *p; p += 2; @@ -770,12 +785,12 @@ boolean I_StartDigSong(const char *musicname, boolean looping) wval[min(wp, 9)] = 0; loop_point = (float)((44.1L+atoi(wval) / 44100.0L)); } - else if (!strncmp(p, key3w, key3len*2)) // MS= wide char + else if (!memcmp(p, key3w, (key3len+1)*2)) // MS= wide char { - p += key3len*2+2; + p += (key3len+1)*2; wstart = (size_t)p; wp = 0; - while (wp < 9 && strncmp(p, wterm, 2)) + while (wp < 9 && memcmp(p, wterm, 2)) { wval[wp] = *p; p += 2; @@ -785,12 +800,12 @@ boolean I_StartDigSong(const char *musicname, boolean looping) loop_point = (float)(atoi(wval) / 1000.0L); } } - else if (!music_length && !strncmp(p, key4w, key4len*2)) // LENGTHMS= wide char + else if (!music_length && !memcmp(p, key4w, (key4len+1)*2)) // LENGTHMS= wide char { - p += key4len*2+2; + p += (key4len+1)*2; wstart = (size_t)p; wp = 0; - while (wp < 9 && strncmp(p, wterm, 2)) + while (wp < 9 && memcmp(p, wterm, 2)) { wval[wp] = *p; p += 2; @@ -824,6 +839,7 @@ boolean I_StartDigSong(const char *musicname, boolean looping) if (I_MusicType() != MU_MOD) Mix_HookMusicFinished(music_loop); // don't bother counting if MOD + songpaused = false; music_bytes = 0; if(I_MusicType() != MU_MOD && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); @@ -848,6 +864,7 @@ void I_StopDigSong(void) if (!music) return; is_looping = false; + songpaused = false; music_bytes = 0; Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_HookMusicFinished(NULL); @@ -924,6 +941,42 @@ UINT32 I_GetMusicLength(void) } } +boolean I_SetMusicLoopPoint(UINT32 looppoint) +{ + if (midimode || gme || !music || I_MusicType() == MU_MOD) + return false; + else + { + loop_point = max((float)(looppoint / 1000.0L), 0); + return true; + } +} + +UINT32 I_GetMusicLoopPoint(void) +{ + if (gme) + { + INT32 looppoint; + gme_info_t *info; + gme_err_t gme_e = gme_track_info(gme, &info, current_track); + + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + looppoint = 0; + } + else + looppoint = info->intro_length > 0 ? info->intro_length : 0; + + gme_free_info(info); + return max(looppoint, 0); + } + else if (midimode || !music || I_MusicType() == MU_MOD) + return 0; + else + return (UINT32)(loop_point * 1000); +} + boolean I_SetMusicPosition(UINT32 position) { UINT32 length; @@ -1056,6 +1109,7 @@ void I_ShutdownMIDIMusic(void) if (!midimode || !music) return; is_looping = false; + songpaused = false; //MIDI does count correctly, but dummy out because unsupported //music_bytes = 0; //Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); @@ -1100,7 +1154,7 @@ boolean I_PlaySong(INT32 handle, boolean looping) } is_looping = looping; - + songpaused = false; //MIDI does count correctly, but dummy out because unsupported //If this is enabled, you need to edit Mix_PlayMusic above to never loop (0) //and register the music_loop callback @@ -1118,7 +1172,7 @@ void I_StopSong(INT32 handle) return; is_looping = false; - + songpaused = false; //MIDI does count correctly, but dummy out because unsupported //music_bytes = 0; //Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); @@ -1132,7 +1186,7 @@ void I_UnRegisterSong(INT32 handle) return; is_looping = false; - + songpaused = false; //MIDI does count correctly, but dummy out because unsupported //music_bytes = 0; //Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); From 9d835614a91c6ca1c68a2bfd8bfc053af30db5dc Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 20:19:54 -0400 Subject: [PATCH 14/19] I_GetMusicLoopPoint and I_SetMusicLoopPoint for other targets --- src/android/i_sound.c | 11 +++++++++++ src/djgppdos/i_sound.c | 11 +++++++++++ src/dummy/i_sound.c | 11 +++++++++++ src/sdl/sdl_sound.c | 11 +++++++++++ src/win32/win_snd.c | 11 +++++++++++ 5 files changed, 55 insertions(+) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index 08721c6a3..6f70134b0 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -163,6 +163,17 @@ UINT32 I_GetMusicLength(void) return 0; } +boolean I_SetMusicLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetMusicLoopPoint(void) +{ + return 0; +} + boolean I_SetMusicPosition(UINT32 position) { (void)position; diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index 8f4e560a8..dbf7a0142 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -556,6 +556,17 @@ UINT32 I_GetMusicLength(void) return 0; } +boolean I_SetMusicLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetMusicLoopPoint(void) +{ + return 0; +} + boolean I_SetMusicPosition(UINT32 position) { (void)position; diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index c16dd8a3f..4cea29049 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -151,6 +151,17 @@ UINT32 I_GetMusicLength(void) return 0; } +boolean I_SetMusicLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetMusicLoopPoint(void) +{ + return 0; +} + boolean I_SetMusicPosition(UINT32 position) { (void)position; diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 748eb4427..e88d874fd 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1993,6 +1993,17 @@ UINT32 I_GetMusicLength(void) return 0; } +boolean I_SetMusicLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetMusicLoopPoint(void) +{ + return 0; +} + boolean I_SetMusicPosition(UINT32 position) { (void)position; diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 987e3498d..066392a41 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -783,6 +783,17 @@ UINT32 I_GetMusicLength() return length; } +boolean I_SetMusicLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetMusicLoopPoint(void) +{ + return 0; +} + boolean I_SetMusicPosition(UINT32 position) { if(midimode) From c64686d8c6249394183e17f6b8b16e47a87c0597 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 20:20:18 -0400 Subject: [PATCH 15/19] I_GetMusicLoopPoint and I_SetMusicLoopPoint for Lua * Fix S_GetMusicLength for player compatibility --- src/lua_baselib.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e7cd69689..83aab8430 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2268,8 +2268,53 @@ static int lib_sSpeedMusic(lua_State *L) #ifdef HAVE_LUA_MUSICPLUS static int lib_sGetMusicLength(lua_State *L) { + player_t *player = NULL; NOHUD - lua_pushinteger(L, (UINT32)S_GetMusicLength()); + if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) + { + player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (!player || P_IsLocalPlayer(player)) + lua_pushinteger(L, (int)S_GetMusicLength()); + else + lua_pushnil(L); + return 1; +} + +static int lib_sSetMusicLoopPoint(lua_State *L) +{ + UINT32 looppoint = (UINT32)luaL_checkinteger(L, 1); + player_t *player = NULL; + NOHUD + if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) + { + player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (!player || P_IsLocalPlayer(player)) + lua_pushboolean(L, S_SetMusicLoopPoint(looppoint)); + else + lua_pushnil(L); + return 1; +} + +static int lib_sGetMusicLoopPoint(lua_State *L) +{ + player_t *player = NULL; + NOHUD + if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) + { + player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (!player || P_IsLocalPlayer(player)) + lua_pushinteger(L, (int)S_GetMusicLoopPoint()); + else + lua_pushnil(L); return 1; } @@ -2851,6 +2896,8 @@ static luaL_Reg lib[] = { {"S_SpeedMusic",lib_sSpeedMusic}, #ifdef HAVE_LUA_MUSICPLUS {"S_GetMusicLength",lib_sGetMusicLength}, + {"S_SetMusicLoopPoint",lib_sSetMusicLoopPoint}, + {"S_GetMusicLoopPoint",lib_sGetMusicLoopPoint}, {"S_SetMusicPosition",lib_sSetMusicPosition}, {"S_GetMusicPosition",lib_sGetMusicPosition}, {"S_PauseMusic",lib_sPauseMusic}, From 6c2fd14b85fb374c641c71893f6fee8a4fcc5a16 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 20:28:52 -0400 Subject: [PATCH 16/19] Loop point modulo by length --- src/sdl/mixer_sound.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 46230e31a..89aef9a7d 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -947,6 +947,11 @@ boolean I_SetMusicLoopPoint(UINT32 looppoint) return false; else { + UINT32 length = I_GetMusicLength(); + + if (length > 0) + looppoint %= length; + loop_point = max((float)(looppoint / 1000.0L), 0); return true; } From 1869c21b6d5c0a7d0e59bdc84b83e286fdaf921e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 20:44:32 -0400 Subject: [PATCH 17/19] Consolidate variable cleanup in mixer_sound * Fix I_SetSongTrack MOD tracking returns the expected result * Make music_loop hook stop digital song properly if not looping --- src/sdl/mixer_sound.c | 56 ++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 89aef9a7d..3cdc061dc 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -76,6 +76,15 @@ static Music_Emu *gme; static INT32 current_track; #endif +static void varcleanup(void) +{ + loop_point = music_length =\ + music_bytes = 0; + + songpaused = is_looping =\ + midimode = false; +} + void I_StartupSound(void) { I_Assert(!sound_started); @@ -474,13 +483,7 @@ static void music_loop(void) music_bytes = loop_point/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetMusicPosition) } else - { - Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); - music_bytes = 0; - songpaused = false; - // be consistent with FMOD, otherwise I'd prefer to freeze music_bytes - // since the other flags indicate music is still playing. - } + I_StopDigSong(); } #ifdef HAVE_LIBGME @@ -584,9 +587,8 @@ void I_ShutdownDigMusic(void) #endif if (!music) return; - is_looping = false; - songpaused = false; - music_bytes = 0; + + varcleanup(); Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_HookMusicFinished(NULL); Mix_FreeMusic(music); @@ -606,7 +608,8 @@ boolean I_StartDigSong(const char *musicname, boolean looping) if (lumpnum == LUMPERROR) return false; - midimode = false; + + varcleanup(); data = (char *)W_CacheLumpNum(lumpnum, PU_MUSIC); len = W_LumpLength(lumpnum); @@ -839,8 +842,6 @@ boolean I_StartDigSong(const char *musicname, boolean looping) if (I_MusicType() != MU_MOD) Mix_HookMusicFinished(music_loop); // don't bother counting if MOD - songpaused = false; - music_bytes = 0; if(I_MusicType() != MU_MOD && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); @@ -863,9 +864,7 @@ void I_StopDigSong(void) #endif if (!music) return; - is_looping = false; - songpaused = false; - music_bytes = 0; + varcleanup(); Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_HookMusicFinished(NULL); Mix_FreeMusic(music); @@ -997,6 +996,7 @@ boolean I_SetMusicPosition(UINT32 position) SDL_LockAudio(); gme_err_t gme_e = gme_seek(gme, position); SDL_UnlockAudio(); + if (gme_e != NULL) { CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); @@ -1008,13 +1008,13 @@ boolean I_SetMusicPosition(UINT32 position) else if (midimode || !music) return false; else if (I_MusicType() == MU_MOD) - // Goes by channels - return Mix_SetMusicPosition(position); + return Mix_SetMusicPosition(position); // Goes by channels else { // Because SDL mixer can't identify song length, if you have // a position input greater than the real length, then // music_bytes becomes inaccurate. + length = I_GetMusicLength(); // get it in MS if (length) position %= length; @@ -1026,6 +1026,7 @@ boolean I_SetMusicPosition(UINT32 position) // NOTE: This block fires on incorrect song format, // NOT if position input is greater than song length. music_bytes = 0; + return true; } } @@ -1096,7 +1097,7 @@ boolean I_SetSongTrack(int track) else #endif if (I_MusicType() == MU_MOD) - Mix_SetMusicPosition(track); + return !Mix_SetMusicPosition(track); (void)track; return false; } @@ -1113,10 +1114,8 @@ void I_ShutdownMIDIMusic(void) { if (!midimode || !music) return; - is_looping = false; - songpaused = false; + varcleanup(); //MIDI does count correctly, but dummy out because unsupported - //music_bytes = 0; //Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_FreeMusic(music); music = NULL; @@ -1150,6 +1149,8 @@ boolean I_PlaySong(INT32 handle, boolean looping) { (void)handle; + varcleanup(); + midimode = true; if (Mix_PlayMusic(music, looping ? -1 : 0) == -1) @@ -1159,11 +1160,10 @@ boolean I_PlaySong(INT32 handle, boolean looping) } is_looping = looping; - songpaused = false; + //MIDI does count correctly, but dummy out because unsupported //If this is enabled, you need to edit Mix_PlayMusic above to never loop (0) //and register the music_loop callback - //music_bytes = 0; //if(!Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) // CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); @@ -1176,10 +1176,8 @@ void I_StopSong(INT32 handle) if (!midimode || !music) return; - is_looping = false; - songpaused = false; + varcleanup(); //MIDI does count correctly, but dummy out because unsupported - //music_bytes = 0; //Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); (void)handle; Mix_HaltMusic(); @@ -1190,10 +1188,8 @@ void I_UnRegisterSong(INT32 handle) if (!midimode || !music) return; - is_looping = false; - songpaused = false; + varcleanup(); //MIDI does count correctly, but dummy out because unsupported - //music_bytes = 0; //Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); (void)handle; Mix_FreeMusic(music); From 0a0537d486521b9c8580830dc996205f3676aff2 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 20:47:14 -0400 Subject: [PATCH 18/19] Fix S_SetMusicLoopPoint wrong method; trigger only on is_looping --- src/s_sound.c | 2 +- src/sdl/mixer_sound.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index af1425abf..3b0c87463 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1429,7 +1429,7 @@ UINT32 S_GetMusicLength(void) boolean S_SetMusicLoopPoint(UINT32 looppoint) { - return I_SetMusicPosition(looppoint); + return I_SetMusicLoopPoint(looppoint); } UINT32 S_GetMusicLoopPoint(void) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 3cdc061dc..3da012c85 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -942,7 +942,7 @@ UINT32 I_GetMusicLength(void) boolean I_SetMusicLoopPoint(UINT32 looppoint) { - if (midimode || gme || !music || I_MusicType() == MU_MOD) + if (midimode || gme || !music || I_MusicType() == MU_MOD || !is_looping) return false; else { From 2f7bdd4aa379857203a999e99a59648b71a035e9 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 21:29:18 -0400 Subject: [PATCH 19/19] Fixed loop point counter bug --- src/sdl/mixer_sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 3da012c85..d7785170a 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -480,7 +480,7 @@ static void music_loop(void) { Mix_PlayMusic(music, 0); Mix_SetMusicPosition(loop_point); - music_bytes = loop_point/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetMusicPosition) + music_bytes = loop_point*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetMusicPosition) } else I_StopDigSong();