Saya memiliki sistem pemrosesan sinyal digital floating-point yang beroperasi pada laju sampel tetap sampel per detik diimplementasikan menggunakan prosesor x86-64. Dengan asumsi bahwa sistem DSP terkunci secara sinkron ke masalah apa pun, apa cara terbaik untuk mengimplementasikan osilator digital pada frekuensi tertentu ?
Secara khusus, saya ingin menghasilkan sinyal: mana untuk jumlah sampel .
Satu ide adalah untuk melacak vektor yang kita putar dengan sudut pada setiap siklus clock.
Sebagai implementasi pseudocode Matlab (implementasi sebenarnya adalah dalam C):
%% Initialization code
f_s = 32768; % sample rate [Hz]
f = 19.875; % some constant frequency [Hz]
v = [1 0]; % initial condition
d_phi = 2*pi * f / f_s; % change in angle per clock cycle
% initialize the rotation matrix (only once):
R = [cos(d_phi), -sin(d_phi) ; ...
sin(d_phi), cos(d_phi)]
Kemudian, pada setiap siklus jam, kami memutar vektor sekitar sedikit:
%% in-loop code
while (forever),
v = R*v; % rotate the vector by d_phi
y = v(1); % this is the sine wave we're generating
output(y);
end
Ini memungkinkan osilator untuk dihitung hanya dengan 4 perkalian per siklus. Namun, saya khawatir tentang kesalahan fase dan stabilitas amplitudo. (Dalam tes sederhana saya terkejut bahwa amplitudo tidak mati atau meledak segera - mungkin sincos
instruksi menjamin ?).
Apa cara yang tepat untuk melakukan ini?
sincos
dibandingkan dengan beberapa perkalian? Apakah ada kemungkinan jebakan yang harus diwaspadai denganmod
operasi?Selain itu kami tidak perlu melakukan ini pada setiap sampel tunggal, tetapi sekali setiap 100 atau 1000 sampel lebih dari cukup untuk menjaga ini stabil. Ini sangat berguna jika Anda melakukan pemrosesan berbasis bingkai. Memperbarui sekali per frame tidak masalah. Berikut ini adalah Matlab cepat yang menghitung 10.000.000 sampel.
sumber
Anda dapat menghindari penyimpangan besarnya tidak stabil jika Anda tidak membuatnya memperbarui vektor v secara rekursif. Sebagai gantinya, putar vektor prototipe v Anda ke fase output saat ini. Ini masih memerlukan beberapa fungsi trigonometri, tetapi hanya sekali per buffer.
Tidak ada frekuensi penyimpangan dan frekuensi arbitrer
kodesemu:
Anda dapat menghapus multiply, fungsi trigonometri yang diperlukan oleh cexp, dan modulus lebih dari 2pi jika Anda dapat mentolerir terjemahan frekuensi yang dikuantisasi. misal fs / 1024 untuk buffer fasor sampel 1024.
sumber