Agréable avec utile ou développement pour ASIO en C ++


En tant que programmeur potentiel et amateur de guitare électrique, je ne pouvais pas m'éloigner du développement de logiciels de musique. Tous ceux qui ont déjà essayé de connecter une guitare électrique à un ordinateur Windows à l'aide d'une sorte de processeur de guitare savent que l'interface ASIO est souvent requise à ces fins (d'autres sont également possibles, mais ASIO est le plus populaire). Cela est dû au fait qu'un temps considérable est consacré au traitement de l'entrée et de la sortie audio et, par conséquent, un retard désagréable se fait entendre lors de la lecture d'un instrument, ce qui rend le jeu très difficile. ASIO vous permet de sauter l'étape de mixage du son lors de sa sortie et, par conséquent, de réduire considérablement le retard. En savoir plus ici .

Quel est le problème


J'ai décidé d'utiliser ASIO, car le pilote est populaire et pratique, mais ici j'ai rencontré un problème: il y a très peu d'articles sur le thème du développement de cette technologie. En fait, tout ce que j'ai pu être guidé au tout début - la documentation officielle du SDK et de plusieurs forums en anglais. J'espère que si vous avez un problème similaire, l'article vous sera au moins un peu utile.

Bibliothèque basse


Le code du site officiel de Stainberg utilisant le SDK, qui joue simplement le silence pendant 20 secondes, prend 500 lignes. Cependant, il existe une merveilleuse bibliothèque Bass . Les fans de travailler avec le son savent comment l'utiliser pour créer des flux et des canaux sonores, comment appliquer des effets FX, mixer ... j'espère vraiment. Bass a un addon Bassasio, qui, en fait, vous permet de configurer le pilote ASIO en quelques lignes de code et d'effectuer la tâche identique à l'exemple ci-dessus.

Installer et configurer des bibliothèques


  1. Téléchargez la bibliothèque Bass et son add-on Bassasio . Ceci est le site officiel
  2. Nous vidons les fichiers .lib dans un dossier séparé. Dans ce cas, j'ai déposé les fichiers bass.lib et bassasio.lib dans le dossier Libs
  3. Les fichiers .dll sont transférés dans les dossiers Release et Debug . (bass.dll et bassasio.dll) Si cela n'est pas fait, alors lorsque vous exécutez le code de votre application, le programme lancera une erreur comme celle-ci:



  4. Ensuite, dans les paramètres du projet, nous attribuons le chemin d'accès à l' éditeur de liens avec les fichiers .lib à l' éditeur de liens . Nous faisons de même pour c / c ++ .





  5. Nous déposons les fichiers .h dans le dossier du projet et les incluons dans le projet, à savoir les fichiers bass.h et bassasio.h .

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


Exemple d'utilisation


Par exemple, créez une petite application console qui jouera le son d'une guitare, c'est-à-dire le programme redirigera le flux de l'entrée audio vers la sortie audio. Le code de l'application est disponible sur le github, il semble simple. Cela devrait ressembler à un combo de guitare (coincé et jouer!), Mais le son jusqu'à présent sera clair (pas d'effets).

Nous avons connecté les bibliothèques dans le paragraphe précédent, nous devons maintenant initialiser les périphériques d'entrée et de sortie audio. Commençons!

BASS_Init () initialise le périphérique de sortie audio et prend les paramètres suivants en entrée:

Paramètres
int device - identifiant du périphérique de sortie. Si vous définissez le paramètre -1, le périphérique de sortie standard sera utilisé, si 0 - le son ne jouera pas du tout, c'est-à-dire ne sera fourni à aucun périphérique de sortie.

DWORD freq - fréquence d'échantillonnage en Hz

Drapeaux DWORD - drapeaux ... Il y en a beaucoup, vous pouvez en lire plus dans la documentation officielle www.un4seen.com/doc/#bass/BASS_Init.html . En bref, à l'aide de drapeaux, vous pouvez choisir la profondeur d'encodage du son, mono ou stéréo, la reproduction du son par plus de deux haut-parleurs, etc.

HWND win - installe la fenêtre principale de l'application. Pour les applications console, définissez sur 0.

GUID * clsid - classe pour initialiser l'objet qui sera utilisé pour initialiser DirectSound. Dans d'autres cas, définissez sur Null.

L'initialisation du pilote ASIO est un peu plus simple. Nous passons seulement 2 paramètres à la fonction BASSASIO_Init :

