Konzervatoř P. J. Vejvanovského Kroměříž Materiály pro výuku IKT v hudbě (2015/2016) Využití Riemannovy teorie k automatizaci hudební sazby v systému Lilypond Adam Šiška 1 Úvod do implementace V tomto textu nastíníme možnosti aplikace počítačového programování a sazby notových zápisů v Riemannově 1 teorii hudební harmonie. Zůstaneme poplatni základním omezením této teorie jako je ignorování oktávového členění tónů, stejně jako jejich enharmonické chápání s tím, že tyto nedostatky mohou sloužit jako náměty pro samostatnou studentskou činnost. Pokusíme se o implementaci základních operací teorie v jazyce Haskell 2. Sazbu notových zápisů zajistí systém Lilypond 3. Podrobnější informace ohledně technických detailů práce s představenými systémy nalezne čtenář v poslední kapitole textu. 2 Zavedení jmen tónů V Riemanově teorii ztotožňujeme jména tónů s dvanácti čísly od nuly do jedenácti. Prvním samozřejmým problémem je tedy nemožnost (enharmonického) rozlišení mezi křížky a béčky. V programovém kódy budeme tedy vytvářet obě dvě varianty výpisu číselných (tónových) řad. Je zřejmé, že díky tomuto faktu, nelze očekávat sto procentní korektnost z hlediska klasické hudební teorie. 1 https://en.wikipedia.org/wiki/neo-riemannian theory (cit. 24.4.2016) 2 https://www.haskell.org/hugs/pages/downloading.htm 3 http://lilypond.org/download.html, http://frescobaldi.org/download 1
Nebudeme hned rozebírat všechny aspekty jazyka Haskell. Díky jeho funkcionálnímu zápisu budou implementace definic teorie velmi přímočaré. Vždy když to jen trochu půjde využijeme triků pro odstranění technikcýh problémů. V první definici funkce ton stanovíme všem číslům příslušná jména tónů s křížky. Následující řádky (a další definice) je třeba uložit do počítačového souboru se správnou příponou, např. tonnetz.hs. ton 0 = " c" ton 1 = " cis" ton 2 = " d" ton 3 = " dis" ton 4 = " e" ton 5 = " f" ton 6 = " fis" ton 7 = " g" ton 8 = " gis" ton 9 = " a" ton 10 = " ais" ton 11 = " b" ton x = ton (x mod 12) Funkce ton převede jedno číslo na jméno tónu, které číslo zastupuje. V jazyce Haskell můžeme jednoduše pracovat s celými řadami čísel (a tedy tónů). Řadu čísel zadáme pomocí hranatých závorek např. takto: [0,4,7,4,4,2,4]. Pro převedení celé takové řady na jména tónů v systému Lilypond definujeme funkci tony. tony s = concat (map ton s) Zbývá doplnit paralelní funkce tonb a tonyb, které budou překládat čísla na názvy tónů s béčky. Stačí doplnit následující řádky kódu. tonb 1 = " des" tonb 3 = " es" tonb 6 = " ges" tonb 8 = " as" tonb 10 = " bes" tonb x = ton x tonyb s = concat (map tonb s) Transpozice a inverze Užití představených funkcí nabývá na efektivitě při použití dvou základních operací Riemannovy teorie transpozice a inverze. Obě operace lze opět přímočaře implementovat, každou operaci následuje rozšíření na řadu čísel. 2
t n x = (x + n) mod 12 trans n s = map (t n) s i n x = (-x + n) mod 12 inv n s = map (i n) s Stupnice Nyní můžeme představit první možnosti automatizace hudební sazby na příkladu stupnic. Stupnice je tónová řada vzniklá historicky, tudíž je třeba definovat základní stupnice jako konstanty. cdur = [0,2,4,5,7,9,11,0] amoll = [9,11,0,2,4,5,7,9] Další stupnice ale lze získat automaticky. Je nutné zdůraznit, že představený systém v obou případech křížků i béček rozeznává pouze pět prvních těchto předznamenání. Stupnice vzdálené již nejsou vypsány korektně z hlediska hudební harmonie, z hlediska enharmonické záměny tónů (a tedy např. výstupu MIDI) jsou všechny stupnice v pořádku. Pokud definice tonnetz.hs otevřeme 4 pomocí programu Hugs (WinHugs), dostaneme možnost využívat definované funkce. Příklady povelů pro systém Hugs budou vždy uvozeny výzvou Main> a bude je následovat výsledek interpretace povelu na novem řádku. Pro začátek zkusíme funkčnost zadaných funkcí 5. Následující řádky ukazují žádanou interakci se systémem Hugs. Main> ton 6 " fis" Main> tonb 10 " bes" Main> tony [2,6,9] " d fis a" Main> tonyb [3,7,10] " es g bes" V generování stupnic začneme (informaticky) od nuly. Následující povel vypíše stupnici cdur, kterou máme zadanou jako konstantu. Main> tony (trans 0 cdur) " c d e f g a b c" 4 Pokud po otevření vidíte výzvu Main> proběhlo vše v pořádku. Pokud vidíte chybový výpis a výzvu Hugs>, je ve vašem souboru nějaký překlep. 5 Definované funkce lze vypsat povelem Main>:b 3
Další stupnice s jedním křížkem (G dur) začíná o sedm půltónů (tj. kvintu) výš než C dur. S každým dalším posunem o sedm (kvintovým) vzniká další stupnice. Main> tony (trans 7 cdur) " g a b c d e fis g" Main> tony (trans 14 cdur) " d e fis g a b cis d" Main> tony (trans 21 cdur) " a b cis d e fis gis a" Stupnice s béčky vznikají při kvartových posunech, tj. posunech o pět půltónů. Main> tonyb (trans 5 cdur) " f g a bes c d e f" Main> tonyb (trans 10 cdur) " bes c d es f g a bes" Main> tonyb (trans 15 cdur) " es f g as bes c d es" Příklady sazby Představené funkce lze použít při tvorbě nejrůznějších (chromatických) cvičení. Rozklady kvintakordů lze v postupu po kvartách definovat třeba takto (připomínáme že výsledek je vhodnější použít spíše sluchově v MIDI, protože z hlediska hudební teorie nejsou všechna jména tónů korektní): Main> concat [ tonyb (trans i [0,4,7]) i<-[0,5,10,15,20,25,30] ] " c e g f a c bes d f es g bes as c es des f as ges bes des" Inverze mění tónorod melodie a umožňuje získat zajímavé náměty z již existující nápěvků. Pokud vezmeme například tóny lidové písně Ovčáci, čtveráci, získáme postup v f moll: Main> tonyb (inv 0 [0,4,7,4,4,2,4,5,2,4,2,0]) " c as f as as bes as g bes as bes c" 4
3 Generování a sazba akordů Kvintakord je trojice tónů znějících zároveň. V systému Lilypond takové souzvuky uzavíráme do lomených závorek <>. Jak lze vidět v posledním příkladu, inverze tvoří z durového kvintakordu [0,4,7] trojici tónů [0,8,5] což je pozpátku jmenovaný mollový kvintakord. Tónorod tedy musíme v implementaci rozeznat, takže definujeme predikáty dur a moll. dur [x,y,z] = ((x+4) mod 12 == y) && ((x+7) mod 12 == z) dur _ = False moll [x,y,z] = ((x+8) mod 12 == y) && ((x+5) mod 12 == z) moll _ = False Následují definice funkcí akord a akordb, které trojici tónů přeloží na zápis jejich souzvuku v systému Lilypond. Pořadí tónů mollového kvintakordu musí být opačná. akord s = if moll s then " <" ++ tony (reverse s) ++ ">" else " <" ++ tony s ++ ">" akordb s = if moll s then " <" ++ tonyb (reverse s) ++ ">" else " <" ++ tonyb s ++ ">" Stejně jako v případě jednotlivých tónů, které tvoří řady, budou nás zajímat řady akordů. Poslední dvě funkce vypisují libovolný počet akordů najednou, například v tónině C dur zadáme TSD jako [[0,4,7],[5,9,0],[7,11,2]]. akordy s = concat (map akord s) akordyb s = concat (map akordb s) Poznamenejme, že v tomto případě nedává výpis s křížky nebo s béčky stejný smysl jako při práci s řadou tónů. Akord sám běžně zadává tóninu, jejíž předznamenání je určeno. Napsat adekvátní funkci akordyt může čtenář zkusit jako cvičení. Na závěr uvedeme příklad povelu vypisujícího TSD v tónině Es dur. Main> akordyb (map (trans 3) [[0,4,7],[5,9,0],[7,11,2]]) " < es g bes> < as c es> < bes d f>" 4 PLR-systém Riemannova teorie dává různé akordy do různých harmonicko-matematických vztahů označených velkými písmeny P, L, R 6. Tyto vztahy následně vytvářejí sít 6 Písmena vycházejí z anglického pojmenování vztahu tónin, tj. Parallel tónina stejnojmenná, Relativ tónina paralelní a Lead tone exchange tónina horní tercie. 5
akordů Tonnetz uspořádaných do tvaru toru (torus je objekt připomínající americkou koblihu s dírou uprostřed, topologicky shodný třeba i s šálkem na kávu). p [x,y,z] = inv (x+z) [x,y,z] r [x,y,z] = inv (x+z) [x,y,z] l [x,y,z] = inv (x+z) [x,y,z] Jednoduchá aplikace nových funkcí je snadná. Při současné aplikaci více operací na akord uplatníme standardní notaci pro skládání funkcí 7, např. operaci l(r(l(r [0,4,7]))), zapíšeme (l.r.l.r) [0,4,7]. Následuje příklad operací P, L, R pro akord a moll, dostáváme postupně A dur, C dur a F dur. Main> akord (p [4,0,9]) " < a cis e>" Main> akord (l [4,0,9]) " < c e g>" Main> akord (r [4,0,9]) " < f a c>" Při úvahách o postupech akordů musíme pracovat s posloupnostmi, ve kterých následující člen závisí na předchozím. Z tohoto pohledu definujeme elementární funkci iter, jež jako parametr dostane funkci následníka f a první hodnotu x, a generuje (nekonečnou) posloupnost [x, f x, f (f x), f (f (f x),...]. iter f x = x : iter f (f x) Například jsme viděli, že kvartové posuny generují nové tóniny s béčky: Main> akordyb (take 6 (iter (trans 5) [0,4,7])) " < c e g> < f a c> < bes d f> < es g bes> < as c es> < des f as>" V analýze postupu akordů nás zajímají vztahy (vazby) po sobě jdoucích akordů. A tyto vztahy jsou pochopitelně různé. Potřebujeme tedy zavést funkci podobnou funkci iter, která ale dostane celou řadu funkcí a bude je postupně uplatňovat na zadaný akord. postup [] a = [a] postup (f:s) a = a : postup s (f a) Pokud funkci použijeme pro tři povely, například postup [f,g,h] x, získáme ve výsledku čtyři prvky [x, f x, g (f x), h (g (f x))]. 7 Platí (.) f g x = f (g x). Pro případně zájemce o problematiku je nutné podotknout, že funkce (.) je jednou z několika málo vstupních bran k pochopení funkcionálního programování. 6
Následující příklady jsou z úvodního textu o Riemannově teorii, jedná se o postup I-vi-IV-V 50. léta, postup Pachelbel a postup Devátá : Main> akordy (postup [r,l, r.l.r.l, l.r] [0,4,7]) " < c e g> < a c e> < f a c> < g b d> < c e g>" Main> akordy (postup [r.l, r.l.r, l.r, l] [2,6,9]) " < d fis a> < a cis e> < b d fis> < fis a cis> < d fis a>" Main> akordy (postup (concat [[r, l] i<-[1..12]]) [0,4,7]) " < c e g> < a c e> < f a c> < d f a> < ais d f> < g ais d>... Rozšíření NSH Základní operace P, L, R lze rozšířit o různé zkratky. Například pro durové kvintakordy platí, že složená operace R L vede na subdominantu, a operace L R vede na dominantnu zadaného akordu. V tzv. neo-riemannovské teorii se užívají tři další operace N, S, H jako zkratky za složené operace P L R, R P L a L P L. n = p.l.r s = r.p.l h = l.p.l V následujících příkladech jsou vypsáni NSH následnící akordu C dur, tj. f moll, cis moll a as moll (všimněme si enharmonicky vyjádřeného tónu b = ces). Main> akord (n [0,4,7]) " < f as c>" Main> akord (s [0,4,7]) " < cis e gis>" Main> akord (h [0,4,7]) " < as b es>" Příbuznost kvintakordů a jejich spoje Pozorný čtenář si jistě všiml, že akordy ve vztazích P, L, R ale i N, S nebo L.R, R.L obsahují vždy nějaké společné tóny. Společné tóny jsou v hudební teorii důsledkem definice příbuznosti na různých skupinách kvintakordů (vždy v jedné diatonické stupnici). V tomto textu zavedeme pojem příbuznosti obecněji v opačném směru 8, právě jako výskyt stejných tónů v obou akordech (dodejme, že u navzájem různých akordů mohou nastat pouze tři situace, žádný, jeden, nebo dva společné tóny). 8 V hudební teorii například akordy C dur a c moll nejsou příbuzné, ačkoliv mají dva společné tóny. Nevyskytují se společně v jedné diatonické stupnici. 7
Harmonické zákonitosti vyžadují, aby akordy se společnými tóny byly napojeny tzv. přísně. To znamená, že společné tóny akordů mají být tzv. zadrženy v jednom hlase a ostatní tóny mají být vedeny nejkratší cestou. V tomto textu nám jde o ukázky algoritmického myšlení aplikovaného v hudební teorii (a ne o úplnou faktickou správnost z jejího hlediska), zkusme tedy i definici přísného spoje poněkud zobecnit. Základní myšlenkou spojování akordů je plynulost. Zajímá nás vzdálenost jednotlivých tónů mezi dva akordy a tuto vzdálenost se snažíme minimalizovat. Zavedeme jednoduchou definici minimální vzdálenosti tónů a na ni založenou vzdálenost dvou akordů: v n m = min ((n-m) mod 12) ((m-n) mod 12) vzd [a,b,c] [x,y,z] = v a x + v b y + v c z Při posuzování vzdáleností jednotlivých tónů v akordech, musíme pochopitelně vyzkoušet všechny možnosti prohození tří tónů druhého akordu. Naprogramovat obecnou funkci permutace libovolných prvků je problém nad rámec tohoto textu. Zde využijeme faktu, že permutace provádíme vždy pouze na trojicích tónů. Možností, jak různě uspořádat tři tóny je šest. Přímo je tedy vyjmenujeme: perm [x,y,z] = [[x,y,z],[x,z,y],[y,x,z],[y,z,x],[z,x,y],[z,y,x]] Nyní stačí definované funkce vhodně zkombinovat. Určíme vzdálenost prvního zadaného akordu [a,b,c] ke všem šesti variantám druhého akordu [x,y,z] a vybereme tu jeho variantu, která vykazuje vzdálenost celkově nejmenší. Pro ilustraci úvahy provedeme příkazy pro spoj akordů C dur a e moll: Main> perm [11,7,4] [[11,7,4],[11,4,7],[7,11,4],[7,4,11],[4,11,7],[4,7,11]] Main> [ vzd [0,4,7] x x<-perm [11,7,4]] [7,1,13,9,9,11] Z výsledku druhého příkazu vidíme, že nejmenší vzdálenost se zadaným akordem C dur vykazuje druhá varianta akordu e moll tvaru [11,4,7]. Zbývá tedy doplnit funkci, která bude pro dva zadané akordy vracet konkrétní obrat druhého z nich. Definice už není úplně triviální, potřebuje pomocné funkce nejmensi a pos, které určí pozici nejmenší hodnoty v seznamu vzdáleností. Na stejném místě v seznamu permutací akordu totiž najdeme výsledný obrat. spoj a b = (perm b)!! nejmensi [vzd a x x<-perm b] nejmensi x = pos 0 x (minimum x) pos i (x:s) y = if x==y then i else pos (i+1) s y 8
Jako ukázku použití těchto definic vytvoříme funkci zpracovávající výstup funkce postup (tj. řadu akordů) z úvodu této kapitoly. Každý spoj vždy závisí na aktuálním akordu a vybraný obrat v následném kroku ovlivňuje další akordy. spoje (a:b:s) = a:spoje (spoj a b:s) spoje s = s Na závěr textu uvedeme příklady generování spojených postupů akordů podle vzoru 50. léta a Pachelbel i s grafickými výstupy: Main> akordy (spoje (postup [r,l, r.l.r.l, l.r] [0,4,7])) " < c e g> < c e a> < c f a> < b d g> < c e g>" Main> akordy (spoje (postup [r.l, r.l.r, l.r, l] [2,6,9])) " < d fis a> < cis e a> < d fis b> < cis fis a> < d fis a>" 5 Technické okénko Poslední kapitola tohoto textu popisuje zprovoznění aplikací a představení způsobu práce s nimi na počítači se systémem Windows. Nejprve nainstalujeme software zmíněný v úvodu textu. Začneme programem WinHugs. Po jeho instalaci a spuštění vidíme prostředí s výzvou Hugs>. Mírně problematické se může jevit vytvoření zdrojového souboru jazyka Haskell. Zdrojový soubor je čistě textový soubor, který v prostředí Windows vytvoříme pomocí aplikace Poznámkový blok. Při ukládání je nutné uvést celé jméno souboru i s příponou.hs a ve volbě typu souboru vybrat Všechny soubory (*.*) místo volby Textové dokumenty (*.txt). Pokud soubor správně uložíte, měl by získat ikonu listu papíru se zahnutým rohem a se symbolem lambda (λ). Tento soubor můžete otevřít v prostředí WinHugs dvojklikem a pokud soubor neobsahuje syntaktické chyby, místo standardní výzvy programu uvidíte výzvu Main>. Nyní můžete vyhodnocovat zadané hodnoty a funkce napsáním jejich jména (případně parametrů) a potvrzením klávesou Enter. V programu funguje historie příkazů ovládaná šipkami nahoru a dolů. Při změně zdrojového souboru stačí v prostředí WinHugs vstupní definice obnovit povelem :r, vypsání načtených funkcí provede povel :b. 9
Druhým krokem je instalace systému Lilypond pro sazbu not. Systém Lilypond nainstalujeme snadno, jeho použití (jedná se o překladač) ale nemusí být pro běžné uživatele GUI systémů pohodlné. Nainstalujeme proto také tzv. frontend s názvem Frescobaldi, který nám umožní s překladačem Lilypond pracovat na úrovni WYSIWYG 9 ve více oddělených částech hlavního okna, z nichž jedno bude obsahovat zdrojový text v jazyce Lilypond a druhé bude zobrazovat výsledný PDF soubor s notami. Mezi nástroji tohoto programu je i průvodce vytvořením složitějších partitur, panel pro rychlé vkládání příkazů, nebo přehrávání výsledných MIDI souborů. Zbývá popsat jak pracovat s představeným programovým kódem. Zadaný soubor tonnetz.hs doporučujeme otevřít jak v Poznámkovém bloku pro úpravy, tak v prostředí WinHugs pro vyvolávání funkcí už od samého začátku vytváření souboru a postupně přidávat definice z tohoto textu. Po každé změně stačí v Poznámkovém bloku soubor uložit (Ctrl+S) a v prostředí WinHugs zadat :r. Podle následující výzvy hned vidíme, zda nemáme v souboru chybu. Pokud ano, je zobrazen řádek jejího výskytu. Textové výstupy jednotlivých příkazů obsahujících noty lze okamžitě využít při sazbě not. Stačí výsledek funkce (bez okrajových uvozovek) vybrat a zkopírovat. Vložení do programu Frescobaldi musí předcházet bud vytvoření nové partitury s průvodcem (ve zdrojovém textu je následně komentářem % Hudba následuje zde. vyznačeno, kam je třeba text vložit), nebo je nutné vytvořit alespoň elementární příklad pro relativní vkládání not: \relative c { % Hudba následuje zde. c4 e g c c,1 } Pro překlad kódu na notový výstup stačí kliknout na ikonu leknínu (Vyrýt). 9 What You See Is What You Get co vidíš, to dostaneš 10