डिजिटल नॉइज़ जनरेटर कैसे काम करते हैं

नींव: छद्म-यादृच्छिक संख्या उत्पादन

WhiteNoise.top पर नॉइज़ इंजन बनाने के मेरे काम में, मैंने गणितीय यादृच्छिकता को विश्वसनीय ऑडियो में बदलने वाली पाइपलाइन को अनुकूलित करने में सैकड़ों घंटे बिताए हैं। हर डिजिटल नॉइज़ जनरेटर एक ही मौलिक घटक से शुरू होता है: एक छद्म-यादृच्छिक संख्या जनरेटर, या PRNG। PRNG एक एल्गोरिथम है जो संख्याओं का एक नियतात्मक अनुक्रम उत्पन्न करता है जो सांख्यिकीय परीक्षणों के अनुसार यादृच्छिक प्रतीत होता है। हार्डवेयर एंट्रॉपी स्रोतों से सच्ची यादृच्छिकता रियल-टाइम ऑडियो के लिए बहुत धीमी और अप्रत्याशित है, इसलिए PRNG सभी डिजिटल नॉइज़ उत्पादन के लिए व्यावहारिक आधार प्रदान करते हैं।

ऑडियो कार्य के लिए उपयुक्त सबसे बुनियादी PRNG लीनियर कॉन्ग्रुएंशियल जनरेटर (LCG) है, जो प्रत्येक मान की गणना पिछले मान के एक रैखिक फंक्शन के रूप में, एक बड़े स्थिरांक के मॉड्यूलो से करता है। तेज़ होते हुए भी, LCG में ज्ञात कमज़ोरियाँ हैं: वे क्रमिक नमूनों के बीच सहसंबंध प्रदर्शित करते हैं जो नॉइज़ सिग्नल में श्रव्य आर्टिफैक्ट्स उत्पन्न कर सकते हैं। मेरे शुरुआती प्रोटोटाइप में, मैंने एक साधारण LCG का उपयोग किया और उच्च-गुणवत्ता वाले हेडफोन के माध्यम से सुनते समय आउटपुट में हल्के आवधिक पैटर्न सुन सकता था। ये पैटर्न FFT विश्लेषण में संकीर्ण स्पेक्ट्रल शिखरों के रूप में दिखाई दिए, जो पुष्टि करते हैं कि PRNG की सांख्यिकीय कमज़ोरियाँ ऑडियो डोमेन में लीक हो रही थीं।

उत्पादन-गुणवत्ता के नॉइज़ के लिए, मैंने xorshift128+ एल्गोरिथम पर स्विच किया, जो अधिकांश JavaScript इंजनों द्वारा Math.random() के लिए आंतरिक रूप से उपयोग किया जाने वाला PRNG है। इसका पीरियड 2 की 128वीं शक्ति माइनस 1 है, उत्कृष्ट सांख्यिकीय गुण हैं, और नगण्य कम्प्यूटेशनल लागत है। जब मैं इसके आउटपुट पर TestU01 यादृच्छिकता परीक्षणों की बैटरी चलाता हूँ, तो यह SmallCrush और Crush सुइट्स के सभी परीक्षण पास करता है। परिणाम श्रव्य आर्टिफैक्ट्स से मुक्त एक नॉइज़ सिग्नल है, जिसमें श्रव्य रेंज में 0.3 dB के भीतर सत्यापित समतल स्पेक्ट्रम है।

यादृच्छिक संख्याओं से ऑडियो सैंपल तक

PRNG संख्याएँ उत्पन्न करता है, लेकिन एक ऑडियो सिस्टम को विशिष्ट आयामों और सैंपल दरों पर तरंगरूप सैंपल की आवश्यकता होती है। रूपांतरण प्रक्रिया में स्केलिंग, वितरण आकार देना और बफर प्रबंधन शामिल है। मेरे कार्यान्वयन में, PRNG अहस्ताक्षरित 32-बिट पूर्णांक आउटपुट करता है, जिन्हें मैं फिर माइनस एक से प्लस एक की रेंज में फ्लोटिंग-पॉइंट मानों में सामान्यीकृत करता हूँ। यह Web Audio API और अधिकांश अन्य ऑडियो फ्रेमवर्क में डिजिटल ऑडियो के लिए मानक आयाम रेंज है।

