Drop links or images here to add them to the editor.

De Parsons-code is een eenvoudige notatiemethode om muziek te identificeren aan de hand van melodische bewegingen — bewegingen van de toonhoogte omhoog, omlaag of statisch.

Parsons code: beweging

Deze rode lijn is een grafische weergave van de Parsons-code van het traditioneel Engels kerstlied We Wish You A Merry Christmas:

URUDDDRRURUDDDDRURUDDDDDRUUDUDU

Elk paar opeenvolgende noten van een melodie wordt aangeduid met één van drie mogelijke hoofdletters die het verband leggen tussen de toonhoogte van de volgende noot en die van de vorige noot:

Elke hoofdletter U, D of R in een Parsons-code wordt een beweging genoemd.

Denys Parsons ontwikkelde dit systeem voor zijn boek The Directory of Tunes and Musical Themes uit 1975. Door muziek op deze manier voor te stellen, wordt het makkelijker om melodieën te indexeren, te analyseren of te zoeken. Vooral wanneer de noten onbekend zijn. Parsons behandelde ongeveer 15.000 klassieke, populaire en volksmuziekstukken in zijn boek. Daarbij ontdekte hij dat UU de meest populaire openingsbeweging is. Ze komt voor in 23% van alle melodieën. Een fenomeen dat wordt waargenomen in alle muziekgenres.

Opgave

Schrijf een bash shell script parsons waarmee een grafische weergave van Parsons-codes kan uitgeschreven worden naar standaard uitvoer (stdout) in SVG-formaat. Verderop bespreken we stap voor stap hoe deze SVG-afbeelding opgebouwd wordt. Het script moet bijvoorbeeld kunnen gebruikt worden om deze weergave van zeven Parsons-codes te genereren in de regenboogkleuren.

Parsons codes

De Parsons-codes die we willen weergeven, moeten als afzonderlijke argumenten aan het script doorgegeven worden.

De kleur van een individuele Parsons-code kan vastgelegd worden door de code zelf te laten volgen door een dubbelpunt (:) en een HTML-kleur, bijvoorbeeld URUDDDRRUR:red voor een Parsons-code die als een rode lijn moet weergegeven worden. Als er geen specifieke kleur wordt opgegeven voor een Parsons-code, dan moet het script die weergeven in een standaardkleur die voor alle Parsons-codes zonder specifieke kleur gebruikt wordt.

Het script moet de volgende opties ondersteunen:

Het script moet voor de verwerking van de opties de flexibiliteit aan de dag leggen die gebruikelijk is bij Unix commando's: volgorde van opties speelt geen rol, opties kunnen samengenomen worden, argument bij een optie moet niet noodzakelijk van de optieletter gescheiden worden door witruimte, ….

Daarnaast moet het script de volgende foutafhandeling voorzien:

Hierbij hebben we de foutafhandeling in volgorde van prioriteit opgelijst. De gepaste foutboodschappen vind je terug in onderstaand voorbeeld.

Opbouw van de SVG-afbeelding

Scalable Vector Graphics (SVG) is een XML-gebaseerd bestandsformaat dat vectorafbeeldingen tekstueel beschrijft aan de hand van eenvoudige meetkundige bouwstenen zoals punten, lijnen, cirkels en veelhoeken.

Je moet geen SVG of XML kennen om deze opgave op te lossen. We bespreken stap voor stap hoe de grafische weergave van Parsons-codes in SVG-formaat opgebouwd wordt aan de hand van vier sjablonen: hoofding, rooster, Parsons-code en voettekst. Daarbij zullen we de variabele onderdelen van elk sjabloon in het groen weergeven. Daar moet het script de juiste waarden invullen. Het is belangrijk dat elk sjabloon exact overgenomen wordt, zodat het resultaat dat het script uitschrijft precies overeenkomt met de beschreven specificatie.

Hoofding
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="-0.5 -7.5 32 13">
<style type="text/css">path{fill:none;stroke-width:0.25;stroke-linecap:round;stroke-linejoin:round}</style>
<rect x="-0.5" y="-7.5" width="32" height="13" fill="black" rx="0.2"/>

