تکنیک های پیشرفته: ایجاد و توالی صوتی

  • 2021-06-22

در این آموزش ، ما قصد داریم ایجاد صدا و اصلاح صدا و همچنین زمان بندی و برنامه ریزی را پوشش دهیم. ما نمونه بارگذاری ، پاکت نامه ها ، فیلترها ، موج های موج و مدولاسیون فرکانس را معرفی خواهیم کرد. اگر با این شرایط آشنا هستید و به دنبال معرفی برنامه آنها با API صوتی وب هستید ، به جای مناسب رسیده اید.

توجه: می توانید کد منبع نسخه ی نمایشی زیر را در GitHub در زیر مجموعه Step-Tequencer از Repo MDN WebAudio-Examples پیدا کنید. همچنین می توانید نسخه ی نمایشی زنده را ببینید.

ما قصد داریم به دنبال یک ترتیب سنج مرحله ای بسیار ساده باشیم:

A sound sequencer application featuring play and BPM master controls and 4 different voices with controls for each.

در عمل ، این کار با یک کتابخانه آسانتر است - API صوتی وب ساخته شده است که بر روی آن ساخته می شود. اگر می خواهید در ساخت چیزی پیچیده تر شروع کنید ، Tone. js مکانی عالی برای شروع خواهد بود. با این حال ، ما می خواهیم نشان دهیم که چگونه می توان چنین نسخه ی نمایشی را از اصول اول به عنوان یک تمرین یادگیری ایجاد کرد.

رابط کاربری شامل کنترل های اصلی است که به ما امکان می دهد ترتیب سنج را بازی یا متوقف کنیم و BPM (ضربان در دقیقه) را تنظیم کنیم تا سرعت یا کند شدن "موسیقی" سرعت یا سرعت یابد.

چهار صدای مختلف یا صدای مختلف قابل پخش است. هر صدا چهار دکمه دارد ، یکی برای هر ضرب و شتم در یک نوار موسیقی. وقتی آنها فعال شوند ، یادداشت صدا خواهد شد. هنگامی که ساز پخش می شود ، در این مجموعه از ضربان ها حرکت می کند و نوار را حلقه می کند.

هر صدا همچنین دارای کنترل های محلی است و به شما امکان می دهد تا اثرات یا پارامترهای خاصی را برای هر تکنیکی که برای ایجاد آن صداها استفاده می کنیم دستکاری کنید. روش هایی که ما استفاده می کنیم عبارتند از:

نام تکنیک ویژگی API صوتی وب مرتبط
"جارو کردن" نوسان ساز ، موج دوره ای Oslatornode ، TeURICWAVE
"نبض" اسیلاتور چندگانه نوسان
"سر و صدا" بافر نویز تصادفی ، فیلتر Biquad کتاب صوتی ، کتاب صوتی ، کتاب صوتی ، biquadfilternode
"شماره گیری" بارگیری یک نمونه صدا برای پخش baseaudiocontext/decodeaudiodata ، audiobuffersourcenode

توجه: ما این ساز را ایجاد نکردیم تا خوب به نظر برسد اما کد تظاهرات را ارائه دهیم. این تظاهرات یک نسخه بسیار ساده از چنین ابزاری را نشان می دهد. صداها بر اساس مودم شماره گیری است. اگر از نحوه صدا چنین دستگاهی آگاه نیستید ، می توانید در اینجا به یکی گوش دهید.

ایجاد یک زمینه صوتی

همانطور که باید در حال حاضر مورد استفاده قرار گیرد ، هر برنامه API صوتی وب با یک زمینه صوتی شروع می شود:

"جارو" - نوسان سازها ، امواج دوره ای و پاکت نامه ها

برای آنچه ما صدای "جارو" می نامیم ، اولین سر و صدایی که هنگام شماره گیری می شنوید ، می خواهیم یک نوسان ساز برای تولید صدا ایجاد کنیم.

Oslatornode با شکل موج های اساسی خارج از جعبه - سینوسی ، مربع ، مثلث یا اره. با این حال ، به جای استفاده از امواج استاندارد که به طور پیش فرض می آیند ، می خواهیم با استفاده از رابط و مقادیر تنظیم شده در یک موج قابل استفاده ، خودمان را ایجاد کنیم. ما می توانیم از سازنده دوره ای () () برای استفاده از این موج سفارشی با نوسان ساز استفاده کنیم.

موج تناوبی

