KissFFT正向/反向输出噪声,为什么?

我试图在java应用程序中原生使用KissFFT,但输入信号的正向/反向不会按原样返回:信号幅度几乎不存在。 如果我删除比例因子(除以2N),结果就是谐波噪声。 谁能发现这个bug?

这是前转呼叫(从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 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 numSamples; i++) { shortSamples[i] = (out[i].r) / (fft->numSamples*2); } env->ReleasePrimitiveArrayCritical(obj_samples, shortSamples, 0); } 

根据protectedmember的请求,这是一个更完整的示例(无论如何,在本机方面)。 我最终稍微修改了libgdx代码(使用v.0.9.4)。 我也用浮点而不是固定编译,因为后者在反转时引入了量化噪声。 这段代码应该适用于(因为kiss_fft_scalar适应短路或浮动,具体取决于编译器标志),但没有重新测试固定,因为我发现它对fft-> ifft系列没用。

我很想知道你是否成功,请告诉我!

(请注意,此代码,在libgdx之后,是在Apache 2.0许可下!)

 #include  #include  #include  #include  #include  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;ispectrumSize;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;inumSamples;i++) { samples[i] = samples[i] / (float)fft->numSamples; } env->ReleasePrimitiveArrayCritical(obj_samples, samples, 0); } 

看到我对类似问题的回答。

或者来自kissfft README文件:

        问:为什么我没有得到我期望的输出?
        答:这两个最常见的原因是
                 1)缩放:你得到的和你想要的之间是否有一个恒定的乘数?
                 2)混合构建环境 - 所有代码必须使用相同的预处理器进行编译
                 FIXED_POINT和kiss_fft_scalar的定义

哎呦! 发现了问题。 我应该一直在做逆变换到短数组:

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