واجهة برمجة تطبيقات Web Audio: لماذا الإنشاء ومتى يمكنك البرمجة؟

نشرت: 2022-03-11

ظهرت المسودة الأولى لواجهة برمجة تطبيقات صوت الويب في W3C خلال عام 2011. على الرغم من دعم الصوت في صفحات الويب لفترة طويلة ، إلا أن الطريقة المناسبة لتوليد الصوت من متصفح الويب لم تكن متاحة حتى وقت قريب جدًا. أنا شخصياً أنسب هذا إلى Google Chrome ، لأنه من أجل مصلحة Google ، بدأ المتصفح يصبح أهم جزء في الكمبيوتر. قد تتذكر أن مجال متصفح الويب لم يبدأ في التغيير كثيرًا حتى ظهر Google Chrome. إذا استخدمت الصوت في صفحة ويب في هذا الوقت ، فسيكون قرار التصميم سيئًا. ولكن منذ ظهور فكرة تجارب الويب ، بدأ صوت الويب يصبح منطقيًا مرة أخرى. تعد متصفحات الويب في الوقت الحاضر أداة أخرى للتعبير الفني ، ويلعب الفيديو والصوت في متصفح الويب دورًا حيويًا فيها.

واجهة برمجة تطبيقات Web Audio: لماذا الإنشاء ومتى يمكنك البرمجة؟

واجهة برمجة تطبيقات Web Audio: لماذا الإنشاء ومتى يمكنك البرمجة؟
سقسقة

قد يكون من الصعب جدًا استخدام Web Audio API لبعض الأغراض ، حيث لا يزال قيد التطوير ، ولكن يوجد بالفعل عدد من مكتبات JavaScript لتسهيل الأمور. في هذه الحالة ، سأوضح لك كيفية بدء استخدام Web Audio API باستخدام مكتبة تسمى Tone.js. باستخدام هذا ، ستتمكن من تغطية معظم احتياجات صوت متصفحك من تعلم الأساسيات فقط.

Hello Web Audio API

ابدء

سنبدأ بدون استخدام المكتبة. ستشمل تجربتنا الأولى عمل ثلاث موجات جيبية. نظرًا لأن هذا سيكون مثالًا بسيطًا ، فسننشئ ملفًا واحدًا فقط باسم hello.html ، وهو ملف HTML خالٍ مع قدر صغير من الترميز.

 <!DOCTYPE html> <html> <head> <meta charset="utf‐8"> <title> Hello web audio </title> </head> <body> </body> <script> </script> </html>

جوهر Web Audio API هو سياق الصوت. سياق الصوت هو كائن يحتوي على كل ما يتعلق بصوت الويب. لا يعتبر وجود أكثر من سياق صوتي في مشروع واحد ممارسة جيدة. سنبدأ بإنشاء مثيل لسياق صوتي باتباع التوصيات التي قدمتها وثائق Web Audio API الخاصة بـ Mozilla.

 var audioCtx = new (window.AudioContext || window.webkitAudioContext);

صنع مذبذب

باستخدام سياق صوتي تم إنشاؤه ، يكون لديك بالفعل مكون صوت: audioCtx.destination. هذا مثل مكبر الصوت الخاص بك. لإصدار صوت ، يجب عليك توصيله بـ audioCtx.destination. الآن لإنتاج بعض الصوت ، لنقم بإنشاء مذبذب:

 var sine = audioCtx.createOscillator();

عظيم ، لكن ليس كافياً. يجب أيضًا أن يتم تشغيله وتوصيله بصيغة audioCtx.

 sine.start(); sine.connect(audioCtx.destination);

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

 //create the context for the web audio var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); //create, tune, start and connect each oscillator sinea, sineb and sinec var sinea = audioCtx.createOscillator(); sinea.frequency.value = 440; sinea.type = "sine"; sinea.start(); sinea.connect(audioCtx.destination); var sineb = audioCtx.createOscillator(); sineb.frequency.value = 523.25; sineb.type = "sine"; sineb.start(); sineb.connect(audioCtx.destination); var sinec = audioCtx.createOscillator(); sinec.frequency.value = 698.46; sinec.type = "sine"; sinec.start(); sinec.connect(audioCtx.destination);

لا تقتصر المذبذبات على الموجات الجيبية ، ولكن يمكن أيضًا أن تكون مثلثات ، وسن المنشار ، ومربع وشكل مخصص ، كما هو مذكور في MDN.

منطق الترقيع من صوت الويب

