Menyenangkan dengan pengembangan atau manfaat untuk ASIO di C ++


Sebagai calon programmer dan pencinta gitar listrik, saya tidak bisa tinggal jauh dari mengembangkan perangkat lunak musik. Setiap orang yang pernah mencoba menghubungkan gitar listrik ke komputer Windows menggunakan beberapa jenis prosesor gitar tahu bahwa antarmuka ASIO sering diperlukan untuk keperluan ini (yang lain juga mungkin, tetapi ASIO adalah yang paling populer). Hal ini disebabkan oleh fakta bahwa waktu yang cukup lama dihabiskan untuk memproses input dan output audio, dan, sebagai akibatnya, keterlambatan yang tidak menyenangkan terdengar ketika memainkan instrumen, yang membuat permainan sangat sulit. ASIO memungkinkan Anda untuk melewati tahap pencampuran suara saat dihasilkan dan, karenanya, secara signifikan mengurangi penundaan. Baca lebih lanjut di sini .

Apa masalahnya?


Saya memutuskan untuk menggunakan ASIO, karena drivernya populer dan nyaman, tetapi di sini saya menemui masalah: ada sangat sedikit artikel tentang topik pengembangan untuk teknologi ini. Bahkan, semua itu bisa saya pandu sejak awal - dokumentasi resmi untuk SDK dan beberapa forum berbahasa Inggris. Saya harap jika Anda memiliki masalah yang sama, maka artikel tersebut setidaknya akan sedikit bermanfaat bagi Anda.

Perpustakaan Bass


Kode dari situs web resmi Stainberg menggunakan SDK, yang hanya memainkan keheningan selama 20 detik, membutuhkan 500 baris. Namun, ada perpustakaan Bass yang luar biasa. Penggemar yang bekerja dengan suara tahu cara menggunakannya untuk membuat aliran suara dan saluran, cara menerapkan efek FX, campuran ... Saya sangat berharap begitu. Bass memiliki addon Bassasio, yang, pada kenyataannya, memungkinkan Anda untuk mengkonfigurasi driver ASIO dalam beberapa baris kode dan melakukan tugas yang identik dengan contoh di atas.

Instal dan konfigurasikan perpustakaan


  1. Unduh perpustakaan Bass dan add-on Bassasio - nya . Ini adalah situs resmi
  2. Kami membuang file .lib ke folder terpisah. Dalam hal ini, saya menjatuhkan file bass.lib dan bassasio.lib ke folder Libs
  3. File .dll ditransfer ke folder Release and Debug . (bass.dll dan bassasio.dll) Jika ini tidak dilakukan, maka ketika Anda menjalankan kode aplikasi Anda, program akan menampilkan kesalahan seperti ini:



  4. Selanjutnya, dalam pengaturan proyek, kami menetapkan path ke linker dengan file .lib ke linker . Kami melakukan hal yang sama untuk c / c ++ .





  5. Kami memasukkan file .h ke folder proyek dan memasukkannya ke dalam proyek, yaitu file bass.h dan bassasio.h .

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


Contoh penggunaan


Misalnya, buat aplikasi konsol kecil yang akan memainkan suara gitar, mis. program akan mengarahkan aliran dari input audio ke output audio. Kode aplikasi tersedia di github. Tampaknya sederhana. Seharusnya terlihat seperti combo gitar (macet dan mainkan!), Tapi suara sejauh ini akan jelas (tidak ada efek).

Kami menghubungkan perpustakaan di paragraf sebelumnya, sekarang kita perlu menginisialisasi perangkat input dan output suara. Ayo mulai!

BASS_Init () menginisialisasi perangkat output suara, dan mengambil parameter berikut sebagai input:

Parameter
int device - pengidentifikasi perangkat output. Jika Anda mengatur parameter -1, maka perangkat output standar akan digunakan, jika 0 - suara tidak akan diputar sama sekali, yaitu. tidak akan diberikan ke perangkat output apa pun.

DWORD freq - frekuensi pengambilan sampel dalam Hz

Bendera DWORD - bendera ... Ada banyak, Anda dapat membaca lebih lanjut di dokumentasi resmi www.un4seen.com/doc/#bass/BASS_Init.html . Singkatnya, dengan bantuan bendera, Anda dapat memilih kedalaman pengkodean suara, mono atau stereo, reproduksi suara oleh lebih dari dua speaker, dll.

HWND win - menginstal jendela aplikasi utama. Untuk aplikasi konsol, atur ke 0.

GUID * clsid - class untuk menginisialisasi objek yang akan digunakan untuk menginisialisasi DirectSound. Dalam kasus lain, atur ke Null.

Menginisialisasi driver ASIO sedikit lebih sederhana. Kami hanya mengirimkan 2 parameter ke fungsi BASSASIO_Init :

