Caculating the PSD using FFTW - c

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)));
}

Related

Checking for null/empty float values when using sscanf

The following program attempts to read an input file line by line using fgets, and save each comma delimited float value into an array of structs using sscanf (this aspect of the code works fine). The issue lies in that the program should also detect when a float value is missing/empty, and assign it the float value 1.500 which then is saved into the array of structs.
EDIT: This is supposed to be compiled using VS2017, so on Windows.
*Note: Please note that the following questions have been studied before posting this question:
How to check if a string returned by scanf is null
How to get scanf to continue with empty scanset
An example of the input file (missing value in the second row):
0.123f, 0.234f, 0.345f, 0.456f, 0.567f
1.987f, , 7.376f, 2.356f, 5.122f
9.111f, 1.234f, 7.091f, 6.672f, 9.887f
Desired output (missing value in second row is detected and set to 1.500):
0.123 0.234 0.345 0.456 0.567
1.987 1.500 7.376 2.356 5.122
9.111 1.234 7.091 6.672 9.887
So far, the first attempt tried to scan all 5 floats (each with 'f' suffix) into strings and then check to see if those strings are null/empty or of zero length using strcmp and strlen, respectively, and finally involved trying to use sscanf again on each of those variables to read each into an array of structs.
The 2nd attempt included a check to see if the sscanf was successful by using if (sscanf(line, "%ff", &data[i].x) == NULL) { // ...some alert and assign 1.500}, which did not work either. The 3rd attempt, as seen below:
#include "stdio.h"
int main() {
typedef struct {
float x, y, vx, vy, mass;
}DATA;
FILE *file = fopen("null_detector.txt", "r");
if (file == NULL)
{
printf(stderr, "ERROR: file not opened.\n");
return EXIT_FAILURE;
}
int N= 3;
DATA* data = malloc(Nbodies * sizeof * data); // Array allocation
char line[256];
int i;
int inc = 1;
for (i = 0; i < Nbodies; i += inc)
{
fgets(line, sizeof(line), file);
// **Some info:
// Scan 5 float variables per line (this part works fine)
sscanf(line, "%ff, %ff, %ff, %ff, %ff",
&data[i].x, &data[i].y, &data[i].vx, &data[i].vy, &data[i].mass); // %ff accounts for 'f' suffix
// Now check if any of above vars are empty/NULL.
// NOTE: aware that these vars CANNOT be compared to NULL,
// but has been included to try and provide clarity for end goal
if (data[i].x == NULL)
{
//.. assign 1.500 to data[i].x
}
if (data[i].y == NULL)
{
//... same as above etc
}
// ...Repeat IF statements for all 5 vars
}
//Print the contents of array of structs to check for correct output
for (i = 0; i < Nbodies; i++)
{
printf("%.3f %.3f %.3f %.3f %.3f\n", data[i].x, data[i].y, data[i].vx, data[i].vy, data[i].mass);
}
return 0;
}
Summary:
Does anyone know how this program can be modified to:
detect missing float values in each line of the file upon reading them with fgets
replace missing float values with the float value 1.500
write these values to the array of structs, like the non-missing values successfully are doing?
As commented in the code, I am aware that the struct float variables cannot be compared to NULL. I have included this comparison in the code to only try to add some clarity as to what the end goal is.
You can use strsep to separate each line.
str = strsep(&line, ",")
Using one function to set the value of data:
void set_data(DATA *dt, int count, float f) {
switch(count) {
case 0: dt->x = f; break;
case 1: dt->y = f; break;
case 2: dt->vx = f; break;
case 3: dt->vy = f; break;
case 4: dt->mass = f; break;
}
}
The complete code:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
float x, y, vx, vy, mass;
}DATA;
void set_data(DATA *dt, int count, float f) {
switch(count) {
case 0: dt->x = f; break;
case 1: dt->y = f; break;
case 2: dt->vx = f; break;
case 3: dt->vy = f; break;
case 4: dt->mass = f; break;
}
}
int main() {
FILE *file = fopen("text.txt", "r");
if (file == NULL)
{
printf( "ERROR: file not opened.\n");
return EXIT_FAILURE;
}
int N= 3;
DATA* data = malloc(N * sizeof(data)); // Array allocation
char *line;
int i;
int inc = 1;
size_t n = 0;
for (i = 0; i < N; i += inc)
{
getline(&line, &n, file);
int count = 0;
char *str;
while((str = strsep(&line, ",")) != NULL) {
if (strcmp(str, " ") == 0) {
set_data(&data[i], count, 1.5);
} else {
set_data(&data[i], count, atof(str));
}
// printf("count = %d\n", count);
// printf("token: %s\n", str);
count++;
}
}
//Print the contents of array of structs to check for correct output
for (i = 0; i < N; i++)
{
printf("%.3f %.3f %.3f %.3f %.3f\n", data[i].x, data[i].y, data[i].vx, data[i].vy, data[i].mass);
}
return 0;
}
The input:
#cat text.txt
0.123f, 0.234f, 0.345f, 0.456f, 0.567f
1.987f, , 7.376f, 2.356f, 5.122f
9.111f, 1.234f, 7.091f, 6.672f, 9.887
The output:
0.123 0.234 0.345 0.456 0.567
1.987 1.500 7.376 2.356 5.122
9.111 1.234 7.091 6.672 9.887
It can also achieved with only sscanf if there is at least a space between the commas when there is an absence of an input value.
#include <stdio.h>
int main(void) {
char *str[] = {"0.123f, 0.234f, 0.345f, 0.456f, 0.567f",
"1.987f, , 7.376f, 2.356f, 5.122f",
"9.111f, 1.234f, 7.091f, 6.672f, 9.887f"};
float float_arr[3][5];
char temp[5][7];
for (unsigned i = 0; i < 3; i++) {
if (5 != sscanf(str[i], "%6[^,],%6[^,],%6[^,],%6[^,],%6[^,]",
temp[0], temp[1], temp[2], temp[3], temp[4]))
return printf("Error\n"), 1;
for (unsigned j = 0; j < 5; j++)
if (1 != sscanf(temp[j], "%ff", &float_arr[i][j]))
float_arr[i][j] = 1.500f;
}
// printing the result
for (unsigned i = 0; i < 3; i++) {
for (unsigned j = 0; j < 5; j++)
printf("%ff ", float_arr[i][j]);
printf("\n");
}
return 0;
}
Output
0.123000f 0.234000f 0.345000f 0.456000f 0.567000f
1.987000f 1.500000f 7.376000f 2.356000f 5.122000f
9.111000f 1.234000f 7.091000f 6.672000f 9.887000f