بعد ذلك ، سنضيف وحدة كسب إلى أوركسترا مكونات Web Audio. تسمح لنا هذه الوحدة بتغيير سعة أصواتنا. إنه أقرب إلى مقبض الصوت. لقد استخدمنا بالفعل وظيفة الاتصال لتوصيل مذبذب بإخراج الصوت. يمكننا استخدام نفس وظيفة الاتصال لتوصيل أي مكون صوتي. إذا كنت تستخدم Firefox ، وألقيت نظرة على وحدة تحكم صوت الويب ، فسترى ما يلي:

إذا أردنا تغيير الحجم ، يجب أن يبدو التصحيح الخاص بنا كما يلي:

مما يعني أن المذبذبات لم تعد متصلة بوجهة الصوت ، ولكن بدلاً من ذلك بوحدة الكسب ، وأن وحدة الكسب هذه متصلة بالوجهة. من الجيد أن تتخيل دائمًا أنك تفعل ذلك بدواسات وكابلات الجيتار. سيبدو الرمز كما يلي:

 var audioCtx = new (window.AudioContext || window.webkitAudioContext) // we create the gain module, named as volume, and connect it to our var volume = audioCtx.createGain(); volume.connect(audioCtx.destination); //these sines are the same, exept for the last connect statement. //Now they are connected to the volume gain module and not to the au var sinea = audioCtx.createOscillator(); sinea.frequency.value = 440; sinea.type = "sine"; sinea.start(); sinea.connect(volume); var sineb = audioCtx.createOscillator(); sineb.frequency.value = 523.25; sineb.type = "sine"; sineb.start(); sineb.connect(volume); var sinec = audioCtx.createOscillator(); sinec.frequency.value = 698.46; sinec.type = "sine"; sinec.start(); sinec.connect(volume); volume.gain.value=0.2;

يمكنك العثور على الحل على https://github.com/autotel/simple-webaudioapi/.

GainNode هي وحدة التأثير الأساسية ، ولكن هناك أيضًا تأخير ، وملفوف ، ومرشح biquadratic ، وبانر ستريو ، ومشكل موجة ، وغيرها الكثير. يمكنك الحصول على تأثيرات جديدة من مكتبات مثل Tone.js.

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

جعل الأمور أسهل مع Tone.js

الآن بعد أن ألقينا نظرة سريعة على كيفية عمل وحدات Vanilla Web Audio ، دعنا نلقي نظرة على إطار عمل Web Audio الرائع: Tone.js. باستخدام هذا (و NexusUI لمكونات واجهة المستخدم) ، يمكننا بسهولة إنشاء المزيد من السماع والأصوات المثيرة للاهتمام. لتجربة الأشياء ، دعنا نصنع عينة ونطبق بعض التأثيرات التفاعلية للمستخدم عليها ، وبعد ذلك سنضيف بعض الضوابط البسيطة لهذه العينة.

Tone.js Sampler

يمكننا البدء بإنشاء هيكل مشروع بسيط:

 simpleSampler |-- js |-- nexusUI.js |-- Tone.js |-- noisecollector_hit4.wav |-- sampler.html

ستوجد مكتبات JavaScript الخاصة بنا في دليل js . لأغراض هذا العرض التوضيحي ، يمكننا استخدام ملف hit4.wav من NoiseCollector والذي يمكن تنزيله من Freesound.org.

يوفر Tone.js وظائفه من خلال كائنات المشغل. القدرة الأساسية للكائن هي تحميل عينة وتشغيلها إما في حلقة أو مرة واحدة. خطوتنا الأولى هنا هي إنشاء كائن مشغل في var “sampler” ، داخل ملف sampler.html:

 <!doctype html> <html> <head> <title> Sampler </title> <script type="text/javascript" src="js/nexusUI.js" ></script> <script type="text/javascript" src="js/Tone.js" ></script> <script> var sampler = new Tone.Player("noisecollector_hit4.wav", function() { console.log("samples loaded"); }); </script> </head> <body> </body> </html>

لاحظ أن المعامل الأول لمنشئ المشغل هو اسم ملف WAV ، والثاني هو وظيفة رد الاتصال. WAV ليس هو نوع الملف الوحيد المدعوم ، ويعتمد التوافق على متصفح الويب أكثر من المكتبة. سيتم تشغيل وظيفة رد الاتصال عندما ينتهي المشغل من تحميل العينة في المخزن المؤقت الخاص به.

علينا أيضًا توصيل جهاز أخذ العينات الخاص بنا بالمخرجات. طريقة Tone.js للقيام بذلك هي:

 sampler.toMaster();