Dit sjabloon bevat de SVG start-tag (svg) en algemene opmaak van de afbeelding (style). Het tekent ook een afgeronde zwarte rechthoek (rect) als achtergrond. Op de eerste en de derde regel van het sjabloon moeten dezelfde drie natuurlijke getallen ingevuld worden: i) de bovengrens van de uitwijkingen $$\Delta_{+}$$, ii) de breedte $$b + 1$$ en iii) de hoogte $$h + 1$$ van de collectie Parsons-codes die aan het script doorgegeven werden. Merk op dat het minteken (-) dat voorafgaat aan het eerste natuurlijke getal dat moet ingevuld worden, en de .5 die erop volgt, vaste onderdelen vormen van het sjabloon.

De breedte $$b$$ van een collectie Parsons-codes is standaard gelijk aan de lengte van de langste Parsons-code, waarbij de lengte van een Parsons-code uitgedrukt wordt als het aantal bewegingen (letters U, D en R) in de Parsons-code. Als de optie -s gebruikt werd, dan is de breedte echter gelijk aan de lengte van de kortste Parsons-code.

De uitwijking van een Parsons-code geeft de hoogte van de grafische weergave aan bij de start en na elke beweging (een letter U, D of R). De weergave van elke Parsons-code start in de oorsprong $$(0, 0)$$ van een cartesisch coördinatenstelsel (X- en Y-as die loodrecht op elkaar staan) en start dus met uitwijking 0. Bij elke beweging U stijgt de uitwijking met 1. Bij elke beweging D daalt de uitwijking met 1. Bij elke beweging R blijft de uitwijking gelijk. Voor de rode Parsons-code

URUDDDRRURUDDDDRURUDDDDDRUUDUDU

die we eerder als voorbeeld gebruikten, verloopt de uitwijking op deze manier

Verloop van de uitwijking voor Parsons-code <samp>URUDDDRRURUDDDDRURUDDDDDRUUDUDU</samp>.

De bovengrens van de uitwijkingen $$\Delta_{+}$$ van een collectie Parsons-codes is de maximale uitwijking langs alle Parsons-codes. Omdat de uitwijking van een Parsons-code altijd start bij 0, geldt dat $$\Delta_{+} \geq 0$$. Voor de twee Parsons-codes in onderstaande afbeelding wordt de bovengrens $$\Delta_{+} = 7$$ bereikt langs de oranje Parsons-code.

De ondergrens van de uitwijkingen $$\Delta_{-}$$ van een collectie Parsons-codes is de minimale uitwijking langs alle Parsons-codes. Omdat de uitwijking van een Parsons-code altijd start bij 0, geldt dat $$\Delta_{-} \leq 0$$. Voor de twee Parsons-codes in onderstaande afbeelding wordt de ondergrens $$\Delta_{-} = -6$$ bereikt langs de rode Parsons-code.

Als de optie -s gebruikt wordt, dan worden de bovengrens en ondergrens van de uitwijkingen enkel berekend langs de eerste $$b$$ bewegingen van elke Parsons-code. Daarbij is $$b$$ de breedte van de collectie Parsons-codes.

Parsons code: uitwijkingsgrenzen

De hoogte $$h$$ van een collectie Parsons-codes is gelijk aan $$\Delta_{+} - \Delta_{-}$$. Voor de twee Parsons-codes in bovenstaande afbeelding is de hoogte $$h = 7 - (-6) = 13$$.

Rooster
<defs><pattern id="grid" viewBox="0,0,1,1" x="-0.5" y="-0.5" width="1" height="1" patternUnits="userSpaceOnUse">
<circle cx="0.5" cy="0.5" r="0.125" fill="#444"/></pattern></defs>
<polygon points="-0.5,0 31.5,-32 31.5,32" fill="url(#grid)"/>

Dit sjabloon tekent roosterpunten (grijze punten) in de achtergrond en moet enkel aan de SVG-afbeelding toegevoegd worden als de optie -g gebruikt wordt. Op de derde regel van het sjabloon moeten de vier natuurlijke getallen $$b$$, $$b + 1$$, $$b$$ en $$b + 1$$ ingevuld worden, met $$b$$ de breedte van de collectie Parsons-codes die aan het script doorgegeven werden. De mintekens (-) en halve waarden (.5) vormen opnieuw vaste onderdelen van het sjabloon.

Parsons-code
<path d="M0,0l1,-1h1l1,-1l1,1l1,1l1,1h1h1l1,-1h1" stroke="red"/>

