घातीय ADSR लिफाफे के समीकरणों में मदद करें


11

एप्लिकेशन कोड के साथ, मैंने एक थरथरानवाला के आउटपुट के आयाम को आकार देने के लिए एक रैखिक ADSR लिफाफा लागू किया है। हमले, क्षय और रिलीज की अवधि के साथ-साथ निरंतर स्तर को लिफाफे पर सेट किया जा सकता है और सब कुछ उम्मीद के मुताबिक काम करता है।

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

मैंने एक डेसमोस ग्राफिंग कैलकुलेटर सत्र को बचाया है जो रैखिक रैंप के लिए दृष्टिकोण का प्रदर्शन करता है जो मैंने ऊपर वर्णित किया था।

अगर कोई मुझे सही दिशा में इंगित करने में मदद कर सकता है, तो यह बहुत सराहना की जाएगी।

जवाबों:


10

मुझे लगता है कि आप क्या भ्रमित करते हैं कि घटता हुआ घातांक ( ) कभी 0 तक नहीं पहुंचता है, इसलिए सही मायने में घातीय खंडों के साथ एक एडीएसआर जनरेटर फंस जाएगा; क्योंकि यह लक्ष्य मूल्य तक कभी नहीं पहुंचेगा। उदाहरण के लिए, यदि जनरेटर हमले के चरण की ऊंचाई पर है ( y = 1 ) और y = 0.5 पर एक स्थिर मूल्य पर उतरना है , तो यह एक सच्चे घातांक के साथ वहां नहीं जा सकता, क्योंकि असली घातांक जीत गया ' t क्षय 0.5 करने के लिए, यह केवल asymptotically 0.5 करने के लिए जाना होगा!-एक्सy=1y=0.5

यदि आप एक एनालॉग लिफाफा जनरेटर को देखते हैं (उदाहरण के लिए 7555 आधारित सर्किट हर कोई उपयोग करना चाहता है ), तो आप देख सकते हैं कि हमले के चरण के दौरान, जब संधारित्र चार्ज हो रहा है, तो यह अंत को इंगित करने के लिए उपयोग किए गए थ्रेशोल्ड की तुलना में "उच्च लक्ष्य" है। हमले के चरण में। + (१५ वी) द्वारा संचालित ५ (V) ५५५ आधारित सर्किट पर, हमले के चरण के दौरान, संधारित्र को + १५ वी चरण के साथ चार्ज किया जाता है, लेकिन हमले का चरण तब समाप्त होता है जब + १० वी की दहलीज पर पहुंच गया होता है। यह एक डिज़ाइन विकल्प है, हालांकि 2/3 "मैजिक नंबर" है जो कई क्लासिक लिफाफे जनरेटर में पाया जाता है, और यह एक ऐसा संगीतकार हो सकता है जिससे परिचित हों।

कैपेसिटर चार्ज के दौरान कुछ एडीएसआर आकार अलग-अलग "उद्देश्य अनुपात" से उत्पन्न होते हैं

इस प्रकार, आप जिन कार्यों से निपटना चाहते हैं, वे एक्सपोनेंशियल नहीं हैं, लेकिन इसे स्थानांतरित / छंटनी / तराजू संस्करण कर सकते हैं, और आपको कुछ विकल्प बनाने होंगे कि आप उन्हें कैसे "स्क्वैश" करना चाहते हैं।

मैं वैसे भी उत्सुक हूं कि आप इस तरह के फार्मूले पाने की कोशिश क्यों कर रहे हैं - शायद यह उस उपकरण की सीमा के कारण है जिसका उपयोग आप संश्लेषण के लिए कर रहे हैं; लेकिन अगर आप लिफाफे के प्रत्येक नमूने के लिए चलने वाले कुछ कोड के साथ एक सामान्य उद्देश्य प्रोग्रामिंग भाषा (C, java, python) का उपयोग करने वालों को लागू करने की कोशिश कर रहे हैं और "राज्य" की धारणा, पर पढ़ें ... क्योंकि यह हमेशा आसान होता है चीजों को व्यक्त करें "जैसे कि यह खंड केवल 0 पर पहुंच गया है, जो भी मूल्य से जाएगा"।

लिफाफे को लागू करने पर मेरी सलाह के दो टुकड़े।

