我正在尝试在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 < 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);
}
答案 0 :(得分:2)
根据protectedmember的请求,这是一个更完整的示例(无论如何都是在本机方面)。我最终稍微修改了libgdx代码(使用v.0.9.4)。我也用浮点而不是固定编译,因为后者在反转时引入了量化噪声。这个代码 应该适用于任何一个(因为kiss_fft_scalar适应短路或浮动,具体取决于编译器标志),但没有重新测试固定,因为我发现它对fft-&gt; 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);
}
答案 1 :(得分:1)
请参阅my answer一个类似的问题。
或来自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
答案 2 :(得分:1)
糟糕!发现了问题。我应该一直在做反变换到短数组:
kiss_fftri( fft->inverseConfig, fft->spectrum, shortSamples );