यादृच्छिक मानों का वितरण नॉइज़ के चरित्र के लिए महत्वपूर्ण है। एक समान वितरण, जहाँ रेंज में सभी मान समान रूप से संभावित हैं, एनालॉग सर्किट में थर्मल नॉइज़ की विशेषता गाउसियन वितरण से थोड़ा भिन्न आयाम वितरण वाला नॉइज़ उत्पन्न करता है। व्यवहार में, अंतर सूक्ष्म है: समान व्हाइट नॉइज़ का क्रेस्ट फैक्टर लगभग 4.8 dB है, जबकि गाउसियन व्हाइट नॉइज़ का सैद्धांतिक रूप से असीमित क्रेस्ट फैक्टर है, हालाँकि व्यवहार में यह विशिष्ट बफर लंबाई के लिए लगभग 12 dB है। अधिकांश अनुप्रयोगों के लिए, समान वितरण पूरी तरह से स्वीकार्य और कम्प्यूटेशनल रूप से सरल है।

जब मुझे उन अनुप्रयोगों के लिए गाउसियन-वितरित नॉइज़ की आवश्यकता होती है जो इसकी माँग करते हैं, तो मैं Box-Muller ट्रांसफॉर्म का उपयोग करता हूँ, जो समान रूप से वितरित यादृच्छिक संख्याओं के जोड़े को गाउसियन-वितरित मानों के जोड़े में परिवर्तित करता है। कम्प्यूटेशनल ओवरहेड मामूली है, लगभग प्रति-सैंपल लागत को दोगुना करता है, लेकिन परिणाम एक ऐसा नॉइज़ सिग्नल है जो एनालॉग नॉइज़ स्रोतों के आयाम आँकड़ों से अधिक निकटता से मेल खाता है। सुनने के परीक्षणों में, समान और गाउसियन व्हाइट नॉइज़ के बीच का अंतर लगभग अश्रव्य है, लेकिन गाउसियन वैरिएंट कुछ सिग्नल प्रोसेसिंग अनुप्रयोगों में बेहतर प्रदर्शन करता है जहाँ आयाम आँकड़े मायने रखते हैं।

स्पेक्ट्रल शेपिंग: व्हाइट को रंगों में बदलना

व्हाइट नॉइज़ वह कच्चा माल है जिससे अन्य सभी नॉइज़ रंग बनाए जाते हैं। परिवर्तन डिजिटल फ़िल्टरिंग के माध्यम से पूरा किया जाता है, व्हाइट नॉइज़ स्पेक्ट्रम पर आवृत्ति-निर्भर गेन कर्व लागू करना। मेरे नॉइज़ इंजन में, मैं IIR (इनफिनिट इम्पल्स रिस्पॉन्स) और FIR (फाइनाइट इम्पल्स रिस्पॉन्स) दोनों फिल्टर का उपयोग करके स्पेक्ट्रल शेपिंग लागू करता हूँ, प्रत्येक के अलग-अलग फायदे हैं।

पिंक नॉइज़ (माइनस तीन डेसिबल प्रति ऑक्टेव ढलान) के लिए, मैं अपनी प्राथमिक विधि के रूप में Voss-McCartney एल्गोरिथम का उपयोग करता हूँ। यह एल्गोरिथम विभिन्न दरों पर अपडेट होने वाले कई स्वतंत्र यादृच्छिक संख्या जनरेटर बनाए रखता है: एक हर सैंपल अपडेट होता है, एक हर दो सैंपल, एक हर चार सैंपल, और इसी तरह आगे। आउटपुट को जोड़ा जाता है ताकि एक ऐसा सिग्नल उत्पन्न हो जिसका स्पेक्ट्रम आदर्श पिंक नॉइज़ ढलान का अनुमान लगाता है। मेरे कार्यान्वयन में, मैं 16 ऑक्टेव परतों का उपयोग करता हूँ, जो 1 Hz से नीचे से 20 kHz से ऊपर तक सटीक स्पेक्ट्रल शेपिंग प्रदान करता है। आदर्श ढलान के सापेक्ष त्रुटि श्रव्य रेंज में 0.5 dB से कम है।

