Octave GNU倍频程:实际FFT数据的1/N倍频程平滑(不是它的表示)

Octave GNU倍频程:实际FFT数据的1/N倍频程平滑(不是它的表示),octave,fft,gnu,smoothing,Octave,Fft,Gnu,Smoothing,我想平滑脉冲响应音频文件。文件的FFT显示它非常尖峰。我想平滑的音频文件,而不仅仅是它的情节,所以我有一个更平滑的红外文件。 我发现这表明FFT图变得平滑了。如何将这种平滑应用于实际FFT数据,而不仅仅是其绘图 [y,Fs] = audioread('test\test IR.wav'); function x_oct = smoothSpectrum(X,f,Noct) %SMOOTHSPECTRUM Apply 1/N-octave smoothing to a frequency spe

我想平滑脉冲响应音频文件。文件的FFT显示它非常尖峰。我想平滑的音频文件,而不仅仅是它的情节,所以我有一个更平滑的红外文件。 我发现这表明FFT图变得平滑了。如何将这种平滑应用于实际FFT数据,而不仅仅是其绘图

[y,Fs] = audioread('test\test IR.wav');

function x_oct = smoothSpectrum(X,f,Noct)
%SMOOTHSPECTRUM Apply 1/N-octave smoothing to a frequency spectrum
    %% Input checking
    assert(isvector(X), 'smoothSpectrum:invalidX', 'X must be a vector.');
    assert(isvector(f), 'smoothSpectrum:invalidF', 'F must be a vector.');
    assert(isscalar(Noct), 'smoothSpectrum:invalidNoct', 'NOCT must be a scalar.');
    assert(isreal(X), 'smoothSpectrum:invalidX', 'X must be real.');
    assert(all(f>=0), 'smoothSpectrum:invalidF', 'F must contain positive values.');
    assert(Noct>=0, 'smoothSpectrum:invalidNoct', 'NOCT must be greater than or equal to 0.');
    assert(isequal(size(X),size(f)), 'smoothSpectrum:invalidInput', 'X and F must be the same size.');

    %% Smoothing

    % calculates a Gaussian function for each frequency, deriving a
    % bandwidth for that frequency

    x_oct = X; % initial spectrum
    if Noct > 0 % don't bother if no smoothing
        for i = find(f>0,1,'first'):length(f)
            g = gauss_f(f,f(i),Noct);
            x_oct(i) = sum(g.*X); % calculate smoothed spectral coefficient
        end
        % remove undershoot when X is positive
        if all(X>=0)
            x_oct(x_oct<0) = 0;
        end
    end
endfunction

function g = gauss_f(f_x,F,Noct)
% GAUSS_F calculate frequency-domain Gaussian with unity gain
% 
%   G = GAUSS_F(F_X,F,NOCT) calculates a frequency-domain Gaussian function
%   for frequencies F_X, with centre frequency F and bandwidth F/NOCT.

    sigma = (F/Noct)/pi; % standard deviation
    g = exp(-(((f_x-F).^2)./(2.*(sigma^2)))); % Gaussian
    g = g./sum(g); % normalise magnitude

endfunction

% take fft
Y = fft(y);
% keep only meaningful frequencies
NFFT = length(y);
if mod(NFFT,2)==0
    Nout = (NFFT/2)+1;
else
    Nout = (NFFT+1)/2;
