FFTW комплекс к реальной ошибке сегментации - PullRequest
0 голосов
/ 24 марта 2020

Я пытаюсь написать наивную реализацию Кратковременного преобразования Фурье, используя последовательные кадры FFT во времени, рассчитанном с использованием библиотеки FFTW, но я получаю Segmentation fault и не могу понять, почему.

Мой код такой, как показано ниже:

// load in audio
AudioFile<double> audioFile;    
audioFile.load ("assets/example-audio/file_example_WAV_1MG.wav");
int N = audioFile.getNumSamplesPerChannel();

// make stereo audio mono
double fileDataMono[N];
if (audioFile.isStereo())
    for (int i = 0; i < N; i++)
        fileDataMono[i] = ( audioFile.samples[0][i] + audioFile.samples[1][i] ) / 2;

// setup stft
//              (test transform, presently unoptimized)
int stepSize = 512;
int M = 2048;       // fft size
int noOfFrames = (N-(M-stepSize))/stepSize;

// create Hamming window vector

double w[M];
for (int m = 0; m < M; m++) {
    w[m] = 0.53836 - 0.46164 * cos( 2*M_PI*m / M );
}

double* input;

// (pads input array if necessary)
if ( (N-(M-stepSize))%stepSize != 0) {
    noOfFrames += 1;
    int amountOfZeroPadding = stepSize - (N-(M-stepSize))%stepSize;
    double ipt[N + amountOfZeroPadding];

    for (int i = 0; i < N; i++)         // copy values from fileDataMono into input
        ipt[i] = fileDataMono[i];
    for (int i = 0; i < amountOfZeroPadding; i++)
        ipt[N + i] = 0;
    input = ipt;
} else {
    input = fileDataMono;
}

// compute stft

fftw_complex* stft[noOfFrames];
double frames[noOfFrames][M];

fftw_plan fftPlan;

for (int i = 0; i < noOfFrames; i++) {
    stft[i] = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * M);
    for (int m = 0; m < M; m++)
        frames[i][m] = input[i*stepSize + m] * w[m];
    fftPlan = fftw_plan_dft_r2c_1d(M, frames[i], stft[i], FFTW_ESTIMATE);
    fftw_execute(fftPlan);
}

// compute istft

double* outputFrames[noOfFrames];
double output[N];

for (int i = 0; i < noOfFrames; i++) {
    outputFrames[i] = (double*)fftw_malloc(sizeof(double) * M);
    fftPlan = fftw_plan_dft_c2r_1d(M, stft[i], outputFrames[i], FFTW_ESTIMATE);
    fftw_execute(fftPlan);
    for (int m = 0; i < M; m++) {
        output[i*stepSize + m] += outputFrames[i][m];
    }
}

fftw_destroy_plan(fftPlan);
for (int i = 0; i < noOfFrames; i++) {
    fftw_free(stft[i]);
    fftw_free(outputFrames[i]);
}

// output audio
AudioFile<double>::AudioBuffer outputBuffer;
outputBuffer.resize (1);
outputBuffer[0].resize(N);
outputBuffer[0].assign(output, output+N);
bool ok = audioFile.setAudioBuffer(outputBuffer);

audioFile.setAudioBufferSize (1, N);
audioFile.setBitDepth (16);
audioFile.setSampleRate (8000);
audioFile.save ("out/audioOutput.wav");

Похоже, что ошибка Segfault возникает при первом fftw_malloc при вычислении прямого STFT.

Заранее спасибо!

1 Ответ

0 голосов
/ 25 марта 2020

Соответствующий бит кода:

double* input;
if ( (N-(M-stepSize))%stepSize != 0) {
    double ipt[N + amountOfZeroPadding];
    //...
    input = ipt;
}
//...
input[i*stepSize + m];

Ваш указатель input указывает на память, которая существует только внутри оператора if. Закрывающая скобка обозначает конец времени жизни массива ipt. При последующем разыменовании указателя вы обращаетесь к памяти, которой больше не существует.

...