ब्राउन नॉइज़ (माइनस छह डेसिबल प्रति ऑक्टेव ढलान) के लिए, मैं सरल एकीकरण का उपयोग करता हूँ: प्रत्येक आउटपुट सैंपल पिछले आउटपुट और एक नए व्हाइट-नॉइज़ सैंपल का योग है, जिसे एक छोटे गुणांक से स्केल किया जाता है। गणितीय रूप से, यह एक प्रथम-क्रम IIR लो-पास फिल्टर है जिसमें यूनिट सर्कल पर एक के बहुत करीब एक पोल है। इस दृष्टिकोण की चुनौती DC ड्रिफ्ट है: चलता योग समय के साथ शून्य से दूर भटक सकता है, अंततः क्लिपिंग सीमा को पार कर सकता है। मैं 5 Hz पर एक बहुत हल्का प्रथम-क्रम हाई-पास फिल्टर जोड़कर इसे हल करता हूँ, जो 20 Hz से ऊपर स्पेक्ट्रम को श्रव्य रूप से प्रभावित किए बिना ड्रिफ्ट को रोकता है।

उन्नत उपयोगकर्ताओं द्वारा अनुरोधित कस्टम स्पेक्ट्रल आकारों के लिए, मैं कैस्केडेड सेकंड-ऑर्डर बाइक्वाड फिल्टर अनुभागों से निर्मित एक पैरामेट्रिक इक्वलाइज़र का उपयोग करता हूँ। प्रत्येक अनुभाग एक मानक फिल्टर प्रकार (पीक, लो शेल्फ, हाई शेल्फ, या नॉच) को उपयोगकर्ता-समायोज्य आवृत्ति, गेन और बैंडविड्थ पैरामीटर के साथ लागू करता है। चार से छह अनुभागों को चेन करके, मैं वस्तुतः किसी भी चिकने स्पेक्ट्रल आकार का अनुमान लगा सकता हूँ जो कोई उपयोगकर्ता चाहता हो, कोमल झुकाव से लेकर जटिल बहु-बैंड समोच्चों तक।

Web Audio API के साथ रियल-टाइम उत्पादन

Web Audio API, जो सभी आधुनिक ब्राउज़रों में उपलब्ध है, बिना किसी सर्वर-साइड प्रोसेसिंग के रियल टाइम में नॉइज़ उत्पन्न करने और बजाने के लिए बुनियादी ढाँचा प्रदान करता है। WhiteNoise.top पर मेरे कार्यान्वयन में, मैं तीन मुख्य Web Audio API घटकों का उपयोग करता हूँ: AudioContext, ScriptProcessorNode (या इसका आधुनिक प्रतिस्थापन, AudioWorkletNode), और BiquadFilterNode।

AudioWorkletNode वह स्थान है जहाँ मुख्य उत्पादन होता है। मैं एक कस्टम AudioWorkletProcessor पंजीकृत करता हूँ जो मुख्य ब्राउज़र थ्रेड से अलग थ्रेड पर चलता है, यह सुनिश्चित करता है कि UI इंटरैक्शन ऑडियो गड़बड़ियों का कारण नहीं बनें। प्रोसेसर की process() विधि को आउटपुट बफर के साथ बार-बार कॉल किया जाता है, आमतौर पर 44.1 kHz पर प्रति कॉल 128 सैंपल। इस विधि के अंदर, मैं PRNG का उपयोग करके व्हाइट नॉइज़ सैंपल उत्पन्न करता हूँ, कोई भी स्पेक्ट्रल शेपिंग लागू करता हूँ, और परिणामों को आउटपुट बफर में लिखता हूँ। पूरी पाइपलाइन आधुनिक हार्डवेयर पर प्रति बफर लगभग 0.01 मिलीसेकंड में चलती है, जो गड़बड़ी-मुक्त प्लेबैक के लिए लगभग तीन-मिलीसेकंड की समय सीमा के भीतर है।