पहले वाला नहीं हैसभी ढलानों / वेतन वृद्धि को मापने की कोशिश करें ताकि लिफाफा शुरू और अंत मूल्यों तक पहुंचे। उदाहरण के लिए, आप एक लिफाफा चाहते हैं जो 2 सेकंड में 0.8 से 0.2 हो जाता है, इसलिए आपको -0.3 / सेकंड की वृद्धि की गणना करने के लिए लुभाया जा सकता है। ऐसा मत करो। इसके बजाय, इसे दो चरणों में तोड़ दें: एक रैंप प्राप्त करना जो 2 सेकंड में 0 से 1.0 तक जाता है; और फिर एक रेखीय परिवर्तन लागू होता है जो 0 से 0.8 और 1.0 से 0.2 तक मैप करता है। इस तरह से काम करने के दो फायदे हैं - पहला यह है कि यह किसी भी संगणना को सरल बनाता है जो आपके पास 0 से 1 तक के रैंप पर लिफाफे के सापेक्ष होगा; दूसरा यह है कि यदि आप लिफाफा मापदंडों (वेतन वृद्धि और प्रारंभ / समाप्ति समय) को बदलते हैं, तो मध्यमार्ग सब कुछ अच्छी तरह से व्यवहार में रहेगा। अच्छा है अगर आप एक सिंथेसिस पर काम कर रहे हैं, क्योंकि लोग मॉड्यूलेशन डेस्टिनेशन के रूप में लिफाफे के समय के मापदंडों को कहेंगे।

