Mutante Mutante - 3 months ago 22
C Question

Movin Average conveting matlab script to C program

I am trying to do a Moving Average code in C, I've already done this in matlab and works. I've converted the matlab script manually to C language, but I am having some problems.

#include <stdio.h>
#include <stdlib.h>

int main()
{
int m = 16; // MEDIA LENGTH
double x[]=0; // X VECTOR = 0
double coef[]=0; // COEF VECTOR = 0
double i; // FOR COUNT VARIABLE
double n; // FOR COUNT VARIABLE
double itera; // LENGTH OF THE INPUT FILE
double aux; // AUX VARIABLE TO MAKE THE SUM
double y[]=0; // AUX VECTOR TO RECEIVE X VECTOR
double saida[]=0; // OUTPUT VECTOR
FILE *arq; // POINTER TO THE FILE

for (i = 0; i < m; i++) {
coef[i] = 1/m;
}
arq = fopen("sweep_100_3400.pcm", "rb");
if (arq == NULL)
{
printf("ERROR WHILE OPENING THE FILE\n");
return;
}
fread(*x,sizeof(double),m,arq);
fclose(arq);
itera = size_t(x);
for (i=0; i < itera; i++) {
y[0] = x[i];
aux=0;
for (n=0; n<m; n++){
aux= aux + coef[n] * y[n];
}
saida[i]=aux;
for (n=m; n <2; n--){
x[n] = x[n-1];
}
}
arq=fopen("saida_medial_movel_c.pcm","wb");
fwrite(*saida, sizeof(double),itera,arq);
fclose(arq);
}


My compiler is showing error in the declaration of variables:


error: invalid initializer


and error when I am trying to use fread and fopen:


error: incompatible type for argument 1 of 'fread'


Someone knows what is it?

Below the script in matlab:

%MOVING AVERAGE EXAMPLE SCRIPT
clear all;
close all;
clc;
% DEFINES MEDIA LENGTH
m = 16;
%VECTOS EQUAL ZERO
x = zeros (m,1);
coef = zeros (m,1);
%INITIALIZE VECTOR
for j = 1 : m,
coef (j,1) = 1/m;
end
%READ INPUT FILE
fid = fopen ('sweep_100_3400.pcm','rb');
s = fread (fid, 'int16');
fclose(fid);
subplot(2,1,1);
plot(s);
grid on;
title('ENTRADA DO FILTRO');
%PROCESS
itera = length(s);
sav_y = zeros (itera, 1);
%EXECUTE PROCESS
for j = 1 : itera,
x(1,1) = s (j,1);
%PRODUCTS SUM
y=0;
for n = 1 : m,
y = y + coef(n,1) * x(n,1);
end
sav_y(j,1) = y;
%SHIFT THE VECTOR
for n = m: -1 : 2,
x (n,1) = x(n-1,1);
end
end
%PLOT OUTPUT
subplot (2,1,2);
plot (sav_y);
grid on;
title('SAÍDA DO FLITRO');
%SAVE THE OUTPUT IN ANOTHER FILE
fid = fopen('saida_mm_manual.pcm','wb');
fwrite(fid,sav_y,'int16');
fclose(fid);





Update: Using the answer below with the absolute path to read and write de file.

The path is:
arq = fopen("D:\Estudo\Univali\8º semestre\DSP\MediMovelC\MediaMovel\sweep_100_3400.pcm", "rb");


CodeBlocks give me the following error:

warning: unknown escape sequence: '\D'
warning: unknown escape sequence: '\s'


An image of the path:

enter image description here

Answer

I have fixed your source so it compiles.

It took me a few minutes to fix it, was a good effort from you. Main errors when you convert matlab to C:

  • arrays work differently. You cannot resize an array/define it empty and then append (well, you can, but that needs realloc, it's better when you know the size already)
  • you must use integers for loop indexes
  • you lost usage of pointers :)
  • 1/m is zero if m is an integer > 1. To get a double just put 1.0/m

Here are the diffs, commented:

