साइन लहर जनरेटर कैसे बनाया जाए जो आसानी से आवृत्तियों के बीच संक्रमण कर सके


27

मैं ऑडियो के लिए एक बुनियादी साइन वेव जनरेटर लिखने में सक्षम हूं, लेकिन मैं चाहता हूं कि यह एक आवृत्ति से दूसरे आवृत्ति पर आसानी से संक्रमण करने में सक्षम हो। अगर मैं बस एक फ्रीक्वेंसी जेनरेट करना बंद कर दूं और तुरंत दूसरे पर स्विच करूं तो सिग्नल में एक असंगति आएगी और एक "क्लिक" सुनाई देगा।

मेरा सवाल यह है कि 250Hz, और फिर 300Hz में परिवर्तन, बिना किसी क्लिक के शुरू करने वाली एक तरंग उत्पन्न करने के लिए एक अच्छा एल्गोरिथ्म क्या है। यदि एल्गोरिथ्म में एक वैकल्पिक ग्लाइड / पोर्ट एंटोनो समय शामिल है, तो इतना बेहतर है।

मैं कुछ संभावित दृष्टिकोणों के बारे में सोच सकता हूं जैसे कि ओवरसम्पलिंग के बाद कम पास फिल्टर, या शायद एक वेवटेबल का उपयोग करना, लेकिन मुझे यकीन है कि यह एक सामान्य पर्याप्त समस्या है कि इससे निपटने का एक मानक तरीका है।


2
आपने संक्रमण अवधि में केवल रैखिक आवृत्ति संक्रमण का उपयोग क्यों नहीं किया। उदाहरण के लिए, आपको समय t1 पर फ्रीक्वेंसी f0 से फ्रीक्वेंसी f0 पर समय t1 पर ट्रांज़िट करने की आवश्यकता है, फिर क्यों न केवल ट्रांस्फ़ॉर्म फ़्रीक्वेंसी f (t) = f0 * (1-q) + f1 * q, जहाँ q = (t -t0) / (t1-t0), फिर एक संकेत A (t) = sin (2 * Pi * f (t) * t) उत्पन्न करते हैं?
म्बाइतॉफ

जवाबों:


24

एक दृष्टिकोण जो मैंने अतीत में इस्तेमाल किया है वह एक चरण संचायक को बनाए रखने के लिए है जो कि एक अनुक्रमणिका के रूप में तरंग तरंग लुकअप तालिका में उपयोग किया जाता है। एक चरण डेल्टा मान प्रत्येक नमूना अंतराल पर संचायक में जोड़ा जाता है:

phase_index += phase_delta

आवृत्ति को बदलने के लिए आप चरण डेल्टा को बदलते हैं जो प्रत्येक नमूने में चरण संचायक में जोड़ा जाता है, जैसे

phase_delta = N * f / Fs

कहा पे:

phase_delta is the number of LUT samples to increment
freq is the desired output frequency
Fs is the sample rate

यह गारंटी देता है कि यदि आप चरण_डेल्टा को गतिशील रूप से बदलते हैं, उदाहरण के लिए, आवृत्ति परिवर्तन, एफएम, आदि के बावजूद आउटपुट तरंग निरंतर है।

फ़्रीक्वेंसी (पोर्ट एंटोनियो) में चिकनी बदलाव के लिए, आप अपने पुराने मूल्य और नए मान के बीच उचित संख्या में नमूनों अंतरालों के बीच चरण_डेल्टा मान को तुरंत बदल सकते हैं।

ध्यान दें कि phase_indexऔर phase_deltaदोनों में एक पूर्णांक और एक आंशिक घटक है, अर्थात उन्हें फ्लोटिंग पॉइंट या फिक्स्ड पॉइंट होना चाहिए। Phase_index (modulo table size) के पूर्णांक भाग को तरंग LUT में एक सूचकांक के रूप में उपयोग किया जाता है, और आंशिक रूप से उच्च गुणवत्ता वाले आउटपुट और / या छोटे LUT आकार के लिए आसन्न LUT मानों के बीच प्रक्षेप के लिए उपयोग किया जा सकता है।


धन्यवाद, मैं उम्मीद कर रहा था कि उत्तर में LUT शामिल हो सकता है। मैं एक LUT के साथ जाने की सोच रहा था जिसमें 1Hz (यानी Fs प्रविष्टियों) में एक तरंग है। क्या अंगूठे का नियम LUT का इष्टतम आकार है?

