e- xy= 1y= 0,5
Se guardi un generatore di inviluppo analogico (ad esempio il circuito basato su 7555 che tutti sembrano usare ), puoi vedere che durante la fase di attacco, quando il condensatore si sta caricando, "punta più in alto" della soglia utilizzata per indicare la fine della fase di attacco. Su un circuito (7) basato su 555 alimentato da + 15 V, durante la fase di attacco, il condensatore viene caricato con una fase di + 15 V, ma la fase di attacco termina quando viene raggiunta una soglia di + 10 V. Questa è una scelta di design, sebbene 2/3 sia il "numero magico" che si trova in molti generatori di buste classiche, e questo potrebbe essere quello con cui i musicisti hanno familiarità.
Pertanto, le funzioni che potresti voler trattare non sono esponenziali, ma versioni spostate / troncate / ridimensionate di esso, e dovrai fare alcune scelte su come "schiacciate" che vuoi che siano.
Sono comunque curioso di sapere perché stai cercando di ottenere tali formule - forse è a causa dei limiti dello strumento che stai usando per la sintesi; ma se stai cercando di implementare quelli che usano un linguaggio di programmazione generico (C, java, python) con del codice in esecuzione per ogni campione della busta e una nozione di "stato", continua a leggere ... Perché è sempre più facile esprimere cose come "tale segmento andrà da qualunque valore abbia appena raggiunto a 0".
I miei due consigli sull'implementazione delle buste.
Il primo noper provare a ridimensionare tutte le pendenze / incrementi in modo che l'inviluppo raggiunga esattamente i valori di inizio e fine. Ad esempio, vuoi un inviluppo che va da 0,8 a 0,2 in 2 secondi, quindi potresti essere tentato di calcolare un incremento di -0,3 / secondo. Non farlo. Invece, suddividilo in due passaggi: ottenere una rampa che va da 0 a 1,0 in 2 secondi; e quindi applicare una trasformazione lineare che mappa da 0 a 0,8 e da 1,0 a 0,2. Ci sono due vantaggi nel lavorare in questo modo: il primo è che semplifica qualsiasi calcolo che avrai rispetto ai tempi di inviluppo a una rampa da 0 a 1; il secondo è che se si cambiano i parametri di inviluppo (incrementi e tempi di inizio / fine) a metà tutto rimarrà ben educato. Buono se stai lavorando su un synth, poiché le persone chiederanno di avere i parametri del tempo di inviluppo come destinazioni di modulazione.
Il secondo consiste nell'utilizzare una tabella di ricerca pre-calcolata con forme di inviluppo. È più leggero dal punto di vista computazionale, elimina molti dettagli sporchi (ad esempio non devi preoccuparti di un esponenziale che non raggiunge esattamente 0 - troncalo a tuo capriccio e ridimensionalo in modo che sia mappato su [0, 1]), ed è facile fornire un'opzione per modificare le forme delle buste, per ogni fase.
Ecco lo pseudo-codice per l'approccio che descrivo.
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