Ero sivun ”Moduuli:Kitarakirja” versioiden välillä

Poistettu sisältö Lisätty sisältö
Hunsvotti (keskustelu | muokkaukset)
Ei muokkausyhteenvetoa
Hunsvotti (keskustelu | muokkaukset)
tyylikkäämpi versio sointuotteesta käyttöön
Merkkaus: Korvattu
 
Rivi 1:
 
 
--- Pilkkoo merkkijonon osiin.
function mw.ustring:split(sep)
local fields = {}
local pattern = mw.ustring.format("([^%s]+)", sep)
self:gsub(pattern, function(c) fields[#fields+1] = c end)
return fields
end
 
--- Tekee matalan kopion taulukosta.
function table.clone(orig)
local orig_type = type(orig)
local copy = {}
for orig_key, orig_value in pairs(orig) do
copy[orig_key] = orig_value
end
return copy
end
 
 
 
-- Nuoteista käytetyt nimitykset. Jos parametri nuotit1 tai nuotit2 on annettu korvataan
-- taulukon arvot annetuilla arvoilla. Nuotit ovat taulukossa abcdefg-järjestelmän mukaan.
-- H lisätään vasta tulostusvaiheessa.
local g_notenames1 = { "c", "c♯", "d", "d♯", "e", "f", "f♯", "g", "g♯", "a", "a♯", "b" }
local g_notenames2 = { "c", "d♭", "d", "e♭", "e", "f", "g♭", "g", "a♭", "a", "b♭", "b" }
 
 
-- Indeksit nuottinnimet-taulukoihin
local indeces = {
["c"] = 0,
["c♯"] = 1,
["c𝄪"] = 2,
["d𝄫"] = 0,
["d♭"] = 1,
["d"] = 2,
["d♯"] = 3,
["d𝄪"] = 4,
["e𝄫"] = 2,
["e♭"] = 3,
["e"] = 4,
["e♯"] = 5,
["e𝄪"] = 6,
["f𝄫"] = 3,
["f♭"] = 4,
["f"] = 5,
["f♯"] = 6,
["f𝄪"] = 7,
["g𝄫"] = 5,
["g♭"] = 6,
["g"] = 7,
["g♯"] = 8,
["g𝄪"] = 9,
["a𝄫"] = 7,
["a♭"] = 8,
["a"] = 9,
["a♯"] = 10,
["a𝄪"] = 11,
["b𝄫"] = 9,
["b♭"] = 10,
["b"] = 11,
["b♯"] = 0,
["b𝄪"] = 1,
["c𝄫"] = 10,
["c♭"] = 11,
["b𝄫 (b♭)"] = 9,
["b♭ (b)"] = 10,
["b (h)"] = 11,
["b♯ (h♯)"] = 0,
["b𝄪 (h𝄪)"] = 1,
}
 
 
local viritys = {
indeces["e"] + 2*12,
indeces["a"] + 2*12,
indeces["d"] + 3*12,
indeces["g"] + 3*12,
indeces["b"] + 3*12,
indeces["e"] + 4*12,
}
 
 
 
--- Lilypondin käyttämä oktaavimerkintä.
-- param index: oktaavi suhteessa keski-c:hen
-- param notename: nuotin nimi
-- return: oktaavi Lilypond-muodossa, esim. ","
function lilyoctave(index, notename)
-- Merkitään eri oktaaviin kuin soivat
if notename == "b♯" or notename == "b𝄪" then
index = index - 1
elseif notename == "c♭" or notename == "c𝄫" then
index = index + 1
end
if index < 0 then
return string.rep(",", -index)
elseif index > 0 then
return string.rep("'", index)
end
return ""
end
 
-- Muuttaa nuotinnimen Lilypondin käyttämään muotoon, esim. "e♭" -> "ees"
function lilyfy(notename)
local out = notename
out = string.gsub(out, "♯", "is")
out = string.gsub(out, "𝄪", "isis")
out = string.gsub(out, "♭", "es")
out = string.gsub(out, "𝄫", "eses")
 
return out
end
 
--- Palauttaa nuotin nimen oktaaveineen Lilypond-notaatiolla, esim. "dis''".
-- param noteset: nuottijoukko josta nuotit valitaan
-- param index: absoluuttinen nuotin indeksi (jossa 36 vastaa keski-c:tä)
function lilynote(noteset, index)
local octave = math.floor((index - (indeces["c"] + 3*12)) / 12)
local note = noteset[index % 12 + 1]
 
if index == -1 then
return ""
end
return lilyfy(note) .. lilyoctave(octave, note)
end
 
--- Palauttaa tabulatuuriin tarkoitetun nuotin nimen Lilypond-notaatiolla, esim. "dis''".
-- Tässä ei tarvitse ottaa huomioon enharmonisia nuotteja vaan käytettään vain toista
-- niistä.
-- param index: nuotin absoluuttinen indeksi
function lilytabnote(index, stringno)
local octave = math.floor((index - (indeces["c"] + 3*12)) / 12)
local note = g_notenames1[index % 12 + 1]
 
if index == -1 then
return ""
end
 
return lilyfy(note) .. lilyoctave(octave, note) .. "\\" .. stringno
end
 
-- Taulukko nuotinnimienm muuttamiseen sisäisestä muodosta tulostettavaan muotoon.
local simple_to_output = {
["b♭"] = "b♭<br/>(b)",
["b"] = "b<br/>(h)",
["b♭"] = "b♭<br/>(b)",
["b𝄫"] = "b𝄫<br/>(b♭)",
["b♯"] = "b♯<br/>(h♯)",
["b𝄪"] = "b𝄪<br/>(h𝄪)"
}
 
-- Taulukko syötteen muuttamiseen sisäiseen muotoon.
local input_to_simple = {
["b♭ (b)"] = "b♭",
["b (h)"] = "b",
["b♭ (b)"] = "b♭",
["b𝄫 (b♭)"] = "b𝄫",
["b♯ (h♯)"] = "b♯",
["b𝄪 (h𝄪)"] = "b𝄪"
}
 
 
--- Muuttaa nuotin nimen tulostettavaan muotoon ts. lisää h-vaihtoehdon b-nuotteihin.
local function notename_to_print(note)
return simple_to_output[note] or note
end
 
-- Muuttaa mahdollisen "b (h)"-muodossa annetun nuottinimen sisäiseen muotoon.
local function input_to_notename(note)
return input_to_simple(note)
end
 
--- Palauttaa otetaulukon nuotinnimiparametrissa näytettävän tekstin.
-- param noteset1: ensimmäisen variantin nuotit
-- param noteset2: toisen variantin nuotit
-- param index: nuotin absoluuttinen indeksi
-- return: esim. "g♯<br/>ab".
local function printable_notename(index)
local note1 = g_notenames1[index % 12 + 1]
local note2 = g_notenames2[index % 12 + 1]
 
--print("ntoe1: " .. note1 .. ", note2: " .. note2)
if note2 == nil or note1 == note2 then
return notename_to_print(note1)
end
return notename_to_print(note1) .. "<br/>" .. notename_to_print(note2)
end
 
local p = {}
 
function p.Sointuote(frame)
 
local kk_sointuote = require('Module:Kitarakirja/Sointuote')
--- Palauttaa soinnun nuotit lilypond notaatiolla. Nuotit valitaan g_notenamesistä.
return kk_sointuote.Sointuote(frame)
-- param notenames: jompi kumpi globaaleista taulukoista g_notenames1 tai g_notenames2
-- noteindeces: taulukko, jossa on joka kielelle oma nuotti-indeksi
-- return: taulukko, jossa on joka kielelle nuotti Lilypondin käyttämässä muodossa
local function make_lilynotes(notenames, noteindeces)
local lilynotes = { "", "", "", "", "", "" }
--print("notenames: " .. table.concat(notenames, " "))
lilynotes[1] = lilynote(notenames, noteindeces[1])
lilynotes[2] = lilynote(notenames, noteindeces[2])
lilynotes[3] = lilynote(notenames, noteindeces[3])
lilynotes[4] = lilynote(notenames, noteindeces[4])
lilynotes[5] = lilynote(notenames, noteindeces[5])
lilynotes[6] = lilynote(notenames, noteindeces[6])
 
return lilynotes
end
 
--- Palauttaa nuottimerkinnän tuottavan Lilypond-koodin (\Staff-lohkon).
-- Jos sointuja on kaksi varianttia, on palautettavan koodilohkon aikayksikkö 2/1. Jos
-- yksi on aikayksikkö 1/1.
-- param lilynotes1: ensimmäisen sointuvariantin nuotit Lilypond-muodossa
-- param lilynotes2: toisen sointuvariantin nuotit Lilypond-muodossa
-- return: \Staff-lohkon koodi
-- return: 1 jos yksi sointu, 2 jos kaksi sointua
local function get_staff_markup(lilynotes1, lilynotes2)
local notes_str1 = table.concat(lilynotes1, " ")
local notes_str2 = table.concat(lilynotes2, " ")
if notes_str2 == notes_str1 then
notes_str2 = ""
elseif notes_str1 == "" then
notes_str1 = notes_str2
notes_str2 = ""
end
 
 
if notes_str1 == "" and notes_str2 == "" then
return "", 1
elseif notes_str1 ~= "" and notes_str2 ~= "" then
return [=[
\new Staff {
\clef "treble_8"
\once \override Staff.TimeSignature #'stencil = ##f
<]=] .. notes_str1 .. [=[>1 | <]=] .. notes_str2 .. [=[>1 |
}
]=], 2
elseif notes_str1 ~= "" then
return [=[
\new Staff {
\clef "treble_8"
\once \override Staff.TimeSignature #'stencil = ##f
<]=] .. notes_str1 .. [=[>1
}
]=], 1
end
 
end
 
--- Muotoilee TabStaff-lohkon.
-- param noteindeces: nuotinnettava sointu absoluuttisina indekseinä
-- param time: aikayksikön nimittäjä (1 tai 2)
-- return: TabStaff-lohkon koodi
local function get_tabstaff_markup(noteindeces, time)
local lilynotestab = { "", "", "", "", "", "" }
 
-- Haetaan nuotit, josta generoidaan tabulatuuri. Nuottien nimillä
-- (onko esim. cis vai des) ei tässä ole väliä.
lilynotestab[1] = lilytabnote(noteindeces[1], 6)
lilynotestab[2] = lilytabnote(noteindeces[2], 5)
lilynotestab[3] = lilytabnote(noteindeces[3], 4)
lilynotestab[4] = lilytabnote(noteindeces[4], 3)
lilynotestab[5] = lilytabnote(noteindeces[5], 2)
lilynotestab[6] = lilytabnote(noteindeces[6], 1)
 
if time == 2 then
return [=[
\new TabStaff {
\override Stem #'transparent = ##t
\override Beam #'transparent = ##t
s2 <]=] .. table.concat(lilynotestab, " ") .. [=[>1 s2
}
]=]
else
return [=[
\new TabStaff {
\override Stem #'transparent = ##t
\override Beam #'transparent = ##t
<]=] .. table.concat(lilynotestab, " ") .. [=[>1
}
]=]
end
end
 
local function get_lilymarkup(noteset1, noteset2, noteindeces)
local lilynotes1 = {}
local lilynotes2 = {}
local notation_markup, tabstaff_markup
local time
local success
 
-- Nuotit, joista generoidaan nuottimerkintä.
success, lilynotes1 = pcall(make_lilynotes, noteset1, noteindeces)
if not success then
lilynotes1 = {}
end
success, lilynotes2 = pcall(make_lilynotes, noteset2, noteindeces)
if not success then
lilynotes2 = {}
end
notation_markup, time = get_staff_markup(lilynotes1, lilynotes2)
 
-- Nuotit, joista generoidaan tabulatuuri.
tabstaff_markup = get_tabstaff_markup(noteindeces, time)
 
return [=[
<<
%\override Score.BarLine.break-visibility = ##(#f #t #t)
\time ]=] .. time .. [=[/1
]=] .. notation_markup .. [=[
 
]=] .. tabstaff_markup .. [=[
>>
]=]
end
 
function p.Sointuote(frame)
local s_idx = 0
local f_idx = -1
local frets = { -1, -1, -1, -1, -1, -1 }
local fingering = { -1, -1, -1, -1, -1, -1 }
local nauha = (tonumber(frame.args.nauhanumero) or 1) - 1
local output = table.clone(frame.args)
local noteindeces = { -1, -1, -1, -1, -1, -1 }
local noteset1 = { nil, nil, nil, nil, nil, nil }
local noteset2 = { nil, nil, nil, nil, nil, nil }
local notes1, notes2 = {}, {}
 
if frame.args.nuotit1 then
notes1 = mw.text.split(frame.args.nuotit1, "–", true)
if frame.args.nuotit2 then
notes2 = mw.text.split(frame.args.nuotit2, "–", true)
end
end
-- Annetaan uudet nimet oletusnuotinnimien tilalle
for i, v in ipairs(notes2) do
local index = indeces[v]
if index then
noteset2[index + 1] = v
g_notenames2[index + 1] = v
end
end
for i, v in ipairs(notes1) do
local index = indeces[v]
if index then
noteset1[index + 1] = v
g_notenames1[index + 1] = v
if not noteset2[index + 1] then
g_notenames2[index + 1] = v
end
end
end
 
 
 
for i, cur in ipairs(frame.args) do
-- Poistetaan tyhjät alusta ja lopusta.
cur = cur:gsub("^%s*(.-)%s*$", "%1")
-- Kielen ja nauhan numero.
s_idx = (i - 1) % 6 + 1
if s_idx == 1 then
f_idx = f_idx + 1
end
if cur == "o" and i >= 0 and i < 7 then -- Vapaat kielet.
frets[s_idx] = f_idx
elseif cur == "o" or cur == "C" or cur == "D" or cur == "-" then
frets[s_idx] = f_idx + nauha
end
 
-- Sormitukset.
if i > 36 and i <= 42 then
fingering[s_idx] = cur
end
end
 
-- Nuotinnimi-parametrit.
output[43] = ""
output[44] = ""
output[45] = ""
output[46] = ""
output[47] = ""
output[48] = ""
 
if frets[1] ~= -1 then
noteindeces[1] = (viritys[1] + frets[1])
output[43] = printable_notename(noteindeces[1])
end
if frets[2] ~= -1 then
noteindeces[2] = (viritys[2] + frets[2])
output[44] = printable_notename(noteindeces[2])
end
if frets[3] ~= -1 then
noteindeces[3] = (viritys[3] + frets[3])
output[45] = printable_notename(noteindeces[3])
end
if frets[4] ~= -1 then
noteindeces[4] = (viritys[4] + frets[4])
output[46] = printable_notename(noteindeces[4])
end
if frets[5] ~= -1 then
noteindeces[5] = (viritys[5] + frets[5])
output[47] = printable_notename(noteindeces[5])
end
if frets[6] ~= -1 then
noteindeces[6] = (viritys[6] + frets[6])
output[48] = printable_notename(noteindeces[6])
end
 
lilyoutput = get_lilymarkup(noteset1, noteset2, noteindeces)
 
return "<div style=\"display: inline-block; text-align: center;\"><div>"
.. frame:extensionTag{ name = "score", content = lilyoutput } .. "</div>\n" .. frame:expandTemplate{ title = "Kitaran sointuote", args = output } .. "\n</div>"
 
 
end
 
function p.Skaala(frame)