Hi, I need some help with a simulation I am working on in matlab. I am working on a noise suppression algorithm for speech signals sampled at 8kHz. When I modify the amplitude of a number of frequency bins, I get distortions in the modified signal when I transfer it back to the time domain. Here is a copy of my script ....I am hoping that somebody in this group could tell me what I am doing wrong. clc close all clear all %% Load signal % x: noisy speech signal % s: clean speech signal % n: noise signal addpath '..\audiofiles' % Load speech signal TargetFs = 8000; Tsec = 7; [s,fs]=wavread('cleanspeech.wav',1); [s,fs]=wavread('cleanspeech.wav',fs*Tsec); s = s'; s = resample(s,TargetFs,fs); % Add white noise to the speech signal dBSNR = 30; x = awgn(s,dBSNR,'measured'); n = x-s; %% Init Variables % sout: final output signal sout = []; % number of samples in a sample block blockSize = TargetFs/100; % reset block counter blockCounter = 0; % calculate total number of blocks to process numberOfBlocks = floor(length(x)/blockSize); % calculate fft size fftSize = 2^nextpow2(3*blockSize); % define frame size frameSize = fftSize; % init sampleframe for output samples sampleFrameOut = zeros(1,frameSize); % init phi angle phi = 0; %% Main DSP Loop while (1) audioBlockIn = x(1+blockCounter*blockSize:blockSize+blockCounter*blockSize); % Do fft of audio block audioVector = zeros(1,fftSize); audioVector(1:blockSize) = audioBlockIn; X = fft(audioVector); % simulate gain changes gainVec = [abs(cos(phi)) abs(cos(phi)) abs(cos(phi)) abs(cos(phi)) abs(cos(phi)) abs(cos(phi)) abs(cos(phi)) ones(1,120)]; phi = phi + 0.03; % Create gain vector G = [1 gainVec 1 gainVec(end:-1:1)]; % Modify spectrum Y = G.*X; % Overlap-Add sampleFrameOut = sampleFrameOut + real(ifft(Y)); audioBlockOut = sampleFrameOut(1:blockSize); sampleFrameOut = [sampleFrameOut(blockSize+1:end) zeros(1,blockSize)]; sout = [sout audioBlockOut]; blockCounter = blockCounter + 1; if (blockCounter == numberOfBlocks) break; end end wavplay(sout,TargetFs)
Online · Live + on demand
February 9-11, 2027
Price goes up Nov 1: register now to lock in today's rate
Register Now →
Changing gain in frequency domain creates funny artefacts
Started by ●May 26, 2011
Reply by ●May 26, 20112011-05-26
Here I do it in the time domain and it sounds fine: %% Main DSP Loop (TIME DOMAIN) numberOfFilterCoefficients = 128; delayLine = zeros(1,numberOfFilterCoefficients-1); while (1) audioBlockIn = x(1+blockCounter*blockSize:blockSize+blockCounter*blockSize); % Create filter h = fir1(numberOfFilterCoefficients-1,0.5+0.4*cos(phi)); phi = phi + 0.03; % Filter audio block [audioBlockOut,delayLine] = filter(h,1,audioBlockIn,delayLine); sout = [sout audioBlockOut]; blockCounter = blockCounter + 1; if (blockCounter == numberOfBlocks) break; end end
Reply by ●May 26, 20112011-05-26
Hi Tim, It works fine when the gain vector does not vary with time. Then there are no artefacts....but as soon as I make the gains time varying (which they would have to be in a noise suppression scheme) I get noise artefacts when I transfer the modified signal back to the time domain.
Reply by ●May 26, 20112011-05-26
On 05/26/2011 11:44 AM, John wrote: (too bad you took out your context)> Here I do it in the time domain and it sounds fine: > > %% Main DSP Loop (TIME DOMAIN) > numberOfFilterCoefficients = 128; > delayLine = zeros(1,numberOfFilterCoefficients-1); > while (1) > audioBlockIn = > x(1+blockCounter*blockSize:blockSize+blockCounter*blockSize); > > % Create filter > h = fir1(numberOfFilterCoefficients-1,0.5+0.4*cos(phi)); > phi = phi + 0.03; > > % Filter audio block > [audioBlockOut,delayLine] = filter(h,1,audioBlockIn,delayLine); > > sout = [sout audioBlockOut]; > > blockCounter = blockCounter + 1; > if (blockCounter == numberOfBlocks) > break; > end > > endI didn't plow through your code, but in general if you multiply in the frequency domain that's the same as filtering in the time domain. Either your time-domain filter isn't derived from your frequency domain filter, or you're suffering from wrapping when you do the ifft. Try taking the IFFT of _just_ your frequency-domain filter and plotting it. Then take the FFT of _just_ the impulse response of your time-domain filter. Compare the time-domain version of your original frequency domain filter, and the frequency-domain version of your original time-domain filter. Ideally, all should match. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com Do you need to implement control loops in software? "Applied Control Theory for Embedded Systems" was written for you. See details at http://www.wescottdesign.com/actfes/actfes.html
Reply by ●May 26, 20112011-05-26
Figured it out...
% Create filter
h = fir1(fftSize/2-1,0.5+0.4*cos(phi));
G = fft(h,fftSize);
phi = phi + 0.03;
% Modify spectrum
Y = G.*X;
The problem was that the phase response of the filter also has to be
included in G. So I can't do it like this:
% Create filter
h = fir1(fftSize/2-1,0.5+0.4*cos(phi));
G = abs(fft(h,fftSize)); % Creates artefacts when taking the abs value
of the impulse resp.
phi = phi + 0.03;
% Modify spectrum
Y = G.*X;
I thought I could get away with modifying the amplitude of the noisy speech
signal and then doing the IFFT of the modified spectrum, but obviously I
also have to change the phase.
Is that correct?
Reply by ●May 26, 20112011-05-26
On 05/26/2011 12:23 PM, John wrote:> Figured it out... > > % Create filter > h = fir1(fftSize/2-1,0.5+0.4*cos(phi)); > G = fft(h,fftSize); > phi = phi + 0.03; > > % Modify spectrum > Y = G.*X; > > The problem was that the phase response of the filter also has to be > included in G. So I can't do it like this: > > % Create filter > h = fir1(fftSize/2-1,0.5+0.4*cos(phi)); > G = abs(fft(h,fftSize)); % Creates artefacts when taking the abs value > of the impulse resp. > phi = phi + 0.03; > > % Modify spectrum > Y = G.*X; > > I thought I could get away with modifying the amplitude of the noisy > speech signal and then doing the IFFT of the modified spectrum, but > obviously I also have to change the phase. > > Is that correct? >Looks that way to me. That 'abs' just hurts to look at, in that context. Certainly, you have to take phase into account or you'll mess everything up. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com Do you need to implement control loops in software? "Applied Control Theory for Embedded Systems" was written for you. See details at http://www.wescottdesign.com/actfes/actfes.html
Reply by ●May 26, 20112011-05-26
On May 26, 3:23�pm, "John" <j...@nospam.thanks> wrote:> Figured it out...i can't tell that. if you're using the FFT and iFFT to do filtering, you have to use either the overlap-add or overlap-save methods. i can't tell you're doing that. the FIR length must be less than the block size and you may advance only the difference between the block size and the FIR length (plus 1 sample, if you want). normally you will have artifacts when changing the FIR characteristic between blocks, which is simply a problem of processing block-by- block. but if the characteristics do not change greatly between blocks, you might be able to get away with overlap-add. i would not use overlap-save with a time-varying transfer function. r b-j
Reply by ●May 26, 20112011-05-26
> i can't tell that.well...it seems to work>if you're using the FFT and iFFT to do filtering, you have to use >either the overlap-add or overlap-save methods. i can't tell you're >doing that.What is this then? sampleFrameOut = sampleFrameOut + real(ifft(Y)); audioBlockOut = sampleFrameOut(1:blockSize); sampleFrameOut = [sampleFrameOut(blockSize+1:end) zeros(1,blockSize)];
Reply by ●May 27, 20112011-05-27
You could change your code such that only the magnitude is changed and the 'noisy phase' is preserved just as in typical noise reduction. You may have problems with time-aliasing. You need to smooth your frequency-domain filter in order to truncate the length of the corresponding time-domain filter. remember that you are doing a circular convolution and that constrains the length of your filter. I'm not sure it is the problem though as I have only glanced quickly over your code. Cheers niarn
Reply by ●May 27, 20112011-05-27
John, you can use a oversampled filter bank for varying with time filtering in the frequency domain and to avoid aliasing artifacts.