Parameter
int device - pengidentifikasi "perangkat" ... teknologi yang digunakan perpustakaan untuk bekerja. Masalahnya adalah bahwa jika Anda telah menginstal perangkat lunak seperti rig gitar atau Anda memiliki kartu suara dengan driver ASIO Anda sendiri, Anda akan melihat beberapa item dalam daftar "perangkat" yang tersedia. Daftar dapat diperoleh dengan memanggil fungsi BASS_ASIO_GetDeviceInfo () untuk setiap pengidentifikasi (memilah-milah mereka). Sebagai aturan, 0 adalah driver ASIO4ALL kami, yang akan kami gunakan di masa depan. Nilai -1 akan mengatur perangkat secara default, seperti yang dijelaskan dalam dokumentasi.

 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; 


Daftar pengemudi

Bendera DWORD - bendera. Hanya ada 2 di antaranya: BASS_ASIO_THREAD - jalankan driver di utas terpisah dan BASS_ASIO_JOINORDER - bertanggung jawab atas pengoperasian saluran saluran.

Kode, inisialisasi perangkat output suara dan driver 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; } 

Mungkin timbul pertanyaan: mengapa perangkat output tidak digunakan di BASS_Init (0). Faktanya adalah bahwa output audio akan dibuat melalui ASIO menggunakan addon BASSASIO. Kami tidak memerlukan output suara standar menggunakan perpustakaan BASS untuk mengimplementasikan tugas yang ada - karena itu 0. Namun, beberapa poin perlu diperhatikan:

  1. Anda dapat menggunakan driver ASIO di satu perangkat dan mengeluarkan suara menggunakan cara standar di perangkat lain (misalnya ... musik akan diputar). Untuk melakukan ini, cukup pilih perangkat yang berbeda saat menginisialisasi BASS dan mengatur driver ASIO (Selama operasi, akan ada ikonnya di area notifikasi).
  2. Untuk daftar perangkat yang tersedia, gunakan 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 hanya berfungsi dengan perangkat yang saat ini aktif. Perangkat yang terputus tidak akan terlihat.


    Perangkat output suara aktif

    BASSASIO benar-benar sama apakah perangkat terputus oleh sistem operasi atau tidak. Dalam pengaturan driver, pilih perangkat input dan output suara yang Anda butuhkan.
  3. Tidak masuk akal untuk mencoba mengeluarkan suara menggunakan BASS dan BASSASIO secara bersamaan ke dalam satu perangkat - teknologi ASIO dirancang khusus untuk fakta bahwa suara tidak akan tercampur oleh sistem operasi dan akan langsung menuju kartu suara untuk keluaran selanjutnya. Yaitu Anda hanya akan mendengar suara dari aplikasi menggunakan ASIO.

Selanjutnya, kita perlu mengarahkan aliran suara dari mikrofon ke perangkat output suara. Ada beberapa cara untuk melakukan ini. Cara termudah adalah dengan "mirror" saluran.

Kami memiliki 3 saluran: mikrofon, earphone kiri dan earphone kanan. Untuk mentransfer sinyal dari mikrofon ke saluran keluaran, kami menggunakan fungsinya

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

Semuanya sederhana di sini. Kita perlu mengirimkan sinyal ke saluran keluaran 0 dan 1 dari saluran input 0:

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

Kemudian muncul pertanyaan: bagaimana saya mengetahui saluran mana yang saya butuhkan untuk mengirimkan sinyal. Jawab - informasi tentang saluran dapat ditemukan menggunakan fungsi 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; 



Semua pengaturan sudah siap. Mulai - BASS_ASIO_Mulai . Anda dapat memberikan parameter untuk panjang sampel maksimum dan jumlah aliran ke input, tetapi untuk tugas kami, kami dapat membiarkan parameter ini secara default (isi dengan nol).

 BASS_ASIO_Start( 0, 0 ); 

Faktanya, itu saja. Namun, ini adalah aplikasi konsol, jangan lupa tentang sistem ("jeda") , sehingga tidak menutup segera setelah peluncuran, dan segera setelah itu, membebaskan memori dan berhenti bekerja dengan perangkat dan driver.

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

Ringkasan


Saya akan meninggalkan kode sumber di github .
Jadi kami mendapat aplikasi konsol sederhana menggunakan teknologi ASIO. Saat menghubungkan instrumen ke kartu suara, kami tidak akan mendengar penundaan yang mungkin terjadi dengan koneksi standar menggunakan alat Windows standar. Tentu saja, kemungkinan perpustakaan BASS dan add-on BASSASIO lebih luas daripada yang disajikan di atas, namun, format artikel atau pengetahuan saya tidak akan cukup untuk menyatakan semuanya secara mutlak.

Jika topik ini setidaknya sedikit menarik bagi Anda, saya senang mencoba. Pada gilirannya, saya akan mencoba mencuri sedikit waktu untuk menulis sekuel di mana kita dapat bekerja dengan efek FX standar dari DX8 dan mendapatkan kemiripan dengan prosesor gitar sederhana.

Terima kasih atas perhatian anda!

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


All Articles