Posts mit dem Label Musik werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Musik werden angezeigt. Alle Posts anzeigen

11.11.2013

Kleine Perl-Spielerei mit Tonleitern

Vor einiger Zeit habe ich mich mal ein bißchen näher mit Noten beschäftigt, und fand es ganz schön faszinierend, wie systematisch man eine Tonleiter selbst aufschreiben kann. Es geht nur darum, den richtigen Nachfolger für jeden Ton zu finden, und schon kann man ganz leicht, ausgehend von C-Dur, jede andere Tonleiter zusammenbauen.

Die Profi-Musiker werden jetzt natürlich schon angefangen haben zu lachen, das ist mir klar ;). Die können das alles auswendig oder merken sich lustige Eselsbrücken ("geh, du alter esel, fische holen"). Da mein Gedächtnis für so etwas nicht geeignet ist, mache ich es anders.

Man kann natürlich sowas mit Stift und Papier erledigen. Das geht aber einem Programmierer an die Ehre, und warum etwas manuell erledigen, was man auch mit einem kleinen Progrämmchen schaffen kann?

Also ein wenig nachgedacht über eine sinnvolle Datenstruktur, und los geht's mit dem perl-Skript, um eine Tonleiter zu konstruieren, wenn der Anfangston gegeben ist. Ich bin ein Anhänger des Konzepts, dass man sich zuerst eine möglichst praktische Datenstruktur ausdenkt, und davon ausgehend ergibt sich der Programmcode nahezu von selbst. Dieses Konzept hat Niklaus Wirth als erster formuliert und dann gleich ein Buch drüber geschrieben ;)

Zunächst mal brauche ich zwei Informationen: wie groß ist der Abstand zwischen jeweils zwei benachbarten Noten, und welche Noten folgen aufeinander.

Mein erster Versuch war, die ganzen Noten und die Halbtöne in zwei Arrays zu packen:

my @toene1=("c",   "d",   "e", "f",   "g",   "a", "h");
my @toene2=("cis", "dis", "f", "fis", "gis", "b", "c");

Als ich schon fast fertig war, hat mir meine Tochter ganz empört erklärt, dass man Kreuze und B nicht mischen darf. Ich müsste also "ais" statt "b" schreiben, wenn ich eine Dur-Tonleiter (also die mit den Kreuzen ...) bauen will. Naja ...

Dann müsste ich in einer Schleife ausgehend vom Grundton, die nächsten 7 Töne suchen. Also eine Fallunterscheidung, ob jetzt ein Sprung um einen ganzen oder halben Ton nötig ist, und dann überlegen, welches der entsprechend entfernte Ton genau ist. Dazu muss man wissen, dass zwischen "c" und "d" ein Abstand von einem Ganzton liegt, von "e" zu "f" aber nur ein Halbton. Bei einer Tonleiter gelten ausgehend vom Grundton, bestimmte Regeln, wie groß der Abstand zum nächsten Ton jeweils ist.

Auf der Klaviertastatur sieht man das ganz wunderbar: es gibt immer abwechselnd Gruppen mit zwei und drei schwarzen Tasten mit Halbtönen, und es gibt pro Oktave zwei Stellen, bei denen oberhalb keine schwarze Taste liegt - links von dem Zweierpärchen schwarzer Tasten liegt jeweils das "c", und rechts davon die zwei weißen Tasten ohne eine schwarze dazwischen sind "e" und "f".

Diese Abstandsregel habe ich als "delta" hingeschrieben, und da ich nicht mit Gleitkommazahlen rechnen wollte, habe ich "2" als Ganzton und "1" als Halbton geschrieben. Das hat mich später auf eine Idee gebracht, wie ich die Datenstruktur der aufeinanderfolgenden Töne verbessern könnte, aber das kommt erst als übernächstes.

my @delta=(2,2,1,2,2,2,1);

Dann brauche ich noch eine Hilfsfunktion, die mir den Index liefert, an dem mein gewünschter Grundton in der C-Dur-Tonleiter liegt.

sub findstart {
        my ($start)=@_;

        for ( my $i=0; $i<$max; ++$i) {
                return ($i) if ($start eq $toene[$i]);
        }
        return 99;
}


my $start=lc($ARGV[0]); 
$ofs=findstart($start);

Diese Funktion liefert mir die Nummer des Tons im Array, und für den schlimmsten Fall (kein Treffer) eine 99, also ein Ergebnis außerhalb des möglichen Bereichs.


