3.4. Spektralmusik

Für Spektralmusik sind Mikrotöne essentiell. Wie in fuzzy:Common Musics erweiterte Streamklasse und Mikrotöne[fuzzy:Common Musics erweiterte Streamklasse und Mikrotöne] gezeigt, können auch über Midi Mikrotöne wiedergegeben werden. Um Spektralakkore abzubilden, ist es in diesem Fall erforderlich, die Mikrotöne in Miditonhöhen umzurechnen. Bei harmonischen Partialtonspektren sind die Frequenzen sämtlicher Partialtöne 'ganzzahlige Vielfache' der Frequenz des Grundtons. Ausgehend von einem großen E (ca. 82.4 Hz) ergeben sich also für die ersten 32 Partialtöne folgende Frequenzen:

(cm:hertz 'e2) ;; -> 82.40689

(loop
   for partial from 1 to 32
   collect (* partial 82.4))

     ;;; -> (82.4 164.8 247.2 329.6 412.0 494.4 576.8 659.2
     ;;;     741.6 824.0 906.4 988.8 1071.2 1153.6 1236.0 1318.4
     ;;;     1400.8 1483.2 1565.6 1648.0 1730.4 1812.8 1895.2
     ;;;     1977.6 2060.0 2142.4 2224.8 2307.2 2389.6 2472.0
     ;;;     2554.4 2636.8)

Diese Frequenzen müssen anschließend für die Midiwiedergabe über einen Synthesizer in Midi Notennummern umgerechnet werden. Dafür kann man die im fuzzy:Exkurs - Nützliche Funktionen von Common Music[fuzzy:Exkurs - Nützliche Funktionen von Common Music] beschriebene Funktion keynum mit dem keyword :hz verwenden:

(let ((partialtoene-von-e
       (loop
          for partial from 1 to 32
          collect (* partial 82.4))))
  (loop
     for frequenz in partialtoene-von-e
     collect (keynum frequenz :hz)))

(39.99855 51.99855 59.018105 63.99855 67.861694 71.0181 73.68681 75.99855
 78.03765 79.861694 81.511734 83.0181 84.403824 85.68681 86.88124 87.99855
 89.0481 90.03765 90.97368 91.861694 92.70637 93.511734 94.281296 95.0181
 95.72482 96.403824 97.057205 97.68681 98.29433 98.88124 99.448906 99.99855)

;;; in einem Schritt:

(loop
   for partial from 1 to 32
   collect (keynum (* partial 82.4) :hz))

;;; -> (39.99855 51.99855 59.018105 63.99855 67.861694 71.0181
;;;     73.68681 75.99855 78.03765 79.861694 81.511734 83.0181
;;;     84.403824 85.68681 86.88124 87.99855 89.0481 90.03765 90.97368
;;;     91.861694 92.70637 93.511734 94.281296 95.0181 95.72482
;;;     96.403824 97.057205 97.68681 98.29433 98.88124 99.448906
;;;     99.99855

Es ist sinnvoll, diese Rechnung in der Funktion partials→midinotes zusammenzufassen, um die Berechnung für verschiedene Grundtöne einfacher handhaben zu können:

(defun partials->midinotes (grundton start end)
  "return a list of midifloat keynums for the partials from start to
  end related to grundton. Grundton is supplied as midi-keynum or cm
  symbol"
  (let ((grundton-frequenz (hertz grundton)))
    (loop
       for partial from start to end
       collect (keynum (* partial grundton-frequenz) :hz))))

;;; Berechnung der Midi Keynummern der ersten 16 Partialtöne vom
;;; großen E:

(partials->midinotes 'e2 1 16)

;;; -> (40.0 52.0 59.019554 64.00001 67.863144 71.01955 73.688255
;;;     76.00001 78.03909 79.863144 81.51318 83.01955 84.40527
;;;     85.688255 86.88269 88.00001

Die Funktion partials→midinotes lässt sich sogar zweckentfremden, um den Abstand in Cent zwischen dem Grundton und den Tönen seiner harmonischen Partialtonreihe zu bestimmen: Da Midifloats so definiert sind, dass sie die Anzahl von Halbtönen bezogen auf ein Subsubkontra C (midinote=0) angibt und ein Halbton 100 Cent entspricht, setzt man in der Funktion den Grundton auf 0 und multipliziert die midifloats der Partialtonreihe mit 100:

;;; Berechnung der Centzahlen der ersten 32 Partialtöne

(loop
   for midifloat in (partials->midinotes 0 1 32)
   collect (* 100 midifloat))

;;; -> (0.0 1200.0 1901.9548 2400.0 2786.3137 3101.9546 3368.826
;;;     3599.9993 3803.9097 3986.313 4151.3174 4301.9546 4440.5273
;;;     4568.8257 4688.268 4799.999 4904.955 5003.9097 5097.5127
;;;     5186.313 5270.781 5351.3174 5428.274 5501.9546 5572.6274
;;;     5640.5273 5705.8647 5768.8257 5829.5776 5888.268 5945.0356
;;;     6000.0)

;;; oder gerundet:

(loop
   for midifloat in (partials->midinotes 0 1 32)
   collect (round (* 100 midifloat)))

;;; -> (0 1200 1902 2400 2786 3102 3369 3600 3804 3986 4151 4302 4441
;;;     4569 4688 4800 4905 5004 5098 5186 5271 5351 5428 5502 5573
;;;     5641 5706 5769 5830 5888 5945 6000)

lalal

(ql:quickload "cm-utils")

(in-package :cm)

;;; öfnet einen Midi Port in jack mit der internen Variable *midi-out1*:

(progn
  (incudine:rt-start)
  (midi-open-default :direction :output)
  (setf *rts-out* (new incudine-stream))
  (make-mt-stream *out01* *midi-out1* '(4 0))
  (initialize-io *out01*))

;;; common lisp Funktionen zur Umrechnung von Tonhöhen und Frequenzverhältnissen:

(defun ct->fv (cent)
  "Umrechnung von Cent in ein Frequenzverhältnis"
  (expt 2 (/ cent 1200)))

;;; Frequenzverhältnis eines temperierten Halbtons:

(ct->fv 100) ;;; 1.0594631

;;; Beispiel: Errechnung der Frequenz des temperierten Bb oberhalb des
;;; Kammertons a (440 Hz):

(* 440 (ct->fv 100)) ;;; -> 466.1638 Hz

(defun fv->ct (fv)
  "Umrechnung von Frequenzverhältnis in Cent"
  (* 1200 (log fv 2)))

;;; Der Centwert einer reinen großen Terz aufwärts:

(fv->ct 5/4) ;;; -> 386.3137 Cent

;;; Umrechnung einer MIDI Tastennummer in Hertz
;;; (bei Kammerton a = 440 Hz)

(defun midi->cps (keynum &key (tuning-ref 440))
  "Umrechnung MIDI note in Frequenz"
  (* tuning-ref (ct->fv (* 100 (- keynum 69)))))

;;; Kammerton ist MIDI 69:

;;; (midi->cps 69) -> 440

;;; Eine Oktave höher:

;;; (midi->cps 81) -> 880

(defun cps->midi (freq)
  "Umrechnung Frequenz in MIDI Note"
  (+ 69 (* 12 (log (/ freq 440) 2))))

;;; (cps->midi 880) -> 81

;;; Die entsprechenden common music Funktionen zur Umrechnung:

;;; cps->midi

(keynum 440.0 :hz) ;;; -> 69.0

;;; midi->cps

(hertz 69) ;;; -> 440.0

Hier einige Beispiele für das Generieren von arpeggierten Partialtonakkorden. Zuvor muss dafür die Mikrotonale Ausgabe initialisiert sein (siehe fuzzy:Common Musics erweiterte Streamklasse und Mikrotöne[fuzzy:Common Musics erweiterte Streamklasse und Mikrotöne]).

(sprout
 (let* ((duration 3)
        (rhythm 0.1)
        (basenote 33)
        (base-freq (hertz basenote)))
   (process
     for partial from 1 to 16
     output (new midi
              :keynum (keynum (* base-freq partial) :hz)
              :duration duration)
     to *out01*
     wait rhythm)))

(sprout
 (let* ((duration 10)
        (rhythm 0.05)
        (basenote 33.5)
        (base-freq (hertz basenote))
        )
   (process
     for partial from 1 to 25
     for amp = 1.0 then (* amp 0.98)
    output (new midi
             :keynum (keynum (* base-freq partial) :hz)
             :amplitude amp
             :duration duration)
    to *out01*
    wait rhythm)))

dabei ist darauf zu achten

(initialize-io *out01*)

;;; Aufgabe: Schreibe einen Prozess, der Partialtonarpeggios spielt und dabei
;;; allmählich von einem Grundton zum anderen "moduliert", indem
;;; zunächst nur Partialtöne von einem Grundton vorkommen und
;;; allmählich immer mehr Partialtöne von dem anderen Grundton
;;; gespielt werden.

(sprout
 (let* ((duration 8))
   (process
     repeat 200
     with partial = (new heap :of (loop for i from 1 to 32 collect i))
     with weight1 = (loop for x from 99 downto 0 collect x)
     with weight2 = (loop for x below 100 collect x)
     with basenote = (new weighting :of (list
                                         (list 31.4 :weight (new line :of weight1))
                                         (list 34.7 :weight (new line :of weight2))))
     for base-freq = (hertz (next basenote))
     for amp = 1.0 then (* amp 0.999)
     for rhythm = (between 0.04 0.15)
     output (new midi
              :keynum (keynum (* base-freq (next partial)) :hz)
              :amplitude amp
              :duration duration)
     to *out01*
     wait rhythm)))

(initialize-io *out01*)

results matching ""

    No results matching ""