Angenehm mit nützlich oder Entwicklung für ASIO in C ++


Als potenzieller Programmierer und E-Gitarren-Liebhaber konnte ich mich nicht von der Entwicklung von Musiksoftware fernhalten. Jeder, der jemals versucht hat, eine E-Gitarre mit einem Gitarrenprozessor an einen Windows-Computer anzuschließen, weiß, dass für diese Zwecke häufig eine ASIO-Schnittstelle erforderlich ist (andere sind ebenfalls möglich, aber ASIO ist die beliebteste). Dies ist auf die Tatsache zurückzuführen, dass viel Zeit für die Verarbeitung der Audioeingabe und -ausgabe aufgewendet wird und infolgedessen beim Spielen eines Instruments eine unangenehme Verzögerung zu hören ist, die das Spiel sehr schwierig macht. Mit ASIO können Sie die Stufe des Mischens von Ton bei der Ausgabe überspringen und dementsprechend die Verzögerung erheblich reduzieren. Lesen Sie hier mehr darüber.

Was ist das Problem


Ich habe mich für ASIO entschieden, weil der Treiber beliebt und praktisch ist, aber hier bin ich auf ein Problem gestoßen: Es gibt nur sehr wenige Artikel zum Thema Entwicklung für diese Technologie. In der Tat alles, was ich am Anfang führen konnte - die offizielle Dokumentation für das SDK und mehrere englischsprachige Foren. Ich hoffe, wenn Sie ein ähnliches Problem haben, wird der Artikel zumindest ein wenig nützlich für Sie sein.

Bass Library


Der Code von der offiziellen Stainberg- Website mit dem SDK, der einfach 20 Sekunden lang die Stille spielt, benötigt 500 Zeilen. Es gibt jedoch eine wunderbare Bassbibliothek . Fans der Arbeit mit Sound wissen, wie man damit Sound-Streams und Kanäle erstellt, wie man FX-Effekte anwendet, mischt ... Ich hoffe es wirklich. Bass verfügt über ein Bassasio-Add-On, mit dem Sie den ASIO-Treiber in wenigen Codezeilen konfigurieren und die mit dem obigen Beispiel identische Aufgabe ausführen können.

Installieren und konfigurieren Sie Bibliotheken


  1. Laden Sie die Bass- Bibliothek und ihr Add-On Bassasio herunter . Dies ist die offizielle Seite
  2. Wir speichern .lib- Dateien in einem separaten Ordner. In diesem Fall habe ich die Dateien bass.lib und bassasio.lib im Ordner Libs abgelegt
  3. DLL- Dateien werden in die Ordner Release und Debug übertragen . (bass.dll und bassasio.dll) Wenn dies nicht erfolgt, gibt das Programm beim Ausführen des Codes Ihrer Anwendung einen Fehler wie den folgenden aus:



  4. Als nächstes weisen wir in den Projekteinstellungen dem Linker den Pfad mit den .lib- Dateien dem Linker zu . Wir machen das gleiche für c / c ++ .





  5. Wir legen die .h- Dateien im Projektordner ab und fügen sie in das Projekt ein, nämlich die Dateien bass.h und bassasio.h .

    #include "bass.h" #include "bassasio.h" 


Anwendungsbeispiel


Erstellen Sie beispielsweise eine kleine Konsolenanwendung, die den Klang einer Gitarre spielt, d. H. Das Programm leitet den Stream vom Audioeingang zum Audioausgang um. Der Anwendungscode ist auf dem Github verfügbar . Es scheint einfach zu sein. Es sollte wie eine Gitarrenkombination aussehen (stecken bleiben und spielen!), Aber der Sound wird bisher klar sein (keine Effekte).

Wir haben die Bibliotheken im vorherigen Absatz verbunden. Jetzt müssen wir die Audioeingabe- und -ausgabegeräte initialisieren. Fangen wir an!

BASS_Init () initialisiert das Tonausgabegerät und verwendet die folgenden Parameter als Eingabe:

Parameter
int device - Kennung des Ausgabegeräts. Wenn Sie den Parameter -1 einstellen, wird das Standardausgabegerät verwendet, wenn 0 - der Ton wird überhaupt nicht abgespielt, d. H. wird keinem Ausgabegerät zur Verfügung gestellt.

DWORD-Frequenz - Abtastfrequenz in Hz