Außerdem brauche ich noch einen separaten Zähler (dachte ich zuerst), mit dem ich die Liste der Abstände (der Deltas) von Anfang an durchlaufe.

Als nächstes also eine Schleife und eine Fallunterscheidung:

for (my $i=0; $i<7; ++$i) {
  if ($delta[$o]==2) { # sprung um einen ganzton
    $neuerton=$toene1[$i];
  }
  else { # sprung halbton
    $neuerton=$toene2[$i];
  }


Das bringt mir allerdings ein Problem, weil die primitive Datenstruktur mit zwei separaten Arrays "toene1" und "toene2" nur ganz schwer die numerische Information liefert, wann in der Tonleiter der Abstand nur einen Halbton ist (e/f und h/c).

Also flugs eine neue Datenstruktur ausgedacht, die das liefert. Ein Array von Arrays, und jedes Element enthält den Namen des Grundtons, den Ton einen Halbton darüber und den einen Ganzton darüber:

my @toene=(
  ["c", "cis", "d"  ],

  ["d", "dis", "e"  ],
  ["e", "f",   "fis"],
  ["f", "fis", "g"  ],
  ["g", "gis", "a"  ],
  ["a", "ais", "h"  ],
  ["h", "c",   "cis"]
);


Das Coolste an dieser Konstruktion ist, dass ich mir die Fallunterscheidung jetzt ganz sparen kann und sich der Sprung zum nächsten Ton in der Tonleiter ganz zwanglos aus dem "delta"-Array ergibt: der Index [0] ist der Grundton im inneren Array, der Index [1] ist der Halbton darüber, und der Index [2] der nächste Ton mit einem Ganzton Abstand. Der schönste Trick ist hier, dass ich $delta[$o], also den Abstand vom Ton an der Stelle $o zu seinem Nachfolger, als Index verwende, um den Namen dieses Tons zu finden.

for (my $i=0; $i<7; ++$i) {
  $neuerton=$toene[$i]->[$delta[$o]]; 
}


Im Endeffekt hat mir das aber auch nicht allzuviel gebracht, weil nach dem ersten Halbtonsprung (z.B. in D-Dur vom "e" zum "fis") der nächste Schritt in der Schleife mit dem "fis" anfangen müsste, meine Schleifenlogik aber vom "e" zum "f" an Index [0] springt. Der Output war dann "d", "e", "fis" (soweit ok), aber dann kam nochmal ein "fis", weil nach dem "e" in der ersten Spalte das "f" kommt, und das ist falsch.

So elegant diese Datenstruktur auch ist, so ungeeignet ist sie nach wie vor für das, was ich bezwecke. Es tat mir dann auch ein bißchen leid, dass ich sie aufgeben musste ;)

Also bin ich wieder zurückgekehrt zu einer flachen Datenstruktur, nämlich einem Array, in dem schlicht und einfach alle Töne und Halbtöne aufeinanderfolgen. Mir kam dann nämlich der Gedanke, dass ich mit dem "delta" 1 oder 2 ganz einfach in einem flachen Array entweder den Nachfolger mit Abstand 1 oder 2 nehmen kann, um den nächsten Ton zu finden.

Dieser Gedanke hat dann tatsächlich zum gewünschten Ergebnis geführt. Nebenbei hat es auch dazu geführt, dass ich die zweite Schleifenvariable entfernen konnte, und den Index des Grundtons (also mein Parameter von der Kommandozeile) mißbrauchen konnte, um zu zählen. Es ist nur wichtig zu bedenken, dass man nicht über das Ende des Arrays hinausgreifen darf. Deshalb verwende ich den "modulo"-Operator, um (wie bei einem Zifferblatt) dafür zu sorgen, dass nach der "11" bei der "0" weitergezählt wird.

Warum kommt es zu "12" als Größe des Arrays? Ganz einfach: es gibt in einer Tonleiter 7 verschiedene Töne (c/d/e/f/g/a/h), und eine "Oktave" höher findet sich wieder der Grundton. Zwischen "e" und "f" und nach dem "h" gibt es keinen Halbton (musikalisch schon, aber nicht mit einem eigenen Namen), deshalb also 2*7-2=12 verschiedene Töne mit Namen. Solche Überlegungen am Rand sind recht nützlich, um zu testen, ob bestimmte Grundannahmen im Programm plausibel sind, und ob man bei Aufzählungen auch alle Varianten wirklich in den Programmtext geschrieben hat oder noch etwas fehlt.


Und das kam als Endprodukt dabei heraus:

#!/usr/bin/perl -w