4
यह विभिन्न कारकों पर निर्भर करता है: आप जिस एसएनआर की तलाश कर रहे हैं, वह शुद्ध साइन तरंग या अधिक जटिल तरंग है, चाहे आप आसन्न LUT प्रविष्टियों के बीच प्रक्षेपित करने की योजना बना रहे हैं या सिर्फ ट्रंकट, आदि यह भी इस बात पर निर्भर करता है कि आप अभी जा रहे हैं या नहीं। एक एकल चतुर्थांश तालिका है और अनुक्रमण अंकगणितीय और अपने आप को उलटने का संकेत है, या एक पूर्ण चार चतुर्थांश तालिका संभालते हैं। व्यक्तिगत रूप से मैं एक 1024 बिंदु (NB: 2 ^ N, मॉडुलो इंडेक्सिंग के लिए अच्छा है) के साथ शुरू करूँगा, चार चतुर्थांश तालिका बिना किसी प्रक्षेप के साथ यह बहुत सरल है और उदाहरण के लिए 16 बिट "उपभोक्ता" ऑडियो के लिए अच्छे परिणाम देने चाहिए।
पॉल आर

1
अच्छा जवाब, पॉल। कुछ समय पहले पोस्ट किए गए विषय पर भी एक समान प्रश्न है ; अधिक जानकारी हमेशा मदद करती है।
जेसन आर

4
इस दृष्टिकोण को देखने का एक अन्य तरीका वोल्टेज-नियंत्रित थरथरानवाला (VCO) का अनुकरण है। VCO की आउटपुट आवृत्ति इनपुट वोल्टेज (आमतौर पर इनपुट वोल्टेज का एक रैखिक कार्य) पर निर्भर करती है, लेकिन आउटपुट सिग्नल में निरंतर चरण होता है, भले ही इनपुट वोल्टेज तुरंत स्विच हो जाए। आउटपुट जहाँ है समय का एक निरंतर कार्य, जबकि उत्पादन आवृत्ति चरण का व्युत्पन्न है, और बराबर होता है, जहां मौन आवृत्ति है।
sin(ϕ(t))=sin(0tω0+kx(τ)dτ)
ϕ(t)
ω0+kx(t)
ω0
दिलीप सरवटे

1
मुझे एक ही समस्या थी, संचायक विचार के लिए धन्यवाद (मैं प्रत्यक्ष गणना का उपयोग कर रहा था, जो कि अनुमानों के कारण काम नहीं करता था): jsfiddle.net/sebpiq/p3ND5/12
sebpiq

12

साइन लहर बनाने के सर्वोत्तम तरीकों में से एक पुनरावर्ती अद्यतन के साथ एक जटिल चरण का उपयोग करना है। अर्थात

z[n+1]=z[n]Ω

जहाँ z [n] फ़ैसर है, , साथ ही रेडियों में ऑसिलेटर की कोणीय आवृत्ति और नमूना सूचकांक है। दोनों वास्तविक और काल्पनिक भाग साइन वेव्स हैं, वे 90 डिग्री फेज से बाहर हैं। बहुत सुविधाजनक है अगर आपको साइन और कोसाइन दोनों की आवश्यकता है। एक एकल नमूना गणना के लिए केवल 4 गुणकों की आवश्यकता होती है और 4 को जोड़ता है और पाप () कॉस () या लुकअप तालिकाओं वाली किसी भी चीज़ की तुलना में बहुत सस्ता है। संभावित समस्या यह है कि संख्यात्मक सटीक मुद्दों के कारण समय के साथ आयाम बढ़ सकता है। हालांकि इसकी मरम्मत के लिए काफी सीधा आगे है। मान लीजिए कि । हम जानते हैं कि में एकता परिमाण होना चाहिए, अर्थात Ω=exp(jω)ωnz[n]z[n]=a+jbz[n]

aa+bb=1

इसलिए हम हर बार एक बार जांच कर सकते हैं कि क्या अभी भी मामला है और उसके अनुसार सही है। सटीक सुधार होगा

z[n]=z[n]aa+bb

यही कारण है कि एक अजीब गणना है लेकिन जब से बहुत एकता के करीब आप अनुमान लगा सकता है है के चारों ओर एक टेलर विस्तार के साथ शर्तों और हम मिलaa+bb1/xx=1

1x3x2

इसलिए सुधार सरल हो जाता है

z[n]=z[n]3a2b22

इस सरल सुधार को हर कुछ सौ नमूनों को लागू करने से ऑसिलेटर हमेशा के लिए स्थिर रहेगा।

आवृत्ति को लगातार गुणा करने के लिए गुणक डब्ल्यू को तदनुसार अद्यतन करने की आवश्यकता होती है। यहां तक ​​कि गुणक में एक गैर-निरंतर परिवर्तन एक निरंतर थरथरानवाला फ़ंक्शन बनाए रखेगा। यदि फ़्रीक्वेंसी रैंपिंग की आवश्यकता है तो अपडेट को या तो कुछ चरणों में तोड़ा जा सकता है या आप एक ही थरथरानवाला एल्गोरिथ्म को मल्टीप्लायर को स्वयं अपडेट करने के लिए उपयोग कर सकते हैं (क्योंकि यह एक एकता लाभ जटिल चरण है)।