बफर प्रबंधन श्रव्य आर्टिफैक्ट्स से बचने के लिए महत्वपूर्ण है। यदि प्रोसेसर बफर भरने में बहुत अधिक समय लेता है, तो ऑडियो आउटपुट अंडररन करता है, जिससे क्लिक या पॉप उत्पन्न होता है। मेरे स्ट्रेस टेस्टिंग में, मैं मुख्य थ्रेड में कम्प्यूटेशनल लोड जोड़कर (जैसे भारी DOM मैनिपुलेशन या बड़े JSON पार्सिंग) सिस्टम को पुश करता हूँ और सत्यापित करता हूँ कि ऑडियो वर्कलेट थ्रेड समय पर बफर देना जारी रखता है। AudioWorklet API द्वारा प्रदान किया गया थ्रेड अलगाव इस मजबूती के लिए आवश्यक है; पुराना ScriptProcessorNode मुख्य थ्रेड पर चलता था और भारी JavaScript निष्पादन के दौरान गड़बड़ियों के लिए संवेदनशील था।

मैं स्पेक्ट्रल शेपिंग के लिए Web Audio API के अंतर्निहित BiquadFilterNode का भी उपयोग करता हूँ जब वांछित फिल्टर एक मानक प्रकार हो। ये नोड अनुकूलित नेटिव कोड में लागू किए जाते हैं, जो उन्हें समतुल्य JavaScript कार्यान्वयन की तुलना में काफी तेज़ बनाता है। सरल कॉन्फ़िगरेशन में पिंक नॉइज़ उत्पादन के लिए, मैं आदर्श माइनस-तीन-डेसिबल-प्रति-ऑक्टेव ढलान का अनुमान लगाने के लिए सावधानीपूर्वक चुनी गई आवृत्तियों और Q कारकों के साथ लो-पास फिल्टर के रूप में कॉन्फ़िगर किए गए कई BiquadFilterNode को कैस्केड करता हूँ।

अनुकूलन और व्यावहारिक विचार

रियल-टाइम ऑडियो उत्पादन में प्रदर्शन अनुकूलन एक निरंतर चिंता है। अपनी विकास प्रक्रिया में, मैंने गुणवत्ता से समझौता किए बिना दक्षता को अधिकतम करने के लिए कई तकनीकें लागू की हैं। पहली प्रीकम्प्यूटेशन है: उन नॉइज़ रंगों के लिए जो गतिशील रूप से नहीं बदलते, मैं आरंभीकरण के दौरान नॉइज़ का एक बड़ा बफर (आमतौर पर 44.1 kHz पर 10 सेकंड, या 441,000 सैंपल) उत्पन्न करता हूँ और प्लेबैक के दौरान इसे लूप करता हूँ। लूप को श्रव्य होने से रोकने के लिए, मैं लूप सीमा पर एक क्रॉसफ़ेड का उपयोग करता हूँ, बफर के अंतिम 4,096 सैंपल को पहले 4,096 सैंपल के साथ एक रेज़्ड-कोसाइन विंडो का उपयोग करके मिश्रित करता हूँ। परिणामी लूप अनुभवात्मक रूप से निर्बाध है।

दूसरा अनुकूलन JavaScript के भीतर SIMD-शैली प्रोसेसिंग है। हालाँकि JavaScript AudioWorklet संदर्भ में स्पष्ट SIMD निर्देश प्रदान नहीं करता, मैं अपने आंतरिक लूप को चार के समूहों में सैंपल संसाधित करने के लिए संरचित करता हूँ, जिससे JavaScript इंजन का JIT कंपाइलर ऑटो-वेक्टराइज़ेशन लागू कर सकता है। मेरे बेंचमार्क में, यह दृष्टिकोण ब्राउज़र इंजन के आधार पर एक समय में एक सैंपल संसाधित करने की तुलना में 15 से 25 प्रतिशत गति वृद्धि प्रदान करता है।

