Skip to content
Snippets Groups Projects

MusicPlus core: Song length, positioning, and fading features with Linedef Exec and Lua support

Merged mazmazz requested to merge public-musicplus-core into next

This is the reason why music-cleanup was proposed (!278 (merged)). This is also a prerequisite for libopenmpt and non-native MIDI.

This branch adds music seeking and fading to the engine, as well as Linedef Exec and Lua support.

See comments for Linedef Exec and Lua documentation.

Implementation

  • The position/seeking methods depend on a new music tag LENGTHMS=milliseconds
    • This tag is necessary because SDL Mixer cannot detect song length.
    • Without this tag, the seeking will still happen, with the following side effects:
      • Seeking past the end of the song may reset the "listening" position at 0, but the internal position counter will increment from the erroneous seek position. It will never reset to 0 until the music is changed.
      • Any future features that depend on reading song position will not work correctly (e.g., jingle resuming) until the music is changed.
    • The game spits a warning in DEVMODE 2 (detailed) if this tag is not present.
    • OGG, FLAC, and MP3 support this length tag. GME and MOD do not need this tag. MIDI cannot use this tag.
    • Auto-tag all your music lumps by running your WAD through musiclengthms.zip (Source). music.dta could use this treatment for future releases.
  • The fading method implements an "internal music volume", a percentage of the user's configured game volume.
    • When an internal volume of less-than 100% is applied, the game adjusts the playback volume to make the song quieter. This is always relative to the user-configured volume. Fading is accomplished by incrementing this internal volume per millisecond.
    • I do not use SDL Mixer's Mix_FadeIn/OutMusic() methods due to these reasons:
      1. They are thread-blocking, e.g., the game window cannot exit until the fade is completed
      2. They cannot be interrupted in the middle of the fade
      3. They do not respect the user's configured volume (at least not easily)
      4. They do not work on GME
    • MIDI cannot fade due to the Win32 volume hack

Test Files

  • test_music.wad - Collection of music lumps in different formats
  • test_musicplus-safe.lua - Lua functions for testing; type musichelp in console for a list of these
    • Sample: musicchange MAP02M 1 0 10000 2000 1000 - Switch to MAP02M music, looping enabled (1), track 0, jump to position 10000, fade out for 2000 ms, fade in for 1000 ms
  • test_le-music.wad - Linedef executor test for fading and positioning functions
  • Srb2-21-changemusic.cfg - ZoneBuilder config for the updated Change Music linedef exec features
  • EXE binaries
Edited by mazmazz

Merge request reports

Loading
Loading

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
  • mazmazz changed the description

    changed the description

  • Author Contributor

    Line Exec 413: Change Music with fading and positioning features

    Linedef Exec Change Music updated to support the new seeking and fading features.

    What it already does

    • Front Upper: Music name
    • Front Lower: Track
    • Solid Midtex: Looping = False
    • No Climb: Music changes for everyone
    • Block Enemies: MUSIC_RELOADRESET = False

    What we added

    • Front Middle: Position to jump to
    • ML_EFFECT1: Start position from current song position, and Front Middle adds or subtracts from this value
    • Front X Offset: Fade out milliseconds from old song, 0 for instant change
    • Front Y Offset: Fade in milliseconds to new song
    • ML_EFFECT2: Fade to custom volume target
      • Front Y Offset: Millisecond length of custom fade
      • Back X Offset: Volume to fade to, 0-100
      • Back Y Offset: Volume to fade from (or 0 for current), 1-100
    • ML_BOUNCY: MUSIC_FORCERELOAD = True
    Edited by mazmazz
  • Author Contributor

    New Lua Functions

    See e2e34598 for brand new Lua functions. I'm pretty sure these are safe from local state hackery, but this commit can be reverted otherwise.

    • S_ChangeMusic(string musicname, [boolean looping?, [player_t player, [int tracknum, [int position, [int prefadems, [int fadeinms]]]]]])
      • position - Millisecond position to start at upon song change
      • prefadems - Milliseconds to fade out of the current song before changing to the new song
      • fadeinms - Milliseconds to fade into the new song
    • S_MusicExists(name[, checkMIDI[, checkDigi]])
      • Check if musicname lump exists. Set checkMIDI or checkDigi flags to enable checking D_ or O_ lumps, respectively. Both flags default to true.
    • S_SetInternalMusicVolume(int volume, [player_t player])
      • Immediately set the internal volume level between 0-100%
    • S_FadeMusic(int target_volume, int ms, [player_t player]) or S_FadeMusic(int target_volume, int ms, [int source_volume, [player_t player]])
      • Fade music from source volume to target volume, 0-100%. If source_volume is not specified, the source volume is the current internal volume.
    • S_FadeOutStopMusic(int ms, [player_t player])
      • Fade music from current internal volume to 0%, then stop the music.
    • S_StopFadingMusic([player_t player])
      • Stop any current fade from running. The music remains playing at the current internal volume.
    Edited by mazmazz
  • Author Contributor

    I realize S_MusicExists can be different across clients because music WADs don't have to be synced, so I'll remove this.

  • mazmazz added 1 commit

    added 1 commit

    Compare with previous version

  • Author Contributor

    Top post updated to add ZoneBuilder config for the Change Music linedef exec, as well as a link to EXE binaries for testing.

  • mazmazz changed the description

    changed the description

  • mazmazz changed the description

    changed the description

  • mazmazz added 1 commit

    added 1 commit

    Compare with previous version

  • Contributor

    hud.MusicExists?

    Edited by toaster
  • Author Contributor

    Possibly, that's a good idea. I wonder what MI or anyone else would prefer. The solutions are:

    • Make Lua functions available as HUD-only
    • Make Lua functions available always, regardless of net safety
    • Implement in code but disable Lua functions by default; hide behind #ifdef HAVE_LUA_MUSICPLUS
    • Don't implement in code

    Included in this MR are what I believe to be net-safe functions:

    • S_ChangeMusic (fade/position update)
    • S_SetInternalMusicVolume
    • S_StopFadingMusic
    • S_FadeMusic
    • S_FadeOutStopMusic

    Excluded for net-unsafety (see https://git.magicalgirl.moe/digiku/SRB2/merge_requests/2 for code):

    • S_MusicType -- Format of currently music
    • S_MusicPlaying -- Is there any music currently playing?
    • S_MusicPaused -- Is the music paused?
    • S_MusicName -- Name of current music
    • S_MusicInfo -- Get type, name, and statuses of current music? This is a multi-function.
    • S_MusicExists -- Lump checker for O_/D_ music
    • S_GetMusicLength
    • S_SetMusicLoopPoint
    • S_GetMusicLoopPoint
    • S_SetMusicPosition
    • S_GetMusicPosition
    • S_PauseMusic
    • S_ResumeMusic

    Already in vanilla:

    • S_StartSound
    • S_StartSoundAtVolume
    • S_StopSound
    • S_ChangeMusic
    • S_SpeedMusic
    • S_StopMusic
    • S_OriginPlaying
    • S_IdPlaying
    • S_SoundPlaying

    It's worth noting that some of the current sound functions are already net-unsafe as it is (S_SoundPlaying in particular)

    Edited by mazmazz
  • mazmazz changed the description

    changed the description

  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
Please register or sign in to reply
Loading