Eine GUI ist eine fantastische Idee … Aber welche soll es sein – SDL, wxWidgets oder Qt?
Die Wahl eines GUI-Frameworks für ein C++-Audio-Projekt ist ein „Fork in the Road“-Moment. Jede dieser Optionen lenkt das Projekt in eine völlig andere architektonische Richtung.
Da dein Kurs derzeit SDL verwendet, ist es der natürliche Favorit. So sieht der Vergleich im Kontext eines Synthesizer-Projekts aus:
SDL (Simple DirectMedia Layer) – Die „Low-Level“-Wahl
Da du SDL bereits in Tutorial 02 eingeführt hast, ist es der Weg mit dem geringsten Widerstand, dabei zu bleiben.
Pros: Es „übernimmt“ deine main()-Funktion nicht so aggressiv wie die anderen. Es eignet sich hervorragend für selbst gezeichnete Drehregler und Slider mit einfachen Formen oder Bitmaps.
Der „Audio“-Fit: Es ist ideal für Visualizer (Oszilloskope oder Spektrumanalysatoren), da du direkten Zugriff auf den Pixelpuffer oder hardwarebeschleunigtes Rendering hast.
Cons: Es hat keine eingebauten „Widgets“ (Buttons, Texteingaben). Du musst dein eigenes UI-System von Grund auf bauen oder eine Bibliothek wie Dear ImGui verwenden.
Qt – Die „professionelle/industrielle“ Wahl
Qt ist der Schwergewichtschampion. Wenn dein Synth wie eine moderne DAW (Digital Audio Workstation) oder ein kommerzielles Plugin aussehen soll, ist das die richtige Wahl.
Pros: Hervorragende Dokumentation und ein „What You See Is What You Get“ (WYSIWYG) Editor. High-DPI-Skalierung und komplexe Layouts werden sehr elegant gehandhabt.
Der „Audio“-Fit: Für ein einfaches Tutorial ist es vielleicht überdimensioniert, aber es eignet sich hervorragend, um Signals und Slots zu vermitteln – einen C++-Mechanismus, der perfekt nachbildet, wie Patchkabel in einem modularen Synthesizer funktionieren.
Cons: Große Binärgröße und eine steile Lernkurve. Außerdem benötigt Qt den moc (Meta-Object Compiler), der eine zusätzliche Ebene von „Magie“ hinzufügt und möglicherweise die rohe C++-Logik verbirgt, die du eigentlich vermitteln möchtest.
wxWidgets – Die „native“ Wahl
wxWidgets verwendet die nativen Controls des Host-Betriebssystems (es sieht unter Windows wie eine Windows-App und unter Linux wie eine GTK-App aus).
Pros: Keine „magischen“ Präprozessoren wie bei Qt. Es ist im traditionellen Sinne „reines“ C++.
Cons: Es wirkt etwas altmodisch. Eigene, „cool aussehende“ Synth-Regler zu gestalten ist in wxWidgets deutlich schwieriger als in SDL oder Qt, da es darauf ausgelegt ist, wie eine klassische Tabellen- oder Dateimanager-Oberfläche auszusehen.
Feature | SDL | Qt | wxWidgets |
Learning Curve | Easy (wenn man SDL kennt) | Steil | Mittel |
Look & Feel | Custom/Game-artig | Modern/Schick | Nativ/Standard |
Best For… | Visualizer & Prototyping | Kommerzielle Software | Klassische Desktop-Apps |
C++ Style | Prozedural/Einfache OOP | Starke OOP & Makros | Traditionelle OOP |
Also wählen wir Qt – installieren wir die Abhängigkeiten und die Qt-Creator-IDE
Wir beginnen einfach damit, Qt 5 plus Abhängigkeiten zu installieren (ungefähr 500 MB):
1
sudo apt install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools qtcreator
Der QtCreator


Der QtCreator erlaubt es uns – zum Beispiel unsere eigene Benutzeroberfläche zu erstellen …
Wir beginnen mit der einfachen *.pro(jekt)-Datei, die beim Anlegen eines neuen Projekts generiert wird …
synth.pro
| |
Der Meta-Object Compiler, kurz moc, ist das Werkzeug, das Qt zu mehr macht als nur eine gewöhnliche C-Bibliothek. Obwohl C sehr leistungsfähig ist, fehlte ihm historisch gesehen Introspektion – also die Fähigkeit eines Programms, seine eigene Struktur (wie Klassen, Methoden oder Eigenschaften) zur Laufzeit zu untersuchen.
Der moc löst dieses Problem, indem er zusätzlichen C-Code generiert, der die Lücke zwischen Standard-C und den erweiterten Qt-Funktionen schließt.
Funktionsweise
Der moc ist kein Ersatz für deinen Compiler (wie GCC oder Clang), sondern ein Präprozessor. Der typische Workflow sieht so aus:
Scanning: Der moc liest deine C++-Headerdateien.
Detection: Er sucht nach dem Makro Q_OBJECT. Wenn er es findet, weiß er, dass diese Klasse „Meta-Fähigkeiten“ benötigt.
Generation: Er erzeugt eine neue C++-Datei (normalerweise moc_filename.cpp), die den Meta-Object-Code enthält.
Compilation: Dein normaler Compiler kompiliert sowohl deinen ursprünglichen Code als auch den vom moc generierten Code und linkt beide in das finale Binary.
Wichtige Funktionen, die durch moc ermöglicht werden
Ohne den Meta-Object Compiler würden die folgenden zentralen Qt-Funktionen nicht existieren:
Signals und Slots Dies ist Qts charakteristische Methode, mit der Objekte miteinander kommunizieren. Da Standard-C++ kein eingebautes „signal“-Schlüsselwort besitzt, erzeugt der moc den notwendigen „Glue Code“, um Funktionen anhand ihres Namens zu finden und auszuführen, wenn ein Signal ausgelöst wird.
Introspektion (Run-Time Type Information) Du kannst ein QObject zur Laufzeit nach seinem Klassennamen fragen, welche Signale es besitzt oder welche Methoden verfügbar sind – über metaObject(). Das ist wesentlich aussagekräftiger als das Standard-C++-typeid.
Properties Der moc ermöglicht das Q_PROPERTY-System, mit dem sich Klassenmitglieder wie Properties in Sprachen wie Python oder C# behandeln lassen. Werte können über String-Namen gelesen oder gesetzt werden – was besonders für Qt Quick (QML) wichtig ist.
==
main.cpp
| |
mainwindow.h
| |
mainwindow.cpp
| |
| |
From linear to logarithmic
Human perception of pitch and loudness is logarithmic, so the slider must be mapped using an exponential function.
The standard approach:
\large \[f = f_{min} * (f_{max} / f_{min} )^{(slider/maxSlider)}\]
This is the valid approach for both, volume and frequency.
So next we show the both adapted files mainwindow.h and mainwindow.cpp
mainwindow.h
| |
mainwindow.cpp
| |