Voor elk argument dat aan het script werd doorgegeven — een Parsons-code die optioneel een specifieke kleur meekrijgt — moet aan de SVG-afbeelding een afzonderlijke regel toegevoegd worden die opgebouwd is volgens dit sjabloon. Het sjabloon tekent de Parsons-code als een gekleurde lijn (path) die start in de oorsprong $$(0, 0)$$ van een cartesisch coördinatenstelsel.

De waarde die moet ingevuld worden voor het attribuut d krijg je door in de Parsons-code

Voor de duidelijkheid: het fragment l1,-1 dat in de plaats komt van elke U in de Parsons-code is een kleine letter l, gevolgd door het cijfer 1, een komma, een minteken (-) en nog een cijfer 1. Het fragment dat in de plaats komt van elke D is hetzelfde, maar dan zonder minteken (-). Als de optie -s gebruikt werd, dan worden enkel de eerste $$b$$ bewegingen van de Parsons-code gebruikt, met $$b$$ de breedte van de collectie Parsons-codes die aan het script doorgegeven werden.

De waarde die in het sjabloon moet ingevuld worden voor het attribuut stroke is de specifieke kleur die in het argument werd opgegeven voor de Parsons-code, of de standaardkleur als er geen specifieke kleur werd opgegeven.

De waarden die in het sjabloon als voorbeeld ingevuld werden, corresponderen met die voor een argument URUDDDRRUR:red of met die voor een argument URUDDDRRUR en de kleur red die als standaardkleur werd doorgegeven aan de optie -c.

Voettekst
</svg>

Dit laatste sjabloon sluit de SVG-afbeelding af met een SVG stop-tag.

Voorbeeld

Onderstaande voorbeeldsessie toont hoe het shell script parsons moet kunnen gebruikt worden.

