हर बजाए गए सुर को उसके बजाए रखे जाने की अवधि के आधार पर रीवरब डिके कैसे दें
हर बजाए गए सुर को उसकी अवधि पर निर्भर अलग रीवरब देने के लिए, उसके नोट-ऑन और नोट-ऑफ के बीच का समय मापें, उस अवधि को डिके समय में बदलें और परिणाम उस सुर के लिए निर्धारित रीवरब पर लागू करें। ध्वनि-स्रोत रिलीज़ होने के बाद भी उस सुर का रीवरब चलने दें।
यह ट्यूटोरियल SuperCollider में यह व्यवहार बनाता है, जिसमें MIDI इनपुट और ओवरलैप होते सुरों का परीक्षण शामिल है। अपेक्षित नतीजा सरल है: थोड़ी देर तक दबाया गया सुर छोटी टेल छोड़ता है, जबकि ज़्यादा देर तक दबाया गया सुर लंबी टेल छोड़ता है—भले ही उनके रीवरब ओवरलैप हों।
हर सुर के लिए अलग रीवरब क्यों चाहिए?
दो ओवरलैप होते सुरों पर विचार करें। आप पहला सुर दो सेकंड तक दबाए रखते हैं और दूसरे को एक चौथाई सेकंड के लिए टैप करते हैं। अगर दोनों एक ही रीवरब में जाते हैं, तो दूसरे सुर के लिए उसका डिके बदलने से पहले सुर की बची हुई रीवरब ध्वनि की प्रोसेसिंग भी बदल जाती है। एक साझा डिके नियंत्रण, एक ही रीवरब अवस्था में दो स्वतंत्र सेटिंग बनाए नहीं रख सकता।
इसलिए रूटिंग ऐसी होनी चाहिए: हर सुर का ध्वनि-स्रोत अपने रीवरब में जाए और फिर पूरी हुई वॉइस के आउटपुट आपस में मिलाए जाएँ। यह आर्किटेक्चर से निकलने वाला निष्कर्ष है: स्वतंत्र टेल के लिए स्वतंत्र प्रोसेसिंग अवस्था चाहिए, जब तक इंस्ट्रूमेंट या इफ़ेक्ट पहले से ही वैसा आंतरिक अलगाव न देता हो।
पॉलीफ़ोनिक पैच इसके लिए उपयोगी ढाँचा देता है। Cycling ’74 बताता है कि Max का poly~ वॉइस इंस्टेंस बनाता है और thispoly~ से हर इंस्टेंस को व्यस्त या उपलब्ध चिह्नित करता है। इस काम में, नोट-ऑफ के तुरंत बाद उपलब्ध होने के बजाय, वॉइस को रीवरब टेल के दौरान व्यस्त रहना चाहिए। Cycling ’74: Polyphony
एक समय-संबंधी सीमा भी है: लाइव प्रदर्शन के दौरान, नोट खत्म होने तक उसकी अंतिम होल्ड अवधि अज्ञात रहती है। नीचे दिए गए तरीके में कुंजी दबे रहने तक अस्थायी डिके इस्तेमाल होता है और रिलीज़ होने पर मापा गया डिके सेट किया जाता है। अगर आपको अंतिम डिके शुरू से ही लागू करना है, तो ऐसी सीक्वेंस से काम करें जिसमें सुरों की अवधि पहले से उपलब्ध हो, या बाद में हर सुर को अलग से रेंडर करें।
होल्ड अवधि किसे नियंत्रित करे?
तीन नियंत्रण अलग रखें: इंस्ट्रूमेंट का एम्प्लीट्यूड रिलीज़, रीवरब का डिके और वेट आउटपुट स्तर। इंस्ट्रूमेंट का लंबा रिलीज़ रीवरब में ध्वनि भेजना जारी रखता है। वेट स्तर बढ़ाने से इफ़ेक्ट ज़्यादा तेज़ सुनाई देता है। इनमें से कोई भी क्रिया अपने आप रीवरब का डिके लंबा नहीं करती।
डिके का अर्थ आम तौर पर किसी सटीक समय पर पूरी तरह रुक जाना नहीं होता। Ableton के Reverb दस्तावेज़ में Decay नियंत्रण को वह समय बताया गया है जिसमें टेल अपने शुरुआती एम्प्लीट्यूड के एक-हज़ारवें हिस्से, यानी −60 dB, तक गिरती है। डिके सेटिंग की तुलना उस क्षण से करते समय यह अंतर मायने रखता है जब टेल सुनाई देना बंद होती है। Ableton: Live Audio Effect Reference, Reverb
पहले कार्यान्वयन के लिए यह स्पष्ट रूप से उदाहरणार्थ मैपिंग इस्तेमाल करें; सभी मान सेकंड में हैं:
decay = min(6.0, max(0.25, 0.25 + 1.5 × heldDuration))
| होल्ड अवधि | निर्धारित डिके |
|---|---|
| 0.10 सेकंड | 0.40 सेकंड |
| 0.25 सेकंड | 0.625 सेकंड |
| 1.00 सेकंड | 1.75 सेकंड |
| 2.00 सेकंड | 3.25 सेकंड |
| 4.00 सेकंड | 6.00 सेकंड, अधिकतम सीमा |
ये मान डिज़ाइन के चुनाव हैं, मापे गए ध्वनिक परिणाम नहीं। न्यूनतम मान छोटे टैप को सुनाई देने वाली टेल देता है; गुणक यह तय करता है कि होल्ड करने से इफ़ेक्ट कितना बदलेगा; अधिकतम सीमा निर्धारित डिके को बाँधती है। इस मैपिंग से शुरू करें, फिर नोट वेलोसिटी और वेट स्तर स्थिर रखते हुए इन तीनों मानों को समायोजित करें।
ऐसी वॉइस बनाएँ जो नोट-ऑफ के बाद भी बनी रहे
इस उदाहरण में SuperCollider का अंतर्निहित GVerb इस्तेमाल होता है, जो मोनो इनपुट स्वीकार करता है, दो आउटपुट चैनल देता है और revtime को सेकंड में व्यक्त करता है। इसके दस्तावेज़ में इंस्टैंशिएशन के समय CPU का बढ़ा हुआ उपयोग और रूम साइज़ बदलने पर आर्टिफ़ैक्ट बनने का भी उल्लेख है। इसलिए इस उदाहरण में रूम साइज़ स्थिर रखा गया है और शुरुआत में एक साथ कुछ ही सुरों के साथ इसे आज़माना बेहतर है। SuperCollider: GVerb
हर वॉइस में दो ऑसिलेटर वाला छोटा ध्वनि-स्रोत, छोटा एम्प्लीट्यूड रिलीज़ और एक रीवरब होता है। एक अलग लाइफ़टाइम एन्वेलप वॉइस को तभी मुक्त करता है जब उसकी टेल के लिए तय समय पूरा हो जाए। SuperCollider का EnvGen ऐसे सस्टेनिंग एन्वेलप का समर्थन करता है जो गेट शून्य होने पर रिलीज़ होते हैं, साथ ही एक कम्प्लीशन ऐक्शन का भी, जो एनक्लोज़िंग सिंथ को मुक्त करता है। SuperCollider: EnvGen
काम करने वाले स्टीरियो ऑडियो आउटपुट के साथ नया SuperCollider सेशन शुरू करें। नीचे दिया पूरा सेटअप ब्लॉक इवैल्युएट करें, फिर Post विंडो में Held-note reverb ready आने तक प्रतीक्षा करें। किसी सैंपल या अतिरिक्त लाइब्रेरी की ज़रूरत नहीं है। कोड को दस्तावेज़ों के आधार पर जाँचा गया है; यहाँ इसे चलाया नहीं गया, क्योंकि SuperCollider इंटरप्रेटर उपलब्ध नहीं है।
(
s.waitForBoot {
SynthDef(\heldNoteVerb, {
|out = 0, freq = 440, amp = 0.035,
gate = 1, decay = 1, alive = 1|
var sourceEnv, lifetime, source, wet;
sourceEnv = EnvGen.kr(
Env.asr(0.01, 1, 0.02), gate
);
lifetime = EnvGen.kr(
Env.asr(0.01, 1, 0.03), alive,
doneAction: 2
);
source = (
SinOsc.ar(freq) + (0.25 * SinOsc.ar(freq * 2))
) * amp * sourceEnv;
wet = GVerb.ar(
source,
roomsize: 20,
revtime: Lag.kr(decay, 0.03),
damping: 0.5,
drylevel: 0,
earlyreflevel: 0.2,
taillevel: 0.5
);
Out.ar(out, ((source ! 2) + wet) * lifetime);
}).add;
s.sync;
~heldVoices = Dictionary.new;
~tailJobs = List.new;
~voiceGroup = Group.head(s);
~voiceKey = { |num, chan, src|
src.asString ++ ":" ++ chan.asString ++ ":" ++ num.asString
};
~decayFor = { |held|
(0.25 + (1.5 * held)).clip(0.25, 6.0)
};
~releaseHeld = { |num, chan = 0, src = 0|
var key, queue, entry, held, decay, node;
key = ~voiceKey.value(num, chan, src);
queue = ~heldVoices[key];
if(queue.notNil) {
if(queue.notEmpty) {
entry = queue.removeAt(0);
node = entry[0];
held = (Main.elapsedTime - entry[1]).max(0);
decay = ~decayFor.value(held);
node.set(\decay, decay, \gate, 0);
[\note, num, \held, held, \decay, decay].postln;
~tailJobs.add(Routine {
((2 * decay) + 0.1).wait;
node.set(\alive, 0);
}.play(SystemClock));
};
if(queue.isEmpty) { ~heldVoices.removeAt(key) };
};
};
~startHeld = { |vel, num, chan = 0, src = 0|
var key, node;
if(vel <= 0) {
~releaseHeld.value(num, chan, src);
} {
key = ~voiceKey.value(num, chan, src);
if(~heldVoices[key].isNil) {
~heldVoices[key] = List.new;
};
node = Synth(\heldNoteVerb, [
\freq, num.midicps,
\amp, (vel / 127) * 0.035
], ~voiceGroup);
~heldVoices[key].add([node, Main.elapsedTime]);
};
};
"Held-note reverb ready".postln;
};
)
रिलीज़ के समय क्रम मायने रखता है: वॉइस को डिके सेटिंग और सोर्स गेट में बदलाव एक साथ मिलते हैं। सोर्स 20 मिलीसेकंड में धीरे-धीरे बंद होता है, जबकि रीवरब प्रोसेसिंग जारी रखता है। निर्धारित डिके के लगभग दोगुने समय और थोड़ी अतिरिक्त अवधि के बाद पूरी वॉइस फ़ेड होकर खुद को मुक्त कर देती है।
यह अंतिम अतिरिक्त अवधि संसाधन प्रबंधन का चुनाव है, चुप्पी का माप नहीं। अगर सफ़ाई के समय बची हुई टेल सुनाई दे, तो इसे बढ़ाएँ। बड़े इंस्ट्रूमेंट के लिए निश्चित अवधि की जगह आउटपुट स्तर की निगरानी और अधिकतम लाइफ़टाइम का इस्तेमाल करें। यह उदाहरण सफ़ाई होने तक पूरे हो चुके जॉब के संदर्भ भी बनाए रखता है, इसलिए यह प्रदर्शन के लिए है, लगातार चलने वाले इंस्ट्रूमेंट के लिए नहीं।
बजाए गए MIDI सुरों को सही वॉइस से जोड़ें
अवधि का माप किसी खास नोट इंस्टेंस से जुड़ा होता है। सिर्फ़ सबसे हाल के नोट-ऑन का टाइमस्टैम्प ट्रैक करना, सुरों के ओवरलैप होते ही विफल हो जाता है। इसके बजाय सेटअप हर वॉइस और उसके शुरू होने का समय, स्रोत, चैनल और पिच से बनी कुंजी के अंतर्गत रखता है।
SuperCollider की MIDI मार्गदर्शिका MIDI शुरू करने, इनपुट जोड़ने और सिंथ संदर्भ सहेजने का तरीका दिखाती है, ताकि नोट-ऑफ सही ध्वनि को रिलीज़ कर सके। MIDIdef संदर्भ में कॉलबैक आर्ग्युमेंट का क्रम वैल्यू, नोट नंबर, चैनल और स्रोत दिया गया है। SuperCollider: Using MIDI, SuperCollider: MIDIdef
सेटअप तैयार होने की सूचना दे, तो कनेक्ट किए गए MIDI इनपुट से इंस्ट्रूमेंट बजाने के लिए यह ब्लॉक इवैल्युएट करें:
(
MIDIClient.init;
MIDIIn.connectAll;
MIDIdef.noteOn(\heldVerbOn, { |vel, num, chan, src|
~startHeld.value(vel, num, chan, src);
});
MIDIdef.noteOff(\heldVerbOff, { |vel, num, chan, src|
~releaseHeld.value(num, chan, src);
});
)
यह उदाहरण “होल्ड” को प्राप्त नोट इवेंट के बीच का समय मानता है। इसमें सस्टेन पेडल का व्यवहार लागू नहीं है। अगर आप पेडल से बढ़ी हुई अवधि चाहते हैं, तो प्रभावित रिलीज़ क्रियाएँ पेडल उठने तक रोकें, फिर वह लंबा अंतराल मापें।
एक ही पिच को बार-बार दबाने पर इवेंट कतार में रखे जाते हैं और सबसे पुराना पहले रिलीज़ होता है। एक ही स्रोत और चैनल पर एक ही पिच के ओवरलैप होते इवेंट के लिए यह स्पष्ट मिलान नीति है। बिना मेल खाने वाले नोट-ऑफ कुछ नहीं करते; बिना मेल खाने वाला नोट-ऑन सफ़ाई होने तक सक्रिय रहता है। इंस्ट्रूमेंट को आगे बढ़ाने से पहले इवेंट की जोड़ियों की जाँच करें।
ध्वनि बदलने से पहले ओवरलैप होती टेल जाँचें
पहले बिना कीबोर्ड के व्यवहार जाँचें। नीचे दी गई सीक्वेंस MIDI इनपुट वाले उन्हीं इवेंट फ़ंक्शन का इस्तेमाल करती है: नोट 60 दो सेकंड तक चलता है, जबकि नोट 67 उसके शुरू होने के बीच में शुरू होता है और एक चौथाई सेकंड तक चलता है। उनके निर्धारित डिके क्रमशः लगभग 3.25 और 0.625 सेकंड होने चाहिए।
(
~heldTest = Routine {
~startHeld.value(100, 60);
1.0.wait;
~startHeld.value(100, 67);
0.25.wait;
~releaseHeld.value(67);
0.75.wait;
~releaseHeld.value(60);
}.play(SystemClock);
)
SystemClock सेकंड में शेड्यूलिंग देता है, जिससे यह परीक्षण संगीत की टेम्पो सेटिंग से स्वतंत्र रहता है। वास्तविक इस्तेमाल में प्रिंट हुई और माँगी गई अवधियों के बीच थोड़ा अंतर हो सकता है। SuperCollider: SystemClock
सुनें कि नीचे वाला सुर जारी रहने के दौरान ऊँचे सुर की छोटी टेल सुनाई देती है, और उसके बाद नीचे वाले सुर की लंबी टेल आती है। फिर अवधियाँ उलट दें। यह दूसरा परीक्षण पुष्टि करने में मदद करता है कि नतीजा पिच से नहीं, अवधि से तय होता है। छपे हुए होल्ड अवधि और डिके की जोड़ियों को सुनाई देने वाली ध्वनि के साथ मिलाकर देखें।
MIDI हैंडलर इंस्टॉल करने के बाद इस उदाहरण को रोकने और हटाने के लिए नीचे दिया सफ़ाई ब्लॉक इवैल्युएट करें। यह वॉइस हटाने से पहले लंबित टेल जॉब भी रद्द करता है:
(
MIDIdef(\heldVerbOn).free;
MIDIdef(\heldVerbOff).free;
if(~heldTest.notNil) { ~heldTest.stop };
~tailJobs.do { |job| job.stop };
~tailJobs.clear;
~voiceGroup.free;
~heldVoices.clear;
)
गलत व्यवहार करने वाली टेल की जाँच कैसे करें?
अगर एक सुर रिलीज़ होने पर हर टेल बदलती है, तो ऑडियो रूटिंग जाँचें। प्रति-सुर टाइमस्टैम्प होने पर भी व्यवहार साझा रहेगा, अगर उसका परिणाम वॉइस के मिक्स के बाद एक ही रीवरब को नियंत्रित करता है। रीवरब को हर वॉइस के भीतर रखें, या अलग-अलग नोट ऑडियो को अलग प्रोसेसिंग इंस्टेंस तक भेजें।
अगर टेल ठीक नोट-ऑफ पर गायब हो जाती है, तो वॉइस लाइफ़टाइम जाँचें। एम्प्लीट्यूड एन्वेलप को ध्वनि-स्रोत रोकना चाहिए, उस स्रोत वाले रीवरब को मुक्त नहीं करना चाहिए। Max के कार्यान्वयन में, दस्तावेज़ित poly~ आवंटन मॉडल के अनुसार, वॉइस की व्यस्त अवस्था तब तक बनाए रखें जब तक उसका वेट आउटपुट समाप्त न हो जाए। Cycling ’74: Polyphony
अगर डिके के अंक गलत हैं, तो रीवरब बदलने से पहले इवेंट कुंजी और टाइमस्टैम्प प्रिंट करें। Max में, इसके लिए समय मापने वाला बिल्डिंग ब्लॉक timer है, जो इवेंट के बीच बीता समय मापता है और डिफ़ॉल्ट रूप से मिलीसेकंड इस्तेमाल करता है। जब गंतव्य को सेकंड चाहिए हों, तो इकाइयों का स्पष्ट रूप से रूपांतरण करें। Cycling ’74: timer
अगर प्रदर्शन असमान हो जाए, तो पैच बढ़ाने से पहले एक साथ चलने वाली वॉइस की संख्या घटाएँ और रीवरब के चुनाव की जाँच करें। यह प्रदर्शन वॉइस की संख्या पर सीमा नहीं लगाता और हर नए सुर के साथ एक और रीवरब बनाता है। प्रोडक्शन इंस्ट्रूमेंट के लिए ऐसी स्पष्ट आवंटन नीति चाहिए जो दबाए हुए सुरों और अब भी गूँज रही टेल—दोनों का ध्यान रखे।
समय और ओवरलैप के परीक्षण सफल होने के बाद, ऑसिलेटर को अपने चुने हुए प्रति-वॉइस ध्वनि-स्रोत से बदलें। यही क्रम बनाए रखें: वॉइस आवंटित करें, शुरू होने का समय दर्ज करें, रिलीज़ पर अवधि मापें, उसका डिके सेट करें और टेल पूरी होने तक रीवरब बनाए रखें। इस क्रम से होल्ड अवधि, प्रदर्शन में दोहराया जा सकने वाला नियंत्रण बन जाती है।
स्रोत
- Polyphony — Cycling ’74 Documentation
- timer — Max Reference — Cycling ’74 Documentation
- Live Audio Effect Reference — Ableton Reference Manual Version 12
- GVerb — SuperCollider Help
- EnvGen — SuperCollider Help
- Using MIDI — SuperCollider Help
- MIDIdef — SuperCollider Help
- SystemClock — SuperCollider Help
