Ich denke, was Sie verwirrt, ist, dass ein abnehmendes Exponential ( ) niemals 0 erreicht, so dass ein ADSR-Generator mit wirklich exponentiellen Segmenten stecken bleiben würde; weil es niemals den Zielwert erreichen würde. Befindet sich der Generator beispielsweise auf dem Höhepunkt der Angriffsphase (z. B. y = 1 ) und muss er bei y = 0,5 auf einem Sustain-Wert landen , kann er nicht mit einem echten Exponential dorthin gelangen, da das wahre Exponential gewonnen hat. ' t auf 0,5 abfallen, geht es nur asymptotisch auf 0,5!e- xy= 1y= 0,5
Wenn Sie sich einen analogen Hüllkurvengenerator ansehen (zum Beispiel die 7555-basierte Schaltung, die anscheinend jeder verwendet ), können Sie sehen, dass der Kondensator während der Angriffsphase beim Laden "höher zielt" als der Schwellenwert, der zur Anzeige des Endes verwendet wird der Angriffsphase. Auf einer (7) 555-basierten Schaltung, die mit +15 V betrieben wird, wird der Kondensator während der Angriffsphase mit einem + 15-V-Schritt aufgeladen, aber die Angriffsstufe endet, wenn ein Schwellenwert von +10 V erreicht wurde. Dies ist eine Design-Wahl, obwohl 2/3 die "magische Zahl" ist, die in vielen klassischen Hüllkurvengeneratoren zu finden ist, und dies könnte diejenige sein, mit der Musiker vertraut sind.
Daher sind die Funktionen, mit denen Sie sich möglicherweise befassen möchten, keine Exponentialfunktionen, sondern verschobene / abgeschnittene / skalierte Versionen davon, und Sie müssen einige Entscheidungen treffen, wie "gequetscht" sie sein sollen.
Ich bin sowieso neugierig, warum Sie versuchen, solche Formeln zu erhalten - vielleicht liegt es an den Grenzen des Werkzeugs, das Sie für die Synthese verwenden; Wenn Sie jedoch versuchen, diese mithilfe einer universellen Programmiersprache (C, Java, Python) zu implementieren, wobei für jedes Beispiel des Umschlags Code ausgeführt wird und der Begriff "Status" verwendet wird, lesen Sie weiter ... Weil dies immer einfacher ist Drücken Sie Dinge aus wie "ein solches Segment wird von dem Wert, den es gerade erreicht hat, auf 0 gehen".
Meine zwei Ratschläge zur Implementierung von Umschlägen.
Der erste ist nichtum zu versuchen, alle Steigungen / Inkremente so zu skalieren, dass die Hüllkurve genau die Start- und Endwerte erreicht. Sie möchten beispielsweise eine Hüllkurve, die in 2 Sekunden von 0,8 auf 0,2 steigt, sodass Sie möglicherweise versucht sind, ein Inkrement von -0,3 / Sekunde zu berechnen. Tu das nicht. Teilen Sie es stattdessen in zwei Schritte auf: Erhalten einer Rampe, die in 2 Sekunden von 0 auf 1,0 geht; und dann Anwenden einer linearen Transformation, die 0 bis 0,8 und 1,0 bis 0,2 abbildet. Auf diese Weise gibt es zwei Vorteile: Der erste besteht darin, dass die Berechnung im Verhältnis zu den Hüllkurvenzeiten für eine Rampe von 0 auf 1 vereinfacht wird. Das zweite ist, dass, wenn Sie die Hüllkurvenparameter (Inkremente und Start- / Endzeiten) auf halbem Weg ändern, sich alles gut verhält. Gut, wenn Sie an einem Synthesizer arbeiten, da die Leute nach Hüllkurvenzeitparametern als Modulationsziele fragen.
Die zweite besteht darin, eine vorberechnete Nachschlagetabelle mit Umschlagformen zu verwenden. Es ist rechnerisch leichter, es entfernt viele schmutzige Details (zum Beispiel müssen Sie sich nicht mit einem Exponential herumschlagen, das nicht genau 0 erreicht - schneiden Sie es nach Lust und Laune ab und skalieren Sie es neu, damit es auf [0, 1] abgebildet wird). und es ist kinderleicht, für jede Stufe eine Option zum Ändern der Umschlagformen bereitzustellen.
Hier ist der Pseudocode für den Ansatz, den ich beschreibe.
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
Dies ist eine ziemlich alte Frage, aber ich möchte nur einen Punkt in der Antwort von Pichenettes hervorheben:
Dieser Prozess wird manchmal als "Lockerung" bezeichnet und sieht aus wie
* Ich denke, das OP ist wahrscheinlich schon lange weg, aber vielleicht hilft das jemand anderem.
quelle
Über den Kommentar von Pichenettes: "Während der Angriffsphase wird der Kondensator mit einem + 15V-Schritt aufgeladen, aber die Angriffsphase endet, wenn ein Schwellenwert von +10 V erreicht wurde. Dies ist eine Entwurfswahl, obwohl 2/3 die" Magie "ist Nummer "in vielen klassischen Hüllkurvengeneratoren zu finden, und dies könnte diejenige sein, mit der Musiker vertraut sind.":
Jeder Umschlag, der für eine 15-V-Asymptote mit einem 10-V-Ziel schießt, erzeugt praktisch einen linearen Angriff. Es ist nur so, dass 15 V die höchste leicht verfügbare Asymptote ist und nahe genug an der Linearität liegt. Das heißt, es gibt nichts "Magisches" daran - sie streben nur so linear an, wie sie nur können.
Ich weiß nicht, wie viele klassische Synthesizer 15 V verwenden - ich würde vermuten, dass es oft ein oder zwei Diodenabfälle gibt. Mein altes Aries-Modul verwendet 13 V für eine 10-V-Hüllkurve, und ich habe gerade einen Curtis ADSR-Chip nachgeschlagen, der 6,5 V für eine 5-V-Hüllkurve verwendet.
quelle
Dieser Code sollte ähnliche Diagramme wie die von Pichenetten erzeugen:
Ich bin dankbar für Verbesserungen. Eine gute Idee ist es, die letzten drei Parameter (die die Steilheit jeder der drei Stufen bestimmen) zwischen 0 und 1 variieren zu lassen, wobei 0,5 eine gerade Linie wäre. Aber ich kann nicht ohne weiteres sehen, wie es geht.
Außerdem habe ich nicht alle Anwendungsfälle gründlich getestet, beispielsweise wenn eine Stufe eine Länge von Null hat.
quelle