Dank leistungsstarker Software-Frameworks und Bibliotheken, die im Laufe der Zeit entwickelt wurden, ist es möglich, selbst mit einem kompakten und kostengünstigen System komplexe Funktionen zu realisieren. In diesem Projekt verwenden wir ein Arduino Uno R4 Board sowie weitere Hardware, um einen vielseitigen und leistungsstarken Sound-Synthesizer und MIDI-Sequenzer zu entwickeln. Im ersten Teil dieser Serie zur Audioklangerzeugung erläutern wir das Blockdiagramm und die Hauptfunktionen der Basic Synth-Software.

Audio-Synthese-Plattform  

Einige von Ihnen erinnern sich vielleicht an den SN76477, den bekannten Klanggenerator von Texas Instruments. Er stammt aus den 1970er Jahren und ermöglichte die Erzeugung verschiedener Klänge wie Schussgeräuschen, Dampflokomotiven, Weltraumgeräuschen und vielem mehr, einschließlich kleiner musikalischer Synthesizer.

Besonders ansprechend war diese letzte Funktion. Seit einiger Zeit hatte ich den Wunsch, einen kleinen Sound-Synthesizer zu bauen, als ich zufällig auf die beeindruckende Mozzi-Bibliothek von Tim Barras stieß. Diese ermöglicht es, Synthesizer und Drum Machines ganz einfach mit einem Arduino Uno R4 Minima Board und einigen weiteren Komponenten zu realisieren.

Miniphonic Arduino-based audio synthesis platform

Nicht nur das, auf dem Weg habe ich auch die OscPocketO-Software von Staffan Melin entdeckt, einen nützlichen Sequencer, der auf der Mozzi-Bibliothek basiert. Daher wurde entschieden, den alten SN76477 zugunsten dieser neuen Lösung aufzugeben und die MiniPhonic Audio Synthesis Platform zu entwickeln – eine Hardware-Sound-Synthese-Plattform mit folgenden Hauptmerkmalen:

  • LCD, 20x4
  • 4 programmierbare Potentiometer zur Echtzeitänderung von Parametern Ein-/Ausgang zur Synchronisation mit einem anderen Synthesizer
  • MIDI Ein-/Ausgang
  • Monitorverstärker für Kopfhörer
  • 4-poliger Tiefpassfilter für den On-Chip-DAC
  • Gehäuse für Arduino Uno R4

Die Audio-Synthese-Plattform besteht aus zwei Leiterplatten: der Hauptplatine und der Anzeigeplatine, die durch ein 14-poliges Flachkabel verbunden sind. Bild 1 zeigt das Blockdiagramm des Synthesizers, das hilfreich ist, um den Betrieb zu verstehen und den Audiostream nachzuvollziehen. Dieser liegt zunächst im digitalen Format vor und wird dann über einen 12-Bit-DAC (Digital-Analog-Wandler) auf dem Chip in ein analoges Signal umgewandelt, das mit dem Tiefpassfilter LPF verbunden ist.

Figure 1: Block diagram of the Miniphonic synthesizer.

Am Ausgang dieses Filters befindet sich ein Entkopplungswiderstand. Dieser ermöglicht es, Audiosignale von anderen Synthesizern über den Insert-Anschluss einzuspeisen. Der Anschluss erlaubt das Einfügen eines externen Effektprozessors, wie beispielsweise eines Hallgeräts. Externe Effektprozessoren haben häufig einen Stereoausgang, weshalb der Lautstärkeregler und der Monitorverstärker in Stereo ausgelegt sind. Auf der Hauptplatine ist es jedoch möglich, die Insert-Pins zu überbrücken, um die gesamte Audiokette im Monomodus zu konfigurieren. Dazu müssen die Pads SJ3 und SJ4 auf der Platine einfach mit einem Tropfen Lötzinn kurzgeschlossen werden (dargestellt im nächsten Teil dieses Artikels).

Die Line-Ausgänge OUT L und OUT R sind ebenfalls mit dem Monitorverstärker verbunden. Die Plattform bietet zwei Hauptfunktionen:

  • Basic Synth: Ein einfacher monophoner Synthesizer, der den MIDI-Eingang nutzt, um eine Standardtastatur zu verbinden und in Echtzeit zu spielen.  
  • Sequence: Als eigenständiger Sequencer konzipiert, mit der Fähigkeit, andere Synthesizer über den SYNC- oder MIDI OUT-Anschluss anzusteuern.

