Skip to content

Commit 2bd661e

Browse files
committed
Completed CBF beatmap loader
Volume normalization (like ReplayGain but it's not) - Quiter sounds will be sounds louder Beatmap selection now with pages Implemented swing + long note (Mermaid Festa vol.2 Master) - Velocity < 64 when making beatmaps with MIDI editor - Updated LS2 specification to reflect this change (code updated soon)
1 parent ef6bb6e commit 2bd661e

11 files changed

+187
-41
lines changed

AquaShine.lua

+17-18
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ local AquaShine = {
1616
}
1717

1818
local love = require("love")
19-
local JSON = require("JSON")
20-
local Yohane = require("Yohane")
2119
local Shelsha = require("Shelsha")
22-
local SkipCall = 0
2320

2421
local ScreenshotThreadCode = [[
2522
local lt = require("love.timer")
@@ -135,15 +132,15 @@ function AquaShine.LoadConfig(key, defval)
135132
return tonumber(data) or data
136133
end
137134

135+
local TemporaryEntryPoint
138136
--! @brief Loads entry point
139137
--! @param name The entry point Lua script file
140138
--! @param arg Additional argument to be passed
141139
function AquaShine.LoadEntryPoint(name, arg)
142140
local scriptdata = assert(love.filesystem.load(name))()
143141
scriptdata.Start(arg or {})
144-
AquaShine.CurrentEntryPoint = scriptdata
145-
146-
SkipCall = 1
142+
--AquaShine.CurrentEntryPoint = scriptdata
143+
TemporaryEntryPoint = scriptdata
147144
end
148145

149146
--! Function used to replace extension on file
@@ -319,6 +316,12 @@ end
319316
------------------------------
320317
function AquaShine.MainLoop()
321318
while true do
319+
-- Switch entry point
320+
if TemporaryEntryPoint then
321+
AquaShine.CurrentEntryPoint = TemporaryEntryPoint
322+
TemporaryEntryPoint = nil
323+
end
324+
322325
-- Process events.
323326
love.event.pump()
324327
for name, a,b,c,d,e,f in love.event.poll() do
@@ -338,18 +341,14 @@ function AquaShine.MainLoop()
338341
love.graphics.clear()
339342

340343
if AquaShine.CurrentEntryPoint then
341-
if SkipCall == 0 then
342-
dt = dt * 1000
343-
AquaShine.CurrentEntryPoint.Update(dt)
344-
love.graphics.push()
345-
346-
love.graphics.translate(AquaShine.LogicalScale.OffX, AquaShine.LogicalScale.OffY)
347-
love.graphics.scale(AquaShine.LogicalScale.ScaleOverall)
348-
AquaShine.CurrentEntryPoint.Draw(dt)
349-
love.graphics.pop()
350-
else
351-
SkipCall = SkipCall - 1
352-
end
344+
dt = dt * 1000
345+
AquaShine.CurrentEntryPoint.Update(dt)
346+
love.graphics.push()
347+
348+
love.graphics.translate(AquaShine.LogicalScale.OffX, AquaShine.LogicalScale.OffY)
349+
love.graphics.scale(AquaShine.LogicalScale.ScaleOverall)
350+
AquaShine.CurrentEntryPoint.Draw(dt)
351+
love.graphics.pop()
353352
else
354353
love.graphics.setFont(font)
355354
love.graphics.print("AquaShine loader: No entry point specificed/entry point rejected", 10, 10)
-3.89 KB
Binary file not shown.
-4.06 KB
Binary file not shown.

assets/image/cbf/star4foreRSmile.png

-3.26 KB
Binary file not shown.

docs/Storyboard.md

+2
Original file line numberDiff line numberDiff line change
@@ -317,3 +317,5 @@ Parameters:
317317
* `attribute` - Note attribute. 1, 2, 3 are Smile, Pure, and Cool respectively. The others depends on beatmap type.
318318

319319
* `is_simul` - Is the note is a simultaneous note? (start holding only)
320+
321+
* `is_slide` - Is the note is a slide note?

livesim.lua

+7
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,13 @@ function DEPLS.Start(argv)
583583
DEPLS.Sound.BeatmapAudio = noteloader_data.song_file
584584
DEPLS.Sound.LiveClear = noteloader_data.live_clear
585585

586+
-- Normalize song volume
587+
-- Enabled on LuaJIT by default, disabled on Lua 5.1 by default
588+
if noteloader_data.song_file and ((jit and not(AquaShine.GetCommandLineConfig("norg"))) or AquaShine.GetCommandLineConfig("forcerg")) then
589+
require("volume_normalizer")(noteloader_data.song_file)
590+
end
591+
592+
-- Load background
586593
if type(noteloader_data.background) == "number" then
587594
BackgroundID = noteloader_data.background
588595
elseif type(noteloader_data.background) == "table" then

main.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
-- Since AquaShine is special for Live Simulator: 2, it's not available as standalone Lua script.
44
-- Please see docs/AquaShine.md for more information.
55

6-
DEPLS_VERSION = "1.0.0-pre1"
6+
DEPLS_VERSION = "1.0.0-pre2"
77

88
----------------------
99
-- AquaShine loader --

note.lua

+24-7
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,21 @@ local function NewNoteObject(note_data)
145145
end
146146

147147
PreviousSlideNote = noteobj
148-
elseif note_data.effect == 3 then
149-
PreviousSlideNote = nil
148+
elseif note_data.effect == 3 or note_data.effect == 13 then
149+
-- Long note (necessarily with swing)
150+
if note_data.effect == 13 then
151+
noteobj.SlideNote = true
152+
153+
if PreviousSlideNote then
154+
noteobj.Rotation =
155+
(PreviousSlideNote.Position - note_data.position > 0 and 0 or math.pi) + PredefinedSlideRotation[note_data.position]
156+
noteobj.PreviousChain = PreviousSlideNote
157+
158+
PreviousSlideNote.NextChain = noteobj
159+
end
160+
else
161+
PreviousSlideNote = nil
162+
end
150163

151164
-- Long note. Use LongNoteObject metatable
152165
noteobj.Audio2 = {
@@ -387,7 +400,8 @@ function LongNoteObject.Update(this, deltaT)
387400
0, -- accuracy (miss)
388401
notedistance, -- distance
389402
this.Attribute, -- attribute
390-
this.SimulNoteImage -- is_simul
403+
this.SimulNote, -- is_simul
404+
this.SlideNote -- is_slide
391405
)
392406
return
393407
end
@@ -434,7 +448,7 @@ function LongNoteObject.Draw(this)
434448

435449
setBlendMode("alpha")
436450
setColor(255, 255, 255, DEPLS.LiveOpacity)
437-
draw(this.NoteImage, this.FirstCircle[1], this.FirstCircle[2], 0, this.CircleScale, this.CircleScale, 64, 64)
451+
draw(this.NoteImage, this.FirstCircle[1], this.FirstCircle[2], this.Rotation or 0, this.CircleScale, this.CircleScale, 64, 64)
438452

439453
-- Draw simultaneous note bar if it is
440454
if this.SimulNoteImage then
@@ -491,7 +505,8 @@ function LongNoteObject.SetTouchID(this, touchid)
491505
this.ScoreMultipler, -- accuracy
492506
notedistance, -- distance
493507
this.Attribute, -- attribute
494-
this.SimulNoteImage -- is_simul
508+
this.SimulNote, -- is_simul
509+
this.SlideNote -- is_slide
495510
)
496511

497512
return
@@ -539,7 +554,8 @@ function LongNoteObject.SetTouchID(this, touchid)
539554
this.ScoreMultipler, -- accuracy
540555
notedistance, -- distance
541556
this.Attribute, -- attribute
542-
this.SimulNote -- is_simul
557+
this.SimulNote, -- is_simul
558+
this.SlideNote -- is_slide
543559
)
544560
end
545561
end
@@ -610,7 +626,8 @@ function LongNoteObject.UnsetTouchID(this, touchid)
610626
this.ScoreMultipler2, -- accuracy
611627
notedistance, -- distance
612628
this.Attribute, -- attribute
613-
this.SimulNote -- is_simul
629+
this.SimulNote, -- is_simul
630+
this.SlideNote -- is_slide
614631
)
615632
end
616633

