Android下Speex庫除0錯誤(SIGFPE)排除

在項目中使用Speex對實時採集到的音頻流進行去噪,發現運行一段時間後程序就會崩潰。


首先需要得到程序崩潰時的調用堆棧,在終端輸入命令:

adb logcat | ndk-stack -sym ./xxxGame/proj.android/obj/local/armeabi


然後再讓程序跑起來等着,出錯後得到如下信息:

********** Crash dump: **********
Build fingerprint: 'Lenovo/smarttp/S898tp:4.4.2/KOT49H/VIBEUI_V2.0_1447_7.5.1_ST_S898t+.:user/release-keys'
pid: 12612, tid: 12700, name: Thread-8281  >>> org.cocos2dx.hellocpp <<<
signal 8 (SIGFPE), code -6 (SI_TKILL), fault addr 00003144
Stack frame #00  pc 00028e7c  /system/lib/libc.so (tgkill+12)
Stack frame #01  pc 00017889  /system/lib/libc.so (pthread_kill+88)
Stack frame #02  pc 00017aa3  /system/lib/libc.so (raise+10)
Stack frame #03  pc 000197d0  /data/app-lib/org.cocos2dx.hellocpp-2/libspeex.so (__aeabi_ldiv0+8): Routine __aeabi_idiv0 at /s/ndk-toolchain/src/build/../gcc/gcc-4.8/libgcc/config/arm/lib1funcs.S:1335
Stack frame #04  pc 0000fe2f  /data/app-lib/org.cocos2dx.hellocpp-2/libspeex.so: Routine DIV32_16_Q15 at /Users/yizeng/ChessGame/proj.android/../cocos2d/../../Legend/library/ext/speex/speex-1.2rc1/./libspeex/preprocess.c:144
Stack frame #05  pc 000103a3  /data/app-lib/org.cocos2dx.hellocpp-2/libspeex.so (speex_preprocess_run+494): Routine DIV32_16_Q15 at /Users/yizeng/ChessGame/proj.android/../cocos2d/../../Legend/library/ext/speex/speex-1.2rc1/./libspeex/preprocess.c:124 (discriminator 2)
Stack frame #06  pc 001fa911  /data/app-lib/org.cocos2dx.hellocpp-2/libcocos2dcpp.so (aacEncode::SpeexPrePareAudio(unsigned char*)+12): Routine aacEncode::SpeexPrePareAudio(unsigned char*) at /Users/yizeng/chessgame/proj.android/jni/../../../Legend/library/rtmp/AACEncode.cpp:278
Stack frame #07  pc 001fa9d5  /data/app-lib/org.cocos2dx.hellocpp-2/libcocos2dcpp.so (aacEncode::Encode(unsigned char*, int, unsigned char*&, int&)+76): Routine aacEncode::Encode(unsigned char*, int, unsigned char*&, int&) at /Users/yizeng/chessgame/proj.android/jni/../../../Legend/library/rtmp/AACEncode.cpp:144
Stack frame #08  pc 001f8f83  /data/app-lib/org.cocos2dx.hellocpp-2/libcocos2dcpp.so (ns::CameraFilter::_initAudioData(unsigned char const*, int)+54): Routine ns::CameraFilter::_initAudioData(unsigned char const*, int) at /Users/yizeng/chessgame/proj.android/jni/../../../Legend/library/platform/NsCameraFilter.cpp:463
Stack frame #09  pc 001f9b01  /data/app-lib/org.cocos2dx.hellocpp-2/libcocos2dcpp.so (Java_org_cocos2dx_lib_Cocos2dxHelper_onAudioRecord+68): Routine Java_org_cocos2dx_lib_Cocos2dxHelper_onAudioRecord at /Users/yizeng/chessgame/proj.android/jni/../../../Legend/library/platform/android/NsCameraAndroid.cpp:524
Stack frame #10  pc 0001e74c  /system/lib/libdvm.so (dvmPlatformInvoke+112)
Stack frame #11  pc 0004fb71  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+484)
Stack frame #12  pc 00027b6c  /system/lib/libdvm.so

據此查看源碼後確定是DIV32_16_Q15調用的DIV32_16引起的,故修改fixed_generic.h的最後幾行:

//fixed by mazi
#define DIV32_16(a,b)  (0==(b) ? 0 : ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b)))))
#define PDIV32_16(a,b) (0==(b) ? 0 : ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b)))))
#define DIV32(a,b)     (0==(b) ? 0 : (((spx_word32_t)(a))/((spx_word32_t)(b))))
#define PDIV32(a,b)    (0==(b) ? 0 : (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b))))

搞定收工!大笑


注: 這裏我用的編譯選項是FIXED_POINT,因爲如果用FLOATING_POINT很多Android手機跑不動。

    另外還有個編譯選項是FIXED_POINT_DEBUG,開啓後也可以避免除0錯誤,但是它內部的判斷較多,估計會慢一些。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章