Creating a histogram from a large file

I have two large files containing float-type data. I want to create a histogram using the two files. However, to access the 256^3 data values, I tried using a nested for-loop in C which failed with a segmentation fault.
Is there an alternative method that I can use to access the data values that would not result in a segmentation fault?
Here is my code:
int main () {
int i,j,k,n_grid;
float pc,mass_g,spat_res,vol_pix,max_vel,min_vel;
float velocity,density,max;
long start,index,index1,index2,counter,lSize,dim;
FILE *p,*q;
pc = 3.085677e-18; //1 parsec in cm
n_grid = 256; //dimension of observed portion of input grid
mass_g = 0.0;
spat_res = pc*0.71/512; //spatial resolution of grid in cm
vol_pix = pow(spat_res,3); //volume of each voxel in cm^3
p = fopen("../dens_104/rho_052.dat","rb");
q = fopen("../dens_104/velz.dat","rb");
if (!p){
printf("Unable to open dens file!");
return 0;
}
else if (!q){
printf("Unable to open the velx file!");
return 0;
}
//obtain file size(s)
fseek(p,0,SEEK_END);
lSize = ftell(p);
rewind(p);
dim = pow(lSize/sizeof(float),1.0/3.0); //actual size of input grid
max = 0;
counter = 0;
index = 0;
while(fread(&density,sizeof(float),1,p),!feof(p) && !ferror(p)) {
if(density > max) max = density,index = counter;
counter += 1;
}
start = index - (pow(dim,2)+dim+1)*(n_grid/2-1);
printf("Starting pixel value: %lu, Dimension of cube: %d\n",start,
(int)dim);
printf("The maximum density is: %e with index: %lu \n", max,index);
rewind(p);
fseek(p,start*sizeof(float),SEEK_SET);
fseek(q,start*sizeof(float),SEEK_SET);
max_vel = 0.0;
min_vel = 0.0;
index1 = 0;
index2 = 0;
while(fread(&velocity,sizeof(float),1,q),!feof(q) && !ferror(q)) {
if(velocity > max_vel) max_vel = velocity,index1=counter;
if(velocity < min_vel) min_vel = velocity,index2=counter;
counter += 1;
}
printf("The maximum velocity is: %e with index: %lu\n", max_vel,index1);
printf("The minimum velocity is: %e with index: %lu\n", min_vel,index2);
density = 0.;
for (k=0;k<n_grid;k++){
fseek(p,(start+k*dim*dim)*sizeof(float),SEEK_SET);
for (j=0;j<n_grid;j++){
fseek(p,(start+j*dim+k*dim*dim)*sizeof(float),SEEK_SET);
for (i=0;i<n_grid;i++){
fread(&density,sizeof(float),1,p);
mass_g += density*vol_pix;
}
}
}
printf("The mass of the observed cube is: %e \n", mass_g);
}

