Moduuli:Kitarakirja/Nuottidata

Wikikirjastosta

Tämän moduulin ohjeistuksen voi tehdä sivulle Moduuli:Kitarakirja/Nuottidata/ohje

--- Nuotteja ja intervalleja koskevia taulukoita ja funktoita.
local p = {}

local function encode(idx, pos)
   return 100 * idx + pos
end

-- 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,
   }

-- Indeksi nuottiviivastolla.
local positions = {
   ["c♭"] = 0,
   ["c"]  = 0,
   ["c♯"] = 0,

   ["d♭"] = 1,
   ["d"]  = 1,
   ["d♯"] = 1,

   ["e♭"] = 2,
   ["e"]  = 2,
   ["e♯"] = 2,

   ["f♭"] = 3,
   ["f"]  = 3,
   ["f♯"] = 3,

   ["g♭"] = 4,
   ["g"]  = 4,
   ["g♯"] = 4,

   ["a♭"] = 5,
   ["a"]  = 5,
   ["a♯"] = 5,

   ["b♭"] = 6,
   ["b"]  = 6,
   ["b♯"] = 6,
}

-- Sävelten oletusnimet, kun tarkempaa ei ole saatavilla. Numerot vastaa noteNames-taulukon
-- ensimmäistä indeksiä.
local indexNames = { "c", "c♯/d♭", "d", "d♯/e♭", "e", "f", "f♯/g♭", "g", "g♯/a♭", "a", "a♯/b♭", "b" }

-- idx + 100 * pos
local noteNames = {
   [  encode(0, 0) ] =  "c",
   [  encode(1, 0) ] =  "c♯",
   [  encode(2, 0) ] =  "c𝄪",
   [  encode(0, 1) ] =  "d𝄫",
   [  encode(1, 1) ] =  "d♭",
   [  encode(2, 1) ] =  "d",
   [  encode(3, 1) ] =  "d♯",
   [  encode(4, 1) ] =  "d𝄪",
   [  encode(2, 2) ] =  "e𝄫",
   [  encode(3, 2) ] =  "e♭",
   [  encode(4, 2) ] =  "e",
   [  encode(5, 2) ] =  "e♯",
   [  encode(6, 2) ] =  "e𝄪",
   [  encode(3, 3) ] =  "f𝄫",
   [  encode(4, 3) ] =  "f♭",
   [  encode(5, 3) ] =  "f",
   [  encode(6, 3) ] =  "f♯",
   [  encode(7, 3) ] =  "f𝄪",
   [  encode(5, 4) ] =  "g𝄫",
   [  encode(6, 4) ] =  "g♭",
   [  encode(7, 4) ] =  "g",
   [  encode(8, 4) ] =  "g♯",
   [  encode(9, 4) ] =  "g𝄪",
   [  encode(7, 5) ] =  "a𝄫",
   [  encode(8, 5) ] =  "a♭",
   [  encode(9, 5) ] =  "a",
   [ encode(10, 5) ] =  "a♯",
   [ encode(11, 5) ] =  "a𝄪",
   [  encode(9, 6) ] =  "b𝄫",
   [ encode(10, 6) ] =  "b♭",
   [ encode(11, 6) ] =  "b",
   [  encode(0, 6) ] =  "b♯",
   [  encode(1, 6) ] =  "b𝄪",
   [ encode(10, 0) ] =  "c𝄫",
   [ encode(11, 0) ] =  "c♭" }

