Core: 16+ Selector

von | Mrz 17, 2023 | Reaktor, ReaktorCore

Primary-Selectoren verfügen über nur 16 Eingänge. Natürlich kann man in Reihe schalten und die Ergebnisse passend routen … Aber einfacher wäre es doch, einen Selector mit so vielen Eingängen zu haben, wie man gerade braucht.

[01]

Um was wird es gehen?

Das zusammenschalten von Selectoren bei einem Bedarf von mehr als 16 Eingängen ist grundsätzlich kein Problem. Lästig ist nur, dass man dazu …

  • mehr als einen Selector bemühen muss (Rechenleistung)
  • den Position-Parameter entsprechend auf die einzelnen Selectoren anpassen muss
  • den Output der Selectoren passend routen muss

Das alles könnte man sich durch Selektoren mit mehr als 16 Eingängen ersparen. Deshalb wird das unser erstes Core-Tutorial. Hierfür benötigen wir keine speziellen DSP-Kenntnisse. Es geht lediglich um das speichern, lesen und routen von Zahlen. Perfekt für den Einstig in die Core-Welt.

[02]

Ein Beispiel aus der Praxis

Wer das Tutorial „Advanced: Multi-Regler“ gesehen hat, kann sich evtl. vorstellen, wozu ich in einem aktuellen Projekt mehr als 16 Werte routen muss. Das habe ich bislang, wie oben beschrieben, mit zwei Selectoren und der entsprechenden Logik drum herum geregelt. Dann habe ich aus Spaß und Langeweile nach einer Lösung auf Core-Ebene recherchiert und in einem Forum einen 20 Jahre(!) alten Beitrag gefunden, der einen Core-Selector mit acht Eingängen erklärt. Entweder gab es zu jener Zeit noch keine Selectoren, oder aber nur welche mit weniger als acht Eingängen.
Wie auch immer: Auf Basis jener Idee ist dieser Core-Selector entstanden, der theoretisch beliebig viele (aktuell 32) Eingänge anbietet die sich auf einen Minimum- und einen Maximum-Wert beschränken lassen. Doch bevor wir uns diesen anschauen, möchte ich euch die „konventionelle“ Primary-Lösung zeigen, damit der Unterschied klar wird:

Abb. 1: 16+-Selector in der Primary-Ebene

So sieht die Primary-Lösung für 18 Eingänge aus. Sicher hätte ich die Selectoren von 16:2 Eingängen bis hin zu 2:16 Eingängen und allen Kombinationen dazwischen wählen können. Letztendlich bot sich 9:9 auch aus optischen Gründen einfach an. Der Drehregler liefert den Wertebereich von 1 – 18, mit dem folgendes geschieht:

  • Für den Pos-Eingang des ersten Selectors wird 1 subtrahiert, da dieser bei 0 zu zählen beginnt. Aber das wisst ihr ja bereits.
  • Für den Pos-Eingang des zweiten Selectors subtrahiere ich 10, so dass dieser erst bei Reglerwert 10 beginnt zu arbeiten.
  • Welcher Selector am Ende das Rennen macht, steuere ich über ein Compare-Modul. Liegt am Regler ein Wert größer 9 an, lässt der dritte Selector den zweiten Selector durch, ansonsten kommt der erste Selector zum Ziel.

Je mehr mehr Eingänge gefragt sind, desto mehr Selectoren und Compare-Module sind nötig, um die Werte brauchbar zu routen. Die kann man zwar nett in einem Macro verpacken, der Bedarf an Rechenleistung bleibt aber trotzdem.

 

Abb. 2: 16+-Selector in der Core-Ebene