end
Y = Y(1:Nout);
f = ((0:Nout-1)'./NFFT).*Fs;
% put into dB
Y = 20*log10(abs(Y)./NFFT);
% smooth
Noct = 12;
Z = smoothSpectrum(Y,f,Noct);
% plot
semilogx(f,Y,'LineWidth',0.7,f,Z,'LineWidth',2.2);
xlim([20,20000])
grid on
[y,Fs]=audioread('test\test IR.wav');
函数x_oct=平滑谱(x,f,Noct)
%SMOOTHSPECTRUM将1/N倍频程平滑应用于频谱
%%输入检查
断言(isvector(X),'smoothSpectrum:invalidX','X必须是向量');
断言(isvector(f),'smoothSpectrum:invalidF','f必须是向量');
断言(isscalar(Noct),'smoothSpectrum:invalidNoct','Noct必须是标量');
断言(isreal(X),'smoothSpectrum:invalidX','X必须是实的');
断言(all(f>=0),'smoothSpectrum:invalidF','f必须包含正值');
断言(Noct>=0,“smoothSpectrum:invalidNoct”,“Noct必须大于或等于0”);
断言(isequal(大小(X),大小(f)),'smoothSpectrum:invalidInput','X和f必须大小相同');
%%平滑
%计算每个频率的高斯函数,导出
%该频率的带宽
x_oct=x;%初始光谱
如果Noct>0%,如果没有平滑,请不要麻烦
对于i=find(f>0,1,'first'):长度(f)
g=高斯f(f,f(i),Noct);
x_oct(i)=和(g.*x);%计算平滑谱系数
结束
%当X为正时,消除下冲
如果全部(X>=0)

x_oct(x_oct我想我找到了。由于音频文件的FFT(实数)是对称的,两边的实部相同,但虚部相反,我想这样做:

  • 取FFT,保留其一半,并应用平滑函数,而不将幅值转换为dB
  • 然后复制一个平滑的FFT,然后只反转虚部
  • 将这两部分结合起来,这样我就得到了与开始时相同的对称FFT,但现在它被平滑了
  • 对其应用逆FFT,取实部并将其写入文件
代码如下:

[y,Fs] = audioread('test IR.wav');

function x_oct = smoothSpectrum(X,f,Noct)
    x_oct = X; % initial spectrum
    if Noct > 0 % don't bother if no smoothing
        for i = find(f>0,1,'first'):length(f)
            g = gauss_f(f,f(i),Noct);
            x_oct(i) = sum(g.*X); % calculate smoothed spectral coefficient
        end
        % remove undershoot when X is positive
        if all(X>=0)
            x_oct(x_oct<0) = 0;
        end
    end
endfunction

function g = gauss_f(f_x,F,Noct)
    sigma = (F/Noct)/pi; % standard deviation
    g = exp(-(((f_x-F).^2)./(2.*(sigma^2)))); % Gaussian
    g = g./sum(g); % normalise magnitude
endfunction

% take fft
Y = fft(y);

% keep only meaningful frequencies
NFFT = length(y);
if mod(NFFT,2)==0
    Nout = (NFFT/2)+1;
else
    Nout = (NFFT+1)/2;
end
Y = Y(1:Nout);
f = ((0:Nout-1)'./NFFT).*Fs;

% smooth
Noct = 12;
Z = smoothSpectrum(Y,f,Noct);

% plot
semilogx(f,Y,'LineWidth',0.7,f,Z,'LineWidth',2.2);
xlim([20,20000])
grid on

#Apply the smoothing to the actual data
Zreal = real(Z); # real part
Zimag_neg = Zreal - Z; # opposite of imaginary part
Zneg = Zreal + Zimag_neg; # will be used for the symmetric Z
# Z + its symmetry with same real part but opposite imaginary part
reconstructed = [Z ; Zneg(end-1:-1:2)];
# Take the real part of the inverse FFT
reconstructed = real(ifft(reconstructed));

#Write to file
audiowrite ('smoothIR.wav', reconstructed, Fs, 'BitsPerSample', 24);
[y,Fs]=audioread('test IR.wav');
函数x_oct=平滑谱(x,f,Noct)
x_oct=x;%初始光谱
如果Noct>0%,如果没有平滑,请不要麻烦
对于i=find(f>0,1,'first'):长度(f)
g=高斯f(f,f(i),Noct);
x_oct(i)=和(g.*x);%计算平滑光谱系数
结束
%当X为正时,消除下冲
如果全部(X>=0)

十月十日(x_oct这个问题你不太可能得到好的答案,因为这个问题本身有点含糊不清,它需要缺少数据才能在本地进行试验,并且不清楚你想要什么结果。还有,你缺少哪些matlab函数?你确定你检查了octave forge吗?谢谢你的回答Taso!好的,让我进一步解释一下:我有(test IR.wav)本质上是一个过滤文件,如果与另一个音频文件进行卷积,将导致该IR的过滤器应用于另一个音频文件。我对IR进行了FFT,正如您所看到的,在高频中有很多尖峰,我想对其进行平滑。我发现了一个函数,可以绘制平滑的图(红色)。但这是用于绘图的。如何在IR的实际数据上实现相同的效果?这是加载在VST插件中的相同IR文件,您可以看到平滑的效果。我想要这种效果,但要保留每个倍频程的相同信息量(例如,1/n,对于半音,n=12)。在图片中,这不会发生。但我找到的函数可以做到。但它是为了表示数据而不是数据本身,这样我就可以导出平滑的IR。我希望它现在有意义了!:)是的;但是仍然缺少数据:p你能提供一份
test IR.wav
?还有,你缺少哪些特定的matlab函数?你确定你检查了octave forge吗?这是IR:。我不确定我是否遗漏了特定的matlab函数,因为我不知道我需要什么。:p | |||