Einführung in C++ (Teil 3)
C++ OOP-Meisterschaft: Die Kraft der Komposition (Has-A)
In der Softwarearchitektur gibt es zwei grundlegende Möglichkeiten, Objekte miteinander zu verbinden: Vererbung (Is-A) und Komposition (Has-A). Während Anfänger oft versuchen, alles durch Vererbung zu lösen („Ein Oszillator ist ein Hüllkurvenmodul“), bevorzugen Profis die Komposition: „Ein Synthesizer hat ein Hüllkurvenmodul.“
1. Warum Komposition?
Stellen Sie sich unseren Synthesizer als modulares Rack vor. Jedes Modul (Oszillator, Hüllkurvenmodul) ist eine eigenständige Klasse. Die SynthEngine fungiert
als Chassis, in das diese Module eingesteckt werden.
Modularität: Wir können die Envelope-Logik aktualisieren, ohne auch nur eine einzige Zeile des Oszillator-Codes anzurühren.
Zustandstrennung: Die Envelope verwaltet ihre eigenen komplexen Zustände (Attack, Decay, Sustain, Release). Der Engine ist es egal, wie die Lautstärke berechnet wird; sie interessiert sich nur für das Ergebnis.
Wiederverwendbarkeit: Wir könnten später problemlos eine zweite oder dritte Hüllkurve für andere Parameter hinzufügen, da die Klasse eine in sich geschlossene Einheit ist.
2. Die Signalkette
Durch Zusammensetzung bauen wir eine „Signalkette“ auf. Selbst in dieser Basisversion fließen die Daten in einer bestimmten Reihenfolge:
Oszillator → Erzeugt die rohen, kontinuierlichen Audio-Samples.
Hüllkurve → Wirkt als „Gate“ und multipliziert diese Samples mit einem Lautstärkepegel (0,0 bis 1,0), je nachdem, wie lange eine Taste gedrückt wurde.
3. Vollständiger Referenzcode (Grundlegende Komposition)
Nachfolgend finden Sie den vollständigen integrierten Code, der die Beziehung zwischen der Engine, dem polymorphen Oszillator und der ADSR-Hüllkurve veranschaulicht.
| |
| |
| |
| |
Wir kompilieren die Datei mit einem einfachen
1
g++ -o synth main.cpp_01 Oscillator.cpp_01 `pkg-config --cflags --libs sdl2`
und können das Programm ausführen:
1
./synth
Jetzt, da die Hüllkurve implementiert ist, klingt es wirklich wie ein echter Synthesizer!!!
4. Fazit
Durch den Einsatz von Komposition haben wir ein System aufgebaut, das leicht zu erweitern ist. Die SynthEngine verwaltet die übergeordnete Logik und
die Hardware-Schnittstelle, während die Envelope die mathematischen Feinheiten der Lautstärkeregelung übernimmt.
Diese klare Trennung der Aufgabenbereiche ist es, was professionelle C++-Anwendungen robust macht. Im nächsten Kapitel werden wir dieser Kette einen spannungsgesteuerten Filter (VCF) hinzufügen, wobei wir genau denselben kompositorischen Ansatz verwenden!
Übersetzt mit DeepL.com (kostenlose Version)