Und so sieht die Core-Lösung aus. Auf den ersten Blick sind das sehr viel mehr Bauteile. Stimmt! Man darf aber nicht vergessen, dass diese zum einen auf einer sehr rudimentären Ebene ablaufen, also nicht sonderlich komplex sind, und andererseits CPU-schonend compiliert werden. Und im praktischen Einsatz ist das „nur ein Selector“, der ohne zusätzlichen Aufwand mit so vielen Eingängen umgehen kann, wie eben gebraucht werden:

  • Linke Spalte: So zeigt sich der Selector in der Primary-Ebene. Als Macro mit
    • … einem Eingang für den Regler,
    • … je einem Eingang für den Minimum- und Maximum-Wert
    • … und genau so vielen Daten-Eingängen, wie gebraucht werden.
    • Warum der Core-Selector in einem Macro steckt, seht ihr in der mittleren Spalte:
  • Mittlere Spalte: Da der Core-Selector bis zu 32 Eingänge bereit stellt, diese aber nicht immer alle benötigt werden, habe ich ihn in ein Macro gesteckt – dann ist er nicht so raumgreifend. Ich benötige aktuell ja nur 18 der Eingänge.
  • Rechte Spalte: Der Selector selbst.

Was sich hinter den rätselhaften Symbolen verbirgt, werden wir im folgenden erforschen.

[03]

Vom Schreiben und Lesen

Bevor wir uns anschauen, was mit den Minimum-, dem Maximum- und Reglerwerten passiert, die die Core-Cell scheinbar nur links oben betreten und rechts oben schon wieder verlassen, müssen wir uns mit dem Schreiben und Lesen von Daten in Core beschäftigen. Und das ist meines Erachtens nicht besonders intuitiv gelöst. für die folgenden Erklärungen habe ich die entsprechenden Module markiert und in grün beschriftet.

Abb. 3: Vom Schreiben und Lesen

Dreh- und Angelpunkt des Selectors ist das Array-Element. In der Function-Spalte links könnt ihr sehen, dass das Array in diesem Fall Floatingpoint-Variablen (im Weiteren: Floats) speichert, mit 32 Bit Präzision arbeitet (Default = 32 Bit) und über 32 Speicherplätze gebietet.

Der Array-Speicher wird Stimmenabhängig zugewiesen. Ein Array mit 1024 Floats in einer 16-stimmigen Reaktor-Konfiguration benötigt demnach 16*1024=16384 Floats. Da jedes Float 4 Bytes benötigt, entspräche das in Summe 64 KBytes. Für heutige Verhältnisse also nichts dramatisches.

Das Array ist über eine OBC-Verbindung (die braunen Leitungen > s. Core-Intro) mit den folgenden 32 Write-Macros und schlussendlich mit dem Read-Macro (rechts oben) verbunden. Alle Elemente, die an der selben OBC-Leitung hängen, teilen sich den selben Speicher. In diesem Fall das Array.
Am linken Rand der Core-Cell findet ihr neben den IN-Ports für Minimum, Maximum und Regler, die IN-Ports für die Daten, die ich (passend zu den 4 Write-Macros/Zeile) in 4er-Blöcke aufgeteilt habe. Die Einteilung der Write-Macro-Kette in jeweils 4 Macros/Zeile dient lediglich der Übersicht und der sinnvollen Darstellung in diesem Tutorial. Ihr könnt die Write-Macros anordnen, wie ihr mögt.

Alles, was zwischen den IN-Ports und dem Read-Macro liegt, reagiert sofort auf Veränderungen. Wenn ihr z. B. das Tutorial (Download unten auf dieser Seite) in Reaktor öffnet, den POS-Regler ganz nach links dreht (Index 0) und am ersten Dateneingang des Primary-Macros (00) z. B. den Wert „1024“ eintragt, wird dieser sofort im OUT-Zahlenfeld angezeigt. Was ist hier passiert?