my @delta=(2,2,1,2,2,2,1);
my @toene=(
        "c",   "cis", "d",   "dis", "e",   "f",
        "fis", "g",   "gis", "a",   "ais", "h",
);
my $max=scalar(@toene);

sub findstart {
        my ($start)=@_;

        for (my $i=0; $i<$max; ++$i) {
                return ($i) if ($start eq $toene[$i]);
        }
        return 99;
}

my $start=lc($ARGV[0]);
my $ofs;

print "# $start-dur Tonleiter ($max)\n";
$ofs=findstart($start);

for (my $o=0; $o<7; ++$o) {
        print "# "," + ",$delta[$o]," = ",$toene[$ofs],"\n";
        $ofs=($ofs+$delta[$o]) % $max;
}


Hier ist der Probelauf für F-Dur noch mit der Debugging-Ausgabe, wie weit entfernt der nächste Ton liegt (also f+1=g, a+1/2=ais usw.):

server:~ # ~ths/perl/tonleiter.pl f
# f-dur Tonleiter
#  + 2 = f
#  + 2 = g
#  + 1 = a
#  + 2 = ais
#  + 2 = c
#  + 2 = d
#  + 1 = e


[Update 2013.11.12: Formatierung, Tippfehler]

05.04.2013

Vater-Tochter-Tag

Ich weiß gar nicht so recht, wo ich anfangen soll mit diesem Bericht. Soll ich über Justin Bieber ablästern oder mich über das kalte Wetter aufregen?

Ne, ganz anders! Ich hatte unglaubliche Lust auf ein Justin-Bieber-Konzert, und damit es für mich nicht so peinlich aussieht, hab ich meine Tochter (=Kind 1) gezwungen, mitzukommen! Ha, das ist eine gute Geschichte. So machen wir's!

Wie auch immer ... aus Gründen musste ich kurzfristig als erwachsene Begleitperson mit meiner Tochter auf ein Konzert von Justin Bieber in Frankfurt mitkommen. Ich gebe ganz offen zu, dass ich gänzlich unbegeistert war. Zumal ich von anderen Konzerten wusste, dass man sehr früh anstehen muss.

Das Konzert sollte um 18.30 beginnen (mit Vorgruppe). Meine Tochter wollte so früh wie möglich nach Frankfurt, allerdings nicht gleich zur offiziell erlaubten Uhrzeit von 2.00 in der Früh. Puh, nochmal Schwein gehabt ;). Da es sehr kurzfristig kam, hatte ich trotzdem großes Glück, dass ich mit Gleitzeit flexibel frühen Feierabend machen konnte. Wir sind dann um 12.45 von daheim losgefahren und sind mit einem Regionalexpress bequem von Friedberg aus zur Festhalle an der Messe gefahren (RMV im Kartenpreis mit drin, also muss das auch ausgenutzt werden). Als wir ankamen, war der Vorplatz schon gut gefüllt. Viele Besucher hatten Decken u.ä. mit, die waren wohl schon deutlich früher angekommen.

Die Konzertkarten waren das letztjährige Geburtstagsgeschenk für unsere Tochter, und damit es auch 'was Besonderes wird, hat meine Frau Karten im "Golden Circle" ausgesucht, d.h. besonders weit vorn. Dazu später noch mehr ...

Wenig verwunderlich waren die meisten Besucher kleine Mädchen (Tschuldigung, ich darf das aber sagen mit 45 ;) ), und ein paar wenige Jungs mit nachgemachter Justin-Bieber-Frisur (sowohl alt als auch neu ...), und alle paar Minuten gingen Aufschreie durch die wartende Menge, wenn sich jemand eingebildet hat, dass gerade das Idol irgendwo hinter einem der Fenster des Halleneingangs zu sehen war. Der Vorplatz der Festhalle war mit Barrieren aufgeteilt in die verschiedenen Preisklassen (Diamond Circle, Golden Circle, ...). Es gab Gedränge, aber es war erträglich. Ich hatte zum Glück ein Buch mitgebracht und während der Wartezeit bin ich  fast 150 Seiten weitergekommen in Terry Pratchetts "Night Watch" (dazu schreib ich auch noch mal eine Buchkritik. Wird Zeit nach dem fünften Lesen oder so).

Gegen 17.00 Uhr hatte ich langsam doch kalte Füße, dann begann zum Glück schon ;) der Einlass. Recht gut organisiert; zuerst die Besucher mit den besten Karten (Diamond), dann kamen wir an die Reihe (Gold). Es gab keine Taschenkontrollen, ich hätte also nicht mein Taschenmesser zuhause lassen müssen (vorletztes Jahr bei Bryan Adams auf dem Hessentag musste ich mein klitzekleines Taschenmesser leider abgeben, weil ich dusslich war und es noch in der Tasche hatte). Handys, Flaschen usw. mussten auch nicht abgegeben werden, ich habe nur gesehen, dass ein CamCorder aussortiert wurde.

