Dank leistungsfähiger Software-Frameworks und Bibliotheken ist es heute möglich, auch mit einem kleinen und günstigen System komplexe Funktionen umzusetzen. Im ersten Teil der MiniPhonic-Artikelserie haben wir das Blockdiagramm und die Hauptfunktionen der Basic Synth-Software vorgestellt. Hier schließen wir mit der Beschreibung der Sequencer-Anwendung und Firmware ab und werfen einen Blick auf die Hardware der Hauptplatine und der Display-Platine, inklusive Montageanleitung und Bauteilliste. Los geht’s!

Sequence

Diese Anwendung basiert ebenfalls auf Tim Barras’ Mozzi-Bibliothek und nutzt eine angepasste Version von Staffan Melins OscPocketO-Software, die es erlaubt, einige Parameter in Echtzeit zu verändern. Das Blockdiagramm der Sequence-Anwendung zeigt Bild 1. Die Hauptfunktionen sind:

 

  • 16-Noten-Sequencer mit 4 Patterns, erweiterbar bei Bedarf, mit MIDI OUT Ausgang
  • Sequenzen werden in alphanumerischer Musiknotation dargestellt (z. B. C, C#, D…)
  • Zwei Wavetable-Oszillatoren DCO1 und DCO2 mit fünf austauschbaren Wellenformen
  • Zweiter Oszillator mit Detune und Transpose
  • Hüllkurvengenerator mit vier Parametern: ATTACK, DECAY, SUSTAIN LEVEL und RELEASE, steuerbar in Echtzeit über Potis
  • Tiefpassfilter mit einstellbarer Frequenz und Resonanz
  • Filtermodulationsgenerator mit wählbaren Parametern: Slow, Fast und Random
  • 4 abrufbare Panels, bei Bedarf erweiterbar
  • Möglichkeit, ein externes Keyboard über MIDI IN anzuschließen und in Echtzeit zu spielen

 

Das Hauptmodul dieser Anwendung ist der SEQUENCER. Damit können Notenfolgen erzeugt werden, die zyklisch wiederholt werden. Sie werden auf 4 Patterns mit je 16 Noten gespeichert und liegen im EEPROM, also dauerhaft.

Figure 1: Block diagram of the Sequence application. MiniPhonic article
Bild 1: Blockschaltbild der Sequence-Anwendung.

Für jede Note lassen sich sowohl die Tonhöhe – also die entsprechende MIDI-Notennummer – als auch ihr Zustand individuell festlegen:
STATE_OFF schaltet die Note stumm und erzeugt somit eine Pause,
STATE_ON spielt die Note mit normaler Lautstärke,
STATE_BOLD spielt sie akzentuiert.

Darüber hinaus kann das gesamte Pattern transponiert werden – nach oben oder unten –, um es an die gewünschte Tonart anzupassen, ohne jede einzelne Note ändern zu müssen. Der Sequencer verfügt zudem über einen SYNC-Ein- und Ausgang, wodurch sich ein oder mehrere Synthesizer parallel betreiben lassen.

Der Sequencer steuert die beiden Oszillatoren DCO1 und DCO2, wobei diese auch direkt MIDI-Daten verarbeiten können – so ist auch ein Echtzeitspiel unabhängig vom Sequencer möglich. Mit den Tasten MNU+ und MNU– gelangt man in die Menüs.

Sehen wir uns das im Detail an:

SEQUENCE: Durch Betätigen der Tasten VAL+ und VAL– wird der Sequencer gestartet bzw. gestoppt.

SYNC: Aktiviert die Synchronisation, die intern oder extern über den entsprechenden Anschluss erfolgen kann. Das Element EXT24 dient zur Synchronisation des Sequencers mit 24 ppq (Pulses per Quarter Note; maximal 140 bpm).

PATTERN: Mit VAL+ und VAL– lässt sich eines der vier verfügbaren Pattern auswählen.

ED pat: Ermöglicht das Bearbeiten des Pattern; mit den Tasten LEFT und RGHT navigiert man durch die Noten, mit VAL+ und VAL– wird die jeweilige Note geändert. Die Darstellung erfolgt alphanumerisch auf der dritten Displayzeile gemäß internationalem Standard: C, C’ (Cis), D, D’ (Dis), E, F, F’ (Fis), G, G’ (Gis), A, A’ (Ais), B. Die darunterstehende Zahl zeigt die Oktave, in der die Note klingt.

STATE: Zeigt den Zustand jeder Note; die Navigation erfolgt wieder mit LEFT und RGHT, die Änderung mit VAL+ und VAL–.

  • – = stumm
  • O = Note wird normal gespielt
  • B = akzentuierte Note

TEMPO: Metronom, ausgedrückt in bpm.

GATE: Notenlänge in Prozent; z. B. bedeutet ein Wert von 30, dass die Note 30 % der Zeit erklingt, gefolgt von 70 % Pause.

SH pat: Verschiebt das komplette Pattern mit VAL+ und VAL– jeweils um einen Halbton nach oben oder unten.

WAVEFORM: Über die Tasten VAL+ und VAL– lässt sich eine von fünf Wellenformen für DCO1 auswählen: Sin = Sinus, Tr = Dreieck, Saw = Sägezahn, Square = Rechteck sowie eine untypische namens Phasor.

FILTER mode: Auch hier kann mit VAL+ und VAL– zwischen verschiedenen Betriebsmodi des Filters umgeschaltet werden:

Fixed: Die Cutoff-Frequenz des DCF (gMFilterCutoff) wird über ein Potentiometer gesteuert.

Random: Die Frequenz ändert sich zufällig, die Geschwindigkeit bestimmt MG1.

Man.Mod: Eine Dreiecksmodulation wird angewendet, deren Geschwindigkeit ebenfalls über MG1 geregelt wird.

Fast: Wie Man.Mod, jedoch mit fester Geschwindigkeit.

MG1 wird über das Panel „mixer“ im Eintrag FRM1 eingestellt.

WAVEFORM2: Erlaubt über VAL+ und VAL– die Auswahl einer von fünf Wellenformen für DCO2: Sinus, Dreieck, Sägezahn, Rechteck und die untypische Phasor.

DETUNE2: Über VAL+ und VAL– kann die Frequenz von DCO2 leicht verstimmt werden. Ein Wert von 2 erzeugt einen deutlich hörbaren Chorus-Effekt.

TRANSPOSE2: Mit VAL+ und VAL– lässt sich DCO2 relativ zur MIDI-Notennummer transponieren.

KEY PLAY: Gibt die ersten vier Noten des aktuellen Patterns sofort wieder, wenn die vier Tasten LEFT, VAL–, VAL+ und RGHT gedrückt werden. Die jeweilige MIDI-Notennummer ist oberhalb der Taste angegeben. Besonders praktisch zum Testen von Sounds oder für Echtzeitspiel – auch ohne angeschlossene Tastatur.

TOOLS:

S speichert die aktuelle Konfiguration inklusive der Pattern im nichtflüchtigen Speicher.

L lädt eine zuvor gespeicherte Konfiguration samt Pattern.
R erzeugt eine Zufallssequenz im aktuellen Pattern.

B generiert eine monophone Basslinie (identische Note), bei der alle Noten den Zustand O besitzen – zur einfachen Bearbeitung.

Mit der Funktion P lässt sich erneut zwischen drei Panels umschalten: main, adsr und mixer.

Die Sequencer-Firmware

 

Im Setup (ca. Zeile 1520) befinden sich alle Instrumenteneinstellungen und Initialisierungen. Insbesondere werden hier die Pins konfiguriert und das Display mit folgendem Befehl gestartet:
 

gUILCD.begin(20, 4)

 

Danach werden benutzerdefinierte Zeichen erstellt, die nicht zum Standardzeichensatz des LCD gehören, jedoch zur Anzeige der Pattern benötigt werden:

 

gUILCD.createChar(0, Dodiesis);

gUILCD.createChar(1, Rediesis);

gUILCD.createChar(2, Fadiesis);

gUILCD.createChar(3, Soldiesis);

gUILCD.createChar(4, Ladiesis);

 

Anschließend folgen die Software-Credits, die Versionsnummern sowie die MIDI-Initialisierung – inklusive Anbindung an die MIDI-Bibliothek über HandleNoteOn und NoteOff:

 

// Connect the HandleNoteOn function to the library,

// so it is called upon reception of a NoteOn.

MIDI.setHandleNoteOn(HandleNoteOn);

// Put only the name of the function

MIDI.setHandleNoteOff(HandleNoteOff);

// Put only the name of the function

 

// Initiate MIDI communications, listen to

// all channels

MIDI.begin(MIDI_CHANNEL_OMNI);
 

Mehrere Funktionen für NOTE ON sind vorhanden. Die zentrale Funktion ist playNote(), etwa ab Zeile 420, die vom Sequencer verwendet wird. playNoteOn ist spezifisch für den KEY PLAY-Modus, bei dem die ersten vier Noten des aktuellen Patterns mit den Tasten LEFT, VAL–, VAL+ und RGHT gespielt werden können.

Die Funktion HandleNoteOn() verarbeitet Noteneingaben über die MIDI-IN-Buchse. Natürlich existieren auch entsprechende Funktionen zum Beenden der Note: playNoteOff und HandleNoteOff. Ab Zeile 1570 werden diese Funktionen mit der MIDI-Bibliothek verbunden.

Ab etwa Zeile 1580 folgen alle Einstellungen für die Mozzi-Bibliothek, um die Klangerzeugung direkt zu starten; ab ca. Zeile 1610 folgen die Einstellungen für den Sequencer.

Die Benutzeroberfläche (User Interface Draw) wird etwa bei Zeile 1630 mit der Funktion UIDraw() aufgerufen. Direkt im Anschluss startet die Mozzi-Bibliothek mit dem Befehl: startMozzi(CONTROL_RATE).

Nun betrachten wir die Funktion updateControl() f, die sich ab Zeile 1640 befindet. Hier werden alle Steuerelemente ausgewertet. Direkt danach folgt die MIDI-Port-Abfrage, um etwaige Tastatureingaben zu erfassen:

 

  if(MIDI.read()){

    gMEnvelope.noteOn(); // play from MIDI input

    PanelHandle();     // handle panel

  }

 

Die Funktion PanelHandle()erlaubt das Ändern jener Parameter, die den vier Potentiometern zugewiesen sind – wie bereits beim Basic Synth beschrieben. Darauf folgt ab etwa Zeile 1648 die Sequencer-Engine. Zunächst wird hier die Synchronisation verarbeitet; anschließend prüft das Programm, ob das aktuelle Sechzehntelnotenintervall abgelaufen ist, bevor es zur nächsten Note übergeht.

 

if (gSyncNoteOn) {

    playNote();

    gSyncNoteOn = false;

 

Auch an dieser Stelle kommt erneut die Funktion PanelHandle() zum Einsatz, sodass bei jeder gespielten Note Parameteränderungen vorgenommen werden können. Anschließend wird die nächste Note verarbeitet – solange, bis die maximale Anzahl an Noten erreicht ist; dann springt der Sequencer wieder zur ersten Note zurück.

 

PanelHandle(); // --- Sequence/Mozzi

gSeqNoteIndex++;

if (gSeqNoteIndex >= MAX_NOTES) {

gSeqNoteIndex = 0;

      }

}

 

Anschließend wird die Notenlänge überprüft, und gegebenenfalls werden Note-Off sowie Sync-Out für externe Geräte ausgelöst. Die Hüllkurve wird dabei mit gMEnvelope.update() aktualisiert.

Zu diesem Zeitpunkt wird auch die Benutzeroberfläche abgefragt, ob Tasten gedrückt wurden – ebenfalls über gMEnvelope.update().

Zum Schluss folgt das Audio-Update mit der Funktion updateAudio(). Dies ist die zentrale Funktion für die Klangverarbeitung, wie bereits beim Basic Synth gezeigt. Tatsächlich wird hier per switch-Anweisung:
 

switch(gSeqStatus[gSeqPatternIndex][NIdx])

 

den Wert von gMGain fest – also die Lautstärke der aktuell gespielten Note. Dieser Wert wird anschließend in der SYNTHESIZER CHAIN 2 verwendet (siehe entsprechender Rahmen in diesem Artikel).

Die Schleife, die den Hauptaufruf der Mozzi-Bibliothek über audioHook() enthält, bildet den Abschluss des Programms.

Synthesizer chain 2
Caption

Praktische Umsetzung

Unter Bezugnahme auf die Platinenabbildungen in den Komponentenlisten empfiehlt es sich, den Aufbau mit den SMD-Bauteilen (Surface-Mounted Devices) auf den jeweiligen Lötseiten zu beginnen – am besten mit den passiven Komponenten. Anschließend folgt die Bestückung der bedrahteten Bauteile (TH, Through-Hole) auf der gegenüberliegenden Seite.

Figure 2: Boards arrangement (Main, Display and Arduino) inside the housing of the MiniPhonic synth.
Bild 2. Anordnung der Platinen (Main, Display und Arduino) im Gehäuse des MiniPhonic-Synths.

Es ist empfehlenswert, den MiniPhonic in ein Gehäuse einzubauen – wie im Titelbild dieses Artikels und in Bild 2 gezeigt. Darin erkennt man die Anordnung der Hauptplatine (siehe Schaltbild in Bild 3) sowie der Display-Platine (Bild 4), die über ein Flachbandkabel miteinander verbunden sind.

Figure 3: Schematic diagram of the Main Board.
Bild 3. Schaltbild der Hauptplatine.

IC3 ist ein TDA2822D-Audioverstärker von STMicroelectronics. Sein Ausgang wird sowohl zu den 6,3-mm-Mono-Klinkenbuchsen L und R als auch zur rückseitigen 3,5-mm-Stereo-Kopfhörerbuchse des MiniPhonic-Gehäuses geführt.

Figure 4: Schematic diagram of the Display Board.
Bild 4. Schaltbild der Display-Platine.

Die verwendeten Potentiometer und Drehknöpfe sind handelsübliche Komponenten. Das erste Potentiometer oben links auf dem Foto der Hauptplatine (siehe Textfeld Komponentenliste Hauptplatine) sollte nicht bestückt werden.
 

Besondere Beachtung verdient der SYNC-Anschluss, insbesondere aber die AUDIOBUS-Verbindung, die im Verdrahtungsplan von Bild 5 grün hervorgehoben ist. Wenn mehrere Synthesizer parallel betrieben werden, müssen alle Audiokanäle ebenfalls parallel geschaltet werden. Dabei ist zu beachten, dass sich der Gesamtausgangspegel um 6 dB verringert – bedingt durch die Last der zusätzlich angeschlossenen Synthesizer.

 

Figure 5: Wiring diagram of the Main Board.
Bild 5. Verdrahtungsplan der Hauptplatine.

 

 

Wenn stattdessen ein Mixer verwendet wird (empfohlene Lösung), sollte die AUDIOBUS-Verbindung vom Anschluss getrennt werden – idealerweise über einen Schalter –, sodass jeder Synthesizer über einen eigenen Kanal verfügt. Über denselben SYNC-Anschluss erfolgt auch die Spannungsversorgung über den DC-IN-Eingang, wodurch sich alle Synthesizer mit einem einzigen Netzteil (Steckernetzgerät) betreiben lassen. Dabei ist zu beachten, dass jeder Synthesizer etwa 200 mA Strom aufnimmt.

 

Figure 6: Mixer panel display.
Bild 6. Anzeige des Mixer-Panels.

 

 

Bild 6 zeigt den Namen des aktiven Panels – in diesem Fall „mixer“ – gefolgt von drei Parametern: LEVL_1, LEVL_2 und FRM1 sowie einem Leerfeld. Diese Parameter sind den Potentiometern P1, P2 und P3 zugeordnet; P4 bleibt in diesem Panel ungenutzt. Die Parameter LEVL_1 und LEVL_2 regeln den Pegel der beiden Oszillatoren, während FRM1 die Frequenz von MG1 steuert. Dieses Panel ist Teil des Basic Synth.

 

Figure 7: Main panel display.
Bild 7. Anzeige des Hauptpanels.

Bild 7 zeigt das Hauptpanel mit dem Menü ED PAT. In der dritten Zeile ist die Notenfolge dargestellt, in der vierten die zugehörigen Oktaven. Die erste Note ist ein C in Oktave 0, gefolgt von einem C# (Cis) in derselben Oktave, dann ein D, ebenfalls in Oktave 0, und so weiter. Die Sequenz endet mit einem D# (Dis) in Oktave 1.

 

 

MiniPhonic-Plattform: Abschließende Betrachtung

 

Die MiniPhonic-Plattform eignet sich nicht nur für den Aufbau kompakter Synthesizer und zum Erlernen der Grundlagen der Klangerzeugung und des MIDI-Protokolls, sondern bietet auch vielfältiges Potenzial für weiterführende Entwicklungen.

So ist der SYNC-Anschluss darauf ausgelegt, die Signale SDI, SDO, SCK und SS nach außen zu führen – für einen SPI-Datenstrom. Dieser ließe sich als Träger für mehrkanalige Audiosignale und zugehörige Steuersignale verwenden, um externe Komponenten wie analoge VCFs, VCAs und andere Geräte anzubinden.

Dank der Leistung des ARM-Prozessors könnte der Basic Synth beispielsweise zu einem dreistimmigen polyphonen System erweitert werden – bei Beibehaltung der bestehenden Struktur. Die beschriebenen Anwendungen sind offen für Weiterentwicklungen und Optimierungen, mit dem Ziel, das volle Potenzial des ARM-Prozessors auszuschöpfen.

 

Miniphonic project
MiniPhonic – Arduino-basierte Plattform zur Klangerzeugung

 

 

Erwähnenswert ist an dieser Stelle der Filter, der ursprünglich für den Arduino UNO R3 konzipiert wurde – das schwächste Glied der Kette. Wird RESONANCE auf Maximum gestellt, neigt der Filter zur Instabilität und beginnt zu schwingen, was erhebliche Verzerrungen verursacht. Nach unserer Einschätzung sollte dieses Bauteil als erstes überarbeitet werden. Dennoch gebührt dem Entwickler der aktuellen Version Anerkennung: Dass das gesamte System überhaupt auf einem Arduino UNO R3 lauffähig ist, ist eine beachtliche Leistung!

 

 

Components 1
MiniPhonic component List (Main Board)
Components 2
MiniPhonic-Komponentenliste (Display-Platine)​

Das vollständige Softwarepaket zum MiniPhonic-Projekt steht auf der entsprechenden Projektseite bei Elektor Labs zum Download bereit.


Fragen zum MiniPhonic-Projekt?

Sie haben technische Fragen oder Anmerkungen zum MiniPhonic-Projekt oder zu diesem Artikel? Dann schreiben Sie gerne an die Redaktion von Elektor: redaktion@elektor.com


Redaktioneller Hinweis: Das Projekt zur MiniPhonic-Audio-Syntheseplattform wurde ursprünglich in der Zeitschrift  Elettronica IN veröffentlicht.

 elettronica in logo.png

Abonnieren
Tag-Benachrichtigung zu Arduino jetzt abonnieren!