Um das zu verstehen, müssen wir uns das Write-Macro näher anschauen:

  • Das Write-Macro erhält den zu schreibenden Wert über den oberen Eingang (weiß/rund = Scalar, Float). Aus Gründen der Übersichtlichkeit habe ich die Kabelverbindungen zwischen den IN-Ports und den Write-Macros durch einen Quick-Bus (s. hier) ersetzt. Der IN-Port mit dem Quickbus „0“ ist also mit dem Eingang „0“ des ersten Write-Macros verbunden, der IN-Port mit dem Quickbus „1“ mit dem Eingang „1“ des zweiten Write-Macros, usw.
  • Am darunter liegenen Eingang des Write-Macros (blau/eckig = Scalar/Integer) liegt der Index für das Array an, also die Adresse im Array, an der der Wert des oberen Write-Macro-Eingangs abzulegen ist. In diesem Fall die Adresse „0“. Wir erinnern uns: der Index der Primary-Selectoren beginnt ebenfalls bei „0“.
  • Im Inneren des Write-Macros kann man sehen, wie das eigentliche Write-Modul und das Index-Modul zusammenarbeiten, um den zu speichernden Wert zusammen mit seiner Adresse links unten auszugeben. Das „M“ im Ausgangsport steht für „Master“ und greift direkt auf das Array zu.
  • Rechts unten befindet sich der Slave-Ausgang („S“), der die Information einfach durchreicht. So ist es möglich, mehrere OBC-Module in Reihe zu schalten.
  • Das R/W-Order-Modul ist fester Bestandteil der Write-/Read-Macros und koordiniert die Reihenfolge der OBC-Signale am Slave-Ausgang. Ist es nicht vorhanden, kann das zu Problemen führen.

Fazit: Zu jedem der 32 Daten-IN-Ports existiert ein Write-Macro, dass dessen Werte ständig aufnimmt und mit dem korrekten Index versehen im Array ablegt. Da vom Array, über die Write-Macros bis hin zum Read-Macro am Ende, eine durchgehende OBC-Verbindung besteht, kann das Read-Macro letztendlich auf jede der 32 Speicherzellen des Arrays zugreifen.

[04]

Und sonst so …

Letzte Runde in diesem Tutorial: Jetzt schauen wir uns an, wie die ankommenden Daten für Minimum, Maximum und Pos-Regler verarbeitet und aufgrund dessen der korrekte Wert aus dem Array ausgelesen wird.

Abb. 4: Ein- und Ausgabe

Eingabe:

Beginnen wir direkt am Eingang der Core-Cell: Die Werte für Minimum, Maximum und Pos-Regler landen zunächst in einem „Clip MinMax„-Macro, in dem geprüft wird, ob die gewählte Regler-Position innerhalb der Grenzwerte liegt. Dazu durchlaufen die Werte eine Schaltung aus Compare- und Router-Modulen und zwei Latch-Macros, in denen eine Variable zwischengespeichert werden kann.

Klären wir zuerst die Funktionsweise der Einzelnen Elemente:

  • Compare-Module vergleichen die beiden Eingangswerte und geben im Fall von „True“ eine „1“ und im Fall von „False“ eine „0“ aus, mit denen ein nachfolgender Router gesteuert wird.
  • Router-Module leiten den Eingangswert bei „TRUE“ an den oberen, bei „False“ an den unteren Ausgang weiter.
  • In den Latch-Macros befindet sich links oben ein Write- und recht unten ein Read-Module. Beide sind via OBC verbunden, beschreiben und lesen als die selbe Speicherzelle. An dieser Stelle müssen wir einen signifikanten Unterschied zwischen Write- und Read-Modulen ansprechen:
    • Aus dem vorangegangenen Abschnitt wisst ihr, dass das Write-Modul am oberen Eingang den zu schreibenen Wert erhält.
    • Nun hat das Read-Module auch einen oberen Eingang, der aber eine ganz anderer Funktion hat – zu schreiben gibt es hier ja nichts. Der obere Eingang wird in diesem Fall als Trigger benutzt, um das Read-Module zu veranlassen, den gespeicherten Wert an seinem oberen Ausgang auszugeben. Kein Trigger, keine Daten am Ausgang.
    • Ein Latch-Macro ist also eine Speicherzelle, die mit einem anliegenden Wert beschrieben und mit einem Triggersignal wieder ausgelesen werden kann.