$ parsons URUDDDRRUR:red > merry_xmas.svg
$ cat merry_xmas.svg
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="-0.5 -2.5 11 4">
<style type="text/css">path{fill:none;stroke-width:0.25;stroke-linecap:round;stroke-linejoin:round}</style>
<rect x="-0.5" y="-2.5" width="11" height="4" fill="black" rx="0.2"/>
<path d="M0,0l1,-1h1l1,-1l1,1l1,1l1,1h1h1l1,-1h1" stroke="red"/>
</svg>
$ parsons -gc red URUDDDRRUR > merry_xmas.grid.svg
$ cat merry_xmas.grid.svg
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="-0.5 -2.5 11 4">
<style type="text/css">path{fill:none;stroke-width:0.25;stroke-linecap:round;stroke-linejoin:round}</style>
<rect x="-0.5" y="-2.5" width="11" height="4" fill="black" rx="0.2"/>
<defs><pattern id="grid" viewBox="0,0,1,1" x="-0.5" y="-0.5" width="1" height="1" patternUnits="userSpaceOnUse">
<circle cx="0.5" cy="0.5" r="0.125" fill="#444"/></pattern></defs>
<polygon points="-0.5,0 10.5,-11 10.5,11" fill="url(#grid)"/>
<path d="M0,0l1,-1h1l1,-1l1,1l1,1l1,1h1h1l1,-1h1" stroke="red"/>
</svg>
$ parsons -g URUDDDRRURUDDDDRURUDDDDDRUUDUDU:red UDDUUUUUUUUDDDDDUURRUDDRRUDDUDD:orange UDDDRRRUDDDRUDDDURDDUDUDDDRUDDD:yellow UURRDUURDRUUDRDDDUDUURRDUURDRUU:lime UDDUUDDURDURDURUDDDUDDURUDDDUDD:lightblue RUDUDRUDRDRRUUDDRDUDRDRDUDUDRUR:blue URRUUDUUUDUDDURDDURRUUDUUUDUDDU:blueviolet > xmas_rainbow.svg
$ cat xmas_rainbow.svg
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="-0.5 -7.5 32 19">
<style type="text/css">path{fill:none;stroke-width:0.25;stroke-linecap:round;stroke-linejoin:round}</style>
<rect x="-0.5" y="-7.5" width="32" height="19" fill="black" rx="0.2"/>
<defs><pattern id="grid" viewBox="0,0,1,1" x="-0.5" y="-0.5" width="1" height="1" patternUnits="userSpaceOnUse">
<circle cx="0.5" cy="0.5" r="0.125" fill="#444"/></pattern></defs>
<polygon points="-0.5,0 31.5,-32 31.5,32" fill="url(#grid)"/>
<path d="M0,0l1,-1h1l1,-1l1,1l1,1l1,1h1h1l1,-1h1l1,-1l1,1l1,1l1,1l1,1h1l1,-1h1l1,-1l1,1l1,1l1,1l1,1l1,1h1l1,-1l1,-1l1,1l1,-1l1,1l1,-1" stroke="red"/>
<path d="M0,0l1,-1l1,1l1,1l1,-1l1,-1l1,-1l1,-1l1,-1l1,-1l1,-1l1,-1l1,1l1,1l1,1l1,1l1,1l1,-1l1,-1h1h1l1,-1l1,1l1,1h1h1l1,-1l1,1l1,1l1,-1l1,1l1,1" stroke="orange"/>
<path d="M0,0l1,-1l1,1l1,1l1,1h1h1h1l1,-1l1,1l1,1l1,1h1l1,-1l1,1l1,1l1,1l1,-1h1l1,1l1,1l1,-1l1,1l1,-1l1,1l1,1l1,1h1l1,-1l1,1l1,1l1,1" stroke="yellow"/>
<path d="M0,0l1,-1l1,-1h1h1l1,1l1,-1l1,-1h1l1,1h1l1,-1l1,-1l1,1h1l1,1l1,1l1,1l1,-1l1,1l1,-1l1,-1h1h1l1,1l1,-1l1,-1h1l1,1h1l1,-1l1,-1" stroke="lime"/>
<path d="M0,0l1,-1l1,1l1,1l1,-1l1,-1l1,1l1,1l1,-1h1l1,1l1,-1h1l1,1l1,-1h1l1,-1l1,1l1,1l1,1l1,-1l1,1l1,1l1,-1h1l1,-1l1,1l1,1l1,1l1,-1l1,1l1,1" stroke="lightblue"/>
<path d="M0,0h1l1,-1l1,1l1,-1l1,1h1l1,-1l1,1h1l1,1h1h1l1,-1l1,-1l1,1l1,1h1l1,1l1,-1l1,1h1l1,1h1l1,1l1,-1l1,1l1,-1l1,1h1l1,-1h1" stroke="blue"/>
<path d="M0,0l1,-1h1h1l1,-1l1,-1l1,1l1,-1l1,-1l1,-1l1,1l1,-1l1,1l1,1l1,-1h1l1,1l1,1l1,-1h1h1l1,-1l1,-1l1,1l1,-1l1,-1l1,-1l1,1l1,-1l1,1l1,1l1,-1" stroke="blueviolet"/>
</svg>
$ parsons -x URUDDDRRUR
Syntax: parsons [-gs] [-c <color>] code[:color] ...
$ echo $?
1
$ parsons
Syntax: parsons [-gs] [-c <color>] code[:color] ...
$ echo $?
2
$ parsons ABC
Syntax: parsons [-gs] [-c <color>] code[:color] ...
$ echo $?
3
$ parsons URUDDDRRUR:blue:yellow
Syntax: parsons [-gs] [-c <color>] code[:color] ...
$ echo $?
3

Epiloog

In deze opgave gebruiken we zeven Parsons-codes als voorbeeld. Ze stellen allemaal bekende kerstliedjes voor. Hieronder staan ze opgelijst in volgorde van de regenboogkleuren die we eraan toegekend hebben:

kleur HTML-kleur kerstliedje Parsons-code
rood red We Wish You A Merry Christmas URUDDDRRURUDDDDRURUDDDDDRUUDUDU
oranje orange White Christmas UDDUUUUUUUUDDDDDUURRUDDRRUDDUDD
geel yellow Jingle Bells UDDDRRRUDDDRUDDDURDDUDUDDDRUDDD
groen lime Once In Royal David's City UURRDUURDRUUDRDDDUDUURRDUURDRUU
blauw lightblue Silent Night UDDUUDDURDURDURUDDDUDDURUDDDUDD
indigo blue Fairytale Of New York RUDUDRUDRDRRUUDDRDUDRDRDUDUDRUR
violet blueviolet O Little Town Of Bethlehem URRUUDUUUDUDDURDDURRUUDUUUDUDDU

Met de Melodic Contour Search tool van Musipedia kan je Parsons-codes gebruiken om liedjes te zoeken.