web-dev-qa-db-fra.com

Implémentation de filtres simples passe-haut et passe-bas en C

Essayez d’utiliser portaudio pour enregistrer des données, puis utilisez un filtre algorithmique pour changer la voix enregistrée, puis lisez-la. J'en ai vérifié beaucoup (venant de l'exemple), mais je suis assez nouveau en C et je pense que dans la mise en œuvre de mon filtre, j'ai fait une bêtise. 

#if LOW_PASS 
{
    float RC = 1.0/(CUTOFF*2*3.14);
    float dt = 1.0/SAMPLE_RATE;
    float alpha = dt/(RC+dt);
    float filteredArray[numSamples];
    filteredArray[0] = data.recordedSamples[0];
    for(i=1; i<numSamples; i++){
        filteredArray[i] = filteredArray[i-1] + (alpha*(data.recordedSamples[i] - filteredArray[i-1]));
    }
    data.recordedSamples = filteredArray;
}
#endif
#if HIGH_PASS
{
    float RC = 1.0/(CUTOFF*2*3.14);
    float dt = 1.0/SAMPLE_RATE;
    float alpha = RC/(RC + dt);
    float filteredArray[numSamples];
    filteredArray[0] = data.recordedSamples[0];
    for (i = 1; i<numSamples; i++){
        filteredArray[i] = alpha * (filteredArray[i-1] + data.recordedSamples[i] - data.recordedSamples[i-1]);
    }
    data.recordedSamples = filteredArray;
}
#endif

Lorsque le signal enregistré essaie de passer par ces filtres, l'erreur suivante apparaît: 

*** glibc detected *** ./paex_record: free(): invalid pointer: 0xbfd68600 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xb75e2ee2]
./paex_record[0x8048fe5]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75864d3]
./paex_record[0x80487f1]
======= Memory map: ========
08048000-0804a000 r-xp 00000000 08:05 2363767    /home/svictoroff/Documents/CompArch/portaudio/examples/paex_record
...
bfd68000-bff1a000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)

Je ne sais vraiment pas ce qui se passe ici. Des pensées? Free est appelé à partir de la fin du script à la fin ici: 

Pa_Terminate();
    if( data.recordedSamples )       /* Sure it is NULL or valid. */
        free( data.recordedSamples );
    if( err != paNoError )
    {
        fprintf( stderr, "An error occured while using the portaudio stream\n" );
        fprintf( stderr, "Error number: %d\n", err );
        fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
        err = 1;          /* Always return 0 or 1, but no other return codes. */
    }
    return err;
7
Slater Victoroff

Le problème est que data.recordedSamples pointe maintenant (à l’époque de free()) vers une structure allouée sur la pile, pas sur le tas!

Depuis que tu as eu cette instruction:

data.recordedSamples = filteredArray;

Le

if( data.recordedSamples )

n'est d'aucune utilité, puisque l'adresse id est valide, mais incohérente: elle n'est jamais allouée avec malloc() et ce n'est pas sur le tas, mais sur la pile!

Au moment où vous appelez free(), cette adresse pourrait bien pointer vers la pile d’une autre fonction.

Copiez vos données filtrées sur la recordedSamples originale si vous le souhaitez, mais ne réattribuez pas ce pointeur.

modifier:

utilisez ceci:

for(i = 0; i<numSamples; i++) {
    data.recordedSamples[i] = filteredArray[i];
}
2
user1284631

On dirait que vous essayez de libérer une variable de pile. La seule fois où vous devez appeler free, c’est lorsque vous avez déjà appelé malloc (ou l’un de ses amis comme calloc) ou lorsque la documentation d’une fonction de bibliothèque que vous appelez indique que vous devez libérer un pointeur qu’elle renvoie.

Incidemment, chaque fois que vous libérez un pointeur, une bonne pratique consiste à le définir sur NULL immédiatement après.

Les variables de pile disparaissent dès qu'elles sont hors de portée. Ceci pourrait vous aider à mieux comprendre.

0
nmichaels