5a6
> #define m 16  // MEDIA LENGTH (had to put a macro to be able to define an array
9,14c10,14
<     int m = 16;                                // MEDIA LENGTH
<     double x[]=0;                              // X VECTOR = 0
<     double coef[]=0;                           // COEF VECTOR = 0
<     double i;                                  // FOR COUNT VARIABLE
<     double n;                                  // FOR COUNT VARIABLE
<     double itera;                              // LENGTH OF THE INPUT FILE
---
>     double *x;                              // X VECTOR = 0   cannot define a resizeable array like in matlab
>     double coef[m];                           // COEF VECTOR = 0
>     int i;                                  // FOR COUNT VARIABLE   indices must be integers
>     int n;                                  // FOR COUNT VARIABLE
>     int itera;                              // LENGTH OF THE INPUT FILE
16,17c16,17
<     double y[]=0;                              // AUX VECTOR TO RECEIVE X VECTOR
<     double saida[]=0;                          // OUTPUT VECTOR
---
>     double *y;                              // AUX VECTOR TO RECEIVE X VECTOR
>     double *saida;                          // OUTPUT VECTOR
21c21
<         coef[i] = 1/m;
---
>         coef[i] = 1.0/m;
29c29
<     fread(*x,sizeof(double),m,arq);
---
>     fread(x,sizeof(double),m,arq);   // use x memory to read size (dirty but OK)
31c31,36
<     itera = size_t(x);
---
>     itera = (size_t)x;   // cast syntax
>   // alloc mem
>   x = malloc(itera*sizeof(double));  // allocate arrays
>   y = malloc(itera*sizeof(double));
>   saida = malloc(itera*sizeof(double));
>   
36c41
<             aux= aux + coef[n] * y[n];
---
>             aux += coef[n] * y[n];   // more C-like
44c49
<     fwrite(*saida, sizeof(double),itera,arq);
---
>     fwrite(saida, sizeof(double),itera,arq);  // already a pointer
45a51,53
>   free(saida);   // free memory
>   free(y);
>   free(x);

And here's the fixed code. Note that I'm not sure it works, but it compiles. Use a debugger if something is not OK

#include <stdio.h>
#include <stdlib.h>



#define m 16  // MEDIA LENGTH

int main()
{
    double *x;                              // X VECTOR = 0
    double coef[m];                           // COEF VECTOR = 0
    int i;                                  // FOR COUNT VARIABLE
    int n;                                  // FOR COUNT VARIABLE
    int itera;                              // LENGTH OF THE INPUT FILE
    double aux;                                // AUX VARIABLE TO MAKE THE SUM
    double *y;                              // AUX VECTOR TO RECEIVE X VECTOR
    double *saida;                          // OUTPUT VECTOR
    FILE *arq;                                 // POINTER TO THE FILE

    for (i = 0; i < m; i++) {
        coef[i] = 1.0/m;
    }
    arq = fopen("sweep_100_3400.pcm", "rb");
    if (arq == NULL)
    {
        printf("ERROR WHILE OPENING THE FILE\n");
        return;
    }
    fread(x,sizeof(double),m,arq);
    fclose(arq);
    itera = (size_t)x;
    // alloc mem
    x = malloc(itera*sizeof(double));
    y = malloc(itera*sizeof(double));
    saida = malloc(itera*sizeof(double));

    for (i=0; i < itera; i++) {
        y[0] = x[i];
        aux=0;
        for (n=0; n<m; n++){
            aux += coef[n] * y[n];
        }
        saida[i]=aux;
        for (n=m; n <2; n--){
            x[n] = x[n-1];
        }
    }
    arq=fopen("saida_medial_movel_c.pcm","wb");
    fwrite(saida, sizeof(double),itera,arq);
    fclose(arq);
    free(saida);
    free(y);
    free(x);
}

My advice would be to rather use C++, because thanks to std::vector and std::string you can port stuff much quicker, with less risks of crashes, memory leaks, undefined behaviour. Well, maybe next time...

Comments