0

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

}
4

3 に答える 3

2

protectedmember の要求ごとに、より完全な例を次に示します (とにかくネイティブ側で)。最終的に、libgdx コードを少し変更しました (v.0.9.4 を使用)。また、固定ではなく浮動小数点を使用してコンパイルしました。これは、後者が反転時に量子化ノイズを導入したためです。このコードはどちらでも機能するはずですが (kiss_fft_scalar はコンパイラ フラグに応じて short または float に適応するため)、fft->ifft シリーズでは役に立たないことがわかったため、fixed で再テストしていません。

あなたが成功したかどうか知りたいです、私に知らせてください!

(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);

}
于 2012-06-29T15:32:32.657 に答える
1

同様の質問 に対する私の答えを参照してください。

またはkissfftREADMEファイルから:

        Q:期待した出力が得られないのはなぜですか?
        A:これの2つの最も一般的な原因は次のとおりです
                1)スケーリング:得たものと欲しいものの間に一定の乗数がありますか?
                2)混合ビルド環境-すべてのコードは同じプリプロセッサでコンパイルする必要があります
                FIXED_POINTとkiss_fft_scalarの定義

于 2012-06-10T20:05:03.730 に答える
1

おっと!問題が見つかりました。逆変換を短い配列に正しく行う必要がありました。

kiss_fftri( fft->inverseConfig, fft->spectrum, shortSamples );
于 2012-06-10T22:24:17.473 に答える