KissFFT前进/逆输出噪音,为什么呢? [英] KissFFT forward / inverse is outputting noise, why?
问题描述
我想在一个Java应用程序本身使用KissFFT,但输入信号的正向/反向没有返回,因为它应该:信号幅度几乎是不存在的。如果删除了缩放因子(由2N分割),则结果为谐波噪声。任何人都可以发现的bug?
下面是转接呼叫(GDX从复制,所以应该OK了!):
JNIEXPORT无效JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_spectrum(JNIEnv的* ENV,JCLASS clazz所jlong手柄,jshortArray obj_samples,jfloatArray obj_spectrum){
短*样品=(短*)env-> GetPrimitiveArrayCritical(obj_samples,0);
浮动*谱=(浮点*)env-> GetPrimitiveArrayCritical(obj_spectrum,0); KissFFT * FFT =(KissFFT *)处理;
kiss_fftr(fft-> forwardConfig,(kiss_fft_scalar *)样品,fft->谱); INT LEN = fft-> NUMSAMPLES / 2 + 1;
的for(int i = 0; I< LEN,我++)
{
浮重=规模(fft->谱[I] .R)* fft-> NUMSAMPLES;
浮IM =规模(fft->谱[I] .7)* fft-> NUMSAMPLES; 如果(I 0)
谱[I] = sqrtf(重*重新+ IM * IM);
其他
谱[I] = sqrtf(重*重新+ IM * IM);
} env-> ReleasePrimitiveArrayCritical(obj_samples,样品,0);
env-> ReleasePrimitiveArrayCritical(obj_spectrum,频谱,0);}
这是逆(我写的,可能有一个错误;)):
JNIEXPORT无效JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_inverse(JNIEnv的* ENV,JCLASS clazz所jlong手柄,jshortArray obj_samples){
短* shortSamples =(短*)env-> GetPrimitiveArrayCritical(obj_samples,0);// @行:108 KissFFT * FFT =(KissFFT *)处理;
kiss_fft_cpx出[fft-> NUMSAMPLES]。 kiss_fftri(fft-> inverseConfig,fft->谱,(kiss_fft_scalar *)出); 的for(int i = 0; I< fft-> NUMSAMPLES;我++){
shortSamples [I] =(出[I] .R)/(fft-> NUMSAMPLES * 2);
} env-> ReleasePrimitiveArrayCritical(obj_samples,shortSamples,0);}
每protectedmember的要求,这里是一个更完整的例子(在本机端,反正)。我结束了小幅修改libgdx code(使用v.0.9.4)。当反演我也编译了浮点,而不是固定的,因为后者引入的量化噪声。这code的应的对或者(因为kiss_fft_scalar适应短期或浮动取决于编译器的标志),但没有固定重新测试,因为我发现它不是一个fft-有益的工作> IFFT系列。
我很想知道,如果你成功了,你让我知道!
(请注意,这code,以下libgdx,是根据Apache 2.0许可!)
的#include< com.badlogic.gdx.audio.analysis.KissFFT.h>#包括LT&; kissfft / kiss_fftr.h>
#包括LT&;&stdlib.h中GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&math.h中GT;结构KissFFT
{
kiss_fftr_cfg forwardConfig;
kiss_fftr_cfg inverseConfig;
kiss_fft_cpx *谱;
INT NUMSAMPLES;
INT spectrumSize;
};JNIEXPORT jlong JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_create(JNIEnv的* ENV,JCLASS clazz所jint NUMSAMPLES){ KissFFT * FFT =新KissFFT();
fft-> forwardConfig = kiss_fftr_alloc(NUMSAMPLES,0,NULL,NULL);
fft-> inverseConfig = kiss_fftr_alloc(NUMSAMPLES,1,NULL,NULL);
fft->谱=(kiss_fft_cpx *)malloc的(的sizeof(kiss_fft_cpx)* NUMSAMPLES);
fft-> NUMSAMPLES = NUMSAMPLES;
fft-> spectrumSize = NUMSAMPLES / 2 + 1;
回报(jlong)FFT;
}JNIEXPORT无效JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_destroy(JNIEnv的* ENV,JCLASS clazz所jlong手柄){ KissFFT * FFT =(KissFFT *)处理;
免费(fft-> forwardConfig);
免费(fft-> inverseConfig);
免费(fft->谱);
免费(FFT);
}JNIEXPORT无效JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_spectrum(JNIEnv的* ENV,JCLASS clazz所jlong手柄,jfloatArray obj_samples,jfloatArray obj_mags){ kiss_fft_scalar *样品=(kiss_fft_scalar *)env-> GetPrimitiveArrayCritical(obj_samples,0);
浮动*弹匣=(浮点*)env-> GetPrimitiveArrayCritical(obj_mags,0); KissFFT * FFT =(KissFFT *)处理; kiss_fftr(fft-> forwardConfig,样品,fft->谱); 的for(int i = 0; I< fft-> spectrumSize;我++){
弹匣[I] = hypotf(fft->谱[I] .R,fft->谱[I] .7);
} env-> ReleasePrimitiveArrayCritical(obj_samples,样品,0);
env-> ReleasePrimitiveArrayCritical(obj_mags,弹匣,0);
}JNIEXPORT无效JNICALL Java_com_badlogic_gdx_audio_analysis_KissFFT_inverse(JNIEnv的* ENV,JCLASS clazz所jlong手柄,jfloatArray obj_samples){
kiss_fft_scalar *样品=(kiss_fft_scalar *)env-> GetPrimitiveArrayCritical(obj_samples,0); KissFFT * FFT =(KissFFT *)处理; kiss_fftri(fft-> inverseConfig,fft->光谱样本); 的for(int i = 0; I< fft-> NUMSAMPLES;我++){
样本[I] =样本[I] /(浮点)fft-> NUMSAMPLES;
} env-> ReleasePrimitiveArrayCritical(obj_samples,样品,0);}
I'm trying to use KissFFT natively in a java app, but the forward/inverse of an input signal isn't returning as it should: the signal amplitude is almost non-existent. If I remove the scaling factor (dividing by 2N), the result is harmonic noise. Can anyone spot the bug?
Here is the forward call (copied from GDX, so should be ok!):
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);
}
And here is the inverse (written by me, probably has an error ;) ):
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);
}
Per protectedmember's request, here is a more complete example (on the native side, anyway). I ended up modifying the libgdx code slightly (using v.0.9.4). I also compiled with floating-point rather than fixed, as the latter introduced quantization noise when inversing. This code should work for either (because kiss_fft_scalar adapts to short or float depending on the compiler flag), but have not re-tested with fixed, since I found it's not useful for a fft->ifft series.
I am curious to know if you are successful, do let me know!
(Please note that this code, following libgdx, is under Apache 2.0 license!)
#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前进/逆输出噪音,为什么呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!