local intervals = {
   [ "vv1"  ] = { -2, 0 },   
   [ "v1"   ] = { -1, 0 },
   [ "1"    ] = {  0, 0 },
   [ "y1"   ] = {  1, 0 },
   [ "yy1"  ] = {  2, 0 },   

   [ "vv2"  ] = { -1, 1 },
   [ "v2"   ] = {  0, 1 },   
   [ "p2"   ] = {  1, 1 },
   [ "s2"   ] = {  2, 1 },
   [ "y2"   ] = {  3, 1 },
   [ "yy2"  ] = {  4, 1 },   

   [ "vv3"  ] = {  1, 2 },
   [ "v3"   ] = {  2, 2 },   
   [ "p3"   ] = {  3, 2 },
   [ "s3"   ] = {  4, 2 },
   [ "y3"   ] = {  5, 2 },
   [ "yy3"  ] = {  6, 2 },   

   [ "vv4"  ] = {  3, 3 },
   [ "v4"   ] = {  4, 3 },   
   [ "4"    ] = {  5, 3 },
   [ "y4"   ] = {  6, 3 },
   [ "yy4"  ] = {  7, 3 },   

   [ "vv5"  ] = {  5, 4 },   
   [ "v5"   ] = {  6, 4 },
   [ "5"    ] = {  7, 4 },
   [ "y5"   ] = {  8, 4 },
   [ "yy5"  ] = {  9, 4 },   

   [ "vv6"  ] = {  6, 5 },
   [ "v6"   ] = {  7, 5 },   
   [ "p6"   ] = {  8, 5 },
   [ "s6"   ] = {  9, 5 },
   [ "y6"   ] = { 10, 5 },
   [ "yy6"  ] = { 11, 5 },         

   [ "vv7"  ] = {  8, 6 },
   [ "v7"   ] = {  9, 6 },         
   [ "p7"   ] = { 10, 6 },      
   [ "s7"   ] = { 11, 6 },
   [ "y7"   ] = {  0, 6 },
   [ "yy7"  ] = {  1, 6 },   

   [ "vv8"  ] = { 12 + 10, 7 },
   [ "v8"   ] = { 12 + 11, 7 },      
   [ "8"    ] = { 12 +  0, 7 },
   [ "y8"   ] = { 12 +  1, 7 },
   [ "yy8"  ] = { 12 +  2, 7 },   

   [ "vv9"  ] = { 12 + -1, 1 },
   [ "v9"   ] = { 12 +  0, 1 },   
   [ "p9"   ] = { 12 +  1, 1 },
   [ "s9"   ] = { 12 +  2, 1 },
   [ "y9"   ] = { 12 +  3, 1 },
   [ "yy9"  ] = { 12 +  4, 1 },   

   [ "vv10" ] = { 12 +  1, 2 },
   [ "v10"  ] = { 12 +  2, 2 },   
   [ "p10"  ] = { 12 +  3, 2 },
   [ "s10"  ] = { 12 +  4, 2 },
   [ "y10"  ] = { 12 +  5, 2 },
   [ "yy10" ] = { 12 +  6, 2 },   

   [ "vv11" ] = { 12 +  3, 3 },
   [ "v11"  ] = { 12 +  4, 3 },   
   [ "11"   ] = { 12 +  5, 3 },
   [ "y11"  ] = { 12 +  6, 3 },   
   [ "yy11" ] = { 12 +  7, 3 },
   
   [ "vv12" ] = { 12 +  5, 4 },
   [ "v12"  ] = { 12 +  6, 4 },   
   [ "12"   ] = { 12 +  7, 4 },
   [ "y12"  ] = { 12 +  8, 4 },
   [ "yy12" ] = { 12 +  9, 4 },   

   [ "vv13" ] = { 12 +  6, 5 },
   [ "v13"  ] = { 12 +  7, 5 },   
   [ "p13"  ] = { 12 +  8, 5 },
   [ "s13"  ] = { 12 +  9, 5 },
   [ "y13"  ] = { 12 + 10, 5 },
   [ "yy13" ] = { 12 + 11, 5 },         

   [ "vv14" ] = { 12 +  8, 6 },
   [ "v14"  ] = { 12 +  9, 6 },         
   [ "p14"  ] = { 12 + 10, 6 },      
   [ "s14"  ] = { 12 + 11, 6 },
   [ "y14"  ] = { 12 +  0, 6 },
   [ "yy14" ] = { 12 +  1, 6 },   

   [ "vv15" ] = { 24 + 10, 7 },
   [ "v15"  ] = { 24 + 11, 7 },      
   [ "15"   ] = { 24 +  0, 7 },
   [ "y15"  ] = { 24 +  1, 7 },
   [ "yy15" ] = { 24 +  2, 7 },   

}

--- Palauttaa annetun nuotin absoluuttisen indeksin kromaattisella asteikolla.
-- Esim. ("c", 1)  -> 12,
--       ("d", 1)  -> 14,
--       ("c", 2)  -> 24,
--       ("c", -1) -> -12,
-- param note:   nuotin nimi, esim. "c♯"
-- param octave: oktaavi (yksiviivainen = 1, jne.)
-- return:       absoluuttinen indeksi kromaattisella asteikolla tai suhteellinen, jos octave = 0
function p.getNoteIndex(note, octave)
   local idx = indeces[note]

   if not idx then
      error("Virheellinen nuotin nimi: " .. note)
   end
   
   return idx + octave*12
end

--- Nuotin viivan/välin indeksi asteikolla.
-- Tässä ei tehdä eroa eri oktaaveissa vaan arvot ovat suhteellisia.
-- param note: nuotin nimi, esim. "c♯"
-- return: indeksi suhteessa c-nuotin paikkaan
function p.getNotePos(note)
   local pos = positions[note]

   if not pos then
      error("Virheellinen nuotin nimi: " .. note)
   end
   
   return pos
end

--- Palauttaa annettua sävel ja nuottiviivastoindeksejä vastaavan nuotin nimen.
-- Esim. (0, 0) -> "c", = c-sävel normaalissa kohdassa
--       (0, 1) -> "d𝄫" = c-säveltä vastaava sävel yhtä viivaa tai väliä ylemmäksi merkittynä
-- param note_idx: sävelen indeksi taulukossa puolisävelaskelina laskettuna,
--                 c-säveltä vastaa 0, cisiä/disiä 1, jne.
-- param note_pos: nuotin paikka nuottiviivastolla viivoina ja väleinä laskettuna,
--                 0 vastaa c:n paikkaa.
function p.getNotename(note_idx, note_pos)
   return noteNames[ encode(note_idx, note_pos) ]
end

--- Palauttaa annetun intervallin tiedot erillisinä arvoina.
-- return: ero sävelaskelina
-- return: ero nuottiviivastolla
-- return: oktaavin muutos
function p.intervalToDiffs(interval)
   local arr = intervals[interval]
   if not arr then
      error("Virheellinen intervallikoodi: " .. interval)
   end
   return arr[1], arr[2], arr[3]
end

--- Palauttaa nuotit jotka ovat annettujen intervallien päässä kantasäveleeseen nähden.
-- Esim. intervalsToNotenames{ root = "c", "1", "s3", "5" } -> { "c", "e♭", "g" }
-- param args
--          .root:        kantasävel
--          (nimettömät): taulukko intervalleista lyhennysmerkinnällä, esim. { "1", "s3", "5" }
function p.intervalsToNotenames(args)
   local root_idx = indeces[args.root]
   local root_pos = positions[args.root]
   local output = {}

   for i, interval in ipairs(args) do
      local idx, pos = p.intervalToDiffs(interval)
      local note = p.getNotename((root_idx + idx) % 12, (root_pos + pos) % 7)
      
      table.insert(output, { note, math.floor((root_idx + idx)/12) })
   end
   
   return unpack(output)
end


function p.getNoteNameForIndex(noteIndex)
   return indexNames[noteIndex % 12 + 1]
end

function p.getNoteOctaveForIndex(noteIndex)
  return math.floor(noteIndex / 12)
end

return p