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.
I took this example from a video in youtube, where a sen(x) is resolved using this approach, I just changed the formula to an arcsin(x).
I am trying to figure out why this code is not working as expected:
#include <stdio.h>
//#include <float.h>
#include <math.h>
int factorial(int x)
{
int fac = 1;
while (x!=0)
{
fac= fac*x;
x--;
}
return fac;
}
int main()
{
int i;
float x, sum, divisor = 1, dividendo = 1, temp;
printf("enter the value of X(in degrees): ");
scanf("%f", &x);
//x = x*3.141592/180;
sum = 0;
for(i=1; ; i++)
{
divisor = (factorial(2*i));
dividendo = (pow(4,(i)) * pow(factorial(i),2)*(2*i+1));
temp = (divisor/dividendo)*pow(x,(2*i+1));
if (temp < FLT_EPSILON)
break;
sum = sum + temp;
printf("our result = %f\n", sum);
}
printf("reference = %f\n", asin(x));
// printf("our result = %f\n", sum);
}
Below is the result, and as you may see the output I get is far below from what is expected. the result printed comes from every iteration, and the reference is just to make a comparison between both outcomes.
enter the value of X(in degrees): 1
our result = 0.166667
our result = 0.241667
our result = 0.286310
our result = 0.316691
our result = 0.339064
our result = 0.356416
our result = 0.356621
our result = 0.356622
our result = 0.356622
our result = 0.356622
**reference = 1.570796**
The Taylor series for arscin is
arcsin(x) = sum n = 0; inf; (2*n)! / (4**n * (n!)**2 * (2*n + 1)) * x**(2*n + 1)
where ** is the power operator and ! denotes a factorial. As was already noted in comments, an int can represent factorials up to 12! only; a 64-bit long can represent factorials up to 20!. Since you use (2*n)!, these limits will be reached quickly.
A better solution to this problem is not to calculate every term separately as given in the formula, but to evolve the term by calculating it from the previous term:
term(n + 1) = fact * term(n)
Since each term is one large factor, you can do that for each subfactor:
2*(n + 1))! = (2*n)! * (2*n + 1) * (2*n + 2)
4**(n + 1) = 4**n * 4
((n + 1)!)**2 = n!**2 * (n + 1)**2
2*(n + 1) + 1 = 2*(n + 1) * (2*n + 3) / (2*n + 1)
x**(2*(n + 1) + 1) = x**(2*n + 1) * x**2
Putting all this together:
float res = x; // first term ...
float fact = x; // ...equals the first factor
for (int n = 0; n < nMax; n++) {
float old = res;
// calculate term(n + 1) as per the formulas above
fact *= (2*n + 1) * (2*n + 2);
fact /= 4.0 * (n + 1)*(n + 1) * (2*n + 3);
fact *= x * x * (2*n + 1);
res += fact;
if (res == old) break;
printf("[%d] %f\n", n, res);
}
printf("ref %f\n", asin(x));
(FLT_EPSILON is the granularity of floating-point numbers near 1.0. The terms are converging to zero, where the granularity is finer. I've tested whether adding the new term doesn't change the sum as a convergence criterion with a fixed maximum number of iterations, nMax.)
This series does not converge well near ±1, where the slope of the function approaches infinity. By Stirling's approximation the nth term approximately equals 1/((2*n+1)*√(πn)), which converges very slowly. For the nth term to be less than FLT_EPSILON, n needs to be greater than 26000. Unfortunately, with that many summations, the finite precision of floating point numbers would prevent the series to converge to the correct answer.
I have been using Ubuntu 12.04 LTS with GCC to compile my the codes for my assignment for a while. However, recently I have run into two issues as follows:
The following code calculates zero for a nonzero value with the second formula is used.
There is a large amount of error in the calculation of the integral of the standard normal distribution from 0 to 5 or larger standard deviations.
How can I remedy these issues? I am especially obsessed with the first one. Any help or suggestion is appreciated. thanks in advance.
The code is as follows:
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#define N 599
long double
factorial(long double n)
{
//Here s is the free parameter which is increased by one in each step and
//pro is the initial product and by setting pro to be 0 we also cover the
//case of zero factorial.
int s = 1;
long double pro = 1;
//Here pro stands for product.
if (n < 0)
printf("Factorial is not defined for a negative number \n");
else {
while (n >= s) {
pro *= s;
s++;
}
return pro;
}
}
int main()
{
// Since the function given is the standard normal distribution
// probability density function we have mean = 0 and variance = 1.
// Hence we also have z = x; while dealing with only positive values of
// x and keeping in mind that the PDF is symmetric around the mean.
long double * summand1 = malloc(N * sizeof(long double));
long double * summand2 = malloc(N * sizeof(long double));
int p = 0, k, z[5] = {0, 3, 5, 10, 20};
long double sum1[5] = {0}, sum2[5] = {0} , factor = 1.0;
for (p = 0; p <= 4; p++)
{
for (k = 0; k <= N; k++)
{
summand1[k] = (1 / sqrtl(M_PI * 2) )* powl(-1, k) * powl(z[p], 2 * k + 1) / ( factorial(k) * (2 * k + 1) * powl(2, k));
sum1[p] += summand1[k];
}
//Wolfamalpha site gives the same value here
for (k = 0; k <= N; k++)
{
factor *= (2 * k + 1);
summand2[k] = ((1 / sqrtl(M_PI * 2) ) * powl(z[p], 2 * k + 1) / factor);
//printf("%Le \n", factor);
sum2[p] += summand2[k];
}
sum2[p] = sum2[p] * expl((-powl(z[p],2)) / 2);
}
for (p = 0; p < 4; p++)
{
printf("The sum obtained for z between %d - %d \
\nusing the first formula is %Lf \n", z[p], z[p+1], sum1[p+1]);
printf("The sum obtained for z between %d - %d \
\nusing the second formula is %Lf \n", z[p], z[p+1], sum2[p+1]);
}
return 0;
}
The working code without the outermost for loop is
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#define N 1200
long double
factorial(long double n)
{
//Here s is the free parameter which is increased by one in each step and
//pro is the initial product and by setting pro to be 0 we also cover the
//case of zero factorial.
int s = 1;
long double pro = 1;
//Here pro stands for product.
if (n < 0)
printf("Factorial is not defined for a negative number \n");
else {
while (n >= s) {
pro *= s;
s++;
}
return pro;
}
}
int main()
{
// Since the function given is the standard normal distribution
// probability density function we have mean = 0 and variance = 1.
// Hence we also have z = x; while dealing with only positive values of
// x and keeping in mind that the PDF is symmetric around the mean.
long double * summand1 = malloc(N * sizeof(long double));
long double * summand2 = malloc(N * sizeof(long double));
int k, z = 3;
long double sum1 = 0, sum2 = 0, pro = 1.0;
for (k = 0; k <= N; k++)
{
summand1[k] = (1 / sqrtl(M_PI * 2) )* powl(-1, k) * powl(z, 2 * k + 1) / ( factorial(k) * (2 * k + 1) * powl(2, k));
sum1 += summand1[k];
}
//Wolfamalpha site gives the same value here
printf("The sum obtained for z between 0-3 using the first formula is %Lf \n", sum1);
for (k = 0; k <= N; k++)
{
pro *= (2 * k + 1);
summand2[k] = ((1 / sqrtl(M_PI * 2) * powl(z, 2 * k + 1) / pro));
//printf("%Le \n", pro);
sum2 += summand2[k];
}
sum2 = sum2 * expl((-powl(z,2)) / 2);
printf("The sum obtained for z between 0-3 using the second formula is %Lf \n", sum2);
return 0;
}
I'm quite certain that the problem is in factor not being set back to 1 in the outer loop..
factor *= (2 * k + 1); (in the loop that calculates sum2.)
In the second version provided the one that works it starts with z=3
However in the first loop since you do not clear it between iterations on p by the time you reach z[2] it already is a huge number.
EDIT: Possible help with precision..
Basically you have a huge number powl(z[p], 2 * k + 1) divided by another huge number factor. huge floating point numbers lose their precision. The way to avoid that is to perform the division as soon as possible..
Instead of first calculating powl(z[p], 2 * k + 1) and dividing by factor :
- (z[p]z[p] ... . * z[p]) / (1*3*5*...(2*k+1))`
rearrange the calculation: (z[p]/1) * (z[p]^2/3) * (z[p]^2/5) ... (z[p]^2/(2*k+1))
You can do this in sumand2 calculation and a similar trick in summand1
I have 3 IPs and every IP has a weight, I want to return the IP's according to its weights using the random function,,,, for example if we have 3 IP's : X with weight 6,Y with weight 4 and Z with weight 2, I want to return X in 50% of cases and Y in 33% of cases and Z in 17% of cases, depending on random function in C.
This code is to the case of 3 IPs:
double r = rand() / (double)RAND_MAX;
double denom = 6 + 4 + 2;
if (r < 6 / denom) {
// choose X
} else if (r < (6 + 4) / denom) {
// choose Y
} else {
// choose Z
}
what if I have n IPs how can I modify the code to deal with n IPs not a specific number of IPs?
Here is an example of how to do this
Weighted random numbers
and from that post:
int sum_of_weight = 0;
for(int i=0; i<num_choices; i++) {
sum_of_weight += choice_weight[i];
}
int rnd = random(sum_of_weight);
for(int i=0; i<num_choices; i++) {
if(rnd < choice_weight[i])
return i;
rnd -= choice_weight[i];
}
assert(!"should never get here");
Build an array with the cumulative weight of the ip's
Something like this
// C99 code
int pick_ip(int weights[], int nweights)
{
// note you can split this step out if you like (a good plan)
int cum_weights[nweights];
int tot_weight = 0;
for(int i=0; i < nweights; i++)
{
tot_weight += weights[i];
cum_weights[i] = tot_weight;
}
int t = (int)(tot_weight * rand() / (double)RAND_MAX);
if(cum_weights[0] > t) { return 0; }
// binary search for point that we picked
int v = -1;
int l = 0, u = nweights -1;
int m = u/2;
do { // binary search
if(cum_weights[m] > t) u = m;
else l = m;
m = (u + l)/2;
if(cum_weights[l+1] > t) {v=l+1; break;}
if(cum_weights[u-1] <= t) {v=u; break;}
} while(1);
}
Note: if you're doing lots of picking split out the building of the cumulative distribution array. Also if you want floating point weights you need to use a Khan sum to compute the cumulative weights (if you want code for doing that comment and I can add it to my example)
I have had to start to learning C as part of a project that I am doing. I have started doing the 'euler' problems in it and am having trouble with the first one. I have to find the sum of all multiples of 3 or 5 below 1000. Could someone please help me. Thanks.
#include<stdio.h>
int start;
int sum;
int main() {
while (start < 1001) {
if (start % 3 == 0) {
sum = sum + start;
start += 1;
} else {
start += 1;
}
if (start % 5 == 0) {
sum = sum + start;
start += 1;
} else {
start += 1;
}
printf("%d\n", sum);
}
return(0);
}
You've gotten some great answers so far, mainly suggesting something like:
#include <stdio.h>
int main(int argc, char * argv[])
{
int i;
int soln = 0;
for (i = 1; i < 1000; i++)
{
if ((i % 3 == 0) || (i % 5 == 0))
{
soln += i;
}
}
printf("%d\n", soln);
return 0;
}
So I'm going to take a different tack. I know you're doing this to learn C, so this may be a bit of a tangent.
Really, you're making the computer work too hard for this :). If we figured some things out ahead of time, it could make the task easier.
Well, how many multiples of 3 are less than 1000? There's one for each time that 3 goes into 1000 - 1.
mult3 = ⌊ (1000 - 1) / 3 ⌋ = 333
(the ⌊ and ⌋ mean that this is floor division, or, in programming terms, integer division, where the remainder is dropped).
And how many multiples of 5 are less than 1000?
mult5 = ⌊ (1000 - 1) / 5 ⌋ = 199
Now what is the sum of all the multiples of 3 less than 1000?
sum3 = 3 + 6 + 9 + ... + 996 + 999 = 3×(1 + 2 + 3 + ... + 332 + 333) = 3×∑i=1 to mult3 i
And the sum of all the multiples of 5 less than 1000?
sum5 = 5 + 10 + 15 + ... + 990 + 995 = 5×(1 + 2 + 3 + ... + 198 + 199) = 5×∑i = 1 to mult5 i
Some multiples of 3 are also multiples of 5. Those are the multiples of 15.
Since those count towards mult3 and mult5 (and therefore sum3 and sum5) we need to know mult15 and sum15 to avoid counting them twice.
mult15 = ⌊ (1000 - 1) /15 ⌋ = 66
sum15 = 15 + 30 + 45 + ... + 975 + 990 = 15×(1 + 2 + 3 + ... + 65 + 66) = 15×∑i = 1 to mult15 i
So the solution to the problem "find the sum of all the multiples of 3 or 5 below 1000" is then
soln = sum3 + sum5 - sum15
So, if we wanted to, we could implement this directly:
#include <stdio.h>
int main(int argc, char * argv[])
{
int i;
int const mult3 = (1000 - 1) / 3;
int const mult5 = (1000 - 1) / 5;
int const mult15 = (1000 - 1) / 15;
int sum3 = 0;
int sum5 = 0;
int sum15 = 0;
int soln;
for (i = 1; i <= mult3; i++) { sum3 += 3*i; }
for (i = 1; i <= mult5; i++) { sum5 += 5*i; }
for (i = 1; i <= mult15; i++) { sum15 += 15*i; }
soln = sum3 + sum5 - sum15;
printf("%d\n", soln);
return 0;
}
But we can do better. For calculating individual sums, we have Gauss's identity which says the sum from 1 to n (aka ∑i = 1 to n i) is n×(n+1)/2, so:
sum3 = 3×mult3×(mult3+1) / 2
sum5 = 5×mult5×(mult5+1) / 2
sum15 = 15×mult15×(mult15+1) / 2
(Note that we can use normal division or integer division here - it doesn't matter since one of n or n+1 must be divisible by 2)
Now this is kind of neat, since it means we can find the solution without using a loop:
#include <stdio.h>
int main(int argc, char *argv[])
{
int const mult3 = (1000 - 1) / 3;
int const mult5 = (1000 - 1) / 5;
int const mult15 = (1000 - 1) / 15;
int const sum3 = (3 * mult3 * (mult3 + 1)) / 2;
int const sum5 = (5 * mult5 * (mult5 + 1)) / 2;
int const sum15 = (15 * mult15 * (mult15 + 1)) / 2;
int const soln = sum3 + sum5 - sum15;
printf("%d\n", soln);
return 0;
}
Of course, since we've gone this far we could crank out the entire thing by hand:
sum3 = 3×333×(333+1) / 2 = 999×334 / 2 = 999×117 = 117000 - 117 = 116883
sum5 = 5×199×(199+1) / 2 = 995×200 / 2 = 995×100 = 99500
sum15 = 15×66×(66+1) / 2 = 990×67 / 2 = 495 × 67 = 33165
soln = 116883 + 99500 - 33165 = 233168
And write a much simpler program:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("233168\n");
return 0;
}
You could change your ifs:
if ((start % 3 == 0) || (start % 5 == 0))
sum += start;
start ++;
and don´t forget to initialize your sum with zero and start with one.
Also, change the while condition to < 1000.
You would be much better served by a for loop, and combining your conditionals.
Not tested:
int main()
{
int x;
int sum = 0;
for (x = 1; x <= 1000; x++)
if (x % 3 == 0 || x % 5 == 0)
sum += x;
printf("%d\n", sum);
return 0;
}
The answers are all good, but won't help you learn C.
What you really need to understand is how to find your own errors. A debugger could help you, and the most powerful debugger in C is called "printf". You want to know what your program is doing, and your program is not a "black box".
Your program already prints the sum, it's probably wrong, and you want to know why. For example:
printf("sum:%d start:%d\n", sum, start);
instead of
printf("%d\n", sum);
and save it into a text file, then try to understand what's going wrong.
does the count start with 1 and end with 999?
does it really go from 1 to 999 without skipping numbers?
does it work on a smaller range?
Eh right, well i can see roughly where you are going, I'm thinking the only thing wrong with it has been previously mentioned. I did this problem before on there, obviously you need to step through every multiple of 3 and 5 and sum them. I did it this way and it does work:
int accumulator = 0;
int i;
for (i = 0; i < 1000; i += 3)
accumulator += i;
for (i = 0; i < 1000; i +=5) {
if (!(i%3==0)) {
accumulator += i;
}
}
printf("%d", accumulator);
EDIT: Also note its not 0 to 1000 inclusive, < 1000 stops at 999 since it is the last number below 1000, you have countered that by < 1001 which means you go all the way to 1000 which is a multiple of 5 meaning your answer will be 1000 higher than it should be.
You haven't said what the program is supposed to do, or what your problem is. That makes it hard to offer help.
At a guess, you really ought to initialize start and sum to zero, and perhaps the printf should be outside the loop.
Really you need a debugger, and to single-step through the code so that you can see what it's actually doing. Your basic problem is that the flow of control isn't going where you think it is, and rather than provide correct code as others have done, I'll try to explain what your code does. Here's what happens, step-by-step (I've numbered the lines):
1: while (start < 1001) {
2: if (start % 3 == 0) {
3: sum = sum + start;
4: start += 1;
5: }
6: else {
7: start += 1;
8: }
9:
10: if (start % 5 == 0) {
11: sum = sum + start;
12: start += 1;
13: }
14: else {
15: start += 1;
16: }
17: printf("%d\n", sum);
18: }
line 1. sum is 0, start is 0. Loop condition true.
line 2. sum is 0, start is 0. If condition true.
line 3. sum is 0, start is 0. sum <- 0.
line 4. sum is 0, start is 0. start <- 1.
line 5. sum is 0, start is 1. jump over "else" clause
line 10. sum is 0, start is 1. If condition false, jump into "else" clause.
line 15. sum is 0, start is 1. start <- 2.
line 16 (skipped)
line 17. sum is 0, start is 2. Print "0\n".
line 18. sum is 0, start is 2. Jump to the top of the loop.
line 1. sum is 0, start is 2. Loop condition true.
line 2. sum is 0, start is 2. If condtion false, jump into "else" clause.
line 7. sum is 0, start is 2. start <- 3.
line 10. sum is 0, start is 3. If condition false, jump into "else" clause.
line 15. sum is 0, start is 3. start <- 4.
line 17. sum is 0, start is 4. Print "0\n".
You see how this is going? You seem to think that at line 4, after doing sum += 1, control goes back to the top of the loop. It doesn't, it goes to the next thing after the "if/else" construct.
You have forgotten to initialize your variables,
The problem with your code is that your incrementing the 'start' variable twice. This is due to having two if..else statements. What you need is an if..else if..else statement as so:
if (start % 3 == 0) {
sum = sum + start;
start += 1;
}
else if (start % 5 == 0) {
sum = sum + start;
start += 1;
}
else {
start += 1;
}
Or you could be more concise and write it as follows:
if(start % 3 == 0)
sum += start;
else if(start % 5 == 0)
sum += start;
start++;
Either of those two ways should work for you.
Good luck!
Here's a general solution which works with an arbitrary number of factors:
#include <stdio.h>
#define sum_multiples(BOUND, ...) \
_sum_multiples(BOUND, (unsigned []){ __VA_ARGS__, 0 })
static inline unsigned sum_single(unsigned bound, unsigned base)
{
unsigned n = bound / base;
return base * (n * (n + 1)) / 2;
}
unsigned _sum_multiples(unsigned bound, unsigned bases[])
{
unsigned sum = 0;
for(unsigned i = 0; bases[i]; ++i)
{
sum += sum_single(bound, bases[i]);
for(unsigned j = i + 1; bases[j]; ++j)
sum -= sum_single(bound, bases[i] * bases[j]);
}
return sum;
}
int main(void)
{
printf("%u\n", sum_multiples(999, 3, 5));
return 0;
}