So erstellen Sie einen Sinusgenerator, der problemlos zwischen den Frequenzen wechseln kann

  • Ich kann einen grundlegenden Sinusgenerator für Audio schreiben, aber ich möchte, dass er reibungslos von einer Frequenz zu einer anderen übergeht. Wenn ich einfach aufhört, eine Frequenz zu erzeugen und sofort zu einer anderen zu wechseln, wird das Signal unterbrochen und ein "Klick" ist zu hören.

    Meine Frage ist, was gut ist Algorithmus zum Erzeugen einer Welle, die bei etwa 250 Hz beginnt und dann auf 300 Hz übergeht, ohne dass Klicks erforderlich sind. Wenn der Algorithmus eine optionale Gleit- / Portamento-Zeit enthält, ist dies umso besser.

    Ich kann mir einige mögliche Ansätze vorstellen, wie beispielsweise Oversampling, gefolgt von einem Tiefpassfilter oder vielleicht mit einer Wavetable, aber ich bin sicher, dass dies ein häufig vorkommendes Problem ist, dass es eine Standardmethode gibt, um es anzugehen.

    16 December 2011
    Rob Lachlan
5 answers
  • Ein Ansatz, den ich in der Vergangenheit verwendet habe, ist das Aufrechterhalten eines Phasenakkumulators, der als Index in einer Wellenformnachschlagetabelle verwendet wird. Bei jedem Abtastintervall wird dem Akkumulator ein Phasen-Delta-Wert hinzugefügt:

     phase_index += phase_delta
     

    Um die Frequenz zu ändern, ändern Sie die Phase Delta, das dem Phasenakkumulator bei jeder Abtastung hinzugefügt wird, z. B.

     phase_delta = N * f / Fs
     

    Dabei gilt Folgendes:

     phase_delta is the number of LUT samples to increment
    freq is the desired output frequency
    Fs is the sample rate
     

    Dies gewährleistet, dass die Ausgangswellenform kontinuierlich ist, auch wenn Sie phase_delta dynamisch ändern, z Für Frequenzänderungen, FM usw.

    Für glattere Frequenzänderungen (Portamento) können Sie den Wert von phase_delta zwischen dem alten Wert und dem neuen Wert über eine geeignete Anzahl von Abtastintervallen erhöhen als bloßes sofortiges Ändern.

    Beachten Sie, dass phase_index und phase_delta beide eine Ganzzahl und eine gebrochene Komponente haben, dh sie müssen Fließkomma oder Festkomma sein. Der ganzzahlige Teil von phase_index (Modulo-Tabellengröße) wird als ein Index in der Wellenform-LUT verwendet, und der gebrochene Teil kann optional für die Interpolation zwischen benachbarten LUT-Werten für eine höhere Qualität und / oder eine kleinere LUT-Größe verwendet werden.

    16 December 2011
    GillesTimeless
  • Eine der besten Möglichkeiten, eine Sinuswelle zu erstellen, ist die Verwendung eines komplexen Zeigers mit rekursiver Aktualisierung. Dh

    $$ z [n + 1] = z [n] \ Omega $$

    wobei z [n] ist der Zeiger $ \ Omega = \ exp (j \ omega) $, wobei $ \ omega $ die Winkelfrequenz des Oszillators im Bogenmaß und $ n $ der Abtastindex ist. Sowohl der Real- als auch der Imaginärteil von $ z [n] $ sind Sinuswellen, sie sind um 90 Grad phasenverschoben. Sehr praktisch, wenn Sie sowohl Sinus als auch Cosinus benötigen. Eine einzelne Beispielberechnung erfordert nur 4 Vielfache und 4 Additionen und ist VIEL billiger als alles, das sin () cos () oder Nachschlagetabellen enthält. Das potenzielle Problem besteht darin, dass die Amplitude aufgrund von numerischen Genauigkeitsproblemen mit der Zeit driften kann. Es ist jedoch ziemlich einfach, das zu reparieren. Nehmen wir an, $ z [n] = a + jb $. Wir wissen, dass $ z [n] $ den Betrag von 1 haben sollte, dh

    $$ a \ cdot a + b \ cdot b = 1 $$

    Wir können also von Zeit zu Zeit überprüfen, ob dies noch der Fall ist, und dies entsprechend korrigieren. Die genaue Korrektur wäre

    $$ z '[n] = \ frac {z [n]} {\ sqrt {a \ cdot a + b \ cdot b}} $ $

    Dies ist eine umständliche Berechnung, aber da $ a \ cdot a + b \ cdot b $ sehr nahe an Eins liegt, können Sie sich die $ 1 / \ sqrt {x} $ - Ausdrücke annähern mit einer Taylor-Erweiterung um $ x = 1 $ und wir erhalten

    $$ \ frac {1} {\ sqrt {x}} \ cong \ frac {3-x} { 2} $$

    So vereinfacht sich die Korrektur auf

    $$ z '[n] = z [n] \ frac { 3-a ^ 2-b ^ 2} {2} $$

    Wenn Sie diese einfache Korrektur alle paar hundert Samples anwenden, bleibt der Oszillator für immer stabil.

    Um die Frequenz kontinuierlich zu ändern, muss der Multiplikator W entsprechend aktualisiert werden. Selbst eine nicht kontinuierliche Änderung des Multiplizierers behält eine kontinuierliche Oszillatorfunktion bei. Wenn ein Frequenzanstieg erforderlich ist, kann das Update entweder in einige Schritte unterteilt werden, oder Sie können den Multiplikator selbst mit demselben Oszillatoralgorithmus aktualisieren (da er auch ein komplexer Zeiger für die Verstärkung eins ist).

    10 May 2016
    aligator007
  • Ich stimme den vorherigen Vorschlägen zur Verwendung eines Phasenakkumulators zu. Im Wesentlichen ist der Steuereingang der Betrag der Phasenvorverstellung pro Schritt oder pro Taktperiode (oder pro Interrupt oder was auch immer), so dass eine Änderung dieses Werts die Frequenz ohne Unterbrechung in der Phase ändert. Die Wellenamplitude wird dann aus dem akkumulierten Phasenwert entweder über eine LUT oder einfach durch Berechnung von sin (Theta) oder cos (Theta) bestimmt.

    Dies ist im Wesentlichen als Numerical Controlled Oscillator (NCO) oder Direct Digital Synthesizer (DDS) bekannt. Eine Websuche nach diesen Begriffen führt wahrscheinlich zu mehr, als Sie über die Theorie und Praxis wissen wollen, damit sie gut funktionieren.

    Durch das Hinzufügen eines zusätzlichen Akkumulators können nahtlose Übergänge zwischen den Frequenzen ermöglicht werden Wenn Sie dies auch wünschen, können Sie, wie von Ihnen vorgeschlagen, die Änderungsrate des Phasenvorschubwerts steuern. Dies wird manchmal als Digital Differential Analyzer oder DDA bezeichnet.

    31 December 2011
    Yaakov Ellis
  • Von dieser Site :

    Um einen sanften Übergang von einer Frequenz zu einer anderen oder von einer Amplitude zu einer anderen zu erzeugen, muss eine unvollständige Sinuswelle mit einem angefügten Abschnitt modifiziert werden, damit die resultierende Welle entsteht Nach jeder Iteration der while-Schleife endet die x-Achse.

    Klingt so, als sollte es funktionieren.

    (Eigentlich, wenn beide beim Übergang auf der x-Achse synchronisiert sind, nehme ich an, dass ein schrittweiser Übergang nicht erforderlich ist.)

    16 December 2011
  • 1. Ordnung, Sie sollten die Startphase des neuen Frequenzsinusoids so einstellen, dass sie der Phase des vorherigen Sinusoids am ersten Übergangspunkt entspricht. Berechnen Sie die erste Frequenz und verwenden Sie ihre Phase für die zweite Frequenz.

    Die zweite Option könnte darin bestehen, die Phase d_phase von einer Frequenz zur nächsten über mehrere Abtastwerte zu erhöhen. Dadurch wird die Kontinuität der 1. Ableitung bereinigt und ein Gleiteffekt erzielt.

    Die dritte Option könnte die Verwendung eines Glättungsfensters, z. B. eines Raised-Cosinus, für die d_phase-Rampenrate sein .

    16 December 2011
    Leigh Riffel