How can I add a harmonic of the input signal ?
without making frequency estimations ( frequency is provided )
by making frequency estimations
input : vectorized form of signal
output : same format as input
NOTE : If you know answer, can you give me algorithm or link which will help me to solve this problem.
If the frequency is known, then you can presumably add a harmonic just by adding a sine wave of the appropriate frequency (i.e. double the known frequency) to the signal. Something like:
result = signal .* sin((0:(1/sample_rate):length_of_signal) * freq));
When the frequency is unknown you could use an FFT (#L7ColWinters linked to the docs for that) to find the frequencies. Since you can convert a signal from the frequency domain back to the time domain (ifft for the inverse), it might be easier to do the FFT, add the harmonic and then do an inverse FFT, or once you know the frequency from the FFT you could add the sine wave to the original input as in the first case.
Suppose your input is the time domain signal with amplitude array A with interval [0, t0]. Then loop over i with
A[i] = A[i] + A0 * sin (2 pi f dt)
where dt is the time difference between each array element, i.e. dt = N/t0.
If you do the Fourier transform first, you just need to add the A0 at the location corresponding to frequency f, and then do inverse Fourier transform, following link by #L7ColWinters
If you look through the trig identities, you will see that
cos(2x) = 2 * (cos(x))^2 -1
Since the first harmonic is double the fundamental frequency, you can simply square your input, scale as needed and remove DC offset. Frequency doen't need to be known or estimated.
Keep in mind that Nyquist still applies, so you may have to low-pass your input to prevent aliasing.
Related
I know that an inverse fast Fourier transform (ifft) sums multiple sine waves together from data obtain from doing an fft on a signal. Is there a way to create a signal using a new type of inverse fast Fourier transform (ifft) using an arbitrary waveform instead of just using sine waves?
I'm not trying to re-create the original signal. I'm trying to create a new signal using a new type of inverse fast Fourier transform (ifft) using a given arbitrary waveform based on the (frequency, amplitude, phase) data calculated from the fft from the source signal.
The arbitrary waveform is a sampled signal that will replace one period of the sine wave used in the fft. That is, the signal is to be scaled, repeated, and shifted according to the values given by the fft.
See simple example below: the signals I will be applying FFT to are human audio signals about 60 seconds long at 44100 samples (large arrays) so I'm trying to see if I can use / alter the ifft command in some way to create a new signal using / based on an arbitrary waveform.
PS: I'm using Octave 4.0 which is similar to Matlab and the arbitrary waveform signal used to create a new signal will be changed to create different signals.
clear all,clf reset, clc,tic
fs=44100 % Sampling frequency
len_of_sig=2; %length of signal in seconds
t=linspace(0,2*pi*len_of_sig,fs*len_of_sig);
afp=[.5,2.43,pi/9;.3,3,pi/2;.3,4.3,pi/3]; %represents Amplitude,frequency,phase data array
%1 create source signal
ya=0;
for zz=1:size(afp,1)
ya = ya+afp(zz,1)*sin(afp(zz,2)*t+afp(zz,3));
end
%2 create source frequency domain data
ya_fft = fft(ya);
%3 rebuild original source signal
mag = abs(ya_fft);
phase = unwrap(angle(ya_fft));
ya_newifft=ifft(mag.*exp(i*phase));
ifft_sig_combined_L1=ifft(mag.*exp(i*phase),length(ya_newifft));
%4 %%%-----begin create arbitrary waveform to use ----
gauss = #(t, t0, g) exp(-((t-t0)/g).^2); % a simple gaussian
t_arbitrary=0:1:44100; % sampling
t_arbitrary_1 = 10000; % pulses peak positions (s)
t_arbitrary_2 = 30000; % pulses peak positions (s)
g = 2000; % pulses width (at 1/e^2) (s)
lilly = gauss(t_arbitrary, t_arbitrary_1, g) - (.57*gauss(t_arbitrary, t_arbitrary_2, g)); %different amplitude peaks
%%%%-----End arbitrary waveform to use----
%5 plot
t_sec=t./(2*pi); %converts time in radians to seconds
t_arbitrary_sec=t_arbitrary./length(lilly); %converts time in radians to seconds
subplot(4,1,1);
plot(t_sec,ya,'r')
title('1) source signal')
subplot(4,1,2);
plot(t_sec,ifft_sig_combined_L1)
title('2) rebuilt source signal using ifft')
subplot(4,1,3);
plot(t_arbitrary_sec,lilly,'r')
title('3) arbitrary waveform used to create new signal')
Added a work-flow chart below with simple signals to see if that explains it better:
Section 1) The audio signal is read into an array
Section 2) FFT is done on the signal
Section 3 Red) Normally Inverse FFT uses sin waves to rebuild the signal see signal in red
Section 3 Blue) I want to use an arbitrary signal wave instead to rebuild the signal using the FFT data calculated in (Section 2)
Section 4) New signals created using a new type of Inverse FFT (Section 3).
Please note the new type of Inverse FFT final signal (in blue ) must use the FFT data taken from the original signal.
The signal Sample rate tested should be 44100 and the length of the signal in seconds should be 57.3 seconds long. I use these numbers to test that the array can handle large amounts and that the code can handle non even numbers in seconds.
Let's start with a function lilly that takes a frequency, an amplitude and a phase (all scalars), as well as a signal length N, and computes a sine wave as expected for the inverse DFT (see note 2 below):
function out = lilly(N,periods,amp,phase)
persistent t
persistent oneperiod
if numel(t)~=N
disp('recomputung "oneperiod"');
t = 0:N-1;
oneperiod = cos(t * 2 * pi / N);
end
p = round(t * periods + phase/(2*pi)*N);
p = mod(p,N) + 1;
out = amp * oneperiod(p);
I have written this function such that it uses a sampled signal representing a single period of the since wave.
The following function uses the lilly function to compute an inverse DFT (see note 1 below):
function out = pseudoifft(ft)
N = length(ft);
half = ceil((N+1)/2);
out = abs(ft(1)) + abs(ft(half)) * ones(1,N);
for k=2:half-1
out = out + lilly(N,k-1,2*abs(ft(k)),angle(ft(k)));
end
out = out/N;
Now I test to verify that it actually computes the inverse DFT:
>> a=randn(1,256);
>> b=fft(a);
>> c=pseudoifft(b);
recomputung "oneperiod"
>> max(abs(a-c))
ans = 0.059656
>> subplot(2,1,1);plot(a)
>> subplot(2,1,2);plot(c)
The error is relatively large, due to the round function: we're subsampling the signal instead of interpolating. If you need more precision (not likely I think) you should use interp1 instead of indexing using round(p).
Next, we replace the sine in the lilly function with your example signal:
function out = lilly(N,periods,amp,phase)
persistent t
persistent oneperiod
if numel(t)~=N
disp('recomputung "oneperiod"');
t = 0:N-1;
%oneperiod = cos(t * 2 * pi / N);
gauss = #(t,t0,g) exp(-((t-t0)/g).^2); % a simple gaussian
t1 = N/4; % pulses peak positions (s)
t2 = 3*N/4; % pulses peak positions (s)
g = N/20; % pulses width (at 1/e^2) (s)
oneperiod = gauss(t,t1,g) - (.57*gauss(t,t2,g)); %different amplitude peaks
oneperiod = circshift(oneperiod,[1,-round(N/4)]); % this will make it look more like cos
end
p = round(t * periods + phase/(2*pi)*N);
p = mod(p,N) + 1;
out = amp * oneperiod(p);
The function pseudoifft now creates a function composed of your basis:
>> c=pseudoifft(b);
recomputung "oneperiod"
>> subplot(2,1,2);plot(c)
Let's look at a simpler input:
>> z=zeros(size(a));
>> z(10)=1;
>> subplot(2,1,1);plot(pseudoifft(z))
>> z(19)=0.2;
>> subplot(2,1,2);plot(pseudoifft(z))
Note 1: In your question you specifically ask to use the FFT. The FFT is simply a every efficient way of computing the forward and inverse DFT. The code above computes the inverse DFT in O(n^2), the FFT would compute the same result in O(n log n). Unfortunately, the FFT is an algorithm built on the properties of the complex exponential used in the DFT, and the same algorithm would not be possible if one were to replace that complex exponential with any other function.
Note 2: I use a cosine function in the inverse DFT. It should of course be a complex exponential. But I'm just taking a shortcut assuming that the data being inverse-transformed is conjugate symmetric. This is always the case if the input to the forward transform is real (the output of the inverse transform must be real too, the complex components of two frequencies cancel out because of the conjugate symmetry).
An IFFT is just a way to implement a IDFT. An IDFT is just a weighted sum of sinusoidal waveforms that are integer periodic in aperture.
If you want, you can take almost any DFT or IDFT algorithm or source code, and replace the sin() function with whatever other function you want for waveform synthesis. You can even use different waveforms for different frequencies, or change the synthesis frequencies to non-integer-periodic-in-aperture, if you wish.
The (inverse) Fast Fourier Transform relies on special properties of sinusoidal functions which allow one to move between the time-domain and frequency domain with a much lower computational cost (O(n.log(n))) than for arbitrary waveforms (O(n^2)). If you change the basis waveforms from sinusoids to something else, in general, you can no longer get the computational advantages of the FFT.
In your case, is sounds like you may want to generate a signal that has the same frequency spectrum as your original signal, but not necessarily the same envelope in the time-domain. As I think you've already implemented in your code, the easiest way to do that is simply to change the phase of each frequency-bin in the output of your FFT, and take the inverse FFT. That will generate a time-domain signal that has quite different appearance from your input signal, but will have the same amount of power in each frequency bin.
One subtlety you may need bear in mind is how to change the phases so that the output signal remains real-valued, rather than involving complex numbers. You can think of the Fourier transform as producing a set of positive and negative frequencies. For a real-valued signal, the corresponding positive and negative frequencies must have amplitudes that are complex conjugates of each other. Assuming that your input signal is real-valued, your FFT will already have this property, but you'll need to arrange that the random phases you apply still preserve this relationship between positive and negative frequencies. In practice, this will mean that you only have about half as many random phases to choose - none for zero-frequency bin, and one each for all the positive frequencies (the first n/2 entries) of your FFT, with the other phases being such that the phase at entry k is -1 times that of the entry at (n-k).
I am new to Matlab and FFT.
I need to extract the dominant frequency from a signal which is varying in magnitude and frequency. I tried to perform a detrend and then an FFT to obtain the frequency but couldn't get rid of the large peak at 0Hz (DC component?). I used diff function on the signal and the resulting signal was processed through FFT. In this case, the FFT output didn't have the peak at zero. I compared the two FFT curves and it seems that except the peak at zero, the two show similar (not same) spectrum. I am wondering if diff function is a valid (and very effective) detrending method or am I losing some information here? In other words, does differentiating a signal have any effect on its frequency: [diff(sin(omega.t))= cos(omega.t) - no change in frequency]?
Thanks a lot!
By differentiating the signal you actually apply a a type of a highpass filter, a not so smart highpass which corrupts your signal. Instead you could try some other filter such as the following:
b=fir1(32,2*0.01/fs,'high');
a=1;
FilteredX=filtfilt(x,a,b)
where:
x is your original signal,
FilteredX is the filtered signal.
fs - your sample frequency.
This way you will filter out any frequencies lower then 0.01 and will almost not hurt the rest of the spectrum allowing you to detect peaks as you wished.
The discrete fourier transform X of a signal x is defined (up to scaling) by
X(k) = Sum[ exp(2*pi*i*k*n/N) * x(n) ]
If we take first differences of the signal you get
Sum[ exp(2*pi*i*k*n/N) * (x(n) - x(n-1)) ]
which you can rearrange to give
(1 - exp(2*pi*i*k/N)) * Sum[ exp(2*pi*i*k*n/N) * x(n) ]
i.e. it is a multiple of the original fourier transform. In the k = 0 case (i.e. the zero frequency component) the multiplier is zero, which explains why this removes the spike at k = 0.
Note however that the multiplier depends on the value of k, so you won't get the same signal out - you can't just take first differences to remove a spike. There is a comparison to be made with the continuous fourier transform, where if g = F(f) and h = F(df/dx) then
h(k) = i * k * g(k)
i.e. the fourier transform of the derivative is the fourier transform of the original function, multiplied by ik.
I'm trying to find a factor using matlab that requires me to compute the Fourier transform of an input signal. The problem was stated to me this way:
fbin = 50HZ
0 <= n <= 1999
alpha = F {Blackman[2000] . cos[-2pi . fbin . n/2000]} (f)
where F is the Continous Time Fourier Transform operator.
My matlab code looks like this:
blackman_v = blackman(2000);
signal_x = cos(-2 * pi() .* fbin * (0:(1999)) ./ 2000) .* blackman_v';
fft_real = abs(fft(signal_x, 2000));
alpha = fft_real(51); %51 is the bin for 50hz => or {(f * N/Fs)+1}==51
My problem is that I'm supposed to get a value of around 412 for 49hz but I get about 250 (I'm actually verifying some previous results). Did I wrongly translate the problem? I've been battling for quite a while and I really don't see anything wrong here. Thought the value a 50Hz (430) is ok.
Would really appreciate any hint!
EDIT
blackman_v = blackman(2000);
signal_x = cos(-2 * pi() .* fbin * (0:(1999)) ./ 2000) .* blackman_v';
alpha = abs(freqz(signal_x , 1, 2*pi*50/10000))
Do you know what the freqz is? I read matlab doc and it is still not to clear in my head.
Maybe I misinterpreted your question but Matlab is not for continuous time analysis. It's for numerical analysis only, with discrete values. You can however calculate the discrete time fourier transform (DFT) of your signal, the resolution of which will depend on the length of your signal. Are you using a Blackmann window because your signal is non-periodic?
How to calculate the FFT (DFT) in Matlab: http://www.mathworks.se/help/matlab/ref/fft.html
Any discrete Fourier transform will assume that your signal is periodic. If it isn't you will obtain spectral leakage where certain frequency peaks "leak" their energy to the sides resulting in less defined peak with smeared out frequency values. Thus, the time-domain signal is preferably made periodic before calculting the DFT - periodic to the extent that a general pattern is repeated, values does not have to exact between periods since noise can/will be inherent in the signal. Applying a window function to the time-domain signal before calculating the DFT will make the signal periodic but you will have change amplitude values and introduced a low frequency component.
I am trying to create an application for calculating coefficients for a graphic equalizer FIR filter. I am doing some prototyping in Matlab but I have some problems.
I have started with the following Matlab code:
% binamps vector holds 2^13 = 8192 bins of desired amplitude values for frequencies in range 0.001 .. 22050 Hz (half of samplerate 44100 Hz)
% it looks just fine, when I use Matlab plot() function
% now I get ifft
n = size(binamps,1);
iff = ifft(binamps, n);
coeffs = real(iff); % throw away the imaginary part, because FIR module will not use it anyway
But when I do the fft() of the coefficients, I see that the frequencies are stretched 2 times and the ending of my AFR data is lost:
p = fft(coeffs, n); % take the fourier transform of coefficients for a test
nUniquePts = ceil((n+1)/2);
p = p(1:nUniquePts); % select just the first half since the second half
% is a mirror image of the first
p = abs(p); % take the absolute value, or the magnitude
p = p/n; % scale by the number of points so that
% the magnitude does not depend on the length
% of the signal or on its sampling frequency
p = p.^2; % square it to get the power
sampFreq = 44100;
freqArray = (0:nUniquePts-1) * (sampFreq / n); % create the frequency array
semilogx(freqArray, 10*log10(p))
axis([10, 30000 -Inf Inf])
xlabel('Frequency (Hz)')
ylabel('Power (dB)')
So I guess, I am using ifft wrong. Do I need to make my binamps vector twice as long and create a mirror in the second part of it? If it is the case, then is it just a Matlab's implementation of ifft or also other C/C++ FFT libraries (especially Ooura FFT) need mirrored data for inverse FFT?
Is there anything else I should know to get the FIR coefficients out of ifft?
Your frequency domain vector needs to be complex rather than just real, and it needs to be symmetric about the mid point in order to get a purely real time domain signal. Set the real parts to your desired magnitude values and set the imaginary parts to zero. The real parts need to have even symmetry such that A[N - i] = A[i] (A[0] and A[N / 2] are "special", being the DC and Nyquist components - just set these to zero.)
The above applies to any general purpose complex-to-complex FFT/IFFT, not just MATLAB's implementation.
Note that if you're trying to design a time domain filter with an arbitrary frequency response then you'll need to do some windowing in the frequency domain first. You might find this article helpful - it talks about arbitrary FIR filter design usign MATLAB, in particular fir2.
To get a real result, the input to any typical generic IFFT (not just Matlab's implementation) needs to be complex-conjugate-symmetric. So doing an IFFT with a given number of independent specification points will require an FFT at least twice as long (preferably even longer to allow for some transition to zero from the highest frequency cut-off).
Trying to get a real result by throwing away the "imaginary" portion of a complex result won't work, as you will be throwing away actual required information content the time-domain filter needs for the given frequency response input to the IFFT. However, if the original data is conjugate-symmetric, then the imaginary portion of the IFFT/FFT result will be (usually insignificant) rounding-error noise that can be thrown away.
Also, the DTFT of a finite frequency response will produce an infinitely long FIR. To get a finite length FIR, you will need to compromise the specification for your frequency response specification so that there is little energy left in the latter portion of the time-domain representation that has to be truncated from the FIR to make it realizable or finite. One common (but not necessary the best) way to do this is to window the FIR result produced by the IFFT, and, by trial-and-error, try different windows until you find a FIR filter for which an FFT produces a result "close enough" to your original frequency spec.
I have a set of data that is periodic (but not sinusoidal). I have a set of time values in one vector and a set of amplitudes in a second vector. I'd like to quickly approximate the period of the function. Any suggestions?
Specifically, here's my current code. I'd like to approximate the period of the vector x(:,2) against the vector t. Ultimately, I'd like to do this for lots of initial conditions and calculate the period of each and plot the result.
function xdot = f (x,t)
xdot(1) =x(2);
xdot(2) =-sin(x(1));
endfunction
x0=[1;1.75]; #eventually, I'd like to try lots of values for x0(2)
t = linspace (0, 50, 200);
x = lsode ("f", x0, t)
plot(x(:,1),x(:,2));
Thank you!
John
Take a look at the auto correlation function.
From Wikipedia
Autocorrelation is the
cross-correlation of a signal with
itself. Informally, it is the
similarity between observations as a
function of the time separation
between them. It is a mathematical
tool for finding repeating patterns,
such as the presence of a periodic
signal which has been buried under
noise, or identifying the missing
fundamental frequency in a signal
implied by its harmonic frequencies.
It is often used in signal processing
for analyzing functions or series of
values, such as time domain signals.
Paul Bourke has a description of how to calculate the autocorrelation function effectively based on the fast fourier transform (link).
The Discrete Fourier Transform can give you the periodicity. A longer time window gives you more frequency resolution so I changed your t definition to t = linspace(0, 500, 2000).
time domain http://img402.imageshack.us/img402/8775/timedomain.png (here's a link to the plot, it looks better on the hosting site).
You could do:
h = hann(length(x), 'periodic'); %# use a Hann window to reduce leakage
y = fft(x .* [h h]); %# window each time signal and calculate FFT
df = 1/t(end); %# if t is in seconds, df is in Hz
ym = abs(y(1:(length(y)/2), :)); %# we just want amplitude of 0..pi frequency components
semilogy(((1:length(ym))-1)*df, ym);
frequency domain http://img406.imageshack.us/img406/2696/freqdomain.png Plot link.
Looking at the graph, the first peak is at around 0.06 Hz, corresponding to the 16 second period seen in plot(t,x).
This isn't computationally that fast though. The FFT is N*log(N) operations.