DWORD-Flags - Flags ... Es gibt viele, mehr dazu in der offiziellen Dokumentation www.un4seen.com/doc/#bass/BASS_Init.html . Kurz gesagt, mit Hilfe von Flags können Sie die Tiefe der Toncodierung, Mono oder Stereo, die Tonwiedergabe mit mehr als zwei Lautsprechern usw. auswählen.

HWND win - Installiert das Hauptanwendungsfenster. Für Konsolenanwendungen auf 0 setzen.

GUID * clsid - Klasse zum Initialisieren des Objekts, das zum Initialisieren von DirectSound verwendet wird. In anderen Fällen auf Null setzen.

Das Initialisieren des ASIO-Treibers ist etwas einfacher. Wir übergeben nur 2 Parameter an die Funktion BASSASIO_Init :

Parameter
int device - Kennung des „Geräts“ ... der Technologie, mit der die Bibliothek arbeiten wird. Wenn Sie Software wie ein Gitarren-Rig installiert haben oder eine Soundkarte mit einem eigenen ASIO-Treiber haben, werden in der Liste der verfügbaren „Geräte“ mehrere Elemente angezeigt. Eine Liste erhalten Sie, indem Sie die Funktion BASS_ASIO_GetDeviceInfo () für jeden Bezeichner aufrufen (durch sie sortieren). In der Regel ist 0 unser ASIO4ALL-Treiber, den wir in Zukunft verwenden werden. Der Wert -1 legt das Gerät standardmäßig fest, wie in der Dokumentation beschrieben.

 std::cout << "ASIO Devices info:" << std::endl; a = 0; count = 0; BASS_ASIO_DEVICEINFO asio_info; for (a = 0; BASS_ASIO_GetDeviceInfo(a, &asio_info); a++) std::cout << "Device " << a << ") " << asio_info.name << std::endl; std::cout << " ________ " << std::endl; 


Treiberliste

DWORD-Flags - Flags. Es gibt nur zwei davon: BASS_ASIO_THREAD - Führen Sie den Treiber in einem separaten Thread aus und BASS_ASIO_JOINORDER - ist für den Betrieb der Kanalkanäle verantwortlich.

Code, Initialisierung des Soundausgabegeräts und des ASIO-Treibers:

 try { if ( ! BASS_Init(0, 44100, 0, 0, NULL) ) throw BASS_ErrorGetCode(); if ( ! BASS_ASIO_Init( 0, NULL ) ) throw BASS_ASIO_ErrorGetCode(); } catch ( int err ) { std::cout << "Err no - " << err << std::endl; system("pause"); return; } 