Was passiert nun genau im Clip MinMax Macro:

  • Das erste Compare-Modul vergleicht den Regler (POS) mit dem Maximalwert (MAX).
    • Ist POS > MAX, also ausserhalb der definierten Grenze, wird das POS-Signal benutzt, um das untere Latch-Modul zur Ausgabe von MAX zu bewegen.
    • Ist POS < MAX, also im „grünen Bereich“, geht POS via diesem Router sowohl zum nächsten Compare-Modul, als auch zu dem anderen Router.
  • Das zweite Compare-Modul vergleicht nun POS (aus dem ersten Router) mit dem bereits anliegenden MIN.
    • Ist MIN > POS, wird POS verwendet, das obere Latch-Modul zu triggern, das dann den MIN-Wert ausgibt.
    • Ist POS > MIN, also immer noch im „grünen Bereich“, wird POS zum Merger weitergeleitet.
  • Alle drei Werte laufen im Merger zusammen, so dass dieser am Ausgang entweder einen gültigen POS-Wert oder ersatzweise die Untergrenze (MIN) oder die Obergrenze (MAX) ausgibt.

Wichtig: Das Merge-Module ist kein Addierer! Laufen mehrere Werte durch den Merger, liegt am Ausgang keine Summe an, sondern der zuletzt angekommene Wert!

Ausgabe:

Im Read-Macro (rechts oben) finden wir das Gegenstück zu dem, was wir im Abschnitt zuvor in den Write-Macros gesehen haben. Der einzige Unterschied besteht – wie bereits erwähnt – darin, dass Read-Module anstatt eines Daten-Eingangs einen Trigger-Eingang haben, mit dem der Lesevorgang initiiert wird. Da hier aber kein valides Triggersignal zur Hand ist, bedienen wir uns eines Core-internen Clock-Buses. Core kennt derer zwei: SR und CR. SR steht für Sampling Rate, CR für Control Rate. In unserem Fall verwenden wir die SR-Clock, um das Read-Macro mit der aktuellen Samplerate zu triggern.
Jetzt braucht das Read-Module nur noch die Adresse (Index) im Array, mit dem es ja über die OBC-Leitung verbunden ist. Dieser Index wird vom Clip MinMax Macro geliefert. Fertig!

Kurzversion: Alle Werte am Selector-Eingang werden in einem Array gespeichert und in Abhängigkeit des POS-Reglers am Ausgang zur Verfügung gestellt. Eben wir ein gängiges Selector-Modul der Primary-Ebene.

 

[05]

Downloads

g

16+-Selector

Mit Interface in der Primary
.ens-Datei, (Zip-File, 9KB)

g

16+-Selector

Core-Cell only
.rcc-Datei, (Zip-File, 6KB)

Kontakt

Bernd Scheurer
Mainstraße 2
64390 Erzhausen
Fon: 06150 865902
Mobil: 0151 50411034
unterricht@bernd-scheurer.de

Freie Plätze

  • Erzhausen
  • Langen
    • Zur Zeit keine Plätze eingeplant.

Infos

Auch interessant

Newsticker

amazona

tastenwelt

klassik heute

jazz thing

  • Be happy
    Source: jazz thing Published on 2011-07-19 By Lili Lameng
  • Der Jazzmusiker ein Feinschmecker?
    Source: jazz thing Published on 2011-06-06 By Anke Helfrich
  • Glamourfaktor
    Source: jazz thing Published on 2011-04-21 By André Nendza
  • Style
    Source: jazz thing Published on 2011-04-09 By Lorenz Hargassner
  • Topsannah
    Source: jazz thing Published on 2011-03-14 By Lili Lameng

musikexpress