Ich kann einen einfachen Sinusgenerator für Audio schreiben, aber ich möchte, dass er reibungslos von einer Frequenz zur anderen wechselt. Wenn ich einfach aufhöre, eine Frequenz zu erzeugen, und sofort auf eine andere umschalte, kommt es zu einer Unterbrechung des Signals, und ein "Klicken" ist zu hören.
Meine Frage ist, was ist ein guter Algorithmus, um eine Welle zu erzeugen, die bei etwa 250 Hz beginnt und dann auf 300 Hz übergeht, ohne dass es zu Klicks kommt. Wenn der Algorithmus eine optionale Gleit- / Portamentozeit enthält, ist dies umso besser.
Ich kann mir ein paar mögliche Ansätze vorstellen, wie Überabtastung, gefolgt von einem Tiefpassfilter, oder vielleicht die Verwendung einer Wavetable, aber ich bin sicher, dass dies ein häufig genug auftretendes Problem ist, dass es eine Standardmethode gibt, um es anzugehen.
Antworten:
Ein Ansatz, den ich in der Vergangenheit verwendet habe, besteht darin, einen Phasenakkumulator beizubehalten, der als Index für eine Wellenform-Nachschlagetabelle verwendet wird. In jedem Abtastintervall wird ein Phasendeltawert zum Akkumulator addiert:
Um die Frequenz zu ändern, ändern Sie das Phasendelta, das dem Phasenakkumulator bei jedem Sample hinzugefügt wird, z
woher:
Dies garantiert, dass die Ausgangswellenform kontinuierlich ist, auch wenn Sie phase_delta dynamisch ändern, z. B. für Frequenzänderungen, FM usw.
Für weichere Frequenzänderungen (Portamento) können Sie den phase_delta-Wert über eine geeignete Anzahl von Abtastintervallen zwischen seinem alten Wert und seinem neuen Wert ändern, anstatt ihn sofort zu ändern.
Beachten Sie, dass
phase_index
undphase_delta
beide eine Ganzzahl- und eine Bruchkomponente haben, dh sie müssen Gleitkomma- oder Festkommazahlen sein. Der ganzzahlige Teil von phase_index (Modulotabellengröße) wird als Index für die Wellenform-LUT verwendet, und der Bruchteil kann optional zur Interpolation zwischen benachbarten LUT-Werten für eine Ausgabe höherer Qualität und / oder eine kleinere LUT-Größe verwendet werden.quelle
Eine der besten Möglichkeiten, eine Sinuswelle zu erstellen, ist die Verwendung eines komplexen Zeigers mit rekursiver Aktualisierung. Dh
So können wir von Zeit zu Zeit prüfen, ob dies noch der Fall ist und entsprechend korrigieren. Die genaue Korrektur wäre
so vereinfacht sich die korrektur zu
Wenn Sie diese einfache Korrektur alle paar hundert Samples anwenden, bleibt der Oszillator für immer stabil.
Um die Frequenz kontinuierlich zu variieren, muss der Multiplikator W entsprechend aktualisiert werden. Selbst eine nicht kontinuierliche Änderung des Multiplikators behält eine kontinuierliche Oszillatorfunktion bei. Wenn eine Frequenzerhöhung erforderlich ist, kann die Aktualisierung entweder in einige Schritte unterteilt werden, oder Sie können denselben Oszillatoralgorithmus verwenden, um den Multiplikator selbst zu aktualisieren (da er auch ein komplexer Zeiger mit Einheitsverstärkung ist).
quelle
Von dieser Seite :
Klingt so, als sollte es funktionieren.
(Wenn beide beim Übergang auf der x-Achse synchronisiert sind, ist vermutlich kein schrittweiser Übergang erforderlich.)
quelle
Ich stimme den bisherigen Vorschlägen zur Verwendung eines Phasenakkumulators zu. Im Wesentlichen ist der Steuereingang der Betrag des Phasenvorschubs pro Schritt oder pro Taktperiode (oder pro Unterbrechung oder was auch immer), so dass das Ändern dieses Werts die Frequenz ohne Unterbrechung in der Phase ändert. Die Wellenamplitude wird dann aus dem akkumulierten Phasenwert entweder über eine LUT oder nur über die Berechnung von sin (Theta) oder cos (Theta) bestimmt.
Dies ist im Wesentlichen das, was allgemein als numerisch gesteuerter Oszillator (NCO) oder direkter digitaler Synthesizer (DDS) bekannt ist. Wenn Sie eine Websuche nach diesen Begriffen durchführen, erhalten Sie wahrscheinlich mehr als Sie in Theorie und Praxis wissen möchten, damit sie gut funktionieren.
Das Hinzufügen eines zusätzlichen Akkumulators kann nahtlose Übergänge zwischen Frequenzen ermöglichen, wie Sie vorgeschlagen haben, wenn dies ebenfalls gewünscht wird, indem die Änderungsrate des Phasenvorschubwerts gesteuert wird. Dies wird manchmal als Digital Differential Analyzer oder DDA bezeichnet.
quelle
1. Ordnung, Sie sollten die Startphase der neuen Frequenz-Sinuskurve so einstellen, dass sie mit der Phase der vorherigen Sinuskurve am 1. Übergang-Abtastpunkt übereinstimmt. Berechnen Sie die erste Frequenz und verwenden Sie deren Phase für die zweite Frequenz.
Die zweite Möglichkeit könnte darin bestehen, d_phase über mehrere Abtastwerte von einer Frequenz zur nächsten zu rampen. Dadurch wird die Kontinuität der 1. Ableitung aufgeräumt und ein Gleiten ermöglicht.
Die dritte Option könnte darin bestehen, ein Glättungsfenster wie einen Raised-Cosine für die d_phase-Anstiegsrate zu verwenden.
quelle