0

I have data in frequency domain that looks like this:

enter image description here

This means I have a vector Y that contains the amplitude for the frequency points in the vector x. For example

f = [0 1 2 3 4 5 6 7 8 9 10]
Y = [0 0 0 0 0 1 0 0 0 0  0]

Performing an inverse fourier transform should give a sine wave with the frequency 5Hz.

The MATLAB function ifft can transform Y and f to time domain. Lets call the vectors in time domain y and t. I'm looking for a way how to get time domain data with a specified samplig frequency and a specified signal length. For example, I want time domain data with a signal length of 1 second and a sampling frequency of 1000Hz.

The output of MATLABs ifft function has always the same length as the input, so I'm not sure what to give as input to get the required sampling frequency and signal length.

To sum it up, I'm trying to write a MATLAB function

[t,y] = custom_ifft(f,Y,sampling_frequency,signal_length)

that converts the frequency domain data (f,Y) to time domain data (t,y), where the length of the time vector t can be specified in signal length (for example 1 second) and the sampling frequency ( length(y)/signal_length ) can be specified with sampling_frequency

EDIT: Please include in your answer the MATLAB code how to implement your idea. I already have the concept of how to do it, but I can't get the actual implementation to work. I'm specifically asking what to give as input argument to the ifft function:

y = ifft(input_arg);

I'm looking for MATLAB code how to create input_arg when (f,Y,sampling_frequency,signal_length) are known.

Here is my implementation that does not work as expected:

Y = [0 zeros(1,100) 1 0 0 zeros(1,500) 0 0 1 zeros(1,100)];
Y_interp = interp1(Y,linspace(1,length(Y),2*length(Y)));
y = ifft(Y) ;
y_interp = ifft(Y_interp);
figure;
plot(y);
figure;
plot(real(y_interp));
figure;
plot(abs(y_interp));
Rambaldi
  • 95
  • 3
  • 7

3 Answers3

2

If you know the sample rate and the duration, then it's easy to calculate the number of points, N:

N = duration (seconds) * sample_rate (Hz)

You need this same number of points, N, in the frequency domain. If you have fewer then this you can just pad with zeroes. The frequency represented by each bin in the frequency domain is equal to i / sample_rate where i is the bin number, and 0 <= i < N / 2.

Note that your frequency domain data needs to be complex conjugate symmetric if you want a purely real time domain signal after the IFFT. If you don't care about phase then just make the real part symmetric about N/2 and the imaginary part zero.

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • It appears to me that you have completely ignored the issue of the final sample rate. – Jim Clay Nov 23 '11 at 16:13
  • @Jim: the "final sample rate" is determined by `sample_rate` above. – Paul R Nov 23 '11 at 16:29
  • Yes, but you can only target an extremely limited number of sample rates with that method. I shouldn't have said "completely ignored", though, so my apologies on that. – Jim Clay Nov 23 '11 at 16:35
  • @Jim: OK - I'm not sure why you think it's a limited number of sample rates, unless perhaps you're assuming that the FFT can only have a power-of-2 size ? – Paul R Nov 23 '11 at 16:38
  • Well, if you start out with N samples and sample rate Fstart, then changing the number of samples to "M" gets you a sample rate of Fstart * (M/N). There are an infinite number of sample rates in between each of those sample rates. – Jim Clay Nov 23 '11 at 16:52
  • So what would the input to ifft be for my case? Can you give MATLAB code? – Rambaldi Nov 23 '11 at 17:01
  • @Jim: OK - I was working with an initial specification of duration and sample rate and then N would be derived from this and rounded. I suppose you're right if you don't want the inaccuracy resulting from this rounding. – Paul R Nov 23 '11 at 18:57
  • 1
    @Rambaldi: as Jim says, I think you have all the information you need now - implementing it in MATLAB yourself will help to solidify the concepts in your mind much better than if someone else does all the work for you. – Paul R Nov 23 '11 at 18:58
0

I would keep it simple and flexible by doing the following steps:

  1. ifft
  2. Calculate the target sample rate divided by the starting sample rate.
  3. Get the upsample/downsample numbers that will get you the target sample rate by using the "rat" command.
  4. Resample the data using the "resample" command.
  5. If you only want a certain amount of data, just chop off some of it. If you need more data, pad your data with zeros before ifft'ing it, as Paul suggested.

There are all sorts of potential problems and ways to make this more efficient. For instance, you can do the resampling in the frequency domain. To start out, though, I would keep it simple and learn your way around.

Jim Clay
  • 963
  • 9
  • 24
  • I want ifft to be the last step. The output of ifft should be a signal in time domain with a specified lengh and sampling frequency. – Rambaldi Nov 23 '11 at 16:59
  • @Rambaldi Then you need to do the resampling in the frequency domain. Why does ifft need to be the last step? – Jim Clay Nov 23 '11 at 17:20
  • OK, it would be acceptable to resample in time domain. But how to implement making Y symmetric and padding it with zeros? I'm not looking for a concept, but for actual MATLAB code. So when you say padding with zeros, how would you implement it? – Rambaldi Nov 23 '11 at 17:39
  • 1
    @Rambaldi No offense, but I don't like it when people demand that I do all the work for them. We have pointed you in the right direction. Do it yourself, and ask questions if you run into problems. – Jim Clay Nov 23 '11 at 17:42
0

If you want the ifft of original vector element K to end up producing a sinusoidal frequency F in a vector of length N at sample rate SR:

Interpolate or resample the original vector using the scale factor: (F * N) / (SR * K)

For non-integer scale factors, use a mirrored Sinc interpolation kernel for decent results.

Zero pad or continue interpolating (depending on the width of your interpolation kernel) to produce a vector of length N/2. If interpolation produces significant bin values above N/2 or below 0, fold and add them.

Convert the real vector to a complex vector ("imaginary" elements all zero for an "even" sinusoidal result).

Mirror the N/2 length vector around N/2 to produce a conjugate symmetric vector of length N, and divide by a scale factor of 2.0;

Optionally, multiply by a scale factor that is the inverse of the scale factor built into your IFFT (1, N, sqrt(N), etc.)

IFFT().

hotpaw2
  • 70,107
  • 14
  • 90
  • 153
  • This sounds very promising. But I don't know how to use a mirrored sinc interpolation kernel in matlab. Could you point me in the right direction? In my implementation (appended to my original question) you can see that interpolation in frequency domain completely changes the output of the ifft function. Why is that and how to avoid it? – Rambaldi Nov 24 '11 at 21:12