तीसरा विचार मेमोरी प्रबंधन है। ऑडियो प्रोसेसिंग के दौरान मेमोरी आवंटित और डी-एलोकेट करना गारबेज कलेक्शन विरामों को ट्रिगर कर सकता है, जो श्रव्य गड़बड़ियों का कारण बनते हैं। मैं आरंभीकरण के दौरान सभी बफर को पूर्व-आवंटित करता हूँ और पूरे सत्र में उनका पुन: उपयोग करता हूँ। process() विधि के अंदर कोई ऑब्जेक्ट नहीं बनाया जाता, और सभी मध्यवर्ती मान पूर्व-आवंटित टाइप्ड एरे में संग्रहीत होते हैं। यह अनुशासन GC-संबंधित ऑडियो आर्टिफैक्ट्स को पूरी तरह से समाप्त कर देता है।

बिजली की खपत एक और व्यावहारिक चिंता है, विशेष रूप से मोबाइल उपकरणों के लिए। स्मार्टफोन पर मेरे परीक्षण में, मैंने पाया है कि एक साधारण नॉइज़ जनरेटर से CPU लोड नगण्य है, आमतौर पर एक प्रतिशत से कम। हालाँकि, ऑडियो आउटपुट को सक्रिय रखना डिवाइस को गहरी नींद की स्थितियों में प्रवेश करने से रोकता है, जो विस्तारित सत्रों में बैटरी खर्च कर सकता है। मैं एक टाइमर सुविधा प्रदान करके इसे कम करता हूँ जो उपयोगकर्ता-निर्दिष्ट अवधि के बाद जनरेटर को रोकती है, और Page Visibility API का उपयोग करके ब्राउज़र टैब अग्रभूमि में न होने पर उत्पादन को रोकती है।

जनरेटर आउटपुट गुणवत्ता का सत्यापन

एक नॉइज़ जनरेटर केवल उतना ही अच्छा है जितनी इसकी आउटपुट गुणवत्ता, और गुणवत्ता को वस्तुनिष्ठ माप के माध्यम से सत्यापित किया जाना चाहिए। मेरी गुणवत्ता आश्वासन प्रक्रिया में, मैं उपयोगकर्ताओं को जारी करने से पहले हर जनरेटर कॉन्फ़िगरेशन को स्वचालित परीक्षणों के एक सुइट से गुज़ारता हूँ। पहला परीक्षण स्पेक्ट्रल समतलता है: मैं व्हाइट नॉइज़ का 60-सेकंड का सैंपल कैप्चर करता हूँ, औसत FFT मैग्निट्यूड की गणना करता हूँ, और सत्यापित करता हूँ कि कोई भी आवृत्ति बिन माध्य से 1 dB से अधिक विचलित नहीं करता। आकार दिए गए नॉइज़ के लिए, मैं मापे गए स्पेक्ट्रम की तुलना लक्ष्य कर्व से करता हूँ और सत्यापित करता हूँ कि विचलन 0.5 dB से कम है।

दूसरा परीक्षण आयाम वितरण है। मैं सैंपल मानों का हिस्टोग्राम गणना करता हूँ और Kolmogorov-Smirnov परीक्षण का उपयोग करके इसकी तुलना अपेक्षित वितरण, चाहे समान हो या गाउसियन, से करता हूँ। 0.05 से ऊपर का p-मान इंगित करता है कि वितरण 95 प्रतिशत विश्वास स्तर पर अपेक्षित आकार से मेल खाता है।

तीसरा परीक्षण आवधिकता पहचान है। मैं 10-सेकंड के सैंपल के ऑटोकोरिलेशन फंक्शन की गणना करता हूँ और जाँचता हूँ कि किसी भी गैर-शून्य लैग में उस लंबाई की यादृच्छिक प्रक्रिया के लिए सैद्धांतिक अधिकतम से अधिक सहसंबंध गुणांक नहीं है। PRNG में आवधिक पैटर्न ऑटोकोरिलेशन फंक्शन में शिखरों के रूप में दिखाई देंगे, भले ही वे श्रव्य न हों, और जनरेटर में एक दोष का संकेत देते हैं जो सिग्नल प्रोसेसिंग अनुप्रयोगों में समस्याएँ पैदा कर सकता है।