Diese Anwendungen können auf der Elektor Labs-Seite für dieses Project heruntergeladen werden. Lassen Sie uns die erste Anwendung im Detail betrachten.

Basic Synth

Das Blockdiagramm der Basic Synth-Anwendung, wie in Bild 2 gezeigt, folgt der klassischen Struktur eines Synthesizers. Es basiert auf einer Softwarearchitektur, die als Synthesizer-Kette (siehe den nahegelegenen Textrahmen) bezeichnet wird und etwa ab Zeile 920 im Code zu finden ist.

Bild 2: Blockdiagramm der Basic Synth-Anwendung.

Im Detail multipliziert die Operation gMOscillator.next() * Lv1 >> 4 die von dem DCO1 oscillator gMOscillator.next() erzeugten Samples mit dem Wert von Lv1, der entsprechend durch den >> 4 Operator skaliert wird. Diese Operation simuliert die Funktion eines Lautstärkepotentiometers, wobei das Signal durch gMOscillator.next()dargestellt wird und Lv1 die Winkelposition des Potentiometers angibt. Dieselbe Operation wird auch für den zweiten Oszillator, DCO2, angewendet.

Die Synthesizer-Kette

Ein weiterer Block im Schaltplan ist der Mixer (MIX). Er funktioniert mit dem + (Summe)-Operator, der die Samples der beiden Oszillatoren addiert. Der DCA (Digital Controlled Amplifier)-Block wird umgesetzt, indem die Summe der beiden Oszillatoren mit der Variablen gMGain multipliziert wird. Diese wird dynamisch durch gMEnvelope.next() aktualisiert. Diese Komponente ist ein ADSR-Hüllkurvengenerator.

Es ist wichtig, die .next-Mitglieder zu berücksichtigen, die die Proben der Audio- oder Steuerströme darstellen. Im Blockdiagramm fällt die ungewöhnliche Position des DCF auf, das nach dem DCA angeordnet ist, anstatt davor; dies liegt am numerischen Format des Audiostreams, das besser zum DCF passt, das ursprünglich für den Arduino Uno R3 entwickelt wurde. Idealerweise sollten die Bibliotheken in einem Format neu geschrieben werden, das für den Arduino Uno R4 geeignet ist, um die Funktionen des Arm Cortex4 RA4M1 Prozessors optimal zu nutzen, der zudem über einen zusätzlichen DSP-Befehlssatz verfügt.

Im Blockdiagramm ist ersichtlich, dass der MIDI-Eingang nicht nur mit DCO1 und DCO2 verbunden ist – um Notencodes zu übertragen und die Oszillatorfrequenz anhand der MIDI-Notennummer zu bestimmen – sondern auch mit dem ADSR-Hüllkurvengenerator. Letzterer nutzt die Note On- und Note Off-Codes, um einen Hüllkurvenzyklus beim Aktivieren oder Loslassen einer Note zu starten. Notencodes können auch vom DCF verwendet werden, um seine Grenzfrequenz durch Aktivierung des manuellen KBD-Tracking-Modus zu verändern. So fungiert das DCF als echtes Tracking-Filter. MG im Blockdiagramm steht für Modulationsgenerator.


Abonnieren
Tag-Benachrichtigung zu Arduino jetzt abonnieren!

User Interface

Betrachten wir nun, wie die Benutzeroberfläche für diese Audio-Synthese-Plattformanwendung eingerichtet wurde. Das Display ist in zwei Abschnitte unterteilt: Die ersten beiden Zeilen zeigen die Bezeichnungen der vier Potentiometer an, die das aktuelle Panel darstellen.


Four Panels are available accessible through the Tools menu, which will be described later. The menus can be reached via the appropriate MNU+ and MNU- buttons, while instead the LEFT and RGHT buttons select a submenu. VAL+ and VAL-, on the other hand, allow parameters to be changed.

