ฉันคิดว่าสิ่งที่คุณสับสนคือเลขชี้กำลังลดลง ( ) ไม่ถึง 0 ดังนั้นตัวสร้าง ADSR ที่มีเซ็กเมนต์อธิบายอย่างแท้จริงจะติดอยู่ เพราะมันจะไม่ถึงค่าเป้าหมาย ตัวอย่างเช่นหากเครื่องกำเนิดไฟฟ้าอยู่ที่ระดับสูงสุดของระยะการโจมตี (พูดว่า ) และต้องลงจอดเพื่อรักษาค่าที่มันจะไม่สามารถไปที่นั่นพร้อมกับเลขชี้กำลังจริงเพราะเลขชี้กำลังที่แท้จริงชนะ ' ไม่สลายตัวถึง 0.5 มันจะไปที่ asymptotically 0.5 เท่านั้น! y = 1 y = 0.5อี- xY= 1Y= 0.5
หากคุณดูที่เครื่องสร้างซองจดหมายแบบแอนะล็อก (ตัวอย่างเช่นวงจรที่ใช้ 7555 ที่ทุกคนดูเหมือนจะใช้ ) คุณจะเห็นว่าในช่วงการโจมตีเมื่อตัวเก็บประจุกำลังชาร์จประจุมันคือ "เล็งที่สูงขึ้น" กว่าเกณฑ์ที่ใช้เพื่อระบุจุดสิ้นสุด ของระยะการโจมตี บนวงจรที่ใช้วงจร (7) 555 ตัวขับเคลื่อนโดย +15V ในระหว่างขั้นตอนการโจมตีตัวเก็บประจุจะถูกชาร์จด้วยขั้นตอน +15V แต่ขั้นตอนการโจมตีจะสิ้นสุดลงเมื่อถึงเกณฑ์ + 10V นี่คือตัวเลือกการออกแบบแม้ว่า2/3 จะเป็น "หมายเลขเวทมนตร์" ที่พบในเครื่องกำเนิดซองจดหมายแบบคลาสสิกจำนวนมากและนี่อาจเป็นสิ่งที่นักดนตรีคนหนึ่งคุ้นเคย
ดังนั้นฟังก์ชั่นที่คุณอาจต้องการจัดการไม่ใช่แบบเอ็กซ์โปเนนเชียล แต่เปลี่ยน / ตัดทอน / ปรับขนาดเวอร์ชั่นของมันแล้วคุณจะต้องเลือกบางอย่างว่า "แบน" คุณต้องการให้มันเป็นอย่างไร
ฉันสงสัยอยู่แล้วว่าทำไมคุณถึงพยายามใช้สูตรดังกล่าว - อาจเป็นเพราะข้อ จำกัด ของเครื่องมือที่คุณใช้ในการสังเคราะห์ แต่ถ้าคุณกำลังพยายามที่จะใช้สิ่งเหล่านั้นโดยใช้ภาษาโปรแกรมทั่วไป (C, java, python) โดยมีโค้ดที่ใช้สำหรับแต่ละตัวอย่างของซองจดหมายและแนวคิดของ "สถานะ" อ่านต่อ ... เพราะง่ายกว่าเสมอ แสดงสิ่งต่าง ๆ ว่า "ส่วนดังกล่าวจะเปลี่ยนจากมูลค่าใด ๆ ที่เพิ่งถึง 0"
คำแนะนำสองข้อของฉันในการติดตั้งซองจดหมาย
คนแรกไม่ใช่เพื่อพยายามปรับสเกลลาด / ส่วนที่เพิ่มขึ้นทั้งหมดเพื่อให้ซองจดหมายถึงค่าเริ่มต้นและค่าสิ้นสุด ตัวอย่างเช่นคุณต้องการซองจดหมายที่เพิ่มขึ้นจาก 0.8 เป็น 0.2 ใน 2 วินาทีดังนั้นคุณอาจถูกคำนวณให้เพิ่ม -0.3 / วินาที อย่าทำอย่างนั้น ให้แบ่งออกเป็นสองขั้นตอนแทนรับทางลาดที่ไปจาก 0 ถึง 1.0 ใน 2 วินาที; จากนั้นใช้การแปลงเชิงเส้นที่แมป 0 ถึง 0.8 และ 1.0 ถึง 0.2 การทำงานด้วยวิธีนี้มีข้อดีสองข้อข้อแรกคือช่วยลดความยุ่งยากในการคำนวณใด ๆ ที่คุณจะสัมพันธ์กับเวลาของซองจดหมายไปยังทางลาดจาก 0 ถึง 1 อย่างที่สองคือถ้าคุณเปลี่ยนพารามิเตอร์ของซองจดหมาย (เพิ่มขึ้นและเวลาเริ่ม / สิ้นสุด) ตรงกลางทุกอย่างจะยังคงทำงานได้ดี ดีถ้าคุณกำลังทำงานกับ synth เพราะคนจะขอให้มีพารามิเตอร์เวลาซองจดหมายเป็นปลายทางการปรับ
ที่สองคือการใช้ตารางการค้นหาที่คำนวณล่วงหน้าด้วยรูปร่างซองจดหมาย มันเบากว่าการคำนวณใช้รายละเอียดที่สกปรกมาก (ตัวอย่างเช่นคุณไม่ต้องกังวลกับเลขยกกำลังที่ไม่ถึง 0 - ตัดมันด้วยความตั้งใจของคุณและช่วยให้มันเป็นแมป [0, 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