इस उत्तर के लिए धन्यवाद, मुझे कुछ वास्तविक विश्व कोड में बदलने के लिए पर्याप्त रूप से समझने में थोड़ा समय लगेगा, लेकिन यह कोशिश करने के लिए एक दिलचस्प विकल्प जैसा दिखता है।
मार्क हीथ

2
मैंने इस समाधान को संदर्भ के लिए golang में लागू किया: github.com/rmichela/Acoustico/blob/…
Ryan Michela

यह एक सुंदर समाधान है जो दुर्भाग्य से, केवल निरंतर समय के आधार का उपयोग करने पर अच्छी तरह से काम करता है। यदि नहीं, तो आपको सही जटिल रोटेशन की गणना करने के लिए एक पाप और एक कॉस की गणना करने की आवश्यकता है।
कैमरन टैकलिंड

2

से इस साइट :

एक आवृत्ति से दूसरे या एक आयाम से दूसरे आयाम में एक चिकनी संक्रमण बनाने के लिए, एक अपूर्ण साइन लहर को एक संशोधित खंड के साथ संशोधित किया जाना चाहिए ताकि परिणामस्वरूप लूप के प्रत्येक पुनरावृत्ति के बाद परिणामी लहर एक्स-अक्ष पर समाप्त हो जाए।

लगता है कि यह काम करना चाहिए।

(वास्तव में, यदि वे संक्रमण पर एक्स-अक्ष में दोनों सिंक्रनाइज़ हैं, तो मुझे लगता है कि एक क्रमिक संक्रमण आवश्यक नहीं है।)


1
यह कहता है, एक चक्र पूरा करने के लिए आवृत्ति पर वर्तमान प्रतीक्षा करें और पर पहुंचें और फिर आवृत्ति पर अन्य पर स्विच करें । यह प्रभावी रूप से चरण की निरंतरता को बनाए रखता है और ऑडियो अनुप्रयोगों के लिए ठीक होने की संभावना है, जिसमें कुछ मिलीसेकंड या माइक्रोसेकंड वांछित स्विच समय (अब) और कार्यान्वित स्विच समय (जब मेरा साइनसॉइड एक चक्र पूरा करता है) के बीच विलंब होता है। हालाँकि, अंतर अन्य अनुप्रयोगों में परेशानी दे सकता है। बस याद रखें कि एक साइनसॉइड एक चक्र में दो बार है और सही को चुनना सुनिश्चित करें! 0 ω 1 0ω00ω10
दिलीप सरवटे

2

मैं एक चरण संचायक का उपयोग करने के पिछले सुझावों से सहमत हूं। अनिवार्य रूप से नियंत्रण इनपुट चरण की अग्रिम प्रति चरण या प्रति घड़ी की अवधि (या प्रति बाधा या जो भी हो) की मात्रा है, ताकि उस मूल्य को बदलने से चरण में एक असंतोष के बिना आवृत्ति में बदलाव हो। लहर आयाम तब संचित चरण मान से या तो LUT या पाप (थीटा) या कॉस (थीटा) के संगणना से निर्धारित होता है।

यह अनिवार्य रूप से है जो आमतौर पर एक संख्यात्मक रूप से नियंत्रित थरथरानवाला (NCO) या एक प्रत्यक्ष डिजिटल सिंथेसाइज़र (DDS) के रूप में जाना जाता है। उन शर्तों पर एक वेब खोज करना संभवत: अधिक से अधिक उपज देगा जो आप सिद्धांत पर जानना चाहते हैं और उन्हें अच्छी तरह से काम करने का अभ्यास करते हैं।

अतिरिक्त संचयक को जोड़ने से आवृत्तियों के बीच सहज संक्रमण की अनुमति मिल सकती है, जैसा कि आपने सुझाव दिया था, यदि यह वांछित है, तो चरण अग्रिम मूल्य के परिवर्तन की दर को नियंत्रित करके। इसे कभी-कभी डिजिटल डिफरेंशियल एनालाइजर या डीडीए कहा जाता है।


अच्छी अतिरिक्त जानकारी। खुशी है कि आपको इधर-उधर देखकर, एरिक; हम एल्गोरिदम के एक मंत्री का उपयोग कर सकते हैं।
जेसन आर

1

1 आदेश, आपको नई आवृत्ति साइनसॉइड के शुरुआती चरण को समायोजित करना चाहिए ताकि यह वही हो जो 1 संक्रमण नमूना बिंदु पर पिछले साइनसॉइड का चरण होगा। पहली आवृत्ति की गणना करें और दूसरी आवृत्ति के लिए इसके चरण का उपयोग करें।

दूसरा विकल्प एक आवृत्ति से अगले नमूने के लिए कई नमूनों पर d_phase रैंप करने के लिए हो सकता है। यह 1 व्युत्पन्न की निरंतरता को साफ करेगा और एक ग्लाइड प्रदान करेगा।

3 विकल्प d_phase ramping दर पर एक चौरसाई खिड़की, जैसे उठाया-कोसाइन का उपयोग करने के लिए हो सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.