noteloader/load_cbf.lua

+33-6
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,31 @@ local UnitIconCache = {
3232
HANAMARU_INITIAL_IDOL = AquaShine.LoadImage("assets/image/cbf/01_Initial_Idolized_game.png"),
3333
ELI_THIEF = AquaShine.LoadImage("assets/image/cbf/02_thief_unidolized_game.png"),
3434
ELI_THIEF_IDOL = AquaShine.LoadImage("assets/image/cbf/02_thief_idolized_game.png"),
35-
-- TODO: Complete it
35+
RIN_ARABIAN = AquaShine.LoadImage("assets/image/cbf/01_arabianSet_unidolized_game.png"),
36+
RIN_ARABIAN_IDOL = AquaShine.LoadImage("assets/image/cbf/01_arabianSet_idolized_game.png"),
37+
NOZOMI_IDOLSET = AquaShine.LoadImage("assets/image/cbf/01_idolCostumeSet_unidolized_game.png"),
38+
NOZOMI_IDOLSET_IDOL = AquaShine.LoadImage("assets/image/cbf/01_idolCostumeSet_idolized_game.png"),
39+
NICO_DEVIL = AquaShine.LoadImage("assets/image/cbf/01_devil_unidolized_game.png"),
40+
NICO_DEVIL_IDOL = AquaShine.LoadImage("assets/image/cbf/01_devil_idolized_game.png"),
41+
UMI_DEVIL = AquaShine.LoadImage("assets/image/cbf/01_devil_unidolized_game_2.png"),
42+
HANAYO_TAISHOROMAN = AquaShine.LoadImage("assets/image/cbf/01_taishoRoman_unidolized_game.png"),
43+
HANAYO_TAISHOROMAN_IDOL = AquaShine.LoadImage("assets/image/cbf/01_taishoRoman_idolized_game.png"),
44+
ELI_POOL = AquaShine.LoadImage("assets/image/cbf/01_pool_unidolized_game.png"),
45+
KANAN_YUKATA = AquaShine.LoadImage("assets/image/cbf/01_yukata_unidolized_game.png"),
46+
KANAN_YUKATA_IDOL = AquaShine.LoadImage("assets/image/cbf/01_yukata_idolized_game.png"),
47+
YOSHIKO_YUKATA = AquaShine.LoadImage("assets/image/cbf/01_yukata_unidolized_game_2.png"),
48+
YOSHIKO_YUKATA_IDOL = AquaShine.LoadImage("assets/image/cbf/01_yukata_idolized_game_3.png"),
49+
YOU_YUKATA = AquaShine.LoadImage("assets/image/cbf/01_yukata_unidolized_game_3.png"),
50+
YOU_YUKATA_IDOL = AquaShine.LoadImage("assets/image/cbf/01_yukata_idolized_game_2.png"),
51+
MAKI_POOL = AquaShine.LoadImage("assets/image/cbf/01_pool_unidolized_game_2.png"),
52+
MAKI_POOL_IDOL = AquaShine.LoadImage("assets/image/cbf/01_pool_idolized_game.png"),
53+
RUBY_GOTHIC = AquaShine.LoadImage("assets/image/cbf/01_gothic_unidolized_game.png"),
54+
RUBY_GOTHIC_IDOL = AquaShine.LoadImage("assets/image/cbf/01_gothic_idolized_game.png"),
55+
YOSHIKO_HALLOWEEN = AquaShine.LoadImage("assets/image/cbf/01_halloween_unidolized_game.png"),
56+
YOSHIKO_HALLOWEEN_IDOL = AquaShine.LoadImage("assets/image/cbf/01_halloween_idolized_game_2.png"),
57+
MARI_HALLOWEEN_IDOL = AquaShine.LoadImage("assets/image/cbf/01_halloween_idolized_game.png"),
58+
RIKO_HALLOWEEN_IDOL = AquaShine.LoadImage("assets/image/cbf/01_halloween_idolized_game_3.png"),
59+
HANAMARU_YUKATA = AquaShine.LoadImage("assets/image/cbf/02_yukata_unidolized_game.png")
3660
}
3761
local IconCache = {
3862
None = {
@@ -181,11 +205,11 @@ local function LoadUnitStrategy2(file)
181205
then
182206
for line in love.filesystem.lines(listname) do
183207
if #line > 0 then
184-
local idx, name = line:match("(%d+)/([^;]+)")
208+
local idx = line:match("([^/]+)/[^;]+")
185209
local _, img = pcall(love.graphics.newImage, file[1].."/Custom Cards/"..idx..".png")
186210

187211
if _ then
188-
UnitIconCache[name] = img
212+
UnitIconCache[idx] = img
189213
end
190214
end
191215
end
@@ -283,7 +307,10 @@ function CBFBeatmap.Load(file)
283307
hold_time = tonumber(hold_time)
284308

285309
if is_customcol == "True" then
286-
attri = bit.bor(bit.bor(bit.lshift(tonumber(r) * 255, 23), bit.lshift(tonumber(g) * 255, 14)), bit.bor(bit.lshift(tonumber(b) * 255, 5), 31))
310+
attri = bit.bor(
311+
bit.bor(bit.lshift(math.floor(tonumber(r) * 255), 23), bit.lshift(math.floor(tonumber(g) * 255), 14)),
312+
bit.bor(bit.lshift(math.floor(tonumber(b) * 255), 5), 31)
313+
)
287314
end
288315

289316
if is_release == "True" then
@@ -387,8 +414,8 @@ function CBFBeatmap.Load(file)
387414
units[i] = CompositionCache[cache_name]
388415
has_custom_units = true
389416
else
390-
local attr, rar, cname, r, g, b, cust_char = line:match("[^/]+/([^/]+)/([^/]+)/([^/]*)/(%d+%.?%d*),(%d+%.?%d*),(%d+%.?%d*)/([False|True]+);")
391-
local a = ComposeUnitImage(attr, rar, cust_char == "True" and cname, r, g, b)
417+
local attr, rar, cname, r, g, b = line:match("[^/]+/([^/]+)/([^/]+)/([^/]*)/(%d+%.?%d*),(%d+%.?%d*),(%d+%.?%d*)/")
418+
local a = ComposeUnitImage(attr, rar, cname, r, g, b)
392419

393420
units[i] = a
394421
CompositionCache[cache_name] = a

select_beatmap.lua

+48-9
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ local CurrentPage = 0
77
local BeatmapSelectedIndex = 0
88
local MouseState = {X = 0, Y = 0, Pressed = {}}
99

10-
local com_button_14
11-
local com_button_14di
12-
local com_button_14se
10+
local com_button_14, com_button_14di, com_button_14se
1311
local com_win_02
14-
local s_button_03
15-
local s_button_03se
12+
local s_button_03, s_button_03se
13+
local com_button_12, com_button_12se
14+
local com_button_13, com_button_13se
1615
local log_etc_08
1716
local liveback_1
1817

@@ -37,6 +36,10 @@ function SelectBeatmap.Start(arg)
3736
s_button_03 = AquaShine.LoadImage("image/s_button_03.png")
3837
s_button_03se = AquaShine.LoadImage("image/s_button_03se.png")
3938
log_etc_08 = AquaShine.LoadImage("assets/image/ui/log_etc_08.png")
39+
com_button_12 = AquaShine.LoadImage("assets/image/ui/com_button_12.png")
40+
com_button_12se = AquaShine.LoadImage("assets/image/ui/com_button_12se.png")
41+
com_button_13 = AquaShine.LoadImage("assets/image/ui/com_button_13.png")
42+
com_button_13se = AquaShine.LoadImage("assets/image/ui/com_button_13se.png")
4043

4144
liveback_1 = AquaShine.LoadImage("assets/image/background/liveback_1.png")
4245

@@ -76,17 +79,45 @@ function SelectBeatmap.Draw()
7679
draw(BackImage, -98, 0)
7780
setColor(0, 0, 0)
7881
drawtext("Select Beatmap", 95, 13)
82+
drawtext(string.format("Page %d", CurrentPage + 1), 52, 500)
7983
setColor(255, 255, 255)
8084
setFont(MTLmr3m)
8185

86+
--[[
8287
if
8388
MouseState.Pressed[1] and
84-
MouseState.X >= 0 and MouseState.X <= 86 and
85-
MouseState.Y >= 0 and MouseState.Y <= 58
86-
then
87-
draw(BackButtonSe)
89+
]]
90+
if MouseState.Pressed[1] then
91+
if
92+
MouseState.X >= 0 and MouseState.X <= 86 and
93+
MouseState.Y >= 0 and MouseState.Y <= 58
94+
then
95+
draw(BackButtonSe)
96+
else
97+
draw(BackButton)
98+
end
99+
100+
if
101+
MouseState.X >= 0 and MouseState.X < 48 and
102+
MouseState.Y >= 272 and MouseState.Y < 328
103+
then
104+
draw(com_button_12se, 0, 272)
105+
else
106+
draw(com_button_12, 0, 272)
107+
end
108+
109+
if
110+
MouseState.X >= 912 and MouseState.X < 960 and
111+
MouseState.Y >= 272 and MouseState.Y < 328
112+
then
113+
draw(com_button_13se, 912, 272)
114+
else
115+
draw(com_button_13, 912, 272)
116+
end
88117
else
89118
draw(BackButton)
119+
draw(com_button_12, 0, 272)
120+
draw(com_button_13, 912, 272)
90121
end
91122

92123
for i = CurrentPage * 40 + 1, (CurrentPage + 1) * 40 do
@@ -166,13 +197,21 @@ function SelectBeatmap.MouseReleased(x, y, button)
166197
then
167198
-- Start livesim
168199
AquaShine.LoadEntryPoint("livesim.lua", {BeatmapList[BeatmapSelectedIndex].name, Random = IsRandomNotesWasTicked})
200+
169201
return
170202
elseif
171203
x >= 476 and x < 508 and
172204
y >= 528 and y < 560
173205
then
206+
-- Random note check
174207
IsRandomNotesWasTicked = not(IsRandomNotesWasTicked)
175208
return
209+
elseif x >= 0 and x < 48 and y >= 272 and y < 328 then
210+
-- Prev
211+
CurrentPage = math.max(CurrentPage - 1, 0)
212+
elseif x >= 912 and x < 960 and y >= 272 and y < 328 then
213+
-- Next
214+
CurrentPage = math.min(math.floor(math.max(#BeatmapList - 1, 0) / 40), CurrentPage + 1)
176215
end
177216
end
178217

volume_normalizer.lua

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
-- Audio volume normalizer, similar to ReplayGain but it's not
2+
-- Part of Live Simulator: 2
3+
4+
local love = love
5+
local _, ffi = pcall(require, "ffi")
6+
7+
if _ == false then
8+
-- Non-FFI functions
9+
return function(sd)
10+
local samples = sd:getSampleCount() * sd:getChannels() - 1
11+
local sample_data = {}
12+
local peak = 0
13+
14+
for i = 0, samples do
15+
local smp = sd:getSample(i)
16+
17+
peak = math.max(peak, math.abs(smp))
18+
sample_data[i] = smp
19+
end
20+
21+
print(peak)
22+
peak = 1 / peak
23+
print(peak)
24+
25+
for i = 0, samples do
26+
sd:setSample(i, sample_data[i] * peak)
27+
end
28+
end
29+
end
30+
31+
-- FFI functions
32+
return function(sd)
33+
local samples = sd:getSampleCount() * sd:getChannels() - 1
34+
local depth = sd:getBitDepth()
35+
local lower_limits = -2 ^ (depth - 1)
36+
local upper_limits = 2 ^ (depth - 1) - 1
37+
local ptr = sd:getPointer()
38+
local peak = 0
39+
40+
if depth == 8 then
41+
ptr = ffi.cast("int8_t*", ptr)
42+
elseif depth == 16 then
43+
ptr = ffi.cast("int16_t*", ptr)
44+
end
45+
46+
for i = 0, samples do
47+
peak = math.max(peak, math.abs(ptr[i]))
48+
end
49+
50+
peak = upper_limits / peak
51+
52+
for i = 0, samples do
53+
ptr[i] = math.min(math.max(ptr[i] * peak, lower_limits), upper_limits)
54+
end
55+
end

0 commit comments

Comments
 (0)