Es stehen vier Panels zur Verfügung: PANEL_MAIN, PANEL_ADSR, PANEL_MIXER and PANEL_FILTER. Diese sind über das Menü Tools zugänglich, das später näher erläutert wird. Die Menüs können mit den Tasten MNU+ und MNU- aufgerufen werden, während die Tasten LEFT und RGHT zur Auswahl eines Untermenüs dienen. Parameter können mit VAL+ und VAL- geändert werden.

Lassen Sie uns die Optionen im Hauptmenü näher betrachten:

WAVEFORM: In diesem Menü können Sie mit VAL+ und VAL- aus fünf Wellenformen für den DCO1-Oszillator wählen: Sine, Triangular, Sawtooth, Square und eine besondere Form namens Phasor.

FILTER- Modus: Mit VAL+ und VAL- können wir den Betriebsmodus des Filters ändern. Zur Auswahl stehen das Manual KBD Tracking, bei der die gMFilterCutoff-Frequenz des DCF durch die MIDI-Notennummer angepasst wird, Random MG1, bei der die Frequenz zufällig und mit einer von MG1 festgelegten Geschwindigkeit verändert wird, Mod MG1 , bei dem eine modulierte Dreieckswelle mit einer konstanten Geschwindigkeit von MG1 angewendet wird, sowie Fast, ähnlich dem vorherigen Modus, jedoch mit fester Geschwindigkeit.

WAVEFORM2: Bietet die gleiche Funktionalität wie WAVEFORM, wirkt jedoch auf den zweiten Oszillator DCO2.

DETUNE 2:  Feineinstellung des DCO2-Oszillators (VAL+ und VAL-). Ein Wert zwischen 1 und 2 verändert die Frequenz von DCO2 leicht, um einen Chorus-Effekt mit DCO1 zu erzeugen.

TRANSPOSE 2: Transposition von DCO2, erneut unter Verwendung von VAL+ und VAL-.

TOOLS: Aus diesem Menü können Sie zwischen den Untermenüs Save, um das gesamte Synthesizer-Setting zu sichern, Load , um das Setting zu laden, und Panel , in dem die Panels zugänglich sind, wählen. Die Untermenüs werden mit den Tasten LEFT und RGHT ausgewählt.


Im PANEL_MAIN finden wir:

 

  • FREQ ATTACK
  • RESO RELEAS

 

FREQ und RESO beziehen sich auf die Grenzfrequenz und Resonanz des Filters, während ATTACK und RELEAS zur ADSR-Hüllkurve gehören, also zur Anstiegs- und Abklingzeit. Im PANEL_ADSR finden wir hingegen alle vier Parameter der ADSR. Insbesondere ermöglichen uns die Parameter SUST_LEV und DECAY das Erzeugen perkussiver Klänge.

 

  • ATTACK DECAY
  • SUST_LEV REL

 

Vom PANEL_MIXER aus können wir die Pegel der beiden Oszillatoren sowie die Frequenz des Modulationsgenerators MG1 über FRM1 einstellen.

 

LEVL_1 FRM1

LEVL_2 ----

 

Es ist auch möglich, die Anzahl der Panels zu erhöhen, indem die Funktion DrawPanel() im Code angepasst wird.

The Firmware Basic Synth

In der Setup-Phase (ungefähr Zeile 806) sind alle Instrumenteneinstellungen und Initialisierungen zu finden. Zunächst wird das Display mit gUILCD.begin(20, 4) eingerichtet. Anschließend werden die Credits und die Versionsnummer der Software sowie die MIDI-Initialisierung dargestellt. Danach folgen die Verbindungen zur MIDI-Bibliothek für HandleNoteOn und HandleNoteOff sowie der Start der MIDI-Bibliothek im MODUS MIDI_CHANNEL_OMNI, der alle MIDI-Kanäle von 1 bis 16 empfängt.

// 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);

Die Funktion HandleNoteOn wird von der an den MIDI IN-Port angeschlossenen Tastatur genutzt und spielt eine Note, sobald die NoteOn -Nachricht empfangen wird. Diese Note bleibt aktiv, bis die NoteOff -Nachricht empfangen wird oder bis die gMSustainTime abgelaufen ist, was über die Funktion HandleNoteOff geregelt wird.