FFTW on real data sequence

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 !

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;
}

Issue with fscanf reading 2-d array of doubles from text file

I'm having some trouble with using fscanf in C. I've written a random matrix to a file and am now trying to read the data in the text file into another matrix. It seems to read the number of rows and columns fine, but it returns zeros for the data values. I'm completely stuck, so any help would be appreciated!
My MATRIX stucture is declared as
typedef struct matrep {
unsigned rows, columns;
double *data;
}MATRIX;
My file looks like this:
rows = 5, columns = 10
-99.75 12.72 -61.34 61.75 17.00 -4.03 -29.94 79.19 64.57 49.32
-65.18 71.79 42.10 2.71 -39.20 -97.00 -81.72 -27.11 -70.54 -66.82
97.71 -10.86 -76.18 -99.07 -98.22 -24.42 6.33 14.24 20.35 21.43
-66.75 32.61 -9.84 -29.58 -88.59 21.54 56.66 60.52 3.98 -39.61
75.19 45.34 91.18 85.14 7.87 -71.53 -7.58 -52.93 72.45 -58.08
And this is my matrix_read function:
MATRIX matrix_read(char file_name[15])
{
int i,j, m, n;
MATRIX B;
FILE *filep;
double *ptr = NULL;
double x;
if((filep = fopen("matrixA.txt", "r"))==NULL)
{
printf("\nFailed to open File.\n");
}
if(fscanf(filep, "\n\nrows = %u, columns = %u\n\n", &m, &n) != 2)
{
printf( "Failed to read dimensions\n");
B.data = 0;
B.columns = 0;
B.rows = 0;
}
B.data = (double *)malloc(B.columns*B.rows*sizeof(double));
if(B.data ==0)
{
printf("Failed to allocate memory");
}
fscanf(filep,"\n\nrows = %u, columns = %u\n\n",&m,&n);
rewind(filep);
ptr = B.data;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (fscanf(filep, " %5.2lf", &x) != 1)
{
printf("Failed to read element [ %d,%d ]\n", i, j);
B.data = 0;
B.columns = 0;
B.rows = 0;
}
printf("%5.2lf\t", x);
*ptr++ = x;
}
}
B.rows=m;
B.columns=n;
return B;
fclose(filep);
free(ptr);
}
Thanks!
You have several problems, one of them is pointed by #simonc, another possible one:
you rewind after reading columns and rows in filep
rewind() sets the position indicator associated with stream to the beginning of the file, you are reading again rows = 5, columns = 10
Finally:
B.data = (double *)malloc(B.columns*B.rows*sizeof(double)); /* Don't cast malloc */
if(B.data ==0)
{
printf("Failed to allocate memory");
/* You have to return or exit here */
}
As Alter Mann denoted, drop the second
fscanf(filep,"\n\nrows = %u, columns = %u\n\n",&m,&n);
as well as the
rewind(filep);
moreover, " %5.2lf" is not a valid scanf conversion specification (you could read the manual about this) - use "%lf" instead.

Resources