Paramètres
int device - identifiant du «périphérique» ... la technologie avec laquelle la bibliothèque fonctionnera. Le truc, c'est que si vous avez installé un logiciel comme un rig de guitare ou si vous avez une carte son avec votre propre pilote ASIO, vous verrez plusieurs éléments dans la liste des «périphériques» disponibles. Une liste peut être obtenue en appelant la fonction BASS_ASIO_GetDeviceInfo () pour chaque identifiant (en les triant). En règle générale, 0 est notre pilote ASIO4ALL, que nous utiliserons à l'avenir. Une valeur de -1 définira le périphérique par défaut, comme décrit dans la documentation.

 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; 


Liste des pilotes

Drapeaux DWORD - drapeaux. Il n'y en a que 2: BASS_ASIO_THREAD - exécutez le pilote dans un thread séparé et BASS_ASIO_JOINORDER - est responsable de l'ordre des canaux.

Code, initialisation du périphérique de sortie audio et du pilote ASIO:

 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; } 

La question peut se poser: pourquoi le périphérique de sortie n'est-il pas utilisé dans BASS_Init (0). Le fait est que la sortie audio se fera via ASIO en utilisant l'addon BASSASIO. Nous n'avons pas besoin d'une sortie audio standard utilisant la bibliothèque BASS pour implémenter la tâche à accomplir - donc 0. Cependant, quelques points méritent d'être notés:

  1. Vous pouvez travailler le pilote ASIO sur un périphérique et produire du son en utilisant des moyens standard sur un autre (disons ... la musique jouera). Pour ce faire, il suffit de sélectionner différents périphériques lors de l'initialisation de BASS et de la configuration du pilote ASIO (Pendant le fonctionnement, il y aura son icône dans la zone de notification).
  2. Pour une liste des périphériques disponibles, utilisez BASS_GetDeviceInfo.
     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 ne fonctionne qu'avec les appareils actuellement actifs. Les appareils déconnectés ne seront tout simplement pas visibles.


    Dispositifs de sortie audio actifs

    BASSASIO est absolument le même, que l'appareil ait été déconnecté par le système d'exploitation ou non. Dans les paramètres du pilote, sélectionnez les périphériques d'entrée et de sortie audio dont vous avez besoin.
  3. Cela n'a aucun sens d'essayer de produire du son en utilisant BASS et BASSASIO simultanément dans un seul appareil - la technologie ASIO est conçue spécifiquement pour le fait que le son ne sera pas mixé par le système d'exploitation et ira directement à la carte son pour une sortie ultérieure. C'est-à-dire vous n'entendrez que le son d'une application utilisant ASIO.

Ensuite, nous devons diriger le flux sonore du microphone vers le périphérique de sortie audio. Il existe plusieurs façons de procéder. Le moyen le plus simple consiste à «mettre en miroir» la chaîne.

Nous avons 3 canaux: microphone, écouteur gauche et écouteur droit. Pour transférer le signal du microphone vers les canaux de sortie, nous utilisons la fonction

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

Ici, tout est simple. Nous devons transmettre le signal aux canaux de sortie 0 et 1 à partir du canal d'entrée 0:

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

Ensuite, la question se pose: comment ai-je découvert à quels canaux je dois transmettre le signal. Réponse - des informations sur les canaux peuvent être trouvées en utilisant la fonction 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; 



Tous les paramètres sont prêts. Démarrer - BASS_ASIO_Start . Vous pouvez donner des paramètres pour la longueur d'échantillon maximale et le nombre de flux à l'entrée, mais pour notre tâche, nous pouvons laisser ces paramètres par défaut (les remplir de zéros).

 BASS_ASIO_Start( 0, 0 ); 

En fait, c'est tout. Cependant, il s'agit d'une application console, n'oubliez pas le système («pause») , afin qu'il ne se ferme pas immédiatement après le lancement, et immédiatement après, libérez de la mémoire et arrêtez de travailler avec les périphériques et le pilote.

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

Résumé


Je vais laisser le code source sur le github .
Nous avons donc obtenu une application console simple utilisant la technologie ASIO. Lors de la connexion de l'instrument à la carte son, nous n'entendons pas le retard qui aurait pu se produire avec une connexion standard à l'aide d'outils Windows standard. Bien sûr, les possibilités de la bibliothèque BASS et de l'add-on BASSASIO sont plus larges que celles présentées ci-dessus, cependant, ni le format de l'article ni mes connaissances ne suffiront à énoncer absolument tout.

Si ce sujet était au moins un peu intéressant pour vous, j'étais heureux d'essayer. À mon tour, je vais essayer de voler un peu de temps pour écrire une suite dans laquelle nous pouvons travailler avec des effets FX standard du DX8 et obtenir un semblant d'un simple processeur de guitare.

Merci de votre attention!

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


All Articles