FFTW on real data sequence - c

I'm reading a raw sound file, and I' m trying to run the fft on it, with aim of getting the PSD at the end, but I'm in the start and I get an error that I can't understand, hope getting some help here, the code is:
#include <stdio.h>
#include <fftw3.h>
int main(){
char* fileName = "sound.raw";
FILE* inp = NULL;
double* data = NULL;
int index = 0;
fftw_plan plan;
fftw_complex* out;
double r,i;
int N = 8192;
//Allocating the memory for the input data
data = (double*) fftw_malloc(sizeof(double)*N);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*N);
plan = fftw_plan_dft_r2c_1d(N,data,out,FFTW_FORWARD);
// opening the file for reading
inp = fopen(fileName,"rb");
if(inp== NULL){
printf(" couldn't open the file \n ");
return -1;
}
while(!feof(inp)){
printf( " index %d",index); // just get where the program crashs
if(index < N){
fread(&data[index],sizeof(short),1,inp);
index = index +1;
}
else{
index = 0;
fftw_execute(plan);
printf("New Plan \n");
printf(" Real \t imag \t Magn \t \n");
for(index = 0 ; index<N; index++){
r=out[index][0];
i =out[index][1];
printf("%lf \t %lf \t %lf \t \n",r,i,index);
}
index = 0 ;
}
}
return 0 ;
}
the program crashes when the index = 8106 and I'm sure that file contain more data. the error that I get is:
Segmentation fault (core dumped )
I know that the error is related to pointer trying to access a memory that it's not allowed to , my question is how can I solve this!
UPDATE
I checked the program again and the error is exactly in line :
fftw_execute(plan) ;
I hope helps more !
thanks in advance!

Found it , the error was in the paramter given to the plan function :
plan = fftw_plan_dft_r2c_1d(N,data,out,FFTW_FORWARD); //
should be instead
plan = fftw_plan_dft_r2c_1d(N,data,out,FFTW_MEASURE);
or
plan = fftw_plan_dft_r2c_1d(N,data,out,FFTW_ESTIMATE);
since the direction of the transformation is implicit in the function's name !
thanks anyway !

Related

How to save the data which i read in an array from a file in C

So while doing this assignment i encountered a problem where i tried to save some set of values(float) in an Array so that i can use them later on producing a graph, but the problem which i face here is that i read the values and i can print them but later which i checked the array the numbers which were stored there were not the same.
Im trying to save in in avg[].
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
float maximum(float array[])
{
float max=0;
for(int i=0;i<100;i++)
{
if (array[i]>max)
max=array[i];
}
return max;
}
float minimum(float array[])
{
float min=0;
for(int i=0;i<100;i++)
{
if (array[i]<min)
min=array[i];
}
return min;
}
char * read(char *filename)
{
FILE * sample;
sample = fopen(filename,"r"); //like file open in notepad ,which file? and what to do?
int count = 0;
static char singleline[100];
int cnt = 0;
int sum = 0;
int oldyear = -1;
float avg[82];
while(!feof(sample)) //read that until end.
{
count++;
fgets(singleline,150,sample);
if (count>21 && singleline[33]!='9')
{
char y[5], t[6];
for (int i = 14; i < 18; i++)
{
y[i - 14] = singleline[i];
}
y[4]='\0';
for (int i= 24;i <29;i++)
{
t[i-24]=singleline[i];
}
t[5]='\0';
int year = atoi(y);
int temp = atoi(t);
//printf("year : %i ,temp: %i\n",year, temp);
if (year == oldyear)
{
cnt++;
sum += temp;
}
else
{
int l=0;
l++;
avg[l] = 0.1 * sum / cnt;
if (cnt != 0)
{
printf("Fuer %i - %i Werte - Durchschnitt %.2f °C\n", oldyear, cnt, avg[l]);
cnt = 1;
sum = temp;
//save[l]=avg;
}
oldyear = year;
}
}
}
float last = 0.1 * sum / cnt;
printf("Fuer %i - %i Werte - Durchschnitt %.2f °C\n", oldyear, cnt-1, last);
fclose(sample);
//for(int i=0;i<)
for(int i=0;i<125;i++)
{
printf("%f\n",avg[i]);
}
printf("\nMax Temp= %f",maximum(avg));
printf("\nMax Temp= %f",minimum(avg));
return singleline;
}
int main()
{
char * file1 = "TG_STAID000476.txt";
read(file1);
//char * file2 = "TG_STAID000179.txt";
//read(file2);
return 0;
}
So yea, the problem was to read the year and the corresponding values and form an Average value for that particular year and then represent it in a graph.
I can do the first part where it takes the Average, but when i tried using it later,it had wrong values stored in it, you can see that where i tried to print all the values of avg[], can anyne please help me figure out how to correct the mistake, i want them to be saved as float.
The assignment datasheet is here. https://www.scribd.com/document/333844245/TG-STAID000179
I tried reading the values and used atoi to save them, and then used them to get the Average, i used Count>21 because the text before them are not required and when it reads a '9' on 34th column,it ignores since its not a valid data(in data sheet)
The variable l, intended to count the computed year temperature averages, is defined and initialized in the block where a year change is handled, thus always reset to zero. Correct this by moving the definition outside of the line read loop, perhaps even at global scope (see 2.).
The maximum() and minimum() functions operate on array elements 0 to 99, irrespective of the fact that the passed argument is defined as avg[82] and some elements at the end are not initialized. Correct this by using the actual number l of stored elements, either as a global scope variable or an additional function argument.
The singleline buffer is too short and thus overflows.
The while(!feof(sample)) loop cycles one extra time after the last line has been read, because EOF is not recognized before the next fgets(). Correct this by using the return value of fgets() to test EOF.
avg[l] = 0.1 * sum / cnt is evaluated even if cnt is zero. Correct this by moving this expression inside the if (cnt != 0) { … } block, also the l++, but behind the printf().
cnt = 1 is not executed if cnt is zero. This causes the very first data point to not be counted. Correct this by moving this expression behind the if (cnt != 0) { … } block.
The extra loop cycle (cf. 4.) may have led to use cnt-1 in the final printf("Fuer %i - %i Werte - Durchschnitt %.2f °C\n", oldyear, cnt-1, last);, but correct is just cnt.
The loop for(int i=0;i<125;i++) should also use the actual number l of stored elements, not 125.
To be noted is that the final year's average is (maybe intentionally) not stored in avg[].

Transfer results to txt file C

so i'm completely new to programming (i've been learning for 3 days) and i find myself infront of a problem i simply don't know how to resolve.
I want this program to give me every single combination from 0 to a specific number in base 36. That is easy enough when the number is only about 50000 or so. But my goal from this is to extract actual words(with numbers too) and if i try to get words with 5 characters, the terminal will start overwriting the previous words(not helpful, i want ALL of them).
So i thought i should look for a way to transfer everything into a txt file and there resides my problem: I don't know how... Sorry for the long text but i wanted to explain precisely what i'm trying to get. Thanks for the help.
int main() {
int dec, j, i, q, r, k;
char val[80];
printf("Enter a decimal number: ");
scanf("%d", &dec);
for (k = 0; k <= dec; k++) { /*repeat for all possible combinations*/
q = k;
for (i = 1; q != 0; i++) { /*convert decimal number to value for base 36*/
r = q % 36;
if (r < 10)
r = r + 48;
else
r = r + 55;
val[i] = r;
q = q / 36;
}
for (j = i - 1; j > 0; j--) { /*print every single value*/
printf("%c", val[j]);
}
printf(" "); /*add spaces because why not*/
}
return (0);
}
A few observations that might help:
First is type related:
In your declarations you create the following:
int dec, j, i, q, r, k;
char val[80];
Then later you make the assignment:
val[i] = r;//assigning an int to a char, dangerous
While r is type int with a range (typically) of –2,147,483,648 to 2,147,483,647,
val[i] is of type char with a range (typically) of only –128 to 127.
Because of this, you may run into an overflow, leading to unexpected results.
The most immediate solution is use the same type for both variables. Pick either int or char, but not both.
The other has already been addressed correctly by #Nasim. Use the file version of printf() - fprintf(). As the link shows, the prototype for fprintf() is:
int fprintf( FILE *stream, const char *format [, argument ]...);
Usage example:
FILE *fp = fopen(".\somefile.txt", "w");//create a pointer to a FILE
if(fp)//if the FILE was successfully created, write to it...
{
// some of your previous code...
for (j = i - 1; j > 0; j--)
{ /*print every single value*/
fprintf(fp, "%c", val[j]);//if val is typed as char
//OR
fprintf(fp, "%d", val[j]);//if val is typed as int
}
fclose(fp);
}
Lastly, there are a wide range of methods to perform base conversion. Some more complicated than others.
create a file and then you can use fprintf() instead of printf the only difference between the two is that you need to specify the file as an argument
FILE *myFile = fopen("file.txt", "w"); //"w" erase previous content, "a" appends
If(myFile == NULL) {printf("Error in openning file\n"); exit(1);}
fprintf(myFile, "some integer : %d\n", myInteger); // same as printf my specify file pointer name in first argument
fclose(myFile); //dont forget to close the file

C - Perceptron school project - single data set, error not converging

Hello everyone,
I'm currently stuck working on a school project described as such:
Your program should read in the file in.csv, and adjust the weights of the perceptron so that when given the inputs it was trained with, it provides the corresponding outputs.
In reality, the error may never get to zero when training an ANN; the goal is to hopefully make it smart enough to recognize most instances. For this project start with an error of 5%, or 0.05. This would mean, for example, that the ANN correctly identified 95/100 of the inputs, and 05/100 were mistakenly classified. See if you can modify the parameters of the ANN training process to do better than 5%, but your program should not continue trying to modify the weights after 500,000 iterations.
Sample run: C:\percy in.csv 100 5 10
where the executable is percy.exe, the input file is in.csv, the learning rate is 100/1000=0.100, the error is 5/100, and max iterations is in thousands, so 10 corresponds to 10,000.
The input file is formatted per the example below. The first 16 characters in line represent sensor inputs, and the last char is always either 0 or 1, and represents which class the input corresponds to.
0000000001000000,0
0000000001000001,1
0000000001000010,1
0000000001000011,1
0000000001000100,1
these few numbers are a portion of the data set being used, the rest of the data set are similar integers
So the output is supposed to look like so:
iterationError = 0.023437500, errCnt = 3, repNum=72
wt[00]: +0.00661 wt[01]: +0.00431 wt[02]: +0.00011 wt[03]: +0.00814
wt[04]: +0.00198 wt[05]: +0.00470 wt[06]: +0.00356 wt[07]: +0.00435
wt[08]: +0.00761 wt[09]: +0.52254 wt[10]: +0.00120 wt[11]: -0.01169
wt[12]: -0.00937 wt[13]: -0.00281 wt[14]: -0.00157 wt[15]: -0.00217
STOP*****(with setting wt[10] to 0.5232)
However, when I run my code (below) with reading in the .csv data set, the program runs until it hits 10k iterations and the error doesn't change and I'm not exactly sure what may be wrong with my loop or calculations. Also I should note that my current code doesn't represent the correct output yet.
Any help would be greatly appreciated, thank you
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define LEARNING_RATE 0.1
#define MAX_ITERATION 10000
float randomFloat()
{
return (float)rand() / (float)RAND_MAX;
}
int calculateOutput(float weights[], int x)
{
float sum = x * weights[0] + weights[1];
return (sum >= 0) ? 1 : -1;
}
int main(int argc, char *argv[])
{
srand(time(NULL));
float weights[2], localError, globalError, MAX_ERROR = 0.05;
float x[208];
int outputs[208], patternCount, i, p, iteration, output;
FILE *fp;
if ((fp = fopen("in.csv", "r")) == NULL) {
printf("Cannot open file.\n");
exit(1);
}
i = 0;
while (fscanf(fp, "%f,%d", &x[i], &outputs[i]) != EOF) {
i++;
}
patternCount = i;
weights[0] = randomFloat();
weights[1] = randomFloat();
iteration = 0;
do {
printf(" Iteration: %d ***********************************\n", iteration);
iteration++;
globalError = 0;
for (p = 0; p < patternCount; p++) {
output = calculateOutput(weights, x[p]);
localError = outputs[p] - output;
weights[0] += LEARNING_RATE * localError * x[p];
weights[1] += LEARNING_RATE * localError;
globalError += (localError*localError);
printf("%.1f \n", weights[0]);
}
globalError = globalError/((float)patternCount);
printf(" iterationError = %.5f\n", globalError);
} while ((globalError > MAX_ERROR) && (i < MAX_ITERATION));
return 0;
}

Caculating the PSD using FFTW