اول از همه ، موج دوره ای خود را ایجاد خواهیم کرد. برای انجام این کار ، ما باید مقادیر واقعی و خیالی را به سازنده دوره ای () () منتقل کنیم:

توجه: در مثال ما ، WaveTable در یک پرونده JavaScript جداگانه (Wavetable. js) برگزار می شود زیرا مقادیر زیادی وجود دارد. ما آن را از مخزن Wavetables ، که در نمونه های API API صوتی وب از آزمایشگاه های Google Chrome یافت می شود ، گرفتیم.

نوسان ساز

اکنون می توانیم یک Oslatornode ایجاد کنیم و موج آن را به روشی که ما ایجاد کرده ایم تنظیم کنیم:

ما یک پارامتر زمان را به عملکرد در اینجا منتقل می کنیم ، که بعداً برای برنامه ریزی رفت و برگشت استفاده خواهیم کرد.

دامنه کنترل کننده

این عالی است ، اما اگر یک پاکت دامنه داشتیم که با آن برویم خوب نیست؟بیایید یک ساده ایجاد کنیم ، بنابراین ما به روش هایی که برای ایجاد یک پاکت با API صوتی وب نیاز داریم عادت می کنیم.

بیایید بگوییم پاکت ما حمله و آزادی دارد. ما می توانیم به کاربر اجازه دهیم که این موارد را با استفاده از ورودی های محدوده در رابط کنترل کند:

اکنون می توانیم برخی از متغیرها را در JavaScript ایجاد کنیم و هنگام به روزرسانی مقادیر ورودی ، آنها را تغییر دهیم:

عملکرد نهایی Playsweep ()

اکنون می توانیم عملکرد نمایشنامه () خود را گسترش دهیم. ما باید یک GainNode را اضافه کنیم و آن را از طریق نمودار صوتی خود وصل کنیم تا تغییرات دامنه را به صدای خود اعمال کنیم. گره Gain دارای یک ویژگی است: GAIN که از نوع Audioparam است.

این مفید است - اکنون می توانیم از قدرت روشهای پارامی صوتی در مقدار افزایش استفاده کنیم. ما می توانیم یک مقدار را در یک زمان خاص تعیین کنیم ، یا می توانیم آن را به مرور زمان با روشهایی مانند Audioparam. linearramptovalueattime تغییر دهیم.

همانطور که در بالا ذکر شد ، ما از روش LinearRamptovalueattime برای حمله و انتشار خود استفاده خواهیم کرد. این دو پارامتر طول می کشد - مقداری که می خواهید پارامتر مورد نظر خود را تنظیم کنید (در این حالت سود) و هنگامی که می خواهید این کار را انجام دهید. در مورد ما که توسط ورودی های ما کنترل می شود. بنابراین ، در مثال زیر ، افزایش با سرعت خطی در طی زمان ورودی محدوده حمله به 1 افزایش می یابد. به طور مشابه ، برای انتشار ما ، سود با نرخ خطی 0 تنظیم می شود ، با گذشت زمان ورودی انتشار.

"پالس"-مدولاسیون نوسان ساز با فرکانس پایین

عالی ، حالا ما جارو خود را گرفتیم! بیایید حرکت کنیم و نگاهی به آن صدای پالس خوب بیندازیم. ما می توانیم با یک نوسان ساز اصلی ، با یک نوسان ساز دوم ، به این هدف برسیم.

نوسان ساز اولیه

ما اولین Oslatornode خود را به همان روشی که صدای جارو خود را تنظیم می کنیم تنظیم خواهیم کرد ، به جز اینکه از WaveTable برای تنظیم موج موزون استفاده نمی کنیم - ما فقط از موج پیش فرض سینوسی استفاده خواهیم کرد:

اکنون می خواهیم یک GainNode ایجاد کنیم ، زیرا این مقدار سود است که با نوسان ساز دوم و با فرکانس پایین خود نوسان خواهیم کرد:

ایجاد نوسان ساز دوم و با فرکانس پایین

