Non negligeable imaginary number after ifft even when hermitian symmetry is kept.

1 次查看(过去 30 天)
Hello,
I am writing a script that is supposed to scramble sounds in the frequency domain. However, when performing the ifft, large imaginary numbers are left in the resulting matrix. Anyone has an idea why and how to avoid this problem? As the lines of the code indicate, I use flipdim in order to be sure that hermitian symmetry is kept before using the ifft. Yet, significant imaginary numbers are still left.
Here is a short description of what this script does. Short parts are taken from the original sound. A FFT is applied to these parts. The values of each bins of the FFT are then semirandomly shuffled around. The randomization process is limited to bins of certain frequencies. The Dc is kept in place since it only contains a real part. A ifft is then ran on the scrambled bins to obtain a scrambled version of a part of the sound. A hamming window is then applied to each part all parts are added together to obtain a scrambled version of the whole sound. Note that each part overlaps by 50%.
I also get a problem when adding the parts when scrambling a pure tone. Normaly, scrambling the pure tone using this method should yield a pure tone of another frequency. However, the results sometimes show a modulated pure tone. Anyone has an idea why? How to correct this?
Thanks a lot.
Here is the code:
%Input Variables
TimeWin = 0.02; % time in seconds of the scrambling window. The scrambling will differ depending on the windows. I strongly suggest that the time window be a factor of the Sample rate of the sounds. If not, the time window is slighly modified
freqmat = [0 150 300 378 476 600 755 952 1200 1511 1904 2400 3023 3809 4800 6047 7619 9600 12095 15239 19200 22050]; %Frequency windows for the FFT
FirsPermu = 1;
[snd,Fs,bits]= wavread(FileName); % Reads sound file
npoints = length(snd); % Gets length of sound file
TimeWinSiz = TimeWin*Fs;
if round(TimeWinSiz) ~= TimeWinSiz %Makes sure that the TimeWindow specified earlier contains a natural number of points
TimeWinSiz = round(TimeWinSiz);
end
if TimeWinSiz/2 ~= round(TimeWinSiz/2), %Makes sure that TimeWinSiz is an even number
TimeWinSiz = TimeWinSiz -1;
end
SndSCRB=zeros(npoints,1); % matrix that will contain the "SCRAMBLED" sound
FirsPermu = 1;
start=1;stop=TimeWinSiz;
while start < npoints %loop until the whole sound is scrambled
if stop > npoints, % If the size of the time scrambled is not amultiple of TimeWinSiz, then the last window is made smaller.
stop = npoints;
if (1 + stop - start)/2 ~= round((1 + stop - start)/2), %Makes sure that last TimeWinSiz is an even number
stop = stop - 1;
end
FirsPermu = 1; %Allows permutations to be made again since the number of bins of the FFT will be smaller.
end
vec = snd(start:stop); % copies the part of the sound to be scrambled
ivec = fft(vec);
RandFFTWin = zeros(size(vec)); %Matrix that will contained the scrambled spectral domain
RandSndWin = zeros(size(vec)); %Matrix that will contain the scrambled time window
Len = length(vec); %Caclulate number of points in the window to be analyzed
FreqBins = zeros(Len,1);
dur = (Len)/Fs;
for ii = 1:Len, %Calculates the middle frequency of each bin of the FFT output. Miss calculates for the seconde half, but that part is not used later on.
FreqBins(ii) = ii*(1/dur);
end
PointFreqMat = zeros(1,length(freqmat)); %Matrix that will be used to put the row number of the FFt that contains the frequencies of freqmat.
for ii = 1:length(freqmat),
temp = find(FreqBins > freqmat(ii)); %Finding the row number of the FFT greater than the Freq
PointFreqMat(ii) = temp(1);
end
PointFreqMat(1) = 2; %Avoids scrambling the DC.
PointFreqMat(length(PointFreqMat)) = Len/2;
if FirsPermu,
Permu = ones(size(ivec))*Len/2; %Matrix that will contain the permutations.
for ii = 1: length(PointFreqMat)-1,
sLen = PointFreqMat(ii+1) - PointFreqMat(ii);
sPermu = randperm(sLen);
Permu(PointFreqMat(ii):PointFreqMat(ii+1)-1) = sPermu + PointFreqMat(ii)-1;
FirsPermu = 0;
end
Permu(1) = 1; %makes sure Dc remains unchanged.
Permu(Len/2 + 1) = Len/2 +1;%
end
RandFFTWin = zeros(size(Permu)); % Contains small scrambled window
for kk = 1:Len, % Creates the randomize FFT. Only does so for the first half because the seconde is redundant.
RandFFTWin(kk) = ivec(Permu(kk));
end
RandFFTWin(2+length(vec)/2:length(vec)) = 0; %Erase second part of FFT to avoid to much scrambling. Dc is left untouched
RandFFTWin(2+length(vec)/2:length(vec)) = flipdim(RandFFTWin(2:length(vec)/2),1); %flip the dimensions to obtain hermitian symmetry.
RandSndWin = ifft(RandFFTWin);
HamWinFul = hamming(TimeWinSiz,'periodic'); %Sections that creates a long Hamming window
HamWin = HamWinFul(1:length(RandSndWin)); %Section that selects the hamming to be used
SndSCRB(start:stop) = RandSndWin.*HamWin + SndSCRB(start:stop); %.*HamWin %Pastes the time window into the large sound. Use the code that is removed if you desire to use samll windows.
start = start + round(TimeWinSiz/2);
stop = stop + round(TimeWinSiz/2);
end
wavwrite(SndSCRB,Fs,bits,['ScramblingDir\SCRFreqWei',FileName]);

采纳的回答

Rick Rosson
Rick Rosson 2012-4-12
Please format your code.

更多回答(1 个)

Richard Brown
Richard Brown 2012-4-12
When you do your flipdim, shouldn't you be taking the complex conjugate also?

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by