簡體   English   中英

KissFFT正向/反向輸出噪聲,為什么?

[英]KissFFT forward / inverse is outputting noise, why?

我正在嘗試在Java應用程序中本機使用KissFFT,但是輸入信號的正向/反向沒有返回應有的狀態:信號振幅幾乎不存在。 如果刪除比例因子(除以2N),則結果是諧波噪聲。 任何人都可以發現該錯誤嗎?

這是前向呼叫(從GDX復制,所以應該可以!):

JNIEXPORT void JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_spectrum(JNIEnv* env, jclass clazz, jlong handle, jshortArray obj_samples, jfloatArray obj_spectrum) {
    short* samples = (short*)env->GetPrimitiveArrayCritical(obj_samples, 0);
    float* spectrum = (float*)env->GetPrimitiveArrayCritical(obj_spectrum, 0);

        KissFFT* fft = (KissFFT*)handle;
        kiss_fftr( fft->forwardConfig, (kiss_fft_scalar*)samples, fft->spectrum );

        int len = fft->numSamples / 2 + 1;
        for( int i = 0; i < len; i++ )
        {
            float re = scale(fft->spectrum[i].r) * fft->numSamples;
            float im = scale(fft->spectrum[i].i) * fft->numSamples;

            if( i > 0 )
                spectrum[i] = sqrtf(re*re + im*im);
            else
                spectrum[i] = sqrtf(re*re + im*im);
        }

    env->ReleasePrimitiveArrayCritical(obj_samples, samples, 0);
    env->ReleasePrimitiveArrayCritical(obj_spectrum, spectrum, 0);

}

這是反函數(我寫的,可能有一個錯誤;)):

JNIEXPORT void JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_inverse(JNIEnv* env, jclass clazz, jlong handle, jshortArray obj_samples) {
    short* shortSamples = (short*)env->GetPrimitiveArrayCritical(obj_samples, 0);

//@line:108

        KissFFT* fft = (KissFFT*)handle;
        kiss_fft_cpx out[fft->numSamples];

        kiss_fftri( fft->inverseConfig, fft->spectrum, (kiss_fft_scalar*)out );

        for (int i=0; i < fft->numSamples; i++) {
            shortSamples[i] = (out[i].r) / (fft->numSamples*2);
        }

    env->ReleasePrimitiveArrayCritical(obj_samples, shortSamples, 0);

}

根據受保護成員的請求,這是一個更完整的示例(無論如何在本機端)。 我最終稍微修改了libgdx代碼(使用v.0.9.4)。 我還使用浮點而不是固定值進行編譯,因為后者在反轉時會引入量化噪聲。 這段代碼應該都適用(因為kiss_fft_scalar取決於編譯器標志適應short還是float),但是還沒有進行過固定測試,因為我發現它對fft-> ifft系列沒有用。

我很好奇您是否成功,請告訴我!

(請注意,libgdx之后的此代碼受Apache 2.0許可!)

#include <com.badlogic.gdx.audio.analysis.KissFFT.h>

#include <kissfft/kiss_fftr.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

struct KissFFT
{
    kiss_fftr_cfg forwardConfig;
    kiss_fftr_cfg inverseConfig;
    kiss_fft_cpx* spectrum;
    int numSamples;
    int spectrumSize;
};

JNIEXPORT jlong JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_create(JNIEnv* env, jclass clazz, jint numSamples) {

    KissFFT* fft = new KissFFT();
    fft->forwardConfig = kiss_fftr_alloc(numSamples,0,NULL,NULL);
    fft->inverseConfig = kiss_fftr_alloc(numSamples,1,NULL,NULL);
    fft->spectrum = (kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx) * numSamples);
    fft->numSamples = numSamples;
    fft->spectrumSize = numSamples/2+1;
    return (jlong)fft;
}

JNIEXPORT void JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_destroy(JNIEnv* env, jclass clazz, jlong handle) {

    KissFFT* fft = (KissFFT*)handle;
    free(fft->forwardConfig);
    free(fft->inverseConfig);
    free(fft->spectrum);
    free(fft);  
}

JNIEXPORT void JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_spectrum(JNIEnv* env, jclass clazz, jlong handle, jfloatArray obj_samples, jfloatArray obj_mags) {

    kiss_fft_scalar* samples = (kiss_fft_scalar*)env->GetPrimitiveArrayCritical(obj_samples, 0);
    float* mags = (float*)env->GetPrimitiveArrayCritical(obj_mags, 0);

    KissFFT* fft = (KissFFT*) handle;

    kiss_fftr(fft->forwardConfig, samples, fft->spectrum);

    for(int i=0;i<fft->spectrumSize;i++) {
        mags[i] = hypotf(fft->spectrum[i].r,fft->spectrum[i].i);
    }

    env->ReleasePrimitiveArrayCritical(obj_samples, samples, 0);
    env->ReleasePrimitiveArrayCritical(obj_mags, mags, 0);
}

JNIEXPORT void JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_inverse(JNIEnv* env, jclass clazz, jlong handle, jfloatArray obj_samples) {
    kiss_fft_scalar* samples = (kiss_fft_scalar*)env->GetPrimitiveArrayCritical(obj_samples, 0);

    KissFFT* fft = (KissFFT*)handle;

    kiss_fftri( fft->inverseConfig, fft->spectrum, samples );

    for(int i=0;i<fft->numSamples;i++) {
        samples[i] = samples[i] / (float)fft->numSamples;
    }

    env->ReleasePrimitiveArrayCritical(obj_samples, samples, 0);

}

看到對類似問題的回答。

或從kissfft自述文件中:

Q: Why don't I get the output I expect?
        A: The two most common causes of this are
                1) scaling : is there a constant multiplier between what you got and what you want?
                2) mixed build environment -- all code must be compiled with same preprocessor
                definitions for FIXED_POINT and kiss_fft_scalar

哎呦! 找到了問題。 我應該一直在對短數組進行逆變換:

kiss_fftri( fft->inverseConfig, fft->spectrum, shortSamples );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM