我正尝试在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);
}发布于 2012-06-29 23:32:33
对于每个受保护成员的请求,这里是一个更完整的示例(无论如何,在本机端)。我最终稍微修改了libgdx代码(使用v.0.9.4)。我还使用浮点数而不是固定数进行编译,因为后者在反转时会引入量化噪声。这段代码应该适用于任何一种(因为kiss_fft_scalar根据编译器标志适应短整型或浮点型),但没有使用fixed重新测试,因为我发现它对fft->ifft系列没有用处。
我很好奇,如果你成功了,一定要让我知道!
(请注意,在libgdx之后,此代码受Apache2.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-11 06:24:17
哇哦!找到了问题所在。我应该直接对短数组进行逆变换:
kiss_fftri( fft->inverseConfig, fft->spectrum, shortSamples );https://stackoverflow.com/questions/10957604
复制相似问题