Es kann sich die Frage stellen, warum das Ausgabegerät in BASS_Init (0) nicht verwendet wird. Tatsache ist, dass die Audioausgabe über ASIO mit dem BASSASIO-Addon erfolgt. Wir benötigen keine Standard-Soundausgabe mit der BASS-Bibliothek, um die vorliegende Aufgabe zu implementieren - daher 0. Einige Punkte sind jedoch erwähnenswert:

  1. Sie können den ASIO-Treiber auf einem Gerät bedienen und den Ton mit Standardmitteln auf einem anderen Gerät ausgeben (z. B. ... Musik wird abgespielt). Wählen Sie dazu einfach verschiedene Geräte aus, wenn Sie BASS initialisieren und den ASIO-Treiber einrichten (während des Betriebs wird das Symbol im Benachrichtigungsbereich angezeigt).
  2. Verwenden Sie BASS_GetDeviceInfo, um eine Liste der verfügbaren Geräte anzuzeigen.
     setlocale(LC_ALL, "Rus"); std::cout << "Devices info:" << std::endl; int a, count = 0; BASS_DEVICEINFO info; for (a = 1; BASS_GetDeviceInfo(a, &info); a++) { if (info.flags&BASS_DEVICE_ENABLED) // device is enabled std::cout << "Device " << a << ") " << info.name << " is availible" << std::endl; else std::cout << "Device " << a << ") " << info.name << " is unable" << std::endl; } std::cout << " ________ " << std::endl; 



    BASS funktioniert nur mit Geräten, die derzeit aktiv sind. Getrennte Geräte sind einfach nicht sichtbar.


    Aktive Tonausgabegeräte

    BASSASIO ist absolut gleich, unabhängig davon, ob das Gerät vom Betriebssystem getrennt wurde oder nicht. Wählen Sie in den Treibereinstellungen die gewünschten Audioeingabe- und -ausgabegeräte aus.
  3. Es macht keinen Sinn, zu versuchen, Sound mit BASS und BASSASIO gleichzeitig in einem Gerät auszugeben. Die ASIO-Technologie wurde speziell dafür entwickelt, dass der Sound vom Betriebssystem nicht gemischt wird und zur späteren Ausgabe direkt auf die Soundkarte übertragen wird. Das heißt, Sie hören nur Ton von einer Anwendung, die ASIO verwendet.

Als nächstes müssen wir den Tonstrom vom Mikrofon zum Tonausgabegerät leiten. Es gibt verschiedene Möglichkeiten, dies zu tun. Am einfachsten ist es, den Kanal zu „spiegeln“.

Wir haben 3 Kanäle: Mikrofon, linker Kopfhörer und rechter Kopfhörer. Um das Signal vom Mikrofon auf die Ausgangskanäle zu übertragen, verwenden wir die Funktion

 BOOL BASS_ASIO_ChannelEnableMirror( DWORD channel -   BOOL input2 -   ? (0  1) DWORD channel2 –    ( ) ); 

Hier ist alles einfach. Wir müssen das Signal von Eingangskanal 0 zu den Ausgangskanälen 0 und 1 übertragen:

 BASS_ASIO_ChannelEnableMirror( 0, 1, 0 ); BASS_ASIO_ChannelEnableMirror( 1, 1, 0 ); 

Dann stellt sich die Frage: Wie habe ich herausgefunden, auf welche Kanäle ich das Signal übertragen muss? Antwort - Informationen zu Kanälen finden Sie mit der Funktion BASS_ASIO_ ChannelGetInfo .

 a = 0; BASS_ASIO_CHANNELINFO channel_info; std::cout << "inputs: " << std::endl; for (a = 0; BASS_ASIO_ChannelGetInfo(0, a, &channel_info ); a++ ) std::cout << a << ") " << channel_info.name << " format: " << channel_info.format << std::endl; std::cout << "Outputs: " << std::endl; for (a = 0; BASS_ASIO_ChannelGetInfo(1, a, &channel_info); a++) std::cout << a << ") " << channel_info.name << " format: " << channel_info.format << std::endl; std::cout << "__________" << std::endl; 



Alle Einstellungen sind fertig. Start - BASS_ASIO_Start . Sie können Parameter für die maximale Stichprobenlänge und die Anzahl der Streams für die Eingabe angeben, aber für unsere Aufgabe können wir diese Parameter standardmäßig belassen (füllen Sie sie mit Nullen).

 BASS_ASIO_Start( 0, 0 ); 

Das ist alles. Dies ist jedoch eine Konsolenanwendung. Vergessen Sie nicht das System („Pause“) , damit es nicht sofort nach dem Start geschlossen wird. Geben Sie unmittelbar danach Speicher frei und beenden Sie die Arbeit mit Geräten und dem Treiber.

 BASS_ASIO_Stop(); BASS_ASIO_Free(); BASS_Stop(); BASS_Free(); return; 

Zusammenfassung


Ich werde den Quellcode auf dem Github belassen .
Wir haben also eine einfache Konsolenanwendung mit ASIO-Technologie erhalten. Beim Anschließen des Instruments an die Soundkarte hören wir nicht die Verzögerung, die bei einer Standardverbindung mit Standard-Windows-Tools hätte auftreten können. Natürlich sind die Möglichkeiten sowohl der BASS-Bibliothek als auch des BASSASIO-Add-ons breiter als die oben dargestellten, jedoch werden weder das Format des Artikels noch mein Wissen ausreichen, um absolut alles anzugeben.

Wenn dieses Thema für Sie zumindest ein wenig interessant war, habe ich es gerne versucht. Im Gegenzug werde ich versuchen, ein wenig Zeit zu stehlen, um eine Fortsetzung zu schreiben, in der wir mit Standard-FX-Effekten des DX8 arbeiten und den Anschein eines einfachen Gitarrenprozessors bekommen können.

Vielen Dank für Ihre Aufmerksamkeit!

Source: https://habr.com/ru/post/de464843/


All Articles