我在android项目中使用android ndk和LibXTract来提取音频特性。libxtract使用库。项目由运行简单示例表单libxtract的按钮组成:
JNIEXPORT void JNICALL Java_com_androidnative1_NativeClass_showText(JNIEnv *env, jclass clazz)
{
float mean = 0, vector[] = {.1, .2, .3, .4, -.5, -.4, -.3, -.2, -.1}, spectrum[10];
int n, N = 9;
float argf[4];
argf[0] = 8000.f;
argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
argf[2] = 0.f;
argf[3] = 0.f;
xtract[XTRACT_MEAN]((void *)&vector, N, 0, (void *)&mean);
__android_log_print(ANDROID_LOG_DEBUG, "AndNat", "com_androidnative1_NativeClass.c before");
xtract_init_fft(N, XTRACT_SPECTRUM);
__android_log_print(ANDROID_LOG_DEBUG, "AndNat", "com_androidnative1_NativeClass.c after");
// Comment for test purpose
//xtract_init_bark(1, argf[1], 1);
//xtract[XTRACT_SPECTRUM]((void *)&vector, N, &argf[0], (void *)&spectrum[0]);
}
libxtract function xtract_init_fft locate in jni/libxtract/jni/src/init.c执行fftw3 function fftwf_plan_r2r_1d,位于jni/fftw3/jni/api/plan-r2r-1d.c
__android_log_print(ANDROID_LOG_DEBUG, "AndNat", "libxtract/src/init.c before");
fft_plans.spectrum_plan = fftwf_plan_r2r_1d(N, input, output, FFTW_R2HC, optimisation);
__android_log_print(ANDROID_LOG_DEBUG, "AndNat", "libxtract/src/init.c after");
应用程序挂在fftwf_paln_r2r_1d内,没有崩溃或任何外部错误,我必须强制它停止工作。
fftwf_paln_r2r_1d看起来像:
X(plan) X(plan_r2r_1d)(int n, R *in, R *out, X(r2r_kind) kind, unsigned flags)
{
__android_log_print(ANDROID_LOG_DEBUG, "AndNat", "fftw3/api/plan-r2r-1d.c");
return X(plan_r2r)(1, &n, in, out, &kind, flags);
}
从catlog我可以看到:
07-16 18:50:09.615: D/AndNat(7313): com_androidnative1_NativeClass.c before
07-16 18:50:09.615: D/AndNat(7313): libxtract/src/init.c before
07-16 18:50:09.615: D/AndNat(7313): fftw3/api/plan-r2r-1d.c
使用gen.sh脚本为fftw3和libxtract生成config.h成功地定位到源文件夹中。两个librier都是静态的,并与共享libary libcom_androidnative1_nativeclass.so链接
命令
nm -Ca libcom_androidnative1_NativeClass.so
显示包含已使用的函数。
应用程序构建并部署到设备上没有任何问题。
我使用标志--disable alloca,-enable float和libxtract构建fftw3,使用标志--enable fft和--disable dependency tracking
只有库源代码中的引用被添加dbgprint并从libxtract中删除define xtract_fft,因为它无法检测fftw库。
如果有人知道我这种奇怪的行为,请帮忙。
在这里,我把整个项目放在github中,也许有人可以帮我处理这个问题。
fftw3
最佳答案
感谢fftw3维修人员的帮助。
解决方案是在fftw3中将优化级别从fftw_度量更改为fftw_估计(从1更改为0)。
fftw的规划器(在xtract_init_fft中)实际执行不同的fft算法并对其进行计时,以便为给定的n选择最快的计划。然而,为了尽可能短的时间内完成这项工作,计时器必须具有非常高的分辨率,为了实现这一点,fftw3采用了硬件周期计数器,这些计数器在大多数cpu上都可用,但在android默认arm配置上没有。
因此,该算法使用的gettimeofday()具有较低的分辨率,并且在arm上永远花费在xtract初始化fft上。