Skip to content

Commit 70a9a11

Browse files
committed
Cleanup music variables
Use old track order if no custom song weights have been set
1 parent 22b9d8c commit 70a9a11

File tree

2 files changed

+83
-61
lines changed

2 files changed

+83
-61
lines changed

source/modules/memory/init.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ end
604604
function memory.runhooks()
605605
local pop
606606
while true do
607-
pop = table.remove(memory.hook_queue, #memory.hook_queue)
607+
pop = table.remove(memory.hook_queue, 1)
608608
if not pop then break end
609609
memory.runhook(pop.name, pop.value)
610610
end

source/music.lua

+82-60
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
local music = {}
1+
local music = {
2+
PLAYLIST = {},
3+
PLAYLIST_ID = -1,
4+
PLAYING = nil,
5+
FINISHED = true,
6+
LOOP = false,
7+
USE_WEIGHTS = false,
8+
TRACK_NUMBER = {},
9+
}
210

311
local log = require("log")
412
local melee = require("melee")
@@ -8,30 +16,25 @@ local wav = require("wav")
816

917
require("extensions.math")
1018

11-
local STAGE_TRACKS = {}
12-
local STAGE_ID = -1
13-
local PLAYING_SONG = nil
14-
local SOURCE_SONG_LOOPS = {}
15-
local SONG_FINISHED_PLAYING = true
16-
local SONG_SHOULD_LOOP = false
17-
1819
-- Given a list of {element, weight} pairs, do a weighted random sample
1920
-- of the elements (returns an index, not the element itself)
2021
local function weightedRandomChoice(list)
2122
if not list or #list == 0 then return nil end
2223
if #list == 1 then return 1 end
23-
local weight_sum = 0
24-
for idx=1,#list do
25-
weight_sum = weight_sum + list[idx].weight
24+
25+
local sum = 0
26+
for i=1, #list do
27+
sum = sum + list[i].WEIGHT
2628
end
27-
local choice = math.random(1, weight_sum)
29+
30+
local choice = math.random(1, sum)
2831
for idx=1,#list do
29-
choice = choice - list[idx].weight
32+
choice = choice - list[idx].WEIGHT
3033
if choice <= 0 then
3134
return idx
3235
end
3336
end
34-
return choice_idx
37+
return choice
3538
end
3639

3740
local function moveFolderContentsTo(from, to)
@@ -51,37 +54,37 @@ local function moveFolderContentsTo(from, to)
5154
end
5255

5356
function music.update()
54-
if not PLAYING_SONG or SONG_FINISHED_PLAYING then return end
57+
if not music.PLAYING or music.FINISHED then return end
5558

56-
local duration = PLAYING_SONG:getDuration("samples")
57-
local position = PLAYING_SONG:tell("samples")
59+
local duration = music.PLAYING.STREAM:getDuration("samples")
60+
local position = music.PLAYING.STREAM:tell("samples")
5861

59-
if SONG_SHOULD_LOOP then
60-
local finished = not PLAYING_SONG:isPlaying()
62+
if music.LOOP then
63+
local finished = not music.PLAYING.STREAM:isPlaying()
6164

6265
if finished then
6366
-- If the song is no longer playing, that means it reached the end
6467
-- Immediately play it again
6568
log.debug("[MUSIC] End of song reached, replaying")
66-
PLAYING_SONG:play()
69+
music.PLAYING.STREAM:play()
6770
end
6871

69-
local info = SOURCE_SONG_LOOPS[PLAYING_SONG]
72+
local info = music.PLAYING.WAV
7073

7174
if info then
7275
for k, loop in pairs(info.loops) do
7376
if finished or position >= loop.sample_end then
7477
log.debug("[MUSIC] Loop point reached, seeking to %d", loop.sample_start)
7578
-- If the song finished playing or reached the looping point, loop back to the start?
76-
PLAYING_SONG:seek(loop.sample_start, "samples")
79+
music.PLAYING.STREAM:seek(loop.sample_start, "samples")
7780
break -- Only handle the first loop for now..
7881
end
7982
end
8083
end
8184
else
82-
if not PLAYING_SONG:isPlaying() or position >= duration then
85+
if not music.PLAYING.STREAM:isPlaying() or position >= duration then
8386
-- We mark that the song has completed, allowing the next game frame hook to play the next song in the playlist
84-
SONG_FINISHED_PLAYING = true
87+
music.FINISHED = true
8588
end
8689
end
8790
end
@@ -137,9 +140,9 @@ function music.init()
137140
end
138141

139142
function music.kill()
140-
if PLAYING_SONG and PLAYING_SONG:isPlaying() then
141-
PLAYING_SONG:stop()
142-
SONG_FINISHED_PLAYING = true
143+
if music.PLAYING and music.PLAYING.STREAM:isPlaying() then
144+
music.PLAYING.STREAM:stop()
145+
music.FINISHED = true
143146
end
144147
end
145148

@@ -156,7 +159,7 @@ function music.shouldPlayMusic()
156159
end
157160

158161
function music.onLoopChange(mode)
159-
if PLAYING_SONG and PLAYING_SONG:isPlaying() then
162+
if music.PLAYING and music.PLAYING.STREAM:isPlaying() then
160163
local loop = false
161164
-- Handle the different loop settings properly
162165
if mode == LOOPING_MENU and melee.isInMenus() then
@@ -166,8 +169,8 @@ function music.onLoopChange(mode)
166169
elseif mode == LOOPING_ALL then
167170
loop = true
168171
end
169-
--PLAYING_SONG:setLooping(loop)
170-
SONG_SHOULD_LOOP = loop
172+
--music.PLAYING.STREAM:setLooping(loop)
173+
music.LOOP = loop
171174
end
172175
end
173176

@@ -211,43 +214,58 @@ function music.setVolume(vol)
211214
memory.writeByte(0x804D3887, (vol/100) * 127)
212215
end
213216

214-
if PLAYING_SONG and PLAYING_SONG:isPlaying() then
215-
PLAYING_SONG:setVolume((vol/100) * (memory.match.paused and 0.35 or 1))
217+
if music.PLAYING and music.PLAYING.STREAM:isPlaying() then
218+
music.PLAYING.STREAM:setVolume((vol/100) * (memory.match.paused and 0.35 or 1))
216219
end
217220
end
218221

219222
function music.playNextTrack()
220223
if not memory.isMelee() or not PANEL_SETTINGS:PlayStageMusic() then return end
221-
if PLAYING_SONG ~= nil and not SONG_FINISHED_PLAYING then return end
222-
if not STAGE_ID then return end
224+
if music.PLAYING ~= nil and not music.FINISHED then return end
225+
if not music.PLAYLIST_ID then return end
223226
if not music.shouldPlayMusic() then return end
224227

225-
local songs = STAGE_TRACKS
228+
local songs = music.PLAYLIST
226229

227-
if songs and #songs > 0 then
228-
local track = weightedRandomChoice(songs)
229-
if not track or not songs[track] then return end
230+
if #music.PLAYLIST > 0 then
231+
local track
230232

231-
PLAYING_SONG = songs[track].source
233+
if music.USE_WEIGHTS then
234+
track = weightedRandomChoice(songs)
235+
if not track or not songs[track] then return end
236+
music.PLAYING = songs[track]
232237

233-
if PLAYING_SONG then
234-
if STAGE_ID == 0x0 then
238+
else
239+
music.TRACK_NUMBER[music.PLAYLIST_ID] = ((music.TRACK_NUMBER[music.PLAYLIST_ID] or -1) + 1) % #songs
240+
track = music.TRACK_NUMBER[music.PLAYLIST_ID] + 1
241+
music.PLAYING = songs[track]
242+
243+
-- Every time we play a song, we randomly place it towards the start of the playlist
244+
local newpos = math.random(1, track)
245+
246+
table.remove(songs, track)
247+
table.insert(songs, newpos, music.PLAYING)
248+
end
249+
250+
251+
if music.PLAYING then
252+
if music.PLAYLIST_ID == 0x0 then
235253
log.info("[MUSIC] Playing track #%d for menu", track)
236254
else
237-
log.info("[MUSIC] Playing track #%d for stage %q", track, melee.getStageName(STAGE_ID))
255+
log.info("[MUSIC] Playing track #%d for stage %q", track, melee.getStageName(music.PLAYLIST_ID))
238256
end
239257

240258
local loop = PANEL_SETTINGS:GetMusicLoopMode()
241259

242-
if STAGE_ID == 0 then
243-
SONG_SHOULD_LOOP = loop == LOOPING_MENU or loop == LOOPING_ALL
260+
if music.PLAYLIST_ID == 0 then
261+
music.LOOP = loop == LOOPING_MENU or loop == LOOPING_ALL
244262
else
245-
SONG_SHOULD_LOOP = loop == LOOPING_STAGE or loop == LOOPING_ALL
263+
music.LOOP = loop == LOOPING_STAGE or loop == LOOPING_ALL
246264
end
247265

248-
PLAYING_SONG:setVolume((PANEL_SETTINGS:GetVolume()/100) * (memory.match.paused and 0.35 or 1))
249-
PLAYING_SONG:play()
250-
SONG_FINISHED_PLAYING = false
266+
music.PLAYING.STREAM:setVolume((PANEL_SETTINGS:GetVolume()/100) * (memory.match.paused and 0.35 or 1))
267+
music.PLAYING.STREAM:play()
268+
music.FINISHED = false
251269
end
252270
end
253271
end
@@ -325,7 +343,7 @@ end)
325343
memory.hook("controller.*.buttons.pressed", "Melee - Music skipper", function(port, pressed)
326344
if PANEL_SETTINGS:IsBinding() or PANEL_SETTINGS:IsSlippiReplay() then return end -- Don't skip when the user is setting a button combination or when watching a replay
327345
local mask = PANEL_SETTINGS:GetMusicSkipMask()
328-
if mask ~= 0x0 and port == love.getPort() and bit.band(pressed, mask) == mask and #STAGE_TRACKS > 1 then
346+
if mask ~= 0x0 and port == love.getPort() and pressed == mask and #music.PLAYLIST > 1 then
329347
log.debug("[MUSIC] [MASK = 0x%X] Button combo pressed, stopping music.", mask)
330348
music.kill()
331349
end
@@ -353,15 +371,18 @@ function music.loadStageMusicInDir(stageid, name)
353371
loaded = loaded + 1
354372

355373
-- Insert the newly loaded track into a random position in the playlist
356-
local pos = math.random(1, #STAGE_TRACKS)
374+
local pos = math.random(1, #music.PLAYLIST)
357375
local prob = tonumber(string.match(filepath, "[^%._\n]+_(%d+)%.%w+$")) or 1
358376

359-
table.insert(STAGE_TRACKS, pos, {source = source, weight = prob})
377+
if prob > 1 then
378+
music.USE_WEIGHTS = true
379+
end
360380

381+
local wavinfo
361382
if ext == "wav" then
362-
SOURCE_SONG_LOOPS[source] = wav.parse(filepath)
363-
log.debug("[MUSIC] Parsed %q for loop points: %d found", file, #SOURCE_SONG_LOOPS[source].loops)
383+
wavinfo = wav.parse(filepath)
364384
end
385+
table.insert(music.PLAYLIST, pos, {STREAM = source, WEIGHT = prob, WAV = wavinfo})
365386
else
366387
local err = ("invalid music file \"%s/%s\""):format(name, file)
367388
log.error("[MUSIC] %s", err)
@@ -376,19 +397,20 @@ function music.loadStageMusicInDir(stageid, name)
376397
end
377398

378399
function music.loadForStage(stageid)
379-
if STAGE_ID == stageid then return end
400+
if music.PLAYLIST_ID == stageid then return end
380401

381402
music.kill()
382403
if not memory.isMelee() or not PANEL_SETTINGS:PlayStageMusic() then return end
383404

384-
STAGE_ID = stageid
405+
music.PLAYLIST_ID = stageid
385406

386-
for k,v in pairs(STAGE_TRACKS) do
387-
v.source:release()
407+
for k,v in pairs(music.PLAYLIST) do
408+
v.STREAM:release()
388409
end
389410

390-
PLAYING_SONG = nil
391-
STAGE_TRACKS = {}
411+
music.PLAYING = nil
412+
music.PLAYLIST = {}
413+
music.USE_WEIGHTS = false
392414

393415
music.loadStageMusicInDir(stageid, "Melee")
394416

@@ -405,7 +427,7 @@ function music.loadForStage(stageid)
405427
local sp = melee.isSinglePlayerStage(stageid)
406428
local aka = melee.isAkaneiaStage(stageid)
407429

408-
if not name then STAGE_ID = nil return end
430+
if not name then music.PLAYLIST_ID = nil return end
409431

410432
if sp then
411433
music.loadStageMusicInDir(stageid, ("Melee/Single Player Music/%s"):format(name)) -- Load everything in the stage specific folder

0 commit comments

Comments
 (0)