ممتعة مع مفيدة أو تطوير ASIO في C ++


كمبرمج محتمل وعشاق الغيتار الكهربائي ، لم أستطع الابتعاد عن تطوير برامج الموسيقى. يعلم كل من حاول توصيل جيتار كهربائي إلى كمبيوتر يعمل بنظام Windows باستخدام نوع من معالج الجيتار أن واجهة ASIO غالبًا ما تكون مطلوبة لهذه الأغراض (والبعض الآخر ممكن أيضًا ، ولكن ASIO هو الأكثر شعبية). ويرجع ذلك إلى حقيقة أن هناك وقتًا طويلًا في معالجة إدخال الصوت وإخراجه ، ونتيجة لذلك ، يتم سماع تأخير غير سارة عند تشغيل أداة ، مما يجعل اللعبة صعبة للغاية. يتيح لك ASIO تخطي مرحلة خلط الصوت عند إخراجه وبالتالي تقليل التأخير بشكل كبير. اقرأ المزيد عنها هنا .

ما هي المشكلة


قررت استخدام ASIO ، لأن برنامج التشغيل مشهور وملائم ، لكنني واجهت مشكلة هنا: هناك عدد قليل جدًا من المقالات حول موضوع التطوير لهذه التكنولوجيا. في الواقع ، كل ما يمكنني توجيهه في البداية - الوثائق الرسمية لـ SDK وعدة منتديات باللغة الإنجليزية. آمل أنه إذا كانت لديك مشكلة مماثلة ، فإن المقالة ستكون مفيدة لك على الأقل.

مكتبة باس


يأخذ الرمز من موقع Stainberg الرسمي باستخدام SDK ، والذي يلعب ببساطة الصمت لمدة 20 ثانية ، 500 سطر. ومع ذلك ، هناك مكتبة باس رائعة. يعرف مستخدمو العمل الصوتي كيفية استخدامه لإنشاء تدفقات وقنوات صوتية ، وكيفية تطبيق تأثيرات FX ، والاختلاط ... أتمنى ذلك حقًا. يحتوي Bass على وظيفة إضافية Bassasio ، والتي ، في الواقع ، تتيح لك تكوين برنامج التشغيل ASIO في بضعة أسطر من التعليمات البرمجية وتنفيذ المهمة المطابقة للمثال أعلاه.

تثبيت وتكوين المكتبات


  1. قم بتنزيل مكتبة Bass والبرنامج الإضافي الخاص بها . هذا هو الموقع الرسمي
  2. نقوم بتفريغ ملفات .lib في مجلد منفصل. في هذه الحالة ، أسقطت ملفات bass.lib و bassasio.lib في مجلد Libs
  3. يتم نقل ملفات .dll إلى مجلدات الإصدار و Debug . (bass.dll و bassasio.dll) إذا لم يتم ذلك ، فعند تشغيل رمز التطبيق الخاص بك ، سيرمي البرنامج خطأ مثل هذا:



  4. بعد ذلك ، في إعدادات المشروع ، نقوم بتعيين المسار للرابط مع ملفات .lib للرابط . نحن نفعل نفس الشيء من أجل c / c ++ .





  5. نقوم بإسقاط ملفات .h في مجلد المشروع وإدراجها في المشروع ، أي ملفات bass.h و bassasio.h .

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


مثال للاستخدام


على سبيل المثال ، قم بإنشاء تطبيق وحدة تحكم صغير يقوم بتشغيل صوت الغيتار ، أي سيقوم البرنامج بإعادة توجيه الدفق من إدخال الصوت إلى إخراج الصوت. رمز التطبيق متاح على جيثب ويبدو أنه بسيط. يجب أن يبدو وكأنه التحرير والسرد الغيتار (عالقة واللعب!) ، ولكن الصوت حتى الآن سيكون واضحا (أي آثار).

لقد قمنا بتوصيل المكتبات في الفقرة السابقة ، والآن نحن بحاجة إلى تهيئة أجهزة إدخال الصوت والإخراج. لنبدأ!

BASS_Init () تهيئة جهاز إخراج الصوت ، ويأخذ المعلمات التالية كمدخل:

المعلمات
الباحث int الجهاز - معرف الجهاز الإخراج. إذا قمت بتعيين المعلمة -1 ، فسيتم استخدام جهاز الإخراج القياسي ، وإذا كان 0 - لن يتم تشغيل الصوت على الإطلاق ، أي لن يتم توفيرها لأي جهاز إخراج.

DWORD التكرار - تردد أخذ العينات في هرتز

علامات DWORD - الإشارات ... هناك الكثير ، يمكنك قراءة المزيد في الوثائق الرسمية www.un4seen.com/doc/#bass/BASS_Init.html . باختصار ، بمساعدة العلامات ، يمكنك اختيار عمق تشفير الصوت أو الصوت أحادي أو ستيريو ، واستنساخ الصوت بأكثر من متكلمين ، إلخ.

فوز HWND - تثبيت نافذة التطبيق الرئيسية. لتطبيقات وحدة التحكم ، اضبط على 0.

GUID * clsid - فئة لتهيئة الكائن الذي سيتم استخدامه لتهيئة DirectSound. في حالات أخرى ، اضبط على Null.

تهيئة برنامج التشغيل ASIO أبسط قليلاً. نقوم بتمرير معلمتين فقط إلى الدالة BASSASIO_Init :