In der Festhalle gab es Getränkestände (3,70 Euro für einen Becher Wasser), und am Anfang war auch das Gedränge in der Halle erträglich. Hinter uns waren auch Barrieren aufgebaut, allerdings mit Durchgängen zu den Ständen. Nachdem wir einen Platz gefunden hatten, kamen plötzlich die restlichen Besucher dazugedrängelt, es gab einen heftigen Ruck und Geschubse nach vorn, und die Ordner mussten schon die ersten Mädchen nach vorn herausziehen und zu den Sanis bringen. Das hat mich doch sehr gewundert. Die Anschaffung der Karten mit "Gold"- oder "Diamond"-Status war also offensichtlich sinnlos, weil auch die "normalen" Karten Zugang zum gesamten Innenraum hatten. Wer genug gedrängelt hat, konnte also locker genauso ganz nach vorn kommen. Schlecht organisiert oder wenigstens schlecht umgesetzt. Schade um's Geld. Wenige Minuten später stellte meine Tochter trocken fest, dass die Sitzplatzkarten im Rang (d.h. auf den Balkonen über dem Innenraum der Festhalle) wohl doch die bessere Entscheidung gewesen wären. Sie trug dünne Chucks (brrr!) und ihr taten wohl recht schnell die Füße vom langen Stehen weh.

Hinter mir war eine extrem nervige englischsprachige Familie, Mutter mit zwei Töchtern. Tochter mit Basecap war dick mit Steppjacke angezogen, links und rechts bei Freundinnen eingehakt und hat lang und ausdauern herumgejammert "I can't breathe ... I can't breathe". Vor ihr war allerdings ein ganzer Meter Platz, und sie hatte auch viel Luft, um zu jammern, dass sie keine Luft hat. Schrecklich nervig und hatte eine gewisse Ironie. Im Zuge des weiteren Gedrängels wurden sie allerdings von mir wegbewegt. Was ein Glück. Ich konnte mich allerdings nicht zurückhalten und hab sie gefragt, woher sie die Luft nimmt, dauernd "I can't breathe" zu jammern. Das fand sie doof und hat sich bei ihrer Mutter darüber beschwert, wie unhöflich doch alle Deutschen wären ;), sie wäre doch ganz freundlich zu mir gewesen.

Die Vorgruppe "Neon Dogs" hat halbwegs erträglichen Deutschrock gespielt, insgesamt waren das sechs oder sieben Lieder. Die Art von Hardrock, die man auf Abi-Partys gern spielt. Die waren dann gegen 19.00 Uhr fertig und der Sänger hat dann noch ganz freundlich "Viel Spaß mit Justin Bieber" gewünscht.

Bis das eigentliche Konzert anfing, wurde es allerdings 20.45 Uhr. Dann gab es eine Flutlichtexplosion und auf der Videoleinwand wurde ein Zehn-Minuten-Countdown eingeblendet. Bei Erreichen jeder vollen Minute gab es Gekreische. Bis zu dieser Uhrzeit mussten die Ordner allerdings in regelmäßigen Abständen Mädchen vorn an der Absperrung herausziehen. Ich hab nicht mitgezählt, aber nach meiner Schätzung sind von 18.00 bis 21.00 Uhr locker allein auf unserer Seite des Laufstegs deutlich über 50 Mädchen zu den Sanis gebracht worden. Das hätte sich sicherlich entspannt und wäre im Sinne des deutlich minderjährigen Publikums gewesen, wenn Justin Bieber nicht diese extrem lange Wartezeit hätte verstreichen lassen. Um 20.30 Uhr sah meine Tochter sogar, dass er noch Twitter-Nachrichten verschickt und hat ihm geantwortet "put your mobile away and get on stage". Ob's was geholfen hat? Bei früheren Auftritten hat er sein Publikum auch warten lassen. Dann muss man auch das Konzert nicht um 18.00 Uhr beginnen lassen, wenn der Sänger dann doch erst um 21.00 Uhr anfängt und das Konzert bis 22.30 dauert (länger war es nicht).

