Eu tenho um sistema de processamento de sinal digital de ponto flutuante que opera a uma taxa de amostragem fixa de amostras por segundo implementada usando um processador x86-64. Supondo que o sistema DSP esteja sincronizado com o que quer que seja importante, qual é a melhor maneira de implementar um oscilador digital em alguma frequência ?
Especificamente, quero gerar o sinal: que para o número da amostra .
Uma idéia é acompanhar um vetor que giramos em um ângulo em cada ciclo do relógio.
Como uma implementação de pseudocódigo do Matlab (a implementação real está em 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)]
Em seguida, em cada ciclo do relógio, rotacionamos o vetor um pouco:
%% 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
Isso permite que o oscilador seja calculado com apenas 4 multiplicações por ciclo. No entanto, eu me preocuparia com erros de fase e estabilidade de amplitude. (Em testes simples, fiquei surpreso que a amplitude não tenha morrido ou explodido imediatamente - talvez a sincos
instrução garanta ?).
Qual é a maneira certa de fazer isso?
sincos
compara a um punhado de multiplicações? Existem possíveis armadilhas a serem observadas com amod
operação?Além disso, não precisamos fazer isso em todas as amostras, mas uma vez a cada 100 ou 1000 amostras é mais que suficiente para manter essa estabilidade. Isso é particularmente útil se você fizer um processamento baseado em quadros. Atualizar uma vez por quadro é bom. Aqui está um rápido Matlab calcula 10.000.000 amostras.
fonte
Você pode evitar o desvio de magnitude instável se não o fizer atualizar recursivamente o vetor v. Em vez disso, gire o vetor protótipo v para a fase de saída atual. Isso ainda requer algumas funções trigonométricas, mas apenas uma vez por buffer.
Desvio de magnitude e frequência arbitrária
pseudo-código:
Você pode eliminar a multiplicação, as funções trigonométricas exigidas pelo cexp e o módulo restante acima de 2pi, se você puder tolerar uma conversão de frequência quantizada. por exemplo, fs / 1024 para um buffer fasor de amostra de 1024.
fonte