दूसरा लिफाफा आकृतियों के साथ पूर्व-गणना लुकअप तालिका का उपयोग करना है। यह कम्प्यूटेशनल रूप से हल्का है, यह कई गंदे विवरणों को बाहर निकालता है (उदाहरण के लिए आपको एक एक्सपोनेंशियल के साथ परेशान नहीं करना है 0 बिल्कुल नहीं पहुंचना - अपने फुसफुसाते हुए इसे फिर से खोलें ताकि यह [0, 1: 1) पर मैप हो जाए, और प्रत्येक चरण के लिए लिफाफा आकृतियों को बदलने का विकल्प प्रदान करना आसान है।

मेरे द्वारा बताए गए दृष्टिकोण के लिए यहाँ छद्म कोड है।

render:
  counter += increment[stage]
  if counter > 1.0:
    stage = stage + 1
    start_value = value
    counter = 0
  position = interpolated_lookup(envelope_shape[stage], counter)
  value = start_value + (target_level[stage] - start_value) * position

trigger(state):
  if state = ON:
    stage = ATTACK
    value = 0  # for mono-style envelopes that are reset to 0 on new notes
    counter = 0
  else:
    counter = 0
    stage = RELEASE

initialization:
  target_level[ATTACK] = 1.0
  target_level[RELEASE] = 0.0
  target_level[END_OF_RELEASE] = 0.0
  increment[SUSTAIN] = 0.0
  increment[END_OF_RELEASE] = 0.0

configuration:
  increment[ATTACK] = ...
  increment[DECAY] = ...
  target_level[DECAY] = target_level[SUSTAIN] = ...
  increment[RELEASE] = ...
  envelope_shape[ATTACK] = lookup_table_exponential
  envelope_shape[DECAY] = lookup_table_exponential
  envelope_shape[RELEASE] = lookup_table_exponential

मुझे लगता है कि मेरी समस्या को हल करने के लिए लग रहा था y = ((y2 - y1) / (x2 - X1) * * (x - X1) + y1 के मेरे रेखीय पैमाने / दो-बिंदु समीकरण को लेते हुए, x से चर द्वारा प्रतिस्थापित करके इसे फिर से लिखना। ^ x से y = ((y2 - y1) / (e ^ x2 - e ^ X1)) * (e ^ x - e ^ X1) + y1। लिंक पर मेरा कैलकुलेटर सत्र इस दृष्टिकोण को दर्शाता है। क्या उनका कोई गोटा इस बात से है कि मुझे इसकी जानकारी होनी चाहिए? परिणाम मुझे सही लगे।
गैरी डेरेस

यह अन्य सिंथेसाइज़र पर पाया जाने वाला लिफाफा आकार नहीं है। प्रारंभ और अंत स्तर के समय / सापेक्ष स्थिति के आधार पर, यह बहुत रैखिक हो सकता है।
pichenettes

@ पिचाइनेट्स, क्या आप उन लिपि को तैयार करने के लिए तैयार हो सकते हैं जो उन लिफाफों को उत्पन्न करती हैं?
पी आई

3

यह एक बहुत पुराना सवाल है, लेकिन मैं सिर्फ pichenettes से जवाब में एक बिंदु को उजागर करना चाहता हूं:

उदाहरण के लिए आप एक लिफाफा चाहते हैं जो 2 सेकंड में 0.8 से 0.2 हो जाता है [...] इसे दो चरणों में तोड़ें: एक रैंप प्राप्त करना जो 2 सेकंड में 0 से 1.0 तक जाता है; और फिर एक रेखीय परिवर्तन लागू होता है जो 0 से 0.8 और 1.0 से 0.2 तक मैप करता है।

इस प्रक्रिया को कभी-कभी "सहजता" के रूप में जाना जाता है और जैसा दिखता है

जी(एक्स,एल,यू)=(एक्स-एलयू-एल)(यू-एल)+एल

एलयू01(एक्स)एक्सn01

(एक्स)

* मुझे लगता है कि ओपी शायद बहुत लंबा चला गया है, लेकिन शायद यह किसी और की मदद करता है।


इसके लिए धन्यवाद, मैं एक DAW मैं के लिए एक डेवलपर के लिए एक नमूना ले रहा था, और Desmos सत्र में प्रदान किए गए सूत्रों में खामियों को दूर किया और उन्होंने पूरी तरह से काम किया। कोई और अधिक लंगड़ा रैखिक लिफाफे! :)
डगलस

1

पिचेनेट्स की टिप्पणी के बारे में, "हमले के चरण के दौरान, संधारित्र को + 15V चरण के साथ चार्ज किया जाता है, लेकिन हमले का चरण तब समाप्त होता है जब + 10V की एक सीमा तक पहुँच गया है। यह एक डिज़ाइन विकल्प है, हालांकि 2/3" जादू है। नंबर "कई क्लासिक लिफाफा जनरेटर में मिला, और यह एक संगीतकार हो सकता है जो परिचित हो।"

कोई भी लिफाफा जो 10v लक्ष्य के साथ 15v के लिए शूटिंग कर रहा है, व्यावहारिक रूप से, एक रैखिक हमला करता है। यह सिर्फ इतना है कि 15v आसानी से उपलब्ध उच्चतम asymptote है, और यह रैखिक के काफी करीब है। यही है, इसके बारे में कुछ भी "जादू" नहीं है - वे सिर्फ रैखिक के लिए जा रहे हैं जैसा कि वे प्राप्त कर सकते हैं।

मैं नहीं जानता कि कितने क्लासिक सिंथेस 15 वी का उपयोग करते हैं - मुझे संदेह है कि अक्सर एक डायोड ड्रॉप या दो होता है। मेरे पुराने मेष मॉड्यूलर 10v लिफाफे के लिए 13v का उपयोग करते हैं, और मैंने अभी एक कर्टिस ADSR चिप देखी है जो 5v लिफाफे के लिए, 6.5v का उपयोग करता है।


1

इस कोड को pichenettes के समान प्लॉट उत्पन्न करना चाहिए:

def ASD_envelope( nSamps, tAttack, tRelease, susPlateau, kA, kS, kD ):
    # number of samples for each stage
    sA = int( nSamps * tAttack )
    sD = int( nSamps * (1.-tRelease) )
    sS = nSamps - sA - sD

    # 0 to 1 over N samples, weighted with w
    def weighted_exp( N, w ):
        t = np.linspace( 0, 1, N )
        E = np.exp( w * t ) - 1
        E /= max(E)
        return E

    A = weighted_exp( sA, kA )
    S = weighted_exp( sS, kS )
    D = weighted_exp( sD, kD )

    A = A[::-1]
    A = 1.-A

    S = S[::-1]
    S *= 1-susPlateau
    S += susPlateau

    D = D[::-1]
    D *= susPlateau

    env = np.concatenate( [A,S,D] )

    # plot
    tEnv = np.linspace( 0, nSamps, len(env) )
    plt.plot( tEnv, env )
    plt.savefig( "OUT/EnvASD.png" )
    plt.close()

    return env

मैं किसी भी सुधार के लिए आभारी हूं, एक चीज जो एक अच्छा विचार हो सकती है वह अंतिम तीन मापदंडों (जो तीन चरणों में से प्रत्येक की स्थिरता का निर्धारण करती है) को 0 और 1 के बीच भिन्न करने की अनुमति देती है, जहां 0.5 एक सीधी रेखा होगी। लेकिन मैं यह नहीं देख सकता कि इसे कैसे किया जाए।

इसके अलावा, मैंने सभी उपयोग मामलों का अच्छी तरह से परीक्षण नहीं किया है, उदाहरण के लिए यदि एक चरण में शून्य लंबाई है।

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