FFT和改变频率以及向量化FOR循环

3

使用FFT和傅里叶级数展开FOR循环,我可以增加和减小信号的频率。但是,如果信号/数组太大,执行速度会非常慢(一个1x44100的数组需要约2分钟才能完成)。我确定这与for循环有关,但我不知道如何矢量化它以改善性能。请注意,这将用于长度为3到6分钟的音频信号。1x44100的数组仅为一秒钟,需要约2分钟才能完成。

请问有什么建议吗?

%create signal
clear all, clc,clf,tic
x= linspace(0,2*pi,44100)';

%Used in exporting to ycalc audio file make sure in sync with above
freq_orig=1;
freq_new=4
vertoff=0;
vertoffConj=0;
vertoffInv=0;
vertoffInvConj=0;
phaseshift=(0)*pi/180 ; %can use mod to limit to 180 degrees

y=sin(freq_orig*(x));
[size_r,size_c]=size(y);

N=size_r; %to test make 50
T=2*pi;
dt=T/N;
t=linspace(0,T-dt,N)';
phase = 0;
f0 = 1/T; % Exactly, one period

y=(y/max(abs(y))*.8)/2; %make the max amplitude here
C = fft(y)/N; % No semicolon to display output


A = real(C);
B = imag(C)*-1; %I needed to multiply by -1 to get the correct sign

% Single-Sided (f >= 0)
An = [A(1); 2*A(2:round(N/2)); A(round(N/2)+1)]; 
Bn = [B(1); 2*B(2:round(N/2)); B(round(N/2)+1)];

pmax=N/2;
ycalc=zeros(N,1); %preallocating space for ycalc
w=0;

for p=2:pmax
               %
       %%1 step) re-create signal using equation
        ycalc=ycalc+An(p)*cos(freq_new*(p-1).*t-phaseshift)
+Bn(p)*sin(freq_new*(p-1).*t-phaseshift)+(vertoff/pmax);
        w=w+(360/(pmax-1)); %used to create phaseshift
        phaseshift=w;

end;

fprintf('\n- Completed in %4.4fsec or %4.4fmins\n',toc,toc/60);

subplot(2,1,1), plot(y),title('Orginal Signal');
subplot(2,1,2),plot(ycalc),title('FFT new signal');

如果有人想要查看输出结果,这里有一个图表,可以看到FOR循环确实非常慢。

enter image description here

1个回答

1

看起来你基本上是在频域中向上移动信号,然后你的“级数展开”只是在移动版本上实现了逆DFT。如你所见,朴素的iDFT将会非常慢。尝试将整个循环更改为ifft调用,你应该能够获得巨大的加速。


是的,我正在使用"傅里叶级数展开"(正弦/余弦)来进行逆离散傅里叶变换。我发现这对我来说更容易全面理解和控制改变新信号的几乎所有方面。我已经使用了fft/ifft将信号从时域转换到频域。问题是,我不确定如何开始这个问题,即如何使用ifft增加/减少频率和/或调整相位。有人有关于这个的例子吗? - Rick T

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接