... حيث يكون sampler كائن Tone.Player ، بعد السطر 10. وظيفة toMaster هي اختصار للاتصال (Tone.Master).

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

 <canvas nx="button"></canvas>

يجب أن تشاهد الآن زرًا مستديرًا يتم تقديمه في المستند. لبرمجتها لتشغيل العينة الخاصة بنا ، نضيف مستمع NexusUI ، والذي يبدو كالتالي:

 button1.on('*',function(data) { console.log("button pressed!"); })

الشيء المميز في NexusUI هو أنه ينشئ متغيرًا شاملاً لكل عنصر من عناصر NexusUI. يمكنك تعيين NexusUI على عدم القيام بذلك ، وبدلاً من ذلك يكون لديك هذه المتغيرات فقط في nx.widgets [] عن طريق تعيين nx.globalWidgets على false. سنقوم هنا بإنشاء عنصرين فقط ، لذلك سنلتزم فقط بهذا السلوك.

كما هو الحال في jQuery ، يمكننا وضع هذه على أحداث ، وستكون الوسيطة الأولى هي اسم الحدث. هنا نقوم فقط بتعيين وظيفة لكل ما يتم القيام به على الزر. هذا كل ما هو مكتوب على أنه "*". يمكنك معرفة المزيد حول الأحداث لكل عنصر في NexusUI API. لتشغيل العينة بدلاً من تسجيل الرسائل عندما نضغط على الزر ، يجب علينا تشغيل وظيفة البدء الخاصة بأخذ العينات.

 nx.onload = function() { button1.on('*',function(data) { console.log("button pressed!"); sampler.start(); }); }

لاحظ أيضًا أن المستمع يدخل داخل رد اتصال onload. يتم رسم عناصر NexusUI في لوحة الرسم ، ولا يمكنك الرجوع إليها حتى يستدعي nx وظيفة onload. تمامًا كما تفعل مع عناصر DOM في jQuery.

يتم تشغيل الحدث عند تمرير الماوس لأسفل وعند التحرير. إذا كنت تريد أن يتم تشغيله عند الضغط فقط ، فعليك تقييم ما إذا كان event.press يساوي واحدًا.

مع هذا ، يجب أن يكون لديك زر يقوم بتشغيل العينة في كل ضغطة. إذا قمت بضبط sampler.retrigger على true ، فسوف يسمح لك بتشغيل العينة بغض النظر عما إذا كان يتم تشغيله أم لا. خلاف ذلك ، عليك الانتظار حتى تنتهي العينة لإعادة تحريكها.

تطبيق التأثيرات

باستخدام Tone.js ، يمكننا بسهولة إنشاء تأخير:

 var delay= new Tone.FeedbackDelay("16n",0.5).toMaster();

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

تتمثل الخطوة التالية في فصل جهاز أخذ العينات من الجهاز الرئيسي وتوصيله بدلاً من ذلك بالتأخير. قم بتعديل الخط حيث يتم توصيل جهاز أخذ العينات بالسيد:

 sampler.connect(delay);

الآن جرب الزر مرة أخرى وشاهد الفرق.

بعد ذلك ، سنضيف قرصين إلى نص وثيقتنا:

 <canvas nx="dial"></canvas> <canvas nx="dial"></canvas>

ونطبق قيم الأوجه على تأثير التأخير باستخدام NexusUIlistener:

 dial1.on('*',function(data) { delay.delayTime.value=data.value; }) dial2.on('*',function(data) { delay.feedback.value=data.value; })

يمكن العثور على المعلمات التي يمكنك تعديلها في كل حدث في وثائق Tone.js. للتأخير ، إنه هنا. أنت الآن جاهز لتجربة المثال وتعديل معلمات التأخير باستخدام طلبات NexusUI. يمكن إجراء هذه العملية بسهولة مع كل عنصر من عناصر NexusUI ، ولا يقتصر على التأثيرات فقط. على سبيل المثال ، حاول أيضًا إضافة قرص آخر وإضافة المستمع الخاص به على النحو التالي:

 dial3.on('*',function(data) { sampler.playbackRate=data.value; })

يمكنك العثور على هذه الملفات على github.com/autotel/simpleSampler

خاتمة

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

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


مزيد من القراءة على مدونة Toptal Engineering:

  • WebAssembly / البرنامج التعليمي حول الصدأ: معالجة صوت مثالية
  • دروس MIDI: إنشاء تطبيقات صوتية مستندة إلى المستعرض يتم التحكم فيها بواسطة أجهزة MIDI