المعلمات
int device - معرف "الجهاز" ... التكنولوجيا التي ستعمل بها المكتبة. الشيء هو أنه إذا قمت بتثبيت برنامج مثل الجيتار أو كان لديك بطاقة صوت مع برنامج التشغيل ASIO الخاص بك ، سترى العديد من العناصر في قائمة "الأجهزة" المتاحة. يمكن الحصول على قائمة عن طريق استدعاء دالة BASS_ASIO_GetDeviceInfo () لكل معرف (الفرز من خلالهم). كقاعدة عامة ، 0 هو برنامج ASIO4ALL الخاص بنا ، والذي سنستخدمه في المستقبل. تقوم القيمة -1 بتعيين الجهاز افتراضيًا ، كما هو موضح في الوثائق.

 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; 


قائمة السائقين

أعلام DWORD - أعلام. لا يوجد سوى 2 منهم: BASS_ASIO_THREAD - قم بتشغيل برنامج التشغيل في سلسلة رسائل منفصلة و BASS_ASIO_JOINORDER - مسؤول عن تشغيل قنوات القنوات.

الكود ، تهيئة جهاز إخراج الصوت وبرنامج تشغيل 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; } 

قد ينشأ السؤال: لماذا لا يتم استخدام جهاز الإخراج في BASS_Init (0). الحقيقة هي أنه سيتم إجراء إخراج الصوت من خلال ASIO باستخدام الملحق BASSASIO. لا نحتاج إلى إخراج صوت قياسي باستخدام مكتبة BASS لتنفيذ المهمة قيد البحث - وبالتالي 0. ​​ومع ذلك ، هناك بضع نقاط تجدر الإشارة إليها:

  1. يمكنك تشغيل برنامج التشغيل ASIO على جهاز واحد وإخراج الصوت باستخدام وسائل قياسية على جهاز آخر (على سبيل المثال ، سيتم تشغيل الموسيقى). للقيام بذلك ، ما عليك سوى اختيار أجهزة مختلفة عند تهيئة BASS وإعداد برنامج تشغيل ASIO (أثناء التشغيل ، سيكون هناك رمزه في منطقة الإعلام).
  2. للحصول على قائمة بالأجهزة المتاحة ، استخدم 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 فقط مع الأجهزة النشطة حاليًا. الأجهزة غير المتصلة ببساطة لن تكون مرئية.


    أجهزة إخراج الصوت النشط

    BASASIO هو نفسه تمامًا سواء تم فصل الجهاز عن طريق نظام التشغيل أم لا. في إعدادات برنامج التشغيل ، حدد أجهزة إدخال الصوت والإخراج التي تحتاج إليها.
  3. لا معنى لمحاولة إخراج الصوت باستخدام BASS و BASSASIO في وقت واحد في جهاز واحد - تم تصميم تقنية ASIO خصيصًا لحقيقة أن الصوت لن يختلط بواسطة نظام التشغيل وسوف ينتقل مباشرةً إلى بطاقة الصوت للإخراج اللاحق. أي سوف تسمع الصوت فقط من تطبيق يستخدم ASIO.

بعد ذلك ، نحتاج إلى توجيه دفق الصوت من الميكروفون إلى جهاز إخراج الصوت. هناك عدة طرق للقيام بذلك. أسهل طريقة هي "عكس" القناة.

لدينا 3 قنوات: الميكروفون وسماعة الأذن اليسرى وسماعة الأذن اليمنى. لنقل الإشارة من الميكروفون إلى قنوات الإخراج ، نستخدم الوظيفة

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

كل شيء بسيط هنا. نحتاج إلى إرسال الإشارة إلى قنوات الإخراج 0 و 1 من قناة الإدخال 0:

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

ثم يطرح السؤال التالي: كيف اكتشفت القنوات التي أحتاج إلى إرسال الإشارة إليها. الإجابة - يمكن العثور على معلومات حول القنوات باستخدام وظيفة 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; 



جميع الإعدادات جاهزة. ابدأ - BASS_ASIO_Start . يمكنك إعطاء معلمات لأقصى طول للعينة وعدد التدفقات إلى المدخلات ، ولكن لمهمتنا يمكننا أن نترك هذه المعلمات بشكل افتراضي (نملأها الأصفار).

 BASS_ASIO_Start( 0, 0 ); 

في الواقع ، هذا كل شيء. ومع ذلك ، هذا هو تطبيق وحدة التحكم ، لا تنسى النظام ("إيقاف مؤقت") ، بحيث لا يغلق مباشرة بعد الإطلاق ، وبعد ذلك مباشرة ، حرر الذاكرة والتوقف عن العمل مع الأجهزة وبرنامج التشغيل.

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

النتائج


سأترك الكود المصدري في جيثب .
لذلك حصلنا على تطبيق وحدة بسيطة باستخدام تقنية ASIO. عند توصيل الأداة ببطاقة الصوت ، لن نسمع التأخير الذي يمكن أن يحدث مع اتصال قياسي باستخدام أدوات Windows القياسية. بطبيعة الحال ، فإن إمكانيات كل من مكتبة BASS وملحق BASSASIO أوسع من تلك المذكورة أعلاه ، ومع ذلك ، لن يكفي تنسيق المقال ولا علمي أن يذكر كل شيء تمامًا.

إذا كان هذا الموضوع مثيرًا لك على الأقل ، فقد كنت سعيدًا بالمحاولة. بدوره ، سأحاول سرقة بعض الوقت لكتابة تكملة يمكننا من خلالها التعامل مع تأثيرات FX القياسية من DX8 والحصول على ما يشبه معالج الغيتار البسيط.

شكرا لاهتمامكم!

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


All Articles