【问题标题】:KissFFT forward / inverse is outputting noise, why?KissFFT正向/反向输出噪声,为什么?
【发布时间】:2012-06-13 00:43:08
【问题描述】:

我正在尝试在 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);

}

【问题讨论】:

    标签: c fft kissfft


    【解决方案1】:

    请参阅my answer 以了解类似问题。

    或来自 Kissfft README 文件:

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

    【讨论】:

    • 谢谢马克,解决了这个问题,但你的缩放技巧也很有帮助!
    【解决方案2】:

    哎呀!发现了问题。我应该一直对短数组进行逆变换:

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

    【讨论】:

      【解决方案3】:

      根据受保护成员的要求,这是一个更完整的示例(无论如何,在本机方面)。我最终稍微修改了 libgdx 代码(使用 v.0.9.4)。我还使用浮点而不是固定进行编译,因为后者在反演时会引入量化噪声。此代码应该适用于任何一种(因为kiss_fft_scalar 适应于short 或float 取决于编译器标志),但没有用fixed 重新测试,因为我发现它对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);
      
      }
      

      【讨论】:

      • 这真的很有帮助,但为什么要写这行:samples[i] = samples[i] / (float)fft-&gt;numSamples;?
      猜你喜欢
      • 2017-11-26
      • 2017-03-28
      • 2015-10-24
      • 1970-01-01
      • 1970-01-01
      • 2018-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多