【WebRTC】在Android上用DK编译WebRtc音频增益模块(AGC),降噪(S),java调用JI实现功能
【WebRTC】在Android上用DK编译WebRtc音频增益模块(AGC),降噪(S),java调用JI实现功能
·········前言
·········前期工作
·········编译工作
·········编码工作(AGC-JAVA)
·········编码工作(AGC-JI)
·········编码工作(S-JAVA)
········编码工作(S-JI)
·········总结
Android 单独抽取 WebRtc-AGC(音频增益) 模块
Android 单独抽取 WebRtc-S(音频降噪) 模块
本文章是基于某个博客主写的移植到Android DK上编译(这边我没有用cMake)
.html
WebRtc单独模块编译的资料网上很多,零零散散,但是看了很多程序大多数都是旧的版本模块源码进行编译的,并且都是在
C/C 的基础上去运行,很少涉及到在DK下的编译和JI的使用。
后续会更新S(降噪),aecm,aec(回音消除) 模块在DK上编译JI上使用的文章。
笔者也是今年才开始正式的接触WebRt,目前正在深入分析其源代码,主要研究的是 底层模块(非算法)、Android模块,希
望后续能把一些经验分享出来。
1:Android Studio 开发工具 ,再次强调一下,这次没有使用 cMake 编译,使用的是传统的 ndk-build 编译,开发工具需要自行
配置一下,当然后面会提供源码 ,你完全可以 自己来配置cMake编译。
2:首先不认识WebRtc的请先百一下度,特别是模块的作用,如果是大佬的话请洗耳恭听。
: audacity2..exe 下载一下这个工具,干什么用 搜一下就知道。
长什么样,长这样 ↓
如何导入PCM数据:文件->导入->选择PCM数据->设置对应的采样率等参数
4:本章文重点讲解DK、JI等使用,需要有一定的基础适合看本文章
后续会把Demo上传,建议想做这些工作但是没做过的可以自行另起一个项目来做。
首先观澜我随手一建的项目工程目录
⑴ 这个是要处理的原始音频文件,当然你也可以直接从SD卡读取,为了方便,这边直接从assets 读取。
⑵ AudioProcessJni 为native 加载的类
其余为测试类和工具类。
(里面代码写的比较乱没有整理,demo下载完后自行调整 )
⑶ agc文件夹是 S和AGC编译所需的头文件和依赖文件,最开始是先调试AGC的,所以文件夹名称没有改,
ns_jni_ 为JI层实现的功能
这里贴一下
这玩意不简单的 , 里面有一些编译错误的默认配置项
code:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
APP_ABI := armeabi x86
LOCAL_MODULE := webrtc_audio
app_platform:=android-21
LOCAL_SRC_FILES := \agc/complex_bit_ \agc/complex_ \agc/cross_ \agc/dot_product_with_ \agc/downsample_ \agc/ \agc/ \agc/get_scaling_ \agc/min_max_ \agc/real_ \agc/ \agc/resample_ \agc/resample_by_ \agc/resample_by_2_ \agc/resample_by_2_ \agc/copy_set_ \agc/division_ \agc/spl_ \agc/spl_ \agc/spl_sqrt_ \agc/ring_ \agc/resample_ \agc/splitting_ \agc/vector_scaling_ \agc/analog_ \agc/digital_ \agc/ns_ \agc/nsx_ \agc/nsx_core_ \agc/nsx_core_neon_ \agc/noise_ \agc/noise_suppression_ \ns_jni_ \#undefined reference to 错误问题解决办法
LOCAL_ALLOW_UDEFIED_SYMBOLS := true
APP_SHORT_COMMADS := true
LOCAL_LDLIBS := -llog
APP_CPPFLAGS := -frtti -std=c11
include $(BUILD_SHARED_LIBRARY)
#APP_ABI := armeabi armeabi-v7a x86
APP_ABI := armeabi x86
APP_STL := stlport_static
APP_CPPFLAGS := -frtti -std=c11
APP_SHORT_COMMADS := true
LOCAL_LDFLAGS = -fuse-ld=bfd
编码前当然你要先把so 编译过来才能调试
编译过程....(省略)
好啦,当我们已经把so库成功的编出来了,并且能正常 loadLibrary
首先看下 AudioProcessJni文件中对Agc 操作的native 函数有哪些?
public class AudioProcessJni {static{System.loadLibrary(webrtc_audio); //加载native code的动态库}//Audio agc音频增益接口public native static void AgcFree();public native static int AgcFun(ByteBuffer buffer1 , short[] sArr, int frameSize);public native static long AgcInit(long minLevel, long maxLevel,long fs);public native static void AgcProcess(); //agc test model
}
AgcInit : 初始化agc模块功能
AgcFun:音频增益处理函数
AgcFree:模块释放销毁
AgcProcess: 这个是增益整个搓成完全在JI层处理,不和java 通信。
其中AgcFun中的 ByteBuffer 是java和JI 交互数据的重点,他是java和JI共享的一个内存块,当然你也可以给个返回值,看个人的编码习惯。
那么我们先来看java的测试代码:
public static final String AGC_OUT_FILE_PATCH_DICTORY=/storage/emulated/0/Pictures/agc;public static final String AGC_OUT_FILE_PATCH=/storage/emulated/0/Pictures/agc/byby_8K_1C_16bit_agc.pcm;
文件的输出目录以及输出的文件。
public static void agc_audio_test(Activity act) {try {int nbread = 0;//读取Assets文件流InputStream is = act.getAssets().open(byby_8K_1C_16bit.pcm);//输出的文件目录File file = new File(AGC_OUT_FILE_PATCH_DICTORY);if (!()){boolean mkdirs = ();if (mkdirs) {log(create dictroy success);} else {log(create dictroy file);return;}}//输出的文件file = new File(AGC_OUT_FILE_PATCH);//调用初始刷Agc模块long res = AudioProcessJni.AgcInit(0, 255, 8000);log( AudioProcessJni.AgcInit res = res);log(sleep 2s );Thread.sleep(2000);//初始化byte转换工具BytesTransUtil bytesTransUtil = BytesTransUtil.getInstance();// rData 为读取的缓冲区 分配160字节byte[] rData = new byte[160];ByteBuffer outBuffer = ByteBuffer.allocateDirect(160);FileOutputStream fos = new FileOutputStream(file);//--------------------开始读取---------------------------while((nbread=is.read(rData))>-1){short[] shorts = bytesTransUtil.Bytes2Shorts(rData);res = AudioProcessJni.AgcFun(outBuffer, shorts,80);for (int i = 0 ;i< 80 ;i){shorts[i] = (short) (outBuffer.get(2*i) ( outBuffer.get(2*i1) << 8));}fos.write(bytesTransUtil.Shorts2Bytes(shorts),0,nbread);}log( 结束Agc = );if (fos!=null){();}} catch (IOException e) {e.printStackTrace();log(e:error -> ());} catch (InterruptedException e) {e.printStackTrace();}finally {AudioProcessJni.AgcFree();}}
这个是java测试的流程代码,也比较清晰,重点来讲解下以下这段代码
//--------------------开始读取---------------------------while((nbread=is.read(rData))>-1){short[] shorts = bytesTransUtil.Bytes2Shorts(rData);res = AudioProcessJni.AgcFun(outBuffer, shorts,80);for (int i = 0 ;i< 80 ;i){shorts[i] = (short) (outBuffer.get(2*i) ( outBuffer.get(2*i1) << 8));}fos.write(bytesTransUtil.Shorts2Bytes(shorts),0,nbread);}log( 结束Agc = );
① 循环读取文件流中的数据,每次读取160个byte, 有点需要注意,底层的处理接口需要传入的是short[] 数组,文件流读取的
byte[]数组需要转换, 这边的话在java 层转换或者在JI层用C转换都是可以的,建议在JI上转换,不过需要注意的是有无
符号的问题,我这边为了方便直接在java层进行转换。
② Byte2Shorts 吧 byte数组转换成了short数组 并传入AgcFun [JI层] 去处理, 返回值res < 0 是错误的 这个根据JI层的逻辑
去调整,我这边为了代码简洁,没有做判断。
③ 最后处理完的音频数据会存放在outBuffer 这个ByteBuff 的变量里,那么在上层就可以去读取它了。
刚开始的时候以为传上来就可以用了,然后打印了数据的十六进制,发现值不一样,正负数处理溢出的问题,这时候才慢慢
意识到,java 基本变量都是有符号的,因为底层是定义成无符号的,为什么定义成无符号这个研究JI的时候再来说。
那么通过
shorts[i] = (short) (outBuffer.get(2*i) ( outBuffer.get(2*i1) << 8));
这个处理将数据还原成正确的。注 : 写文件操作在JI层是很方便实现的,AgcProcess读写都是JI层实现的,这边放到上层
考虑到有些人 java这边可能需要用到 这个处理完的buffer。 现在只是读取文件,其实从MIC 读取的PCM文件也基本类似。
因此:将数据还原成了short[]之后 写入文件还要转到byte[]
不知道各位小伙伴是否有更好的解决方法,或者看了我的demo之后又什么更好的解决办法一定要通知我。值得是有无符号
转换这一块。
现在来看下JI的处理,其实也很简单一共个函数先贴代码:
初始化函数:
JIEXPORT jlong JICALL Java_com_webrtc_ns_AudioProcessJni_AgcInit(JIEnv *env, jclass cls, jlong minLevel , jlong maxLevel , jlong fs){minLevel = 0;maxLevel = 255;agc_samples =fs;int agcMode = kAgcModeFixedDigital;LOGE(Java_com_webrtc_ns_AudioProcessJni_AgcInit! -> %d \n, sizeof(short));if ( ( WebRtcAgc_Create(&agcHandle) ) != 0) { //allocate dynamic memory on native heap for S instance pointed by hS.LOGE(oise_Suppression WebRtcs_Create err! \n);return S_ERROR; //error occurs}LOGE(Java_com_webrtc_ns_AudioProcessJni_AgcCreate success! \n);if (0 != WebRtcAgc_Init(agcHandle, minLevel, maxLevel, agcMode, agc_samples) ){LOGE(WebRtcAgc_Init WebRtcs_Init err! \n);return S_ERROR; //error occurs}LOGE(Java_com_webrtc_ns_AudioProcessJni_AgcInit success! \n);WebRtcAgc_config_t agcConfig;agcConfigpressionGaindB = 20; //在Fixed模式下,越大声音越大agcConfig.limiterEnable = 1; = ; //dbfs表示相对于full scale的下降值,0表示full scale,越小声音越大WebRtcAgc_set_config(agcHandle, agcConfig);return S_SUCCESS;
}
处理函数 & 销毁函数:
JIEXPORT jint JICALL Java_com_webrtc_ns_AudioProcessJni_AgcFun(JIEnv *env, jclass type, jobject jdirectBuff,jshortArray sArr_, jint frameSize) {if(agc_buffer == ULL){LOGE(gc_buffer == ULL! \n);void* buffer = (*env)->GetDirectBufferAddress(env,jdirectBuff);agc_buffer = buffer;}uint8_t saturationWarning;int outMicLevel = 0;int micLevelOut = 0;int i =0 ;int inMicLevel = micLevelOut;ct short *pData = ULL;short *pOutData = ULL;pOutData = (short*)malloc(frameSize*sizeof(short));pData =(*env)->GetShortArrayElements(env,sArr_,ULL);if(agcHandle == ULL){LOGE(agcHandle is null! \n);return -;}if(frameSize <= 0){return -2;}int agcProcessResult = WebRtcAgc_Process(agcHandle,pData,ULL,frameSize,pOutData,ULL,inMicLevel,&outMicLevel,0,&saturationWarning);if (0 != agcProcessResult ){LOGE(failed in WebRtcAgc_Process! agcProcessResult = %d \n ,agcProcessResult);return S_ERROR ; //error occurs}//memset(agc_buffer, 0, 160);shortTobyte(80,pOutData,agc_buffer);(*env)->ReleaseShortArrayElements(env, sArr_, pData, 0);return AGC_SUCCESS;
}JIEXPORT void JICALL Java_com_webrtc_ns_AudioProcessJni_AgcFree(JIEnv *env , jclass cls){WebRtcAgc_Free(agcHandle);
}
① 初始化函数看起来很简单,确实很简单。
关于一下
WebRtcAgc_config_t agcConfig;agcConfigpressionGaindB = 20; //在Fixed模式下,越大声音越大agcConfig.limiterEnable = 1; = ; //dbfs表示相对于full scale的下降值,0表示full scale,越小声音越大
可以自己编译调试, 用工具去比对效果。
② void* buffer = (*env)->GetDirectBufferAddress(env,jdirectBuff); 获取java层分配的ByteBuff 实例,最后一个 char指针指向了
这个 实例,需要注意的是 这里
unsigned char* agc_buffer = ULL;
是无符号的,如果有符号的话后面可能会有溢出问题,所以在底层char指针表示的我这边都用无符号。
WebRtcAgc_Process 函数处理数据最后得到 short * 的数据 , 最后通过 shortTobyte 函数将short 的值赋给 ByteBuff 的实
例,这样java层就能得到这个数据。
③释放工作比较简单 WebRtcAgc_Free 即可。
降噪模块基本流程和增益模块大同小异。
目前处理的是8K采样率音频, 如果处理2K采样率音频,那么可能需要传入高频,低频数据做处理。
音频降噪部分较为简单,用起来也就几个函数,除了需要传入的音频数据以外,需要调整的参数也就是音频采样率和降噪等级。另外这部分代码采用纯C语言语法编写,可以跨平台编译。整个算法也不算特别复杂,运行起来占CPU也不是很多,可以上至i7 8核CPU的高配电脑,下至80Mhz的小嵌入式系统以及一切版本的移动端产品中编译运行。另外效果也十分不错,通过本文附带的测试demo大家就可以感受一下。
降噪有两部分代码,一套是定点算法(noise_suppression_x.h),一套是浮点算法(noise_suppression.h)。相对来说浮点算法精度更高,但是耗系统资源更多,特别是浮点计算能力较弱的低端ARM CPU上。但是一般来说浮点和定点算法在实际效果上听不出区别出来,估计是我没遇到过必须必须要用浮点的情况。在使用上,浮点和定点也仅仅只是变量名和函数没中多出了一个x。
音频处理的时候webrtc一次仅能处理10ms数据,小于10ms的数据不要传入,因为即时是传入小于10ms的数据最后传入也是按照10ms的数据传出,此时会出现问题。另外支持采样率也只有8K,16K,2K三种,不论是降噪模块,或者是回声消除增益等等均是如此。对于8000采样率,16bit的音频数据,10ms的时间采样点就是80个,一个采样点16bit也就是两个字节,那么需要传入WebRtcsx_Process的数据就是160字节。对于8000和16000采样率的音频数据在使用时可以不管高频部分,只需要传入低频数据即可,但是对于2K采样率的数据就必须通过滤波接口将数据分为高频和低频传入,传入降噪后再组合成音频数据。大于2K的音频文件就必须要通过重采样接口降频到对应的采样率再处理,在demo源码里面有对应的接口使用者可以去查。
降噪的开源代码包括定点降噪,浮点降噪,音频重采样,滤波接口,抠出来后修改了头文件包含位置使其都在同一目录下,如果是xcode下编译可能会有once函数编译不过的问题,此时修改一个宏即可,为了尽量避免修改问题就不改动这部分了。
示例代码给了2K采样率的测试demo,也有8K采样率实现。16K采样率只需要将8K内部的数据大小由80改成160即可,PCM音频文件可以由Audacity软件通过文件--导入--原始数据,选择好bit位数,声道,采样率即可显示波形,播放。
public class Tests {public static final String AGC_OUT_FILE_PATCH_DICTORY=/storage/emulated/0/Pictures/ns;public static final String AGC_OUT_FILE_PATCH=/storage/emulated/0/Pictures/ns/byby_8K_1C_16bit_ns_android.pcm;public static void ns_audio_test(Activity act) {try {File file = null;InputStream is = act.getAssets().open(byby_8K_1C_16bit.pcm);FileOutputStream fos = null;file = new File(AGC_OUT_FILE_PATCH_DICTORY);if (!()){boolean mkdirs = ();if (mkdirs) {log(create dictroy success);} else {log(create dictroy file);return;}}file = new File(AGC_OUT_FILE_PATCH);fos = new FileOutputStream(file);log(sleep 2s );Thread.sleep(2000);long res = AudioProcessJni.initiateSInstance(8000,);if (res == 7 ){//success}BytesTransUtil bytesTransUtil = BytesTransUtil.getInstance();byte[] rData = new byte[160];ByteBuffer outBuffer = ByteBuffer.allocateDirect(160);int nbread = 0;long startTime = ();while((nbread=is.read(rData))>-1){short[] shorts = bytesTransUtil.Bytes2Shorts(rData);// ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_EDIA).asShortBuffer().get(data);res = AudioProcessJni.processS(outBuffer, shorts, 80);for (int i = 0 ;i< 80 ;i){shorts[i] = (short) ( (outBuffer.get(2*i)&0x00FF ) ( outBuffer.get(2*i1) << 8));}fos.write(bytesTransUtil.Shorts2Bytes(shorts),0,nbread);}long endTime = ();log( 结束 s = 程序运行时间:(endTime-startTime)ms);if (fos!=null){();}} catch (IOException e) {e.printStackTrace();log(e:error -> ());} catch (InterruptedException e) {e.printStackTrace();}finally {}}
初始化函数 Java_com_webrtc_ns_AudioProcessJni_initiateSInstance
降噪处理函数 Java_com_webrtc_ns_AudioProcessJni_processS
销毁函数 Java_com_webrtc_ns_AudioProcessJni_destoryS
//初始化频率的降噪结构体参数
/** nSample:采集数据的频率*/
JIEXPORT jint JICALL Java_com_webrtc_ns_AudioProcessJni_initiateSInstance(JIEnv *env, jclass cls, jlong nSample, jint nMode){//创建webrtc降噪处理句柄//sHandle *hS = ULL; //create a pointer to sHandle on native stack.if ( ( WebRtcs_Create(&pS_inst) ) != 0) { //allocate dynamic memory on native heap for S instance pointed by hS.LOGE(oise_Suppression WebRtcs_Create err! \n);return S_ERROR; //error occurs}if (0 != WebRtcs_Init(pS_inst,nSample)){LOGE(oise_Suppression WebRtcs_Init err! \n);return S_ERROR; //error occurs}if (0 != WebRtcs_set_policy(pS_inst,nMode)){printf(oise_Suppression WebRtcs_set_policy err! \n);return S_ERROR; //error occurs}// return ((int) (Sinst_t *) pS_inst); //returns the address of S instance on native heap.return S_SUCCESS;
}
JIEXPORT jint JICALL Java_com_webrtc_ns_AudioProcessJni_processS(JIEnv *env, jclass type, jobject jdirectBuff,jshortArray outframe_,jint sf) {jshort *outframe = (*env)->GetShortArrayElements(env, outframe_, ULL);short *pOutData = ULL;int frameSize =sf;if(pS_inst == ULL){LOGE(nsHandle is null! \n);return -;}if(ns_buffer == ULL){LOGE(gc_buffer == ULL! \n);void* buffer = (*env)->GetDirectBufferAddress(env,jdirectBuff);ns_buffer = buffer;}pOutData = (short*)malloc(frameSize*sizeof(short));if ( WebRtcs_Process(pS_inst, outframe, ULL, pOutData,ULL) != 0){LOGE(failed in WebRtcAgc_Process! \n );return S_ERROR ; //error occurs}shortTobyte(80,pOutData,ns_buffer);(*env)->ReleaseShortArrayElements(env, outframe_, outframe, 0);return AGC_SUCCESS;}
JIEXPORT jint JICALL Java_com_webrtc_ns_AudioProcessJni_destoryS(JIEnv *env, jclass cls){WebRtcs_Free(pS_inst);
}
处理2K语言
以下当 sf=2*1000 时,进入处理2K语言的过程;
此过程全程在JI中执行,读取pcm文件进行降噪处理
/*JI全处理*/
JIEXPORT void JICALL Java_com_webrtc_ns_AudioProcessJni_SProcess(JIEnv *env, jclass type ,jint sf) {ct char *sFile = /storage/emulated/0/Pictures/ns/lhydd_1C_16bit_2K.pcm;ct char *dFile =/storage/emulated/0/Pictures/ns/lhydd_1C_16bit_2K_ns.pcm;ct char *sFile_8k = /storage/emulated/0/Pictures/ns/byby_8K_1C_16bit.pcm;ct char *dFile_8k =/storage/emulated/0/Pictures/ns/byby_8K_1C_16bit_ns.pcm;// TODO test agc modelchar *pInBuffer = ULL;char *pOutBuffer = ULL;int i = 0;long nFileSize = 0;if(sf == 2*1000) {FILE * fpIn = fopen(sFile, rb);FILE * fpOut = fopen(dFile, wb);if(fpIn == ULL || fpOut == ULL){LOGE(file open filed);return;}LOGE(S Java_com_webrtc_ns_AudioProcessJni_SProcess 2K start);do {fseek(fpIn, 0, SEEK_ED);nFileSize = ftell(fpIn);printf(nFileSize = %d \n , nFileSize);fseek(fpIn, 0, SEEK_SET);pInBuffer = (char *) malloc(nFileSize);memset(pInBuffer, 0, nFileSize);fread(pInBuffer, sizeof(char), nFileSize, fpIn);pOutBuffer = (char *) malloc(nFileSize);memset(pOutBuffer, 0, nFileSize);int filter_state1[6], filter_state12[6];int Synthesis_state1[6], Synthesis_state12[6];memset(filter_state1, 0, sizeof(filter_state1));memset(filter_state12, 0, sizeof(filter_state12));memset(Synthesis_state1, 0, sizeof(Synthesis_state1));memset(Synthesis_state12, 0, sizeof(Synthesis_state12));for (i = 0; i < nFileSize; i = 640) {if (nFileSize - i >= 640) {short shBufferIn[20] = {0};short shInL[160], shInH[160];short shOutL[160] = {0}, shOutH[160] = {0};memcpy(shBufferIn, (char *) (pInBuffer i), 20 * sizeof(short));//首先需要使用滤波函数将音频数据分高低频,以高频和低频的方式传入降噪函数内部WebRtcSpl_AnalysisQMF(shBufferIn, 20, shInL, shInH, filter_state1,filter_state12);//将需要降噪的数据以高频和低频传入对应接口,同时需要注意返回数据也是分高频和低频if (0 == WebRtcs_Process(pS_inst, shInL, shInH, shOutL, shOutH)) {short shBufferOut[20];//如果降噪成功,则根据降噪后高频和低频数据传入滤波接口,然后用将返回的数据写入文件WebRtcSpl_SynthesisQMF(shOutL, shOutH, 160, shBufferOut, Synthesis_state1,Synthesis_state12);memcpy(pOutBuffer i, shBufferOut, 20 * sizeof(short));}}}fwrite(pOutBuffer, sizeof(char), nFileSize, fpOut);} while (0);LOGE(S 结束);WebRtcs_Free(pS_inst);fclose(fpIn);fclose(fpOut);free(pInBuffer);free(pOutBuffer);} else{FILE * fpIn = fopen(sFile_8k, rb);FILE * fpOut = fopen(dFile_8k, wb);if(fpIn == ULL || fpOut == ULL){LOGE(file open filed);return;}LOGE(S Java_com_webrtc_ns_AudioProcessJni_SProcess 8K start);int len;int frameSize =80;int i = 0 ;ct short *pData = ULL;short *pOutData = ULL;pData = (short*)malloc(frameSize*sizeof(short));pOutData = (short*)malloc(frameSize*sizeof(short)); //160len = frameSize*sizeof(short);while(1){memset(pData, 0, len);if (len > 0){len = fread(pData, 1, len, fpIn);int nSRet = WebRtcs_Process(pS_inst, pData, ULL, pOutData,ULL);if (nSRet != 0){LOGE(failed in WebRtcAgc_Process\n);break;}fwrite(pOutData, 1, len, fpOut);} else {break;}}LOGE(S 结束);WebRtcs_Free(pS_inst);fclose(fpIn);fclose(fpOut);free(pInBuffer);free(pOutBuffer);}}
总结一句话,给你们代码就是了,下载地址:
#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
推荐阅读
留言与评论(共有 19 条评论) |
本站网友 jiubo | 20分钟前 发表 |
= -frtti -std=c11 APP_SHORT_COMMADS | |
本站网友 small是什么意思 | 8分钟前 发表 |
后续会更新S(降噪) | |
本站网友 iframe滚动条 | 21分钟前 发表 |
整个算法也不算特别复杂,运行起来占CPU也不是很多,可以上至i7 8核CPU的高配电脑,下至80Mhz的小嵌入式系统以及一切版本的移动端产品中编译运行 | |
本站网友 什么是root权限 | 29分钟前 发表 |
写文件操作在JI层是很方便实现的,AgcProcess读写都是JI层实现的,这边放到上层 考虑到有些人 java这边可能需要用到 这个处理完的buffer | |
本站网友 神楽坂真冬 | 14分钟前 发表 |
nFileSize);int filter_state1[6] | |
本站网友 中国移动安徽分公司 | 16分钟前 发表 |
public class Tests {public static final String AGC_OUT_FILE_PATCH_DICTORY=/storage/emulated/0/Pictures/ns;public static final String AGC_OUT_FILE_PATCH=/storage/emulated/0/Pictures/ns/byby_8K_1C_16bit_ns_android.pcm;public static void ns_audio_test(Activity act) {try {File file = null;InputStream is = act.getAssets().open(byby_8K_1C_16bit.pcm);FileOutputStream fos = null;file = new File(AGC_OUT_FILE_PATCH_DICTORY);if (!()){boolean mkdirs = ();if (mkdirs) {log(create dictroy success);} else {log(create dictroy file);return;}}file = new File(AGC_OUT_FILE_PATCH);fos = new FileOutputStream(file);log(sleep 2s );Thread.sleep(2000);long res = AudioProcessJni.initiateSInstance(8000 | |
本站网友 无锡恒隆广场美食 | 29分钟前 发表 |
里面有一些编译错误的默认配置项 code | |
本站网友 软磷脂 | 19分钟前 发表 |
outframe_ | |
本站网友 蚌埠人流 | 20分钟前 发表 |
WebRtcAgc_Process 函数处理数据最后得到 short * 的数据 , 最后通过 shortTobyte 函数将short 的值赋给 ByteBuff 的实 例,这样java层就能得到这个数据 | |
本站网友 酒巷深深 | 21分钟前 发表 |
⑵ AudioProcessJni 为native 加载的类 其余为测试类和工具类 | |
本站网友 侧脑室 | 30分钟前 发表 |
wb);if(fpIn == ULL || fpOut == ULL){LOGE(file open filed);return;}LOGE(S Java_com_webrtc_ns_AudioProcessJni_SProcess 8K start);int len;int frameSize =80;int i = 0 ;ct short *pData = ULL;short *pOutData = ULL;pData = (short*)malloc(frameSize*sizeof(short));pOutData = (short*)malloc(frameSize*sizeof(short)); //160len = frameSize*sizeof(short);while(1){memset(pData | |
本站网友 孕妇前三个月注意事项 | 16分钟前 发表 |
pOutData | |
本站网友 亲胸视频 | 7分钟前 发表 |
那么我们先来看java的测试代码: public static final String AGC_OUT_FILE_PATCH_DICTORY=/storage/emulated/0/Pictures/agc;public static final String AGC_OUT_FILE_PATCH=/storage/emulated/0/Pictures/agc/byby_8K_1C_16bit_agc.pcm; 文件的输出目录以及输出的文件 | |
本站网友 黄金比例身材 | 21分钟前 发表 |
error -> ());} catch (InterruptedException e) {e.printStackTrace();}finally {}} 编码工作(S-JI) 初始化函数 Java_com_webrtc_ns_AudioProcessJni_initiateSInstance 降噪处理函数 Java_com_webrtc_ns_AudioProcessJni_processS 销毁函数 Java_com_webrtc_ns_AudioProcessJni_destoryS //初始化频率的降噪结构体参数 /** nSample | |
本站网友 徐明明 | 5分钟前 发表 |
另外支持采样率也只有8K,16K | |
本站网友 长沙新东方厨师学校 | 9分钟前 发表 |
80);for (int i = 0 ;i< 80 ;i){shorts[i] = (short) (outBuffer.get(2*i) ( outBuffer.get(2*i1) << 8));}fos.write(bytesTransUtil.Shorts2Bytes(shorts) | |
本站网友 9月22 | 10分钟前 发表 |
= true APP_SHORT_COMMADS | |
本站网友 最常用的杀毒软件 | 13分钟前 发表 |
降噪的开源代码包括定点降噪,浮点降噪,音频重采样,滤波接口,抠出来后修改了头文件包含位置使其都在同一目录下,如果是xcode下编译可能会有once函数编译不过的问题,此时修改一个宏即可,为了尽量避免修改问题就不改动这部分了 |