I'm sound file that I've record using the `ALSA' lib using following setups :
Fs = 96000; // sample frequency
channelNumber = 1 ;
format =int16 ;
length = 5sec;
meaning that I get 480000 16bit value. Now I want to calculate the PSD of the set of that to get something like :
what I'm trying to do is tto save the result as a bunch of double value in a extra data so I can plot them of evaluating them ( I'm not sure if that's correct) :
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fftw3.h>
int main(){
char fileName[] = "sound.raw";
char magnFile[] = "data.txt";
FILE* inp = NULL;
FILE* oup = NULL;
float* data = NULL;
fftwf_complex* out;
int index = 0;
fftwf_plan plan;
double var =0;
short wert = 0;
float r,i,magn;
int N = 512;
data =(float*)fftwf_malloc(sizeof(float)*N);
out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex)*N);
//Allocating the memory for the input data
plan = fftwf_plan_dft_r2c_1d(N,data,out, FFTW_MEASURE);
// opening the file for reading
inp = fopen(fileName,"r");
oup = fopen(magnFile,"w+");
if(inp== NULL){
printf(" couldn't open the file \n ");
return -1;
}
if(oup==NULL){
printf(" couldn't open the output file \n");
}
while(!feof(inp)){
if(index < N){
fread(&wert,sizeof(short),1,inp);
//printf(" Wert %d \n",wert);
data[index] = (float)wert;
//printf(" Wert %lf \n",data[index]);
index = index +1;
}
else{
index = 0;
fftwf_execute(plan);
//printf("New Plan \n");
//printf(" Real \t imag \t Magn \t \n");
for(index = 0 ; index<N; index++){
r=out[index][0];
i =out[index][1];
magn = sqrt((r*r)+(i*i));
printf("%.10lf \t %.10lf \t %.10lf \t \n",r,i,magn);
//fwrite(&magn,sizeof(float),1,oup);
//fwrite("\n",sizeof(char),1,oup);
fprintf(oup,"%.10lf\n ", magn);
}
index = 0 ;
fseek(inp,N,SEEK_CUR);
}
}
fftwf_destroy_plan(plan);
fftwf_free(data);
fftwf_free(out);
fclose(inp);
fclose(oup);
return 0 ;
}
the problem that I have is how can I implement the winding function in my code ?
and I don't think that result is accurate, since I'get a lot of zero in magnitude values ? ?
if somebody has an example I'll be thankful .
Here is a simple example of applying a "Hanning" window to your data prior to the FFT:
for (int i = 0; i < N; ++i)
{
data[i] *= 0.5 * (1.0 + cos(2.0 * M_PI * (double)i / (double)(N - 1)));
}

Reading integers from a text file in C line by line and storing them in an array

I am new to C and have been trying to do this for a while now.
I need to read the integer values from a text file that has :
G = 10
P = 5
Gayle: 1,2,3,4
Price: 4,3,5,6.6
Need to pick out the Gayle and Price values and store them in 2 seperate arrays and store the G and P values in 2 separate variables.
So far I have done :
FILE* file = fopen(abc.txt, "r");
//for gayle values
int g_array[100];
int i=0;
int gayle_val;
while(fscanf("%d", &gayle_val)==1)
{
g_array[i]=gayle_val;
}
//for price values
int p_array[100];
int i=0;
int price_val;
while(fscanf("%d", &price_val)==1)
{
p_array[i]=price_val;
}
//for G and P values
How do I combine the searches for the 4 lines such that the read is done line by line and values stored accordingly ?
Thank you so much in advance !
This has been answered before and I'm pretty sure it was suggested to you as the question was typed:
I am not going to give you a code sample but instead am going to advise you on what could be done to get the contents of the file to be inserted in a single array rather than one.
Try to create a 2D array instead and assigning the values to it rather than having multiple arrays and use a FOR loop to do so.
simple E.G.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
int gayle_val, g_array[100], g_count, p_count;
float price_val, p_array[100];
int i;
char line_buff[128], *p;
FILE *file = fopen("abc.txt", "r");
while(NULL!=fgets(line_buff, sizeof(line_buff), file)){
if(strncmp("G = ", line_buff, 4) == 0){//simple match
gayle_val = atoi(line_buff + 4);
} else if(strncmp("P = ", line_buff, 4) == 0){
price_val = atof(line_buff + 4);
} else if(strncmp("Gayle: ", line_buff, 7) == 0){
g_count = 0;
for(p = line_buff + 7;NULL!=(p=strtok(p, ","));p=NULL){
g_array[g_count++] = atoi(p);
}
} else if(strncmp("Price: ", line_buff, 7) == 0){
p_count = 0;
for(p = line_buff + 7;NULL!=(p=strtok(p, ","));p=NULL){
p_array[p_count++] = atof(p);
}
}
}
fclose(file);
//check print
printf("gayle_val: %d\n", gayle_val);
printf("gayle: ");
for(i = 0;i<g_count;++i)
printf("%d ", g_array[i]);
printf("\n");
printf("price_val: %g\n", price_val);
printf("price: ");
for(i = 0;i<p_count;++i)
printf("%g ", p_array[i]);
printf("\n");
return 0;
}

Resources