I'm trying to interpolate a Brownian motion. The function does not return me an error but it seems like Julia does not put the value on vector B. Here the codes.
function interpolation(i,j,N,BM)
if j-i>1
k = sqrt((j-i)/((2^N))/4)
d = (i+j)/2
BM[d] =((BM[i]+BM[j])/2)+k*randn(1)
BM = interpolation(i,d,N,BM)
BM = interpolation(d,j,N,BM)
end
end
plot(BM)
Thanks a lot!
I think that your code could be simplified by using array views. That eliminates all of the extra parameters from you code and makes it easier to see what it is doing. The normalization so that changes are smaller for interior steps could be simplified as well.
So here is a stab at this simplification:
function fractal(x)
if length(x) > 2
n = length(x)
mid = (n+1)รท2
x[mid] = (x[1] + x[n])/2 + randn() * sqrt(n)
fractal(#view x[1:mid])
fractal(#view x[mid:n])
end
end
And here is a result of this code running:
a = zeros(1024)
fractal(a)
plot(a, legend=false)
The point of the simplification is to highlight the idea that the algorithm involves:
Interpolating the middle value based on the end-points
Do the same to the left and right halves of the array
if we don't have a big enough array, just return
This approach avoids complicating the picture with all of the housekeeping and it worked first try, largely because, I think, I didn't have to keep all that stuff straight.
Using R, before assessing some metric of accuracy on my own manual implementation of DFT, I wanted to do a sanity check on how well stats::fft() performs by doing the following:
sig.ts = ts( sin(2*pi*freq1*t) + sin(2*pi*freq2*t) );
sig.rt = fft(fft(sig.ts)/N, inverse="true");
#the two plots so perfectly align that you can't see them both
max(abs(sig.ts - sig.rt)) / max(sig.ts);
#arbitrary crude accuracy metric=1.230e-15 - EXCELLENT!
But I wanted to write the code for DFT myself, to ensure I understand it, then invert it in the hopes that it would be the same:
##The following is the slow DFT for now, not the FFT...
sR = 102.4; #the number of Hz at which we sample
freq1=3; freq2=12; #frequency(ies) of the wave
t = seq(1/sR,10, 1/sR);
sig.ts = ts( sin(2*pi*freq1*t) + sin(2*pi*freq2*t) );
N=length(t); kk=seq(0,N/2-1, 1); nn=seq(0,N-1, 1);
for(k in kk){
sig.freqd[k]=0;
for(n in nn){
sig.freqd[k] = sig.freqd[k] + sig.ts[n+1]*exp(-j*2*pi*n*k/N); } }
sig.freqd = (1/N)*sig.freqd; #for Normalization
#Checking the "accuracy" of my manual implementation of DFT...
sig.freqd_inv=Re(fft(sig.freqd, inverse="true"));
plot(t[1:100], window(sig.ts,end=100), col="black", type="l",lty=1,lwd=1, xaxt="n");
lines(t[1:100],window(sig.freqd_inv,end=100), col="red", type="l",lty=1,lwd=1, xaxt="n");
axis(1, at=seq(round(t[1],1),round(t[length(t)],1), by=0.1), las=2);
max(abs(sig.ts[1:(N/2-1)] - sig.freqd_inv)) / max(sig.ts[1:(N/2-1)]); #the metric here =1.482 unfortunately
Even without the metric, the plot makes it obvious that something's off here - it's lower amplitude, maybe out of phase, and more jagged. In all of my self-studying, I will say that I am a bit confused about how sensitive this all is to vector length..as well as how to ensure that the imaginary component's phase information is taken into account when plotting.
Bottom line, any insight into what's wrong with my DFT algorithm would be helpful. I don't want to just blackbox my use of functions - I want to understand these things more deeply before moving on to more complicated functions.
Thanks,
Christian
The main issues arise from the signal indexing. First to get a full transform usable by R's fft(..., inverse = TRUE), you would need to compute all N coefficients (even if the coefficients above N/2-1 could be obtained by symmetry).
Then you should realize that array indexing in R are 1-based. So, while indexing sig.freqd[k], the index k should start at 1 instead of 0. Since the argument to exp(-1i*2*pi*n*k/N) should start with n=0andk=0`, you'll need to adjust the indices:
kk=seq(1,N, 1); nn=seq(1,N, 1);
for(k in kk){
sig.freqd[k]=0i;
for(n in nn){
sig.freqd[k] = sig.freqd[k] + sig.ts[n]*exp(-1i*2*pi*(n-1)*(k-1)/N);
}
}
I've also changed you usage of j to represent the imaginary number 1i since that's the usual notation recognized by R (and R was complaining about it when trying your posted sample as-is). If you had defined j=1i that shouldn't affect the results.
Note also that R's fft is unnormalized. So to obtain the same result for the forward transform, your DFT implementation should not include the 1/N normalization. On the other hand, you will need to add this factor as a final step in order to get the full-circle forward+backward transform to match the original signal.
With these changes you should have the following code:
##The following is the slow DFT for now, not the FFT...
sR = 102.4; #the number of Hz at which we sample
freq1=3; freq2=12; #frequency(ies) of the wave
t = seq(1/sR,10, 1/sR);
sig.ts = ts( sin(2*pi*freq1*t) + sin(2*pi*freq2*t) );
N=length(t); kk=seq(1,N, 1); nn=seq(1,N, 1);
for(k in kk){
sig.freqd[k]=0i;
for(n in nn){
sig.freqd[k] = sig.freqd[k] + sig.ts[n]*exp(-1i*2*pi*(n-1)*(k-1)/N);
}
}
#Checking the "accuracy" of my manual implementation of DFT...
sig.freqd_inv=(1/N)*Re(fft(sig.freqd, inverse="true"));
plot(t[1:100], window(sig.ts,end=100), col="black", type="l",lty=1,lwd=2, xaxt="n");
lines(t[1:100],window(sig.freqd_inv,end=100), col="red", type="l",lty=2,lwd=1, xaxt="n");
axis(1, at=seq(round(t[1],1),round(t[length(t)],1), by=0.1), las=2);
max(abs(sig.ts - sig.freqd_inv)) / max(sig.ts)
This should yield a metric around 1.814886e-13, which is probably more in line with what you were expecting. The corresponding plot should also be showing the orignal signal and the roundtrip signal overlapping:
I am tying to achieve sine wave gradually changing from 8Hz to 2Hz over 5 seconds:
This waveform was produced in Cool Edit. I gave it a start frequency of 8Hz, an end frequency of 2Hz and a duration of 5 seconds. The sine wave gradually changes from one frequency to the other over the given time.
My question is, how can I accurately find the start time of each cycle (highlighted with a red dot), using a FOR loop?
Pseudo code:
time = 5 //Duration
freq1 = 8 //Start frequency
freq2 = 2 //End frequency
cycles = ( (freq1 + freq2) / 2 ) * time //Total number of cycles
for(i = 0; i < cycles; i++) {
/* Formula to find start time of each cycle */
}
That is backward thinking for this problem which leads to madness in the program. Not to mention the individual waves will not be a sin wave because the frequency is changing (they will be slightly distorted) which you will not achieve with your generator and also there is very slight chance the ending signal will stop on zero after 5sec. Instead do a continuous sin wave with variable frequency:
First compute actual frequency
linear interpolation will suffice (unless you need different change)
f=f0+(f1-f0)*t/T
where:
f0=8 [Hz] start frequency
f1=2 [Hz] stop frequency
T =5 [s] change time
t =<0,T> is actual time in [s]
compute the sin wave data
for (t=0.0,angle=0.0;t<=T;t+=dt)
{
f=f0+((f1-f0)*t/T); // actual frequency
signal=Amplitude*sin(angle); // your signal put it in a array or output somewhere ...
angle+=6.283185307179586476925286766559*dt*f; // update phase
while (angle>6.283185307179586476925286766559) // cut just to avoid floating rounding problems
angle-=6.283185307179586476925286766559;
}
Where dt [s] is a time step you want to sample your signal with. If you are generating this in Real Time and outputting to real HW you can use a timer or measure the time directly (with performance counters on Windows or by RDTSC or whatever you have at disposal)
If you got predefined number of samples n for this then
dt=T/double(n-1);
Here sample output (n=image width):
If you also need the number of periods then add counter increment inside the angle cut while loop And also there is your zero point too (but if samplerate is too small or you need high precision you need to interpolate the real zero position).
I am creating a program to generate a sinusoidal wave over a long period of time.
Currently I am doing it like this, every update. with these starting values for time 0.0f;
time += 0.025f;
if(time > 1.0f)
{
time -= 2.0f;
}
The problem with this approach is that as you can see I have some value that if time goes beyond that my calculations start to break. So I need to reset it back to something less than that value.
Doing it this way there's obvious jumps in my wave once it's passed that threshold.
What's the method to make a smooth sine wave without this limitation?
You can use the trigonometric theorems to get an iteration for the sequence of sine values.
sin(A+B) + sin(A-B) = 2*sin(A)*cos(B)
Thus if you want to generate the sequence of values sin(w*k*dt) then you only have to compute
s[0] = 0, s[1] = sin(w*dt), cc = 2*cos(w*dt)
and then iterate
s[k+1] = cc*s[k] - s[k-1]
This linear recursion has eigenvalues on the unit circle and thus accumulates floating point errors, which may lead to phase shift and changes in amplitude over very long time spans. However, locally it will always look like a sine wave.
The second effect can be avoided by iterating the cosine sequence c[k]=cos(w*k*dt) at the same time,
s[k+1] = c[1]*s[k] + s[1]*c[k]
c[k+1] = c[1]*c[k] - s[1]*s[k]
and periodically rescaling the pair c[k],s[k] to have euclidean length 1.
I am trying to figure out how to solve this problem;
Now make a new sinusoid with amplitude 1 and frequency 1000Hz.
Calculate the dot product of this sinusoid with your complex tone
using vector multiplication between the heterodyne and the transposed
complex tone signal.
So far no good. I have managed to represent a complex tone by:
octave:65> t = [0 : 441];
octave:68> A = 0.25;
octave:69> x = A*sin(2*pi*t*441) + A*sin(2*pi*t*882) + A*sin(2*pi*t*1323) + A*sin(1764*pi*t*2);
And the new sinusoid
octave:66> y = sin(pi*2*t*1000);
Now I find myself trapped with the heterodyne concept and its application. I can tell that the vector multiplication would be like;
octave:75> abs(y*x')
However, parameter 'y' which needs to be the the heterodyne of 'y'(I guess), is driving me nuts...
Any suggestion would be appreciated