ما اکنون یک نوسان ساز موج دوم (مربع - موج (یا پالس) ایجاد خواهیم کرد تا تقویت اولین موج سینوسی خود را تغییر دهیم:

اتصال نمودار

نکته اصلی در اینجا اتصال به درستی نمودار و همچنین شروع هر دو نوسان ساز است:

توجه: ما همچنین نیازی به استفاده از انواع موج پیش فرض برای هر یک از این نوسانگرهایی که ایجاد می کنیم استفاده نمی کنیم - می توانیم مانند گذشته از WaveTable و روش موج دوره ای استفاده کنیم. تعداد زیادی از امکانات با حداقل گره وجود دارد.

کنترل کاربر نبض

برای کنترل های UI ، بیایید هر دو فرکانس نوسان ساز خود را در معرض دید قرار دهیم و به آنها اجازه می دهیم از طریق ورودی های محدوده کنترل شوند. یکی لحن را تغییر می دهد و دیگری تغییر می کند که چگونه پالس موج اول را تعدیل می کند:

مانند گذشته ، وقتی کاربر مقادیر دامنه را تغییر می دهد ، پارامترها را تغییر خواهیم داد.

عملکرد نهایی PlayPulse ()

در اینجا کل عملکرد PlayPulse () وجود دارد:

"نویز" - بافر نویز تصادفی با فیلتر Biquad

حال باید سر و صدایی ایجاد کنیم! همه مودم ها سر و صدا دارند. نویز فقط اعداد تصادفی در هنگام داده های صوتی است ، بنابراین ، یک چیز نسبتاً ساده برای ایجاد با کد است.

ایجاد یک بافر صوتی

ما باید یک ظرف خالی ایجاد کنیم تا این شماره ها را در آن قرار دهیم ، با این حال ، API صوتی وب می فهمد. این جایی است که اشیاء صوتی وارد می شوند. می توانید یک پرونده را واکشی کرده و آن را در یک بافر رمزگشایی کنید (بعداً در آموزش به آن خواهیم رسید) ، یا می توانید یک بافر خالی ایجاد کرده و آن را با داده های خود پر کنید.

برای سر و صدا ، بیایید دومی را انجام دهیم. برای ایجاد آن ابتدا باید اندازه بافر خود را محاسبه کنیم. ما می توانیم از ویژگی های baseaudiocontext. samplate برای این کار استفاده کنیم:

اکنون می توانیم آن را با اعداد تصادفی بی ن-1 تا 1 پر کنیم:

توجه: چر ا-1 تا 1؟هنگام خروج صدا به یک پرونده یا بلندگو ، ما به یک عدد به نمایندگی از مقیاس کامل 0 dB نیاز داریم - حد عددی رسانه نقطه ثابت یا DAC. در Audio Point Floating ، 1 یک عدد مناسب برای نقشه برداری به "مقیاس کامل" برای عملیات ریاضی بر روی سیگنال ها است ، بنابراین نوسان سازها ، ژنراتورهای نویز و سایر منابع صوتی به طور معمول سیگنال های دو قطبی خروجی در محدود ه-1 تا 1. یک مرورگر مقادیر را گیره می کندخارج از این محدوده

ایجاد منبع بافر

اکنون ما بافر صوتی داریم و آن را با داده ها پر کرده ایم. ما به یک گره نیاز داریم تا به نمودار خود اضافه کنیم که می تواند از بافر به عنوان منبع استفاده کند. ما برای این کار یک کتاب صوتی ایجاد خواهیم کرد و داده هایی را که ایجاد کرده ایم منتقل می کنیم:

وقتی این کار را از طریق نمودار صوتی خود وصل می کنیم و آن را پخش می کنیم:

متوجه خواهید شد که بسیار تند و تیز است. ما سر و صدای سفید ایجاد کرده ایم. اینگونه باید باشد. مقادیر ما ا ز-1 به 1 پخش می شود ، به این معنی که ما قله های همه فرکانس ها را داریم که در واقع کاملاً چشمگیر و سوراخ کننده هستند. ما می توانیم تابع را فقط مقادیر گسترش از 0. 5 ت ا-0. 5 تغییر دهیم یا شبیه به قله ها از بین بروند و ناراحتی را کاهش دهند. با این حال ، سرگرمی در آن کجاست؟بیایید سر و صدایی را که از طریق یک فیلتر ایجاد کرده ایم مسیریابی کنیم.

اضافه کردن یک فیلتر Biquad به مخلوط

ما چیزی را در محدوده سر و صدای صورتی یا قهوه ای می خواهیم. ما می خواهیم آن فرکانس های بالا و احتمالاً برخی از موارد پایین را قطع کنیم. بیایید یک فیلتر Bandpass Biquad را برای کار انتخاب کنیم.

توجه: API صوتی وب دارای دو نوع گره فیلتر است: BiquadFilternode و IIRFilternode. در بیشتر موارد ، یک فیلتر Biquad به اندازه کافی خوب خواهد بود - از انواع مختلفی مانند Lowpass ، HighPass و Bandpass همراه است. اگر به دنبال انجام کاری بیشتر هستید ، با این حال ، فیلتر IIR ممکن است گزینه خوبی باشد - برای اطلاعات بیشتر به استفاده از فیلترهای IIR مراجعه کنید.

سیم کشی این همان چیزی است که قبلاً دیدیم. ما BiquadFilternode را ایجاد می کنیم ، خواص مورد نظر خود را پیکربندی می کنیم و آن را از طریق نمودار خود وصل می کنیم. انواع مختلف فیلترهای Biquad دارای خصوصیات مختلفی هستند - به عنوان مثال ، تنظیم فرکانس در یک نوع باند فرکانس میانی را تنظیم می کند. با این حال ، در سطح پایین ، فرکانس بالایی را تعیین می کند.

کنترل کاربر سر و صدا

در رابط کاربری ، مدت زمان نویز و فرکانس مورد نظر ما را در معرض خطر قرار می دهیم و به کاربر امکان می دهد آنها را از طریق ورودی های محدوده و دستیار رویداد درست مانند بخش های قبلی تنظیم کند:

عملکرد نهایی Playnoise ()

در اینجا کل عملکرد Playnoise () وجود دارد:

"شماره گیری"-بارگذاری یک نمونه صدا

شبیه سازی صداهای شماره گیری تلفن (DTMF) با پخش چند نوسانگر با هم و با استفاده از روش هایی که قبلاً استفاده کرده ایم، به اندازه کافی ساده است. در عوض، ما یک فایل نمونه را در این بخش بارگذاری می کنیم تا ببینیم چه چیزی در این مورد وجود دارد.

در حال بارگیری نمونه

ما می خواهیم مطمئن شویم که فایل ما قبل از استفاده از آن بارگیری شده و در یک بافر رمزگشایی شده است، بنابراین بیایید یک تابع async ایجاد کنیم تا به ما اجازه انجام این کار را بدهد:

سپس می‌توانیم هنگام فراخوانی این تابع از اپراتور await استفاده کنیم، که تضمین می‌کند که فقط زمانی می‌توانیم کد بعدی را اجرا کنیم که اجرای آن به پایان رسید.

بیایید یک تابع همگام دیگر برای تنظیم نمونه ایجاد کنیم - می‌توانیم دو تابع همگام را در یک الگوی نوید دوست‌داشتنی با هم ترکیب کنیم تا در هنگام بارگیری و بافر کردن این فایل، اقدامات بعدی را انجام دهیم:

توجه: به راحتی می توانید تابع بالا را تغییر دهید تا آرایه ای از فایل ها را بگیرید و روی آنها حلقه بزنید تا بیش از یک نمونه بارگذاری شود. این تکنیک برای ابزارهای پیچیده تر یا بازی مناسب است.

اکنون می توانیم از setupSample () مانند این استفاده کنیم:

هنگامی که نمونه برای پخش آماده شد، برنامه رابط کاربری را تنظیم می کند، بنابراین آماده اجرا است.

در حال پخش نمونه

بیایید یک تابع playSample() مشابه آنچه که با صداهای دیگر انجام دادیم ایجاد کنیم. این بار یک AudioBufferSourceNode ایجاد می کنیم، داده های بافری را که واکشی و رمزگشایی کرده ایم در آن قرار می دهیم و آن را پخش می کنیم:

توجه: ما می‌توانیم stop() را در AudioBufferSourceNode فراخوانی کنیم، با این حال، زمانی که نمونه به پایان رسید، این به طور خودکار اتفاق می‌افتد.

کنترل های کاربر شماره گیری

AudioBufferSourceNode دارای ویژگی playbackRate است. بیایید آن را در UI خود قرار دهیم تا بتوانیم سرعت نمونه خود را افزایش داده و کاهش دهیم. ما این کار را به همان روش قبلی انجام خواهیم داد:

تابع ()playSample نهایی

سپس یک خط برای به روز رسانی ویژگی playbackRate به تابع ()playSample خود اضافه می کنیم. نسخه نهایی به شکل زیر است:

توجه: فایل صوتی از soundbible. com تهیه شده است.

پخش صدا به موقع

یک مشکل رایج در برنامه های صوتی دیجیتال پخش به موقع صداها است تا ضرب آهنگ ثابت بماند و چیزها از زمان خارج نشوند.

می‌توانیم صداهایمان را برای پخش در یک حلقه for برنامه‌ریزی کنیم. با این حال، بزرگترین مشکل با این به روز رسانی در حین بازی است، و ما قبلاً کنترل های UI را برای انجام این کار پیاده سازی کرده ایم. همچنین، بسیار خوب است که یک کنترل BPM در سطح ابزار را در نظر بگیرید. بهترین راه برای واداشتن صدایمان به اجرای آهنگ این است که یک سیستم زمان بندی ایجاد کنیم که به موجب آن به زمان پخش نت ها به آینده نگاه می کنیم و آنها را در صف قرار می دهیم. ما می‌توانیم آنها را در زمان دقیقی با ویژگی currentTime شروع کنیم و همچنین هرگونه تغییر را در نظر بگیریم.

توجه: این یک نسخه بسیار ساده از مقاله کریس ویلسون A Tale Of Two Clocks (2013) است که با جزئیات بسیار بیشتری به این روش می‌پردازد. تکرار همه چیز در اینجا فایده ای ندارد، اما خواندن این مقاله و استفاده از این روش را به شدت توصیه می کنیم. بسیاری از کدهای اینجا از نمونه مترونوم او گرفته شده است، که او در مقاله به آن اشاره می کند.

بیایید با تنظیم BPM پیش‌فرض (ضربان در دقیقه) شروع کنیم، که از طریق - حدس زدید - ورودی محدوده دیگری نیز توسط کاربر قابل کنترل خواهد بود.

سپس متغیرهایی ایجاد می کنیم تا مشخص کنیم که چقدر جلوتر می خواهیم نگاه کنیم و چقدر جلوتر می خواهیم برنامه ریزی کنیم:

بیایید تابعی ایجاد کنیم که نت را با یک ضرب به جلو حرکت می‌دهد و وقتی به عدد چهارم (آخرین) رسید، به اولین حلقه بازمی‌گردد:

ما می‌خواهیم یک صف مرجع برای نت‌هایی که قرار است پخش شوند، و قابلیت پخش آنها با استفاده از توابعی که قبلا ایجاد کرده‌ایم ایجاد کنیم:

در اینجا به زمان فعلی نگاه می کنیم و آن را با زمان یادداشت زیر مقایسه می کنیم. وقتی این دو با هم مطابقت داشته باشند، دو تابع قبلی را فراخوانی می کند.

نمونه‌های شیء AudioContext دارای ویژگی currentTime هستند که به ما اجازه می‌دهد تا تعداد ثانیه‌های پس از ایجاد زمینه را برای اولین بار بازیابی کنیم. ما از آن برای زمان بندی در ترتیب سنج گام خود استفاده خواهیم کرد. بسیار دقیق است و مقدار شناور را با دقت حدود 15 رقم اعشار برمی گرداند.

ما همچنین به یک تابع draw() برای به روز رسانی رابط کاربری نیاز داریم، بنابراین می توانیم ببینیم چه زمانی ضربان پیشرفت می کند.

همه اش را بگذار کنار هم

اکنون تنها کاری که باید انجام دهید این است که مطمئن شوید نمونه را قبل از نواختن ساز بارگذاری کرده ایم. ما یک صفحه بارگیری اضافه می کنیم که وقتی فایل واکشی و رمزگشایی شد ناپدید می شود. سپس می‌توانیم به زمان‌بندی اجازه دهیم تا از رویداد کلیک دکمه پخش استفاده کند.

خلاصه

ما اکنون یک ابزار در داخل مرورگر خود داریم! به بازی و آزمایش ادامه دهید - می توانید هر یک از این تکنیک ها را گسترش دهید تا چیزی بسیار دقیق تر ایجاد کنید.

ثبت دیدگاه

مجموع دیدگاهها : 0در انتظار بررسی : 0انتشار یافته : ۰
قوانین ارسال دیدگاه
  • دیدگاه های ارسال شده توسط شما، پس از تایید توسط تیم مدیریت در وب منتشر خواهد شد.
  • پیام هایی که حاوی تهمت یا افترا باشد منتشر نخواهد شد.
  • پیام هایی که به غیر از زبان فارسی یا غیر مرتبط باشد منتشر نخواهد شد.