अंत में, मैं हेडफोन के साथ व्यक्तिपरक सुनने के परीक्षण करता हूँ, क्लिक, पॉप, स्वर आर्टिफैक्ट्स, और विस्तारित प्लेबैक अवधि में स्तर या स्वर में भिन्नताओं की जाँच करता हूँ। स्वचालित परीक्षण अधिकांश समस्याओं को पकड़ते हैं, लेकिन मानव कान ऑडियो गुणवत्ता का अंतिम न्यायाधीश बना हुआ है, और मैं प्लेटफ़ॉर्म पर लाइव होने से पहले हर जनरेटर वैरिएंट को व्यक्तिगत रूप से सुनने का एक बिंदु बनाता हूँ।

संदर्भ

अक्सर पूछे जाने वाले प्रश्न

क्या एक डिजिटल नॉइज़ जनरेटर वास्तव में यादृच्छिक आउटपुट उत्पन्न कर सकता है?

नहीं। डिजिटल नॉइज़ जनरेटर छद्म-यादृच्छिक संख्या जनरेटर (PRNG) का उपयोग करते हैं जो नियतात्मक अनुक्रम उत्पन्न करते हैं। हालाँकि, एक अच्छी तरह से डिज़ाइन किया गया PRNG ऐसा आउटपुट उत्पन्न करता है जो सभी व्यावहारिक ऑडियो अनुप्रयोगों के लिए सच्ची यादृच्छिकता से सांख्यिकीय रूप से अप्रभेद्य है।

Web Audio API ScriptProcessorNode के बजाय AudioWorklet का उपयोग क्यों करता है?

AudioWorklet मुख्य ब्राउज़र थ्रेड से अलग थ्रेड पर चलता है, UI संचालन को ऑडियो गड़बड़ियों का कारण बनने से रोकता है। ScriptProcessorNode मुख्य थ्रेड पर चलता था और भारी JavaScript निष्पादन के दौरान ड्रॉपआउट के लिए प्रवण था। ScriptProcessorNode अब पदावनत है।

नॉइज़ जनरेटर में क्लिक या पॉप का क्या कारण है?

क्लिक और पॉप आमतौर पर बफर अंडररन के कारण होते हैं, जहाँ जनरेटर समय पर आउटपुट बफर नहीं भर पाता, या JavaScript में गारबेज कलेक्शन विरामों के कारण। उचित बफर प्रबंधन और मेमोरी का पूर्व-आवंटन इन आर्टिफैक्ट्स को समाप्त कर देता है।

एक नॉइज़ जनरेटर कितना CPU उपयोग करता है?

एक साधारण नॉइज़ जनरेटर आमतौर पर आधुनिक हार्डवेयर पर एक प्रतिशत से कम CPU का उपयोग करता है। मुख्य प्रदर्शन चिंता ऑडियो गड़बड़ियों को रोकने के लिए सुसंगत समय बनाए रखना है, न कि समग्र CPU लोड।

क्या मैं रियल टाइम में उत्पन्न करने के बजाय नॉइज़ सैंपल को लूप कर सकता हूँ?

हाँ, लेकिन श्रव्य क्लिक को रोकने के लिए आपको लूप सीमा पर एक क्रॉसफ़ेड लागू करने की आवश्यकता है। 44.1 kHz पर लगभग 4,096 सैंपल का रेज़्ड-कोसाइन क्रॉसफ़ेड एक अनुभवात्मक रूप से निर्बाध लूप बनाता है।

Leo Chen

Leo Chen एक टूल डेवलपर और ऑडियो प्रेमी हैं, जो व्यावहारिक ऑनलाइन साउंड और उत्पादकता टूल बनाने पर केंद्रित हैं।