Saya pikir yang membingungkan Anda adalah bahwa penurunan eksponensial ( ) tidak pernah mencapai 0, sehingga generator ADSR dengan segmen yang benar-benar eksponensial akan tetap macet; karena tidak akan pernah mencapai nilai target. Misalnya, jika generator berada pada puncak fase serangan (katakanlah ) dan harus mendarat ke nilai yang dipertahankan pada , ia tidak dapat pergi ke sana dengan eksponensial sejati, karena eksponensial sejati menang ' t membusuk menjadi 0,5, itu hanya asimtotik pergi ke 0,5! y = 1 y = 0,5e−xy=1y=0.5
Jika Anda melihat generator amplop analog (misalnya rangkaian berbasis 7555 yang tampaknya semua orang gunakan ), Anda dapat melihat bahwa selama fase serangan, ketika kapasitor sedang diisi, itu "mengarah lebih tinggi" daripada ambang yang digunakan untuk menunjukkan akhir dari fase serangan. Pada (7) 555 berbasis sirkuit didukung oleh + 15V, Selama tahap serangan, kapasitor diisi dengan langkah + 15V, tetapi tahap serangan berakhir ketika ambang + 10V telah tercapai. Ini adalah pilihan desain, meskipun 2/3 adalah "angka ajaib" yang ditemukan di banyak generator amplop klasik, dan ini mungkin satu-satunya musisi yang akrab dengannya.
Dengan demikian, fungsi yang mungkin ingin Anda tangani bukanlah versi eksponensial, tetapi versi yang digeser / terpotong / skala, dan Anda harus membuat beberapa pilihan tentang seberapa "terjepit" Anda inginkan.
Saya tetap penasaran mengapa Anda mencoba untuk mendapatkan formula seperti itu - mungkin itu karena batas alat yang Anda gunakan untuk sintesis; tetapi jika Anda mencoba untuk mengimplementasikan yang menggunakan bahasa pemrograman tujuan umum (C, java, python) dengan beberapa kode berjalan untuk setiap sampel amplop, dan gagasan "negara", baca terus ... Karena selalu lebih mudah untuk mengungkapkan hal-hal sebagai "segmen tersebut akan berubah dari nilai apa pun yang baru saja mencapai 0".
Dua saran saya tentang penerapan amplop.
Yang pertama bukanuntuk mencoba skala semua kemiringan / peningkatan sehingga amplop tepat mencapai nilai awal dan akhir. Misalnya Anda menginginkan amplop yang bergerak dari 0,8 menjadi 0,2 dalam 2 detik, jadi Anda mungkin tergoda untuk menghitung kenaikan -0,3 / detik. Jangan lakukan itu. Sebagai gantinya, bagi menjadi dua langkah: dapatkan tanjakan yang bergerak dari 0 hingga 1.0 dalam 2 detik; dan kemudian menerapkan transformasi linear yang memetakan 0 hingga 0,8 dan 1,0 hingga 0,2. Ada dua keuntungan untuk bekerja dengan cara ini - yang pertama adalah bahwa hal itu menyederhanakan perhitungan yang akan Anda miliki relatif terhadap waktu amplop ke ramp dari 0 ke 1; yang kedua adalah bahwa jika Anda mengubah parameter amplop (kenaikan dan waktu mulai / akhir) di tengah-tengah semuanya akan tetap berperilaku baik. Baik jika Anda mengerjakan synth, karena orang akan meminta parameter waktu amplop sebagai tujuan modulasi.
Yang kedua adalah menggunakan tabel pencarian pra-komputasi dengan bentuk amplop. Ini lebih ringan secara komputasi, mengeluarkan banyak detail kotor (misalnya Anda tidak perlu repot dengan eksponensial yang tidak mencapai 0 persis - terpotong sesuai keinginan dan skala ulang sehingga dipetakan ke [0, 1]), dan itu sangat mudah untuk memberikan opsi untuk mengubah bentuk amplop, untuk setiap tahap.
Berikut adalah pseudo-code untuk pendekatan yang saya jelaskan.
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
Ini adalah pertanyaan yang cukup lama, tetapi saya hanya ingin menyoroti satu hal dalam jawaban dari pichenettes:
Proses ini kadang-kadang dikenal sebagai "pelonggaran," dan terlihat seperti
di mana dan adalah batas bawah dan atas (nilai yang mungkin adalah , , dan level penopang) dan adalah sesuatu seperti . Perhatikan bahwa Anda tidak memerlukan ini untuk fase serangan karena sudah berkisar dari hingga .u 0 1 f ( x ) x n 0 1l u 0 1 f(x) xn 0 1
Inilah sesi Desmos asli, yang diperbarui untuk menggunakan pendekatan ini. Saya menggunakan bentuk kubik di sini, tetapi Anda * dapat menggunakan bentuk apa pun yang Anda suka, selama menghasilkan output mulai dari nol hingga satu input yang diberikan mulai dari nol hingga satu.f(x)
* Saya kira OP mungkin sudah lama hilang, tapi mungkin ini membantu orang lain.
sumber
Tentang komentar pichenettes, "Selama tahap serangan, kapasitor diisi dengan langkah + 15V, tetapi tahap serangan berakhir ketika ambang + 10V telah tercapai. Ini adalah pilihan desain, meskipun 2/3 adalah" sihir " angka "ditemukan di banyak generator amplop klasik, dan ini mungkin satu-satunya musisi yang akrab dengannya.":
Setiap amplop yang memotret untuk asimtot 15v dengan target 10v, praktis, menciptakan serangan linier. Hanya saja 15v adalah asimtot tertinggi yang tersedia dengan mudah, dan cukup dekat dengan linier. Artinya, tidak ada "keajaiban" tentang hal itu — mereka hanya berjalan se linear yang bisa mereka dapatkan.
Saya tidak tahu berapa banyak synth klasik yang menggunakan 15v — saya menduga sering ada satu atau dua dioda drop. Modular Aries lama saya menggunakan 13v untuk amplop 10v, dan saya baru saja mencari chip Curtis ADSR yang menggunakan, setara, 6,5v untuk amplop 5v.
sumber
Kode ini harus menghasilkan plot yang mirip dengan pichenettes:
Saya bersyukur atas perbaikan apa pun, satu hal yang mungkin merupakan ide yang baik adalah membiarkan tiga parameter terakhir (yang menentukan kecuraman masing-masing dari tiga tahap) bervariasi antara 0 dan 1, di mana 0,5 akan menjadi garis lurus. Tapi saya tidak bisa melihat langsung bagaimana melakukannya.
Juga saya belum menguji secara menyeluruh semua kasus penggunaan, misalnya jika satu tahap memiliki panjang nol.
sumber