Nu ja, dann fing es halt doch an. Die Tonqualität fand ich extrem schlecht, die Bässe waren zu laut und übersteuert, und das dünne Stimmchen war zu leise eingestellt im Vergleich zum Rest der Instrumente. Ich war froh, dass ich Ohrenstöpsel dabei hatte, und zu meiner Überraschung hat sich meine Tochter freiwillig ebenfalls Stöpsel in die Ohren gesteckt. Zu hören war trotzdem noch genug ;)

Die Show hatte hohen Unterhaltungswert, abgesehen von der Musik hab ich mich blendend unterhalten. Die Videowände, die Pyrotechnik und die Hebebühne haben zusammen mit je 5 weiblichen und männlichen Tänzern eine tolle Choreographie abgeliefert. Der Anfang war ziemlich kitschig mit den riesigen Flügeln. Der Übergang - Flug nach links und rechts - zwischen den diversen Videowänden war nichtsdestotrotz cool gemacht. Später gab es ebenfalls noch einen sehr schönen Übergang zwischen Bühne und Videowand: auf dem Zwischenbalkon vor der Band gab es jede Menge Trockeneis-Nebel; er ließ sich fallen und verschwand im Nebel, das Licht ging aus, und auf der Videowand direkt darunter sah man ihn ins Wasser fallen. Dann gingen alle Videowände an, und Sänger mitsamt kompletter Tanzgruppe war unter Wasser zu sehen. Sehr schön gemacht!

Das ganze Konzert war eine voll durchkomponierte Show, die Zugabe von zwei Liedern war ebenfalls vorher einkalkuliert (auf der Videowand ein Anheizer, der sich über die Handyvideos lustig macht, zum "get a life" aufruft und dazu, lauter zu schreien, damit Justin wieder auf die Bühne kommt), und nach der einzigen Zugabe war plötzlich Schluss. Man merkt deutlich, dass die ganze Show voll durchgeplant ist und die Musiker ihr Programm abziehen. Keine Spontaneität, sogar das hübsche Mädchen aus dem Publikum für "one less lonely girl" wurde vermutlich vorher schon ausgesucht. Geld verdienen als Devise; das merkt man auch an den Eintrittspreisen. Mag sein, dass der Aufwand für die Show auch extrem hoch ist (angeblich 300 Lkws mit Material), aber der Preis war eigentlich schon jenseits meiner Schmerzgrenze, und es war nur den Dackelaugen von Tochter und Frau geschuldet, dass wir die Karten gekauft haben (noch dazu mussten es ja zwei sein, weil Kind 1 erst 12 Jahre alt ist und eine erwachsene Begleitperson benötigt).


Was ich total erstaunlich fand, war die Duldung der Handyaufnahmen. Andererseits: jeder hat ein Handy oder Smartphone oder Minikamera dabei; es wäre unmöglich, das alles auszusortieren. Die Verbreitung von hochpreisigen Geräten wie iPhone, S3, xperia u.ä. bei den Jugendlichen hat mich durchaus verblüfft. So'n Ding bekommt man nicht gerade für'n Apple und 'n Ei (haha, der musste jetzt sein).



Meine Tochter hatte natürlich schon auf dem Vorplatz den Akku leergespielt, und der Reserveakku (gute Anschaffung, wenn man ein Smartphone hat!) konnte das kaum schnell genug nachladen, zumal im Gehopse immer mal das Kabel gewackelt hat. So musste ich dann auch ein paar Fotos machen als Erinnerung ;). Erstaunlich, wie robust so ein Smartphone ist, es hält sogar Bilder von Justin Bieber aus.

Auf dem Rückweg zur S-Bahn hab ich dann doch gemerkt, dass ich Rücken habe ;). Ich konnte mich kaum hinsetzen, nur ganz, ganz langsam ...

Was für ein Abenteuer! Muss man einfach mal erlebt haben als Papa.


Update [08.04.]:
Das scheint Methode zu sein mit der Verspätung. Einen Tag später ließ Justin Bieber das Konzert erst um 22.00 Uhr anfangen, da warteten viele Eltern schon wieder vor der Halle zum Abholen.
Und am Wochenende las mir meine Tochter vor, dass es einem Fan "peinlich" sei und er sich schäme, weil Justin Bieber ja aufgrund der massiven Beschwerden jetzt Deutschland hassen würde.
Ich sehe das eher umgekehrt: ein Star wird durch seine Fans zum Star. Wenn er seine Fans arrogant behandelt, verdient er keinen Respekt. Und wer nicht mit der Wahrheit umgehen kann, sollte aufhören, in der Zeitung Berichte über sich zu lesen. Das ist ungefähr genauso, wie sich selbst zu googeln ;)