FFT algorithm in MATLAB [closed] - c
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm looking to implement an FFT algorithm on microcontrollers so I want to simulate the codes before actually using it
I got 2 examples which I converted to matlab codes but the result just isn't what I'm expected
Here are the codes:
function [ H ] = fft_2( g )
%FFT2 Summary of this function goes here
% Detailed explanation goes here
NUMDATA = length(g);
NUMPOINTS = NUMDATA/2;
N = NUMPOINTS;
% for(k=0; k<N; k++)
% {
% IA[k].imag = -(short)(16383.0*(-cos(2*pi/(double)(2*N)*(double)k)));
% IA[k].real = (short)(16383.0*(1.0 - sin(2*pi/(double)(2*N)*(double)k)));
% IB[k].imag = -(short)(16383.0*(cos(2*pi/(double)(2*N)*(double)k)));
% IB[k].real = (short)(16383.0*(1.0 + sin(2*pi/(double)(2*N)*(double)k)));
% }
for k=0:(N-1)
IA(k+1,2) = -floor(16383.0*(-cos(2*pi/(2*N)*k)));
IA(k+1,1) = floor(16383.0*(1.0 - sin(2*pi/(2*N)*k)));
IB(k+1,2) = -floor(16383.0*(cos(2*pi/(2*N)*k)));
IB(k+1,1) = floor(16383.0*(1.0 + sin(2*pi/(2*N)*k)));
end
% Note, IA(k) is the complex conjugate of A(k) and IB(k) is the complex conjugate of
% B(k).
% *********************************************************************************/
% #include <math.h>
% #include ”params1.h”
% #include ”params.h”
% extern short g[];
% void dft(int, COMPLEX *);
% void split(int, COMPLEX *, COMPLEX *, COMPLEX *, COMPLEX *);
% main()
% {
% int n, k;
% COMPLEX x[NUMPOINTS+1]; /* array of complex DFT data */
% COMPLEX A[NUMPOINTS]; /* array of complex A coefficients */
% COMPLEX B[NUMPOINTS]; /* array of complex B coefficients */
% COMPLEX IA[NUMPOINTS]; /* array of complex A* coefficients */
% COMPLEX IB[NUMPOINTS]; /* array of complex B* coefficients */
% COMPLEX G[2*NUMPOINTS]; /* array of complex DFT result */
% for(k=0; k<NUMPOINTS; k++)
for k=0:(NUMPOINTS-1)
% {
% A[k].imag = (short)(16383.0*(-cos(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% A[k].real = (short)(16383.0*(1.0 - sin(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% B[k].imag = (short)(16383.0*(cos(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% B[k].real = (short)(16383.0*(1.0 + sin(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% IA[k].imag = -A[k].imag;
% IA[k].real = A[k].real;
% IB[k].imag = -B[k].imag;
% IB[k].real = B[k].real;
% }
A(k+1, 2) = floor(16383.0*(-cos(2*pi/(2*NUMPOINTS)*k)));
A(k+1, 1) = floor(16383.0*(1.0 - sin(2*pi/(2*NUMPOINTS)*k)));
B(k+1, 2) = floor(16383.0*(cos(2*pi/(2*NUMPOINTS)*k)));
B(k+1, 1) = floor(16383.0*(1.0 + sin(2*pi/(2*NUMPOINTS)*k)));
IA(k+1, 2) = -A(k+1, 2);
IA(k+1, 1) = A(k+1, 1);
IB(k+1, 2) = -B(k+1, 2);
IB(k+1, 1) = B(k+1, 1);
end
% /* Forward DFT */
% /* From the 2N point real sequence, g(n), for the N-point complex sequence, x(n) */
% for (n=0; n<NUMPOINTS; n++)
% {
for n=0:(NUMPOINTS-1)
% x[n].imag = g[2*n + 1]; /* x2(n) = g(2n + 1) */
% x[n].real = g[2*n]; /* x1(n) = g(2n) */
% }
x(n+1,2)=g(2*n + 1+1);
x(n+1,1)=g(2*n +1);
end
% /* Compute the DFT of x(n) to get X(k) -> X(k) = DFT{x(n)} */
% dft(NUMPOINTS, x);
% void dft(int N, COMPLEX *X)
% {
% int n, k;
% double arg;
% int Xr[1024];
% int Xi[1024];
% short Wr, Wi;
% for(k=0; k<N; k++)
% {
N=NUMPOINTS;
for k=0:(N-1)
% Xr[k] = 0;
% Xi[k] = 0;
Xr(k+1)=0;
Xi(k+1)=0;
% for(n=0; n<N; n++)
% {
for n=0:(N-1)
% arg =(2*PI*k*n)/N;
% Wr = (short)((double)32767.0 * cos(arg));
% Wi = (short)((double)32767.0 * sin(arg));
% Xr[k] = Xr[k] + X[n].real * Wr + X[n].imag * Wi;
% Xi[k] = Xi[k] + X[n].imag * Wr – X[n].real * Wi;
arg = (2*pi*k*n)/N;
Wr = floor(32767*cos(arg));
Wi = floor(32767*sin(arg));
Xr(k+1) = Xr(k+1)+x(n+1,1)*Wr+x(n+1,2)*Wi;
Xi(k+1) = Xr(k+1)+x(n+1,2)*Wr-x(n+1,1)*Wi;
% }
% }
end
end
% for (k=0;k<N;k++)
% {
for k=0:(N-1)
% X[k].real = (short)(Xr[k]>>15);
% X[k].imag = (short)(Xi[k]>>15);
x(k+1,1)=floor(Xr(k+1)/pow2(15));
x(k+1,2)=floor(Xi(k+1)/pow2(15));
% }
% }
end
% /* Because of the periodicity property of the DFT, we know that X(N+k)=X(k). */
% x[NUMPOINTS].real = x[0].real;
% x[NUMPOINTS].imag = x[0].imag;
x(NUMPOINTS+1,1)=x(1,1);
x(NUMPOINTS+1,2)=x(1,2);
% /* The split function performs the additional computations required to get
% G(k) from X(k). */
% split(NUMPOINTS, x, A, B, G);
% void split(int N, COMPLEX *X, COMPLEX *A, COMPLEX *B, COMPLEX *G)
% {
% int k;
% int Tr, Ti;
% for (k=0; k<N; k++)
% {
for k=0:(NUMPOINTS-1)
% Tr = (int)X[k].real * (int)A[k].real – (int)X[k].imag * (int)A[k].imag +
% (int)X[N–k].real * (int)B[k].real + (int)X[N–k].imag * (int)B[k].imag;
Tr = x(k+1,1)*A(k+1,1)-x(k+1,2)*A(k+1,2)+x(NUMPOINTS-k+1,1)*B(k+1,1)+x(NUMPOINTS-k+1,2)*B(k+1,2);
% G[k].real = (short)(Tr>>15);
G(k+1,1)=floor(Tr/pow2(15));
% Ti = (int)X[k].imag * (int)A[k].real + (int)X[k].real * (int)A[k].imag +
% (int)X[N–k].real * (int)B[k].imag – (int)X[N–k].imag * (int)B[k].real;
Ti = x(k+1,2)*A(k+1,1)+x(k+1,1)*A(k+1,2)+x(NUMPOINTS-k+1,1)*B(k+1,2)-x(NUMPOINTS-k+1,2)*B(k+1,1);
% G[k].imag = (short)(Ti>>15);
G(k+1,2)=floor(Ti/pow2(15));
% }
end
% }
% /* Use complex conjugate symmetry properties to get the rest of G(k) */
% G[NUMPOINTS].real = x[0].real - x[0].imag;
% G[NUMPOINTS].imag = 0;
% for (k=1; k<NUMPOINTS; k++)
% {
% G[2*NUMPOINTS-k].real = G[k].real;
% G[2*NUMPOINTS-k].imag = -G[k].imag;
% }
G(NUMPOINTS+1,1) = x(1,1) - x(1,2);
G(NUMPOINTS+1,2) = 0;
for k=1:(NUMPOINTS-1)
G(2*NUMPOINTS-k+1,1) = G(k+1,1);
G(2*NUMPOINTS-k+1,2) = -G(k+1,2);
end
for k=1:(NUMDATA)
H(k)=sqrt(G(k,1)*G(k,1)+G(k,2)*G(k,2));
end
end
Another one:
function [ fr, fi ] = fix_fft( fr, fi )
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
N_WAVE = 1024; % full length of Sinewave[]
LOG2_N_WAVE = 10; % log2(N_WAVE)
m = nextpow2(length(fr));
% void fix_fft(short fr[], short fi[], short m)
% {
% long int mr = 0, nn, i, j, l, k, istep, n, shift;
mr=0;
% short qr, qi, tr, ti, wr, wi;
%
% n = 1 << m;
n = pow2(m);
% nn = n - 1;
nn = n-1;
%
% /* max FFT size = N_WAVE */
% //if (n > N_WAVE) return -1;
%
% /* decimation in time - re-order data */
% for (m=1; m<=nn; ++m)
for m=1:nn
% {
% l = n;
l=n;
% do
% {
% l >>= 1;
% } while (mr+l > nn);
not_done = true;
while(mr+l>nn || not_done)
l=floor(l/2);
not_done=false;
end
%
% mr = (mr & (l-1)) + l;
mr = (mr & (l-1)) + l;
% if (mr <= m) continue;
if (mr <= m)
continue
end
%
% tr = fr[m];
% fr[m] = fr[mr];
% fr[mr] = tr;
% ti = fi[m];
% fi[m] = fi[mr];
% fi[mr] = ti;
tr = fr(m+1);
fr(m+1) = fr(mr+1);
fr(mr+1) = tr;
ti = fi(m+1);
fi(m+1) = fi(mr+1);
fi(mr+1) = ti;
% }
end
%
% l = 1;
% k = LOG2_N_WAVE-1;
l=1;
k = LOG2_N_WAVE-1;
%
% while (l < n)
% {
while (l < n)
% /*
% fixed scaling, for proper normalization --
% there will be log2(n) passes, so this results
% in an overall factor of 1/n, distributed to
% maximize arithmetic accuracy.
%
% It may not be obvious, but the shift will be
% performed on each data point exactly once,
% during this pass.
% */
%
% // Variables for multiplication code
% long int c;
% short b;
%
% istep = l << 1;
istep = l*2;
% for (m=0; m<l; ++m)
% {
for m=0:(l-1)
% j = m << k;
% /* 0 <= j < N_WAVE/2 */
% wr = Sinewave[j+N_WAVE/4];
% wi = -Sinewave[j];
j = m*(pow2( k));
wr = sin((j+N_WAVE/4)*2*pi/N_WAVE)*32768;
wi = -sin(j*2*pi/1024)*32768;
%
% wr >>= 1;
% wi >>= 1;
wr = floor(wr/2);
wi = floor(wi/2);
%
% for (i=m; i<n; i+=istep)
% {
i=m;
while(i<n)
% j = i + l;
j = i+l;
%
% // Here I unrolled the multiplications to prevent overhead
% // for procedural calls (we don't need to be clever about
% // the actual multiplications since the pic has an onboard
% // 8x8 multiplier in the ALU):
%
% // tr = FIX_MPY(wr,fr[j]) - FIX_MPY(wi,fi[j]);
% c = ((long int)wr * (long int)fr[j]);
% c = c >> 14;
% b = c & 0x01;
% tr = (c >> 1) + b;
c = wr * fr(j+1);
c = floor(c / pow2(14));
b = c & 1;
tr = floor(c /2) + b;
%
% c = ((long int)wi * (long int)fi[j]);
% c = c >> 14;
% b = c & 0x01;
% tr = tr - ((c >> 1) + b);
c = wi * fi(j+1);
c = floor(c / pow2(14));
b = c & 1;
tr = tr - (floor((c/2)) + b);
%
% // ti = FIX_MPY(wr,fi[j]) + FIX_MPY(wi,fr[j]);
% c = ((long int)wr * (long int)fi[j]);
% c = c >> 14;
% b = c & 0x01;
% ti = (c >> 1) + b;
c = wr*fi(j+1);
c = floor(c / pow2(14));
b = c & 1;
ti = floor((c /2)) + b;
%
% c = ((long int)wi * (long int)fr[j]);
% c = c >> 14;
% b = c & 0x01;
% ti = ti + ((c >> 1) + b);
c = wi * fr(j+1);
c = floor(c / pow2(14));
b = c & 1;
ti = ti + (floor((c/2)) + b);
%
% qr = fr[i];
% qi = fi[i];
% qr >>= 1;
% qi >>= 1;
%
% fr[j] = qr - tr;
% fi[j] = qi - ti;
% fr[i] = qr + tr;
% fi[i] = qi + ti;
qr = fr(i+1);
qi = fi(i+1);
qr = floor(qr/2);
qi = floor(qi/2);
fr(j+1) = qr - tr;
fi(j+1) = qi - ti;
fr(i+1) = qr + tr;
fi(i+1) = qi + ti;
% }
i = i+istep;
end
% }
end
%
% --k;
% l = istep;
% }
k=k-1;
l=istep;
end
% }
end
Those in comments are the original, those aren't are the translated code
Then I simulated with this
function [ r ] = mfft( f )
%MFFT Summary of this function goes here
% Detailed explanation goes here
Fs = 2048;
T = 1/Fs;
L = 2048;
t = (0:L-1)*T;
NFFT = 2^nextpow2(L);
l = length(f);
y = 0;
for k=1:l
y = y + sin(2*pi*f(k)*t);
end
%sound(y, Fs);
Y = fft(y,NFFT)/L;
YY = fft_2(y)/L;
[Y1 Y2] = fix_fft(y, zeros(1, L));
YYY = Y1+j()*Y2;
f = Fs/2*linspace(0,1,NFFT/2+1);
plot(f, 2*abs(Y(1:NFFT/2+1)), ':+b');
hold on
plot(f, 2*abs(YY(1:NFFT/2+1)), '-or');
plot(f, abs(YYY(1:NFFT/2+1)), '--*g');
hold off
r=0;
end
Basically create a simple sine wave with a specific frequency (say 400Hz)
The expected output of the FFT should be a spike at 400 only, which the builtin FFT function agrees but the other codes didn't
Here's the output graph
The blue line is from builtin function and is what expected
The red line is the above code which, well, looks pretty good except there is a spike elsewhere with higher amplitude
The green line is absolute mess
I tried checking the program several times but to no avail
Did I ported them wrong or somehow I can fix them?
There are several ways to approach this problem, and a programmer should try all of them. First, an FFT is an optimization of a Fourier Transform, so as a first step code a Fourier Transform. That is, don't do an FFT, just do a FT directly.
These days an FT is not as slow as you might think. Unless the project needs to transform something like 10,000 data points in less than a few milliseconds. Also, an FT, compared to an FFT, is simple and easy to debug.
Doing this for a problem provides a baseline, that is, the correct answer. This is important because when you work on the FFT how do you know if the problem is in the code for the FFT or that the data is correct and just giving you an unexpected, but correct, answer.
Next, use a pre-written package to do an FFT. Scan the web, I know there are packages written in C that do FFTs.
Third, if you just have to write your own FFT then do so. But only if tasks (1) or (2) don't meet your requirements. It will be difficult to out-do any pre-written FFT packages.
You will learn much along this path.
Related
CS50 Credit: Luhn's Algorithm - Please assist
I'm a beginner in CS50 trying to do the Credit problem from Problem Set 1. We are using C. The problem asks us to validate credit card numbers using Luhn's algorithm. I was going to use an array, but code using one wasn't easy to understand for me. I'm trying to type out the full Luhn formula to calculate. I don't know where I'm messing up. Every time I run a card number that's supposed to be valid, it's never card_total % 10 = 0 like it should be. Example Card Number: 4003600000000014 => checksum total (int card_total) = 33 Below is just code that asks for the credit card number, runs it through the algorithm, and prints out the total checksum just for me to see if it's working properly. I know this is really long, but this is just for my understanding of all the pieces. I've written much shorter and nicer code before. I swear! EDIT: I run my code in the cs50 VS virtual codespace, which uses Linux I think. I will take the advice of changing the other ints to longs and see if this fixes my problem. My formulas are consistent, so this is a formatting issue. Once this is fixed, the rest of the problem is easy to solve. Someone mentioned my complicated calculations. Sorry. I know this could be more brief, but I just wanted to follow the algorithm so I can see what's going on. The lecture for this week didn't touch on going through arrays or manipulating strings, so I'm just doing what I know so far in C. This would be a lot easier in python. EDIT 2: All that needed to change was int to long. The code now works perfectly and incorporates properly with the rest of my code checking for Amex, Visa, etc. THANK YOU SO MUCH! #include <cs50.h> #include <stdio.h> int get_number(void); int main(void) { long n = get_number(); //calculating card number with modulo long a = ((n % 10000000000000000) / 1000000000000000); long b = ((n % 1000000000000000) / 100000000000000); long c = ((n % 100000000000000) / 10000000000000); long d = ((n % 10000000000000) / 1000000000000); long e = ((n % 1000000000000) / 100000000000); long f = ((n % 100000000000) / 10000000000); long g = ((n % 10000000000) / 1000000000); long h = ((n % 1000000000) / 100000000); long i = ((n % 100000000) / 10000000); long j = ((n % 10000000) / 1000000); long k = ((n % 1000000) / 100000); long l = ((n % 100000) / 10000); long m = ((n % 10000) / 1000); long ene = ((n % 1000) / 100); long o = ((n % 100) / 10); long p = ((n % 10) / 1); //The "/ 1" is just for visualization // multiply odd numbers by 2 //Also for visualization long q = a * 2; long r = c * 2; long s = e * 2; long t = g * 2; long u = i * 2; long v = k * 2; long w = m * 2; long x = o * 2; //process odd products //Luhn's has exceptions for double digit numbers long qq; if (q < 10) { qq = ((q % 10) + ((q % 100)/10)); } else if (q > 10) { qq = (q % 10) + 1; } else if (q == 10) { qq = 1; } else { qq = q; } long rr; if (r < 10) { rr = ((r % 10) + ((r % 100) / 10)); } else if (r > 10) { rr = (r % 10) + 1; } else if (r == 10) { rr = 1; } else { rr = r; } long ss; if (s < 10) { ss = ((s % 10) + ((s % 100) / 10)); } else if (s > 10) { ss = (s % 10) + 1; } else if (s == 10) { ss = 1; } else { ss = s; } long tt; if (t < 10) { tt = ((t % 10) + ((t % 100) / 10)); } else if (t > 10) { tt = (t % 10) + 1; } else if (t == 10) { tt = 1; } else { tt = t; } long uu; if (u < 10) { uu = ((u % 10) + ((u % 100) / 10)); } else if (u > 10) { uu = (u % 10) + 1; } else if (u == 10) { uu = 1; } else { uu = u; } long vv; if (v < 10) { vv = ((v % 10) + ((v % 100) / 10)); } else if (v > 10) { vv = (v % 10) + 1; } else if (v == 10) { vv = 1; } else { vv = v; } long ww; if (w < 10) { ww = ((w % 10) + ((w % 100) / 10)); } else if (w > 10) { ww = (w % 10) + 1; } else if (w == 10) { ww = 1; } else { ww = w; } long xx; if (x < 10) { xx = ((x % 10) + ((x % 100) / 10));; } else if (x > 10) { xx = (x % 10) + 1; } else if (x == 10) { xx = 1; } else { xx = x; } //Sum processed odd products long total_odd = qq + rr + ss + tt + uu + vv + ww + xx; //sum total odd products and even card numbers long bb = ((b % 10) + ((b % 100) / 10)); long dd = ((d % 10) + ((d % 100) / 10)); long ff = ((f % 10) + ((f % 100) / 10)); long hh = ((h % 10) + ((h % 100) / 10)); long jj = ((j % 10) + ((j % 100) / 10)); long ll = ((l % 10) + ((l % 100) / 10)); long eneene = ((ene % 10) + ((ene % 100) / 10)); long pp = ((p %10) + ((p % 100) / 10)); long total_even = bb + dd + ff + hh+ jj + ll + eneene + pp; //sum odd & even long card_total = total_odd + total_even; printf(" %li\n", card_total); } int get_number(void) //Works perfectly { long n; do { n = get_long("Number: "); // Records credit card number } while (n < 1000000000000 || n > 5599999999999999); // CC at least 13 digits but < 17 digits return n; }
Trying out your code and debugging it, the issue I found right away is that the return size element for your "get_number" function is too small. int get_number(void); When I debugged the returned value to the main function, the value was a negative number since the integer return value is too small for your long integer. Changing the function definition to "long get_number(void)" in the prototype and the function, allowed for the entered value to flow back to the main function and get tested properly. Following was the test output on my terminal (FYI, I added a couple of printf statements to illustrate that the entered value was flowing through properly). #Vera:~/C_Programs/Console/CC_Luhn/bin/Release$ ./CC_Luhn Number: 4003600000000014 Value stored is: 4003600000000014 Returned number: 4003600000000014 20 Just as a double-check, I ran a Luhn calculator program I had built some time back to answer a similar problem. Following is the output again using your credit card example as input. #Vera:~/C_Programs/Console/Luhn/bin/Release$ ./Luhn Enter a number: 4003600000000014 Length of number is: 16 Digit is: 4 Value is: 8 Sum is 8 Digit is: 0 Value is: 0 Sum is 8 Digit is: 0 Value is: 0 Sum is 8 Digit is: 3 Value is: 3 Sum is 11 Digit is: 6 Value is: 3 Sum is 14 Digit is: 0 Value is: 0 Sum is 14 Digit is: 0 Value is: 0 Sum is 14 Digit is: 0 Value is: 0 Sum is 14 Digit is: 0 Value is: 0 Sum is 14 Digit is: 0 Value is: 0 Sum is 14 Digit is: 0 Value is: 0 Sum is 14 Digit is: 0 Value is: 0 Sum is 14 Digit is: 0 Value is: 0 Sum is 14 Digit is: 0 Value is: 0 Sum is 14 Digit is: 1 Value is: 2 Sum is 16 Digit is: 4 Value is: 4 Sum is 20 Valid The result of the final calculation was the value of "20" which is a number that ends in zero, which indicates a valid number. This might have been a bit verbose, but the bottom line is be careful mixing your integer sizes in functions and formulas. Give that a try to see if it meets the spirit of your project.
how to create a simple iir low pass filter with not round errors? (16 bit pcm data)
i have an array of n length fullfilled by 16 bit (int16) pcm raw data,the data is in 44100 sample_rate and stereo,so i have in my array first 2 bytes left channel then right channel etc...i tried to implement a simple low pass converting my array into floating points -1 1,the low pass works but there are round errors that cause little pops in the sound now i do simply this : INT32 left_id = 0; INT32 right_id = 1; DOUBLE filtered_l_db = 0.0; DOUBLE filtered_r_db = 0.0; DOUBLE last_filtered_left = 0; DOUBLE last_filtered_right = 0; DOUBLE l_db = 0.0; DOUBLE r_db = 0.0; DOUBLE low_filter = filter_freq(core->audio->low_pass_cut); for(UINT32 a = 0; a < (buffer_size/2);++a) { l_db = ((DOUBLE)input_buffer[left_id]) / (DOUBLE)32768; r_db = ((DOUBLE)input_buffer[right_id]) / (DOUBLE)32768; ///////////////LOW PASS filtered_l_db = last_filtered_left + (low_filter * (l_db -last_filtered_left )); filtered_r_db = last_filtered_right + (low_filter * (r_db - last_filtered_right)); last_filtered_left = filtered_l_db; last_filtered_right = filtered_r_db; INT16 l = (INT16)(filtered_l_db * (DOUBLE)32768); INT16 r = (INT16)(filtered_r_db * (DOUBLE)32768); output_buffer[left_id] = (output_buffer[left_id] + l); output_buffer[right_id] = (output_buffer[right_id] + r); left_id +=2; right_id +=2; } PS: the input buffer is an int16 array with the pcm data from -32767 to 32767; i found this function here Low Pass filter in C and was the only one that i could understand xd DOUBLE filter_freq(DOUBLE cut_freq) { DOUBLE a = 1.0/(cut_freq * 2 * PI); DOUBLE b = 1.0/SAMPLE_RATE; return b/(a+b); } my aim is instead to have absolute precision on the wave,and to directly low pass using only integers with the cost to lose resolution on the filter(and i'm ok with it)..i saw a lot of examples but i really didnt understand anything...someone of you would be so gentle to explain how this is done like you would explain to a little baby?(in code or pseudo code rapresentation) thank you
Assuming the result of function filter_freq can be written as a fraction m/n your filter calculation basically is y_new = y_old + (m/n) * (x - y_old); which can be transformed to y_new = ((n * y_old) + m * (x - y_old)) / n; The integer division / n truncates the result towards 0. If you want rounding instead of truncation you can implement it as y_tmp = ((n * y_old) + m * (x - y_old)); if(y_tmp < 0) y_tmp -= (n / 2); else y_tmp += (n / 2); y_new = y_tmp / n In order to avoid losing precision from dividing the result by n in one step and multiplying it by n in the next step you can save the value y_tmp before the division and use it in the next cycle. y_tmp = (y_tmp + m * (x - y_old)); if(y_tmp < 0) y_new = y_tmp - (n / 2); else y_new = y_tmp + (n / 2); y_new /= n; If your input data is int16_t I suggest to implement the calculation using int32_t to avoid overflows. I tried to convert the filter in your code without checking other parts for possible problems. INT32 left_id = 0; INT32 right_id = 1; int32_t filtered_l_out = 0; // output value after division int32_t filtered_r_out = 0; int32_t filtered_l_tmp = 0; // used to keep the output value before division int32_t filtered_r_tmp = 0; int32_t l_in = 0; // input value int32_t r_in = 0; DOUBLE low_filter = filter_freq(core->audio->low_pass_cut); // define denominator and calculate numerator // use power of 2 to allow bit-shift instead of division const uint32_t filter_shift = 16U; const int32_t filter_n = 1U << filter_shift; int32_t filter_m = (int32_t)(low_filter * filter_n) for(UINT32 a = 0; a < (buffer_size/2);++a) { l_in = input_buffer[left_id]); r_in = input_buffer[right_id]; ///////////////LOW PASS filtered_l_tmp = filtered_l_tmp + filter_m * (l_in - filtered_l_out); if(last_filtered_left < 0) { filtered_l_out = last_filtered_left - filter_n/2; } else { filtered_l_out = last_filtered_left + filter_n/2; } //filtered_l_out /= filter_n; filtered_l_out >>= filter_shift; /* same calculation for right */ INT16 l = (INT16)(filtered_l_out); INT16 r = (INT16)(filtered_r_out); output_buffer[left_id] = (output_buffer[left_id] + l); output_buffer[right_id] = (output_buffer[right_id] + r); left_id +=2; right_id +=2; } As your filter is initialized with 0 it may need several samples to follow a possible step to the first input value. Depending on your data it might be better to initialize the filter based on the first input value.
Optimizing a nested loop in C
I have a nested loop to find all possible combinations of numbers between 1 and x in groups of 4, where a < b < c < d. A method is called as each group is discovered to do a simple equivalency test on the sum of those numbers. The loop does work and produces expected output (1 set of numbers for this particular x), however it takes 12+ seconds to find this answer and another ~5 to test the remaining possibilities, which is definitely bad, considering the x values are < 1000. I tried having the outer loop iterate a < x - 3 times, the b loop b < x - 2 times, down to d < x times which didn't make a noticeable difference. What would be a better approach in changing this loop? for (a = 1; a < x; a++) { for (b = a + 1; b < x; b++) { for (c = b + 1; c < x; c++) { for (d = c + 1; d < x; d++) { check(a, b, c, d); } } } }
With such a deep level of nesting, any early exit you can introduce - particularly at the outer loops - could net big gains. For example, you write that check is testing a + b + c + d == x && a * b * c * d == x - so you can compute the intermediate sum and product, and break when you encounter numbers that would make any selection of later numbers impossible. An example: for (a = 1; a < x; a++) { for (b = a + 1; b < x; b++) { int sumAB = a + b; if (sumAB + sumAB > x) break; int prodAB = a * b; if (prodAB * prodAB > x) break; for (c = b + 1; c < x; c++) { int sumABC = sumAB + c; if (sumABC + c > x) break; int prodABC = prodAB * c; if (prodABC * c > x) break; for (d = c + 1; d < x; d++) { int sumABCD = sumABC + d; if (sumABCD > x) break; if (sumABCD != x) continue; int prodABCD = prodABC * d; if (prodABCD > x) break; if (prodABCD != x) continue; printf("%d, %d, %d, %d\n", a, b, c, d); } } } } This is just an example - you can constrain all the checks here further (e.g. make the first check be sumAB + sumAB + 3 > x). The point is to focus on early exits. I added a counter for each loop, counting how many times it was entered, and tried your version and my version, with x = 100. My version has orders of magnitude less loop entries: No early exits: 99, 4851, 156849, 3764376 With early exits: 99, 4851, 1122, 848
PI control algorithm manually implemented in matlab
I'm trying to implement a simple script performing a PI control for a cruise control application, but I'm founding some problems with the integral part. Here is my code: function [] = PI_cruisecontrol() clc; close all; t0 = 0; tfinal = 50; dt = 0.001; % time parameters r = 10; % reference of 10 m/s m = 1000; % mass b = 50; % friction coeff. (depends on v) yp = zeros(tfinal/dt,1); t = yp; % initialize speed and time array Ki = 40; % integrarl constant Kp = 800; % proportional constant int = 0; % itinialize int error % CONTROL LOOP (Forward-Euler integrator is used to solve the ODE) for i=t0+2:tfinal/dt err = r-yp(i-1); % update error int = int+err; % integral term u = (Kp*err)+(Ki*int*dt); % action of control yp(i) = yp(i-1)+((-b*yp(i)/m) + (u/m))*dt; % solve ode for speed t(i) = t(i)+dt*i; % log the time end % Results figure(1) plot(t,yp) title ('Step Response') xlabel('Time (seconds)') ylabel('Amplitud') axis([0 20 0 12]) hold on reference = ones(tfinal/dt,1)*10; plot(t,reference,':') end And this is how it should be, using predefinided matlab functions: function [] = PI_cruisecontrol2() m = 1000; b = 50; r = 10; s = tf('s'); P_cruise = 1/(m*s + b); Kp = 800; Ki = 40; C = pid(Kp,Ki); T = feedback(C*P_cruise,1); t = 0:0.1:20; step(r*T,t) axis([0 20 0 12]) end What am I doing wrong in my code? Thanks!
I managed to fix the problem, working with float variables instead of arrays. Moreover, I added the derivative term (although for this first order problem was not necessary) Here I left the code: function [] = aFortran_PI() clc; close all; r = 10; % reference of 10 m/s m = 1000; % mass b = 50; % friction coeff. (depends on v) yp = 0; % init response Kp = 800; % proportional constant Ki = 40; % proportional constant Kd = 0; % derivative term is not necessary in this problem previous_error = 0; integral = 0; dt = 0.001; % CONTROL LOOP for i=1:20000 error = r-yp; % update error integral = integral + error*dt; % integral term derivative = (error-previous_error)/dt; % derivative term u = Kp*error+Ki*integral+Kd*derivative; % action of control yp = yp+(-b*yp/m + u/m)*dt % solve ode for velocity end end
FFT returning conjugate of true answer
I have an odd problem. Following (re: copying) from here, I've been trying to implement the Cooley–Tukey FFT algorithm for arrays with a power-of-2 size, but the answers returned from this implementation are the conjugate of the true answers. int fft_pow2(int dir,int m,float complex *a) { long nn,i,i1,j,k,i2,l,l1,l2; float c1,c2,tx,ty,t1,t2,u1,u2,z; float complex t; /* Calculate the number of points */ nn = 1; for (i=0;i<m;i++) nn *= 2; /* Do the bit reversal */ i2 = nn >> 1; j = 0; for (i=0;i<nn-1;i++) { if (i < j) { t = a[i]; a[i] = a[j]; a[j] = t; } k = i2; while (k <= j) { j -= k; k >>= 1; } j += k; } /* Compute the FFT */ c1 = -1.0; c2 = 0.0; l2 = 1; for (l=0;l<m;l++) { l1 = l2; l2 <<= 1; u1 = 1.0; u2 = 0.0; for (j=0;j<l1;j++) { for (i=j;i<nn;i+=l2) { i1 = i + l1; t = u1 * crealf(a[i1]) - u2 * cimagf(a[i1]) + I * (u1 * cimagf(a[i1]) + u2 * crealf(a[i1])); a[i1] = a[i] - t; a[i] += t; } z = u1 * c1 - u2 * c2; u2 = u1 * c2 + u2 * c1; u1 = z; } c2 = sqrt((1.0 - c1) / 2.0); if (dir == 1) c2 = -c2; c1 = sqrt((1.0 + c1) / 2.0); } /* Scaling for forward transform */ if (dir == 1) { for (i=0;i<nn;i++) { a[i] /= (float)nn; } } return 1; } int main(int argc, char **argv) { float complex arr[4] = { 1.0, 2.0, 3.0, 4.0 }; fft_pow2(0, log2(n), arr); for (int i = 0; i < n; i++) { printf("%f %f\n", crealf(arr[i]), cimagf(arr[i])); } } The results: 10.000000 0.000000 -2.000000 -2.000000 -2.000000 0.000000 -2.000000 2.000000 whereas the true answer is the conjugate. Any ideas?
The FFT is often defined with Hk = sum(e–2•π•i•j•k/N•hj, 0 < j ≤ N). Note the minus sign in the exponent. The FFT can be defined with a plus sign instead of the minus sign. In large part, the definitions are equivalent, because +i and –i are completely symmetric. The code you show is written for the definition with the negative sign, and it is also written so that the first parameter, dir, is 1 for a forward transform and something else for a reverse transform. We can determine the intended direction because of the comment about scaling for the forward transform: It scales if dir is 1. So, where your code in main calls fft_pow2 with 0 for dir, it is requesting a reverse transform. Your code has performed a reverse transform using the FFT definition with a negative sign. The reverse of the transform with a negative sign is a transform with a positive sign. For [1, 2, 3, 4], the result is: 10•1 + 11•2 + 12•3 + 13•4 = 1 + 2 + 3 + 4 = 10. i0•1 + i1•2 + i2•3 + i3•4 = 1 + 2i – 3 – 4i = –2 – 2i. (–1)0•1 + (–1)1•2 + (–1)2•3 + (–1)3•4 = 1 – 2 + 3 – 4 = –2. (–i)0•1 + (–i)1•2 + (–i)2•3 + (–i)3•4 = 1 – 2i – 3 + 4i = –2 + 2i. And that is the result you obtained.