0

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

Mutante
  • 278
  • 5
  • 18

1 Answers1

2

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
  • input file is a list of short integers

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
---
>     short *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

... this zone has heavy edits because it was completely wrong

>   
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()
{
    short *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;
    }
    // compute size of file
    fseek(arq,0,SEEK_END);
    itera = ftell(arq)/sizeof(short);
    rewind(arq);

    // alloc mem for x, read the vector from input file
    x = malloc(itera*sizeof(short));
    fread(x,sizeof(short),itera,arq);
    fclose(arq);
    // alloc mem for y

    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...

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • Thanks again, I've used C because i need to transfer this program to a embed hardware. Thanks! – Mutante Aug 21 '16 at 21:56
  • Jean, why the program is not creating the output file? any idea? – Mutante Aug 21 '16 at 22:51
  • 1
    @Mutante you may want to try to give the absolute path. It is common when compilig a program that the path used is the same as the path where file where your program is compiled (and not your current path). This may not be the problem, but it may, so try this anyway. – patrik Aug 22 '16 at 05:47
  • I gave the absolut path in the program, but codeBlocks is giving me an error. I've updated the question to show de problem. – Mutante Aug 22 '16 at 11:45
  • The problem is in the "\" character, when, the compiler indicates error in every "\" of the path, should I use the ASC II code of this "\" to solve the problem? – Mutante Aug 22 '16 at 14:07
  • I removed the "8º semestre" but stills appearing error In "\", that is strange. – Mutante Aug 22 '16 at 16:31
  • I get it: replace backslashes by slashes or double the backslashes. Like this: `arq = fopen("D:\\Estudo\\Univali\\8_semestre\\DSP\\MediMovelC\\MediaMovel\\sweep_100_3400.pcm", "rb")`. backslash is the C escape character! – Jean-François Fabre Aug 22 '16 at 16:51
  • Now it's partially working! My output file stays blank, but i think the error is in the parameters of fread and fopen, i will post this doubt in another topic! Thanks again! – Mutante Aug 22 '16 at 18:11
  • It's and audio file (format pcm), the input file has 5 seconds of audio, when I execute the program the output file stays with 52 minutes of blank audio. The values of the file are integer numbers. I think the problem is in the fread and fwrite parameters, i've created a post with this doubt [here](http://stackoverflow.com/questions/39086285/fread-and-fwrite-parameters-in-c), but I don't if it's this that makes my output file stays blank. – Mutante Aug 22 '16 at 18:53
  • you shouldn't have asked another question. Anyway, I have fixed the code see my last edit: automatic size computation of inputs (`itera`), changed x from double to short (int16). – Jean-François Fabre Aug 22 '16 at 19:01
  • Now it's working, but my output file has an loud noise in the background of the audio, i will revise my algorithm here, maybe I encoded something wrong in the C, because works in matlab. – Mutante Aug 22 '16 at 19:08
  • or maybe it's unsigned short and not short. Good luck with that. – Jean-François Fabre Aug 22 '16 at 19:12