web-dev-qa-db-ja.com

Cでの単純なハイパスフィルターとローパスフィルターの実装

Portaudioを使用してデータを録音し、アルゴリズムフィルターを使用して録音した音声を変更してから再生しようとしています。私はそれをたくさん検証しましたが(例から)、私はCにまったく慣れていないので、フィルターの実装では何かばかげたことをしたと思います。

#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

記録された信号がこれらのフィルターを通過しようとすると、次のエラーが発生します。

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

ここで何が起こっているのかよくわかりません。何かご意見は? Freeは、ここで終了するスクリプトの最後から呼び出されます。

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

問題は、data.recordedSamplesが(free()の時点で)ヒープではなくスタックに割り当てられた構造を指していることです。

この指示があったので:

_data.recordedSamples = filteredArray;
_

ザ・

_if( data.recordedSamples )
_

アドレスIDは有効ですが、一貫性がないため、役に立ちません。malloc()で割り当てられることはなく、ヒープではなくスタックにあります。

free()を呼び出している時点で、そのアドレスは別の関数のスタックを指している可能性があります。

必要に応じて、フィルタリングしたデータを元のrecordedSamplesにコピーして戻します。そのポインタは、再割り当てしないでください。

編集:

これを使って:

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

スタック変数を解放しようとしているようです。 freeを呼び出す必要があるのは、以前にmalloc(またはcallocのようなその友人の1つ)を呼び出したとき、またはライブラリ関数のドキュメントを呼び出したときだけです。再呼び出しすると、返されるポインタを解放する必要があると言われます。

ちなみに、ポインタを解放するときはいつでも、直後にNULLに設定することをお勧めします。

スタック変数は、スコープ外になるとすぐに消えます。 This 理解を深めるのに役立つかもしれません。

0
nmichaels