Abonnieren
Tag-Benachrichtigung zu Synthesizer jetzt abonnieren!

Ab Zeile 834 folgen alle Anweisungen der Mozzi-Bibliothek, sodass der Synthesizer sofort mit dem Spielen beginnen kann. Die Benutzeroberfläche (User Interface Draw) wird etwa ab Zeile 868 gestartet, und unmittelbar danach wird die Mozzi-Bibliothek initialisiert.

UIDraw();

startMozzi(CONTROL_RATE)
 

In der Funktion updateControl() wird der MIDI-Port über MIDI.read() abgefragt, die Hüllkurve mit gMEnvelope.update() aktualisiert und die Tasten über die Funktion UIHandle()gesteuert.
 

Anschließend wird der STEP RANDOM GENERATOR oder MG1 aktiviert, der für die Erzeugung einer zufälligen Datenfolge sowie einer Dreieckswelle zuständig ist, was zu RndAcc und MG1acc führt.

Beide Werte werden später zur Modulation des Filters eingesetzt. Die Frequenz wird durch den Modulationsgenerator MG1 festgelegt, dessen Wert über den Potentiometer FRM1 im dritten Menüfeld gesteuert wird. Es ist wichtig zu beachten, dass diese Frequenz proportional zur CONTROL_RATE ist, die bereits in der Funktion StartMozzi eingeführt wurde.

Es gibt außerdem einen zweiten Modulationsgenerator, MG2, der mit dem ersten kombiniert werden kann, um zusätzliche Modulationsmöglichkeiten zu bieten. Die Funktion updateAudio() aktualisiert schließlich den Audiostream. Diese Funktion ist entscheidend, da sie die Verarbeitung des Audiostreams umfasst, also die Synthesizerkette, die wir zu Beginn betrachtet haben. Sie schließt die Schleife ab, die den Hauptaufruf an die Mozzi-Bibliothek audioHook() beinhaltet.


Die Klangsynthese, kurz gefasst

Der Klang wird hauptsächlich durch die Frequenz bestimmt – die Anzahl der Schwingungen pro Sekunde – und wird in Hertz (Hz) gemessen. Zum Beispiel bedeutet 100 Hz, dass es 100 Schwingungen pro Sekunde gibt (Bild A). Im Fall einer Saite bedeutet dies, dass sie sich 100 Mal pro Sekunde bewegt.

Bild A

Liegt die Frequenz bei 440 Hz, spielen wir ein A. Sinkt die Frequenz auf 220 Hz, spielen wir ebenfalls ein A, jedoch eine Oktave tiefer. 880 Hz entsprechen einem A eine Oktave höher. Zudem wird der Klang durch die Klangfarbe geprägt, also durch den harmonischen Gehalt, der es uns ermöglicht, verschiedene Klänge zu unterscheiden, wie den einer Jazzgitarre mit wenigen Harmoniken im Vergleich zu einem verzerrten Klang mit vielen Harmoniken.

Wenn ein Klang keine Harmoniken hat, wird er als Sinuswelle bezeichnet und ist ein pure tone, wie in Bild A gezeigt. Wenn Harmoniken vorhanden sind, wird die Wellenform viel komplexer. Harmoniken sind Töne, die man fundamental nennt. Sie legen sich über den Grundton, der die Frequenz des Klangs bestimmt. Diese Töne können doppelte, dreifache Frequenzen usw. haben und werden als zweite Harmonische, dritte Harmonische usw. bezeichnet. Ein Beispiel ist eine Rechteckwelle, die durch die erste Harmonische gekennzeichnet ist und die überlagerten dritten, fünften, siebten Harmonischen usw. in ungerader Reihenfolge und mit abnehmender Lautstärke enthält.

Bild B

Die Rechteckwelle hat einen eher rauen Klang. Wenn jedoch gerade Harmonische hinzukommen, wird die Wellenform asymmetrisch, ähnlich wie bei einer Rampen- oder Sägezahnwelle, die angenehmer klingt. Synthesizer-Oszillatoren können normalerweise grundlegende Wellenformen wie SINUSOIDAL, RAMP, SQUARE and TRIANGULAR erzeugen (Bild B). Es gibt aber auch Oszillatoren, die viel komplexere Wellenformen erzeugen können, sogar solche, die von echten Instrumenten gesampelt wurden. Diese nennt man Wavetables-Oszillatoren und sie werden in unserem Synthesizer verwendet.

Bild C

Es ist auch möglich, zwei Oszillatoren zu nutzen, wobei der zweite um eine Quinte (7 Halbtöne) oder eine Oktave (12 Halbtöne) höher gestimmt wird. Das erzeugt besonders reiche Klänge. Ein weiterer wichtiger Teil ist der DCF, der in Bild C zu sehen ist. Das steht für den digital gesteuerten Filter, der den harmonischen Gehalt unseres Tons dynamisch verändern kann.

Bild D

In der Regel ist das ein Tiefpassfilter mit Resonanz. Das bedeutet, dass der Filter nur Frequenzen unterhalb einer einstellbaren Grenzfrequenz durchlässt (siehe Bild D). Diese Einstellung kann man zum Beispiel mit einem AR (Attack Release) Hüllkurvengenerator oder einem MG (Modulationsgenerator) in unserem Synthesizer verändern.

Der RESONANCE- Parameter erzeugt im Filter einen Resonanzgipfel (Bild E). Seine Amplitude kann über einen Potentiometer angepasst werden, und er lässt sich offensichtlich in der Frequenz verschieben, wobei er mit der CUTOFF FREQUENCY zusammenhängt.

Bild E

Ein weiterer wichtiger Aspekt des Schalls ist die Amplitude. Das bedeutet, wie stark die Schwingung ist. Die Amplitude kann zum Beispiel durch das Erhöhen und Senken der Lautstärke verändert werden. Besonders interessant ist, wie sich die Amplitude über die Zeit verändert. Zum Beispiel erzeugt eine Flöte einen Klang, der nicht sofort seinen höchsten Punkt erreicht, sondern nach einer gewissen Zeit allmählich ansteigt. Diese Zeit nennt man ATTACK.

Bild F

Bei Saiteninstrumenten bleibt der Klang lange nach dem Zupfen der Saite hörbar, ganz allmählich wird er leiser. Der Moment, in dem der Klang aufhört, wird als RELEASE bezeichnet. Der ENVELOPE GENERATOR, übernimmt zusammen mit dem Amplitudenmodulator (in diesem Fall der DCA oder Digital Controlled Amplifier in Bild F) die Manipulation des Klangs über die Parameter ATTACK und RELEASE (Bild G).

Bild G

Der ATTACK-Parameter, der in Bild H rot markiert ist, regelt die Amplitude des Audiosignals von null bis maximal. Die Zeitspanne dafür kann je nach Position des Potentiometers kurz oder lang sein.

Bild H

Um einen besseren Klang zu erreichen, wäre es sinnvoll, einen fortschrittlicheren Hüllkurvengenerator namens ADSR zu nutzen, wie er in unserem Synthesizer eingebaut ist. Dieser hat zwei zusätzliche Einstellungen im Vergleich zum AR-Generator: die DECADE- oder DECAY-Zeit und das SUSTAIN- oder SUSTAIN LEVEL (Bild I).

Bild I

Dieser Hüllkurvengenerator hilft uns, den Klang einer gezupften Saite gut nachzustellen, wie zum Beispiel den einer Cembalo oder Gitarre. Um das zu testen, wählen wir das ADSR-Panel aus, stellen ATTACK auf Minimum, SUST_LEV auf ein Drittel und DECAY auf etwa die Hälfte ein. So bekommen wir einen tollen perkussiven Klang, der einer gezupften Saite ähnelt, besonders wenn wir eine Sägezahn-Wellenform verwenden.


Demnächst

Im zweiten Teil dieser Artikelreihe zur Audio-Synthese schauen wir uns die Sequence-Anwendung und -Firmware an. Außerdem zeigen wir die Verdrahtungsdiagramme der Hauptplatine und der Displayplatine, inklusive der Komponentenliste für beide. Bleiben Sie dran!

Abonnieren
Tag-Benachrichtigung zu Audio jetzt abonnieren!

 

Hinweis des Herausgebers: Dieses Projekt zur Audio-Synthese-Plattform wurde ursprünglich in Elettronica IN veröffentlicht.