Wie sieht man Sinus verschiedener Frequenzen aus einer Nachschlagetabelle mit fester Größe?

8

Ich nehme eine Sinuswelle bei 48 kHz, der Frequenzbereich meiner Sinuswelle kann von 0 bis 20000 Hz mit einer Stufe von etwa 100 Hz variieren. Ich verwende einen Nachschlagetabellen-Ansatz. Also erstelle ich 4096 Samples für eine Sinuswelle für 4096 verschiedene Phasen. Ich denke, die allgemeine Idee dahinter ist, die Schrittweite zu erhöhen und unterschiedliche Schrittweiten für unterschiedliche Frequenzen zu verwenden. Also mache ich folgendes (Pseudocode). Aber ich bin mir nicht sicher, wie die Schrittgröße mit der Frequenz zusammenhängt, mit der ich die Samples der Sinuswelle erzeugen will? Zum Beispiel, wenn meine Frequenz 15000 Hz ist, was wäre die Schrittweite, die ich durchqueren muss? Ist meine Stichprobengröße (4096) zu niedrig?

%Vor%

Vielen Dank im Voraus.

    
as3rdaccount 20.11.2012, 04:31
quelle

5 Antworten

15

Sie sind auf der richtigen Spur - zuerst müssen wir eine Sinus-LUT erzeugen:

%Vor%

Beachten Sie, dass wir diese LUT nur einmal generieren müssen, z. während der Initialisierung.

Nun, da wir eine Sinuswellen-LUT haben, können wir damit jede beliebige Frequenz erzeugen, die wir mit einem Phasenakkumulator verwenden möchten:

%Vor%

Hinweis: Für eine höhere Ausgabequalität können Sie lineare Interpolation zwischen den LUT-Werten bei phase_i und phase_i + 1 verwenden, aber der obige Ansatz ist für die meisten Audioanwendungen gut genug.

    
Paul R 20.11.2012, 05:51
quelle
4

Bei der Nachschlagetabelle kann man den Speicher effizient verwenden und nur den ersten Quadranten der Sinuswelle speichern.

%Vor%

Ich würde lineare Interpolation empfehlen, aber es gibt auch einen Vektorrotationsansatz für die Sinusgenerierung (der gleichzeitig Sinus und Kosinus erzeugt)

%Vor%

wobei alpha = Phasendifferenz der Frequenz = 2pi * fHz / Ts, wobei fHz die Frequenz ist, die erzeugt werden soll (in Hertz) und Ts die Abtastzeit (oder 1 / Ts = Abtastfrequenz) zB 44100 Hz).

was zu einem resonierenden Rückkopplungsfilter führt, dessen Übertragungsfunktion f (z) zwei konjugierte Pole im Einheitskreis hat (z = e ^ jomegaT).

%Vor%

Der spaßige Teil ist, dass man das Alpha (cos (alpha)) im Flug ändern kann. Der Nachteil dieses IIR-Filter-Ansatzes ist, dass er definitionsgemäß instabil ist. Gleitkomma- und insbesondere Fixpunktungenauigkeiten akkumulieren und führen entweder zu exponentiellem Abfall oder exponentiellem Wachstum der Magnitude. Dies kann jedoch mit einer leichten Phasenverzerrung behoben werden.

Statt wie in CORDIC Rotation mit einem bekannten Per-Iterations-Verstärkungsfaktor:

%Vor%

erzeugt keine perfekten Kreise für (x ', y' ') sondern stabile Ellipsen, selbst bei Festkommaarithmetik. (Beachten Sie, dass dies relativ kleine Alpha-Werte annimmt, also auch relativ niedrige Frequenzen.)

    
Aki Suihkonen 20.11.2012 06:50
quelle
3

Wenn Sie eine hohe Genauigkeit wünschen, können Sie eine trigonometrische Identität verwenden, um sowohl eine kleine LUT als auch saubere Sinuswellen zu erhalten.

%Vor%     
jfaller 20.11.2012 17:11
quelle
0

Sehr gute Antwort, das ist klassische Software DDS. Gegen das gleiche Problem in diesen Tagen. Es ist nicht notwendig, Floats zu verwenden

%Vor%

Lassen Sie die Phasenumbruch-LUT-Größe als Maske. Und es ist mir egal, Quadranten zu verwenden, denn für meinen Zweck habe ich bereits einen riesigen MIPS für diese Anforderungen.

    
user1973900 24.07.2013 21:10
quelle
-1

Laut "http://en.wikipedia.org/wiki/X86_instruction_listings", wenn Sie x80387 oder neuer haben, gibt es eine Sinus-Anweisung, also rufen Sie sie einfach direkt an. Sie müssen nur herausfinden, wie Sie Ihrem Programm eine Inline-Assembler-Sprache hinzufügen. Auf diese Weise müssen Sie sich keine Sorgen machen, wenn Ihr Eingabewert nicht genau mit dem in Ihrer Tabelle übereinstimmt.

    
Marichyasana 20.11.2012 05:23
quelle