176 lines
4.3 KiB
Lua
176 lines
4.3 KiB
Lua
--[[
|
|
README
|
|
|
|
Karaoke Helper
|
|
|
|
Does simple karaoke tasks. Adds blank padding syllables to the beginning of lines,
|
|
and also adjusts final syllable so it matches the line length.
|
|
|
|
Will add more features as ktimers suggest them to me.
|
|
|
|
|
|
]]--
|
|
|
|
script_name = "Karaoke helper"
|
|
script_description = "Miscellaneous tools for assisting in karaoke timing."
|
|
script_version = "0.2.0"
|
|
script_author = "lyger"
|
|
script_namespace = "lyger.KaraHelper"
|
|
|
|
local DependencyControl = require("l0.DependencyControl")
|
|
local rec = DependencyControl{
|
|
feed = "https://raw.githubusercontent.com/TypesettingTools/lyger-Aegisub-Scripts/master/DependencyControl.json",
|
|
{
|
|
{"lyger.LibLyger", version = "2.0.0", url = "http://github.com/TypesettingTools/lyger-Aegisub-Scripts"},
|
|
}
|
|
}
|
|
local LibLyger = rec:requireModules()
|
|
local libLyger = LibLyger()
|
|
|
|
function make_config(styles)
|
|
local stopts={"selected lines"}
|
|
for i=1,styles.n,1 do
|
|
stopts[i+1] = ("style: %q").format(styles[i].name)
|
|
end
|
|
local config=
|
|
{
|
|
--What to apply the automation on
|
|
{
|
|
class="label",
|
|
label="Apply to:",
|
|
x=0,y=0,width=1,height=1
|
|
},
|
|
{
|
|
class="dropdown",
|
|
name="sselect",items=stopts,
|
|
x=1,y=0,width=1,height=1,
|
|
value="selected lines"
|
|
},
|
|
--Match syls to line length
|
|
{
|
|
class="checkbox",
|
|
name="match",label="Match syllable lengths to line length",
|
|
x=0,y=1,width=2,height=1,
|
|
value=true
|
|
},
|
|
--Add blank syl at the start
|
|
{
|
|
class="checkbox",
|
|
name="leadin",label="Add start padding:",
|
|
x=0,y=2,width=1,height=1,
|
|
value=false
|
|
},
|
|
{
|
|
class="intedit",
|
|
name="leadindur",
|
|
x=1,y=2,width=1,height=1,
|
|
min=0,
|
|
value=0
|
|
},
|
|
--Add blank syl at the end
|
|
{
|
|
class="checkbox",
|
|
name="leadout",label="Add end padding:",
|
|
x=0,y=3,width=1,height=1,
|
|
value=false
|
|
},
|
|
{
|
|
class="intedit",
|
|
name="leadoutdur",
|
|
x=1,y=3,width=1,height=1,
|
|
min=0,
|
|
value=0
|
|
}
|
|
}
|
|
return config
|
|
end
|
|
|
|
--Match syllable and line durations
|
|
function match_durs(line)
|
|
local ldur=line.end_time-line.start_time
|
|
local cum_sdur=0
|
|
for sdur in line.text:gmatch("\\[Kk][fo]?(%d+)") do
|
|
cum_sdur=cum_sdur+tonumber(sdur)
|
|
end
|
|
local delta=math.floor(ldur/10)-cum_sdur
|
|
line.text=line.text:gsub("({[^{}]*\\[Kk][fo]?)(%d+)([^{}]*}[^{}]*)$",
|
|
function(pre,val,post)
|
|
return ("%s%d%s"):format(pre, tonumber(val)+delta, post)
|
|
end)
|
|
return line
|
|
end
|
|
|
|
--Add padding at the start
|
|
function add_prepad(line,pdur)
|
|
line.text=line.text:gsub("^({[^{}]*\\[Kk][fo]?)(%d+)",
|
|
function(pre,val)
|
|
return ("{\\k%d}%s%d"):format(pdur, pre, tonumber(val)-pdur)
|
|
end)
|
|
line.text=line.text:gsub("^{\\k(%d+)}({[^{}]*\\[Kk][fo]?)(%-?%d+)([^{}]*}{)",
|
|
function(val1,mid,val2,post)
|
|
return ("%s%d%s"):format(mid, tonumber(val1)+tonumber(val2), post)
|
|
end)
|
|
return line
|
|
end
|
|
|
|
--Add padding at the end
|
|
function add_postpad(line,pdur)
|
|
line.text=line.text:gsub("(\\[Kk][fo]?)(%d+)([^{}]*}[^{}]*)$",
|
|
function(pre,val,post)
|
|
return ("%s%d%s{\\k%d}"):format(pre, tonumber(val)-pdur, post, pdur)
|
|
end)
|
|
line.text=line.text:gsub("(\\[Kk][fo]?)(%-?%d+)([^{}]*}){\\k(%d+)}$",
|
|
function(pre,val1,mid,val2)
|
|
return ("%s%d%s"):format(pre, tonumber(val1)+tonumber(val2), mid)
|
|
end)
|
|
return line
|
|
end
|
|
|
|
--Load config and display
|
|
function load_kh(sub,sel)
|
|
libLyger:set_sub(sub, sel)
|
|
|
|
-- Basic header collection, config, dialog display
|
|
local config = make_config(libLyger.styles)
|
|
local pressed,results=aegisub.dialog.display(config)
|
|
if pressed=="Cancel" then aegisub.cancel() end
|
|
|
|
--Determine how to retrieve the next line, based on the dropdown selection
|
|
local tstyle, line_cnt, get_next = results["sselect"], #sub
|
|
|
|
if tstyle:match("^style: ") then
|
|
tstyle=tstyle:match("^style: \"(.+)\"$")
|
|
get_next = function(uindex)
|
|
for i = uindex, line_cnt do
|
|
local line = libLyger.dialogue[uindex]
|
|
if line.style == tstyle and (not line.comment or line.effect == "karaoke") then
|
|
return line, i
|
|
end
|
|
end
|
|
end
|
|
else
|
|
get_next = function(uindex)
|
|
if uindex <= #sel then
|
|
return libLyger.lines[sel[uindex]], uindex+1
|
|
end
|
|
end
|
|
end
|
|
|
|
--Control loop
|
|
local line, uindex = get_next(1)
|
|
while line do
|
|
if results["match"] then match_durs(line) end
|
|
if results["leadin"] then add_prepad(line, results["leadindur"]) end
|
|
if results["leadout"] then add_postpad(line, results["leadoutdur"]) end
|
|
sub[line.i] = line
|
|
line, uindex = get_next(uindex)
|
|
end
|
|
|
|
aegisub.set_undo_point(script_name)
|
|
end
|
|
|
|
rec:registerMacro(load_kh)
|
|
|
|
|
|
|