android ios opus语音编码压缩库编译
来源:互联网 发布:爱情观知乎 编辑:程序博客网 时间:2024/05/16 06:50
据说Opus 比speex库,aac各方面性能更好,也很适合做网络语音通话。
采样率 :
音频取样频率, 指每秒钟取得声音样本的次数。采样频率越高,声音的质量也就越好,声音的还原也就越真实,但同时它占的资源比较多。一般采样率有 8000HZ 16000HZ 44100HZ。
比特率:
每秒的传输速率(位速, 也叫比特率)。如256kbps 或256000bps, 其中的 b 是 bit, ps 是每秒的意思,表示每秒256000bit的容量。
8bit=1Byte
帧:
帧记录了一个声音单元,其长度为样本长度(采样位数)和通道数的乘积。采样率X通道数X采样位数=8000X1X16=128000bit=16000Byte。
Opus压缩的声音需要pcm编码.
Android Opus编译过程
编译好下载地址:http://download.csdn.net/download/undiif123/9854940
1.打开android studio,点击sdk-manager->android sdk勾选红色箭头进行安装ndk等库,ndk需要设置一下环境变量,设置后cmd就可以直接编译了。
2.下载Opus_1.1.4 解压后把本文件名命名jni,celt_headers.mk,celt_sources.mk,opus_headers.mk,opus_sources.mk,silk_headers.mk,silk_sources.mk 把这mk放在jni同级目录中
3.配置android.mk
LOCAL_PATH := $(call my-dir) #加载当前路径include $(CLEAR_VARS)include celt_sources.mk #加载celt 所有.c的 mkinclude silk_sources.mk #加载silk 所有.c 的mkinclude opus_sources.mk #加载opus 所有.c 的mkMY_MODULE_DIR := newopus #库的名称LOCAL_MODULE := $(MY_MODULE_DIR)SILK_SOURCES += $(SILK_SOURCES_FIXED)#编译的源代码.cCELT_SOURCES += $(CELT_SOURCES_ARM)SILK_SOURCES += $(SILK_SOURCES_ARM)LOCAL_SRC_FILES := opusmain.c\ #封装接口opusmain.c$(CELT_SOURCES) $(SILK_SOURCES) $(OPUS_SOURCES)LOCAL_LDLIBS := -lm –llog #加载系统的库 日志库LOCAL_C_INCLUDES := \ #包含头文件$(LOCAL_PATH)/include \$(LOCAL_PATH)/silk \$(LOCAL_PATH)/silk/fixed \$(LOCAL_PATH)/celt#附加编译选项LOCAL_CFLAGS := -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT=1 -DDISABLE_FLOAT_API -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -O3 -fno-math-errnoLOCAL_CPPFLAGS := -DBSD=1LOCAL_CPPFLAGS += -ffast-math -O3 -funroll-loopsinclude $(BUILD_SHARED_LIBRARY) #编译动态库设置
4.配置Application.mk
APP_ABI := armeabi armeabi-v7a #编译运行的系统,平台NDK_TOOLCHAIN_VERSION=4.9 #指定交叉编译器APP_PLATFORM := android-19 #设定ndk编译的版本
5.以上配置完编译
Cmd 到项目中 有jni文件夹 进行ndk-build编译就ok了 把libopus复制到项目libs对应的armeabi armeabi-v7a 目录下
封装接口源代码:
Opusmain.c#include <jni.h>#include <string.h>#include <android/log.h>#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <limits.h>#include <stdint.h>#include <math.h>#include <string.h>#include <time.h>#if (!defined WIN32 && !defined _WIN32) || defined(__MINGW32__)#include <unistd.h>#else#include <process.h>#define getpid _getpid#endif#include "opus_multistream.h"#include "opus.h"#include "../src/opus_private.h"#define MAX_PACKET (1500)#define SAMPLES (48000*30)#define SSAMPLES (SAMPLES/3)#define MAX_FRAME_SAMP (5760)//每采集一帧大小为160short=320个字节//帧的计算,例如 采样率8000 单通道 采样位数16bit//1秒采集到数据8000X1X16=16000Byte//网络语音传输20ms一次 也就是说1秒发50次320Byte的包 320Byte=160Short//采集一次是160Short#define FRAME_SIZE 160#define SAMPLE_RATE 8000#define CHANNELS 1#define APPLICATION OPUS_APPLICATION_AUDIO//参数调整压缩倍数可设置7000 声音还能正常,压缩率160short 压缩成18short#define BITRATE 8000#define MAX_FRAME_SIZE 6*960#define MAX_PACKET_SIZE (3*1276)OpusEncoder *encoder;OpusDecoder *decoder;int bandwidth = OPUS_AUTO;int use_vbr = 0;int cvbr=1;int complexity = 4;int packet_loss_perc=0;//初始化语音//com_gauss_ opus _encode java层的包名,Opus类名,open函数名 这样定义好java就可以直接调用了jint Java_com_gauss_opus_encode_Speex_open(JNIEnv *env,jobject thiz,jint compression){ int err; encoder = opus_encoder_create(SAMPLE_RATE, CHANNELS, APPLICATION, &err); if (err<0) { return 0; } err = opus_encoder_ctl(encoder, OPUS_SET_BITRATE(BITRATE)); if (err<0) { return 0; } opus_encoder_ctl(encoder, OPUS_SET_BANDWIDTH(bandwidth)); opus_encoder_ctl(encoder, OPUS_SET_VBR(use_vbr)); opus_encoder_ctl(encoder, OPUS_SET_VBR_CONSTRAINT(cvbr)); opus_encoder_ctl(encoder, OPUS_SET_COMPLEXITY(compression)); opus_encoder_ctl(encoder, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc)); decoder = opus_decoder_create(SAMPLE_RATE, CHANNELS, &err); if (err<0) { return 0; } return 1;}JNIEXPORTjint Java_com_gauss_opus_encode_Opus_getFrameSize(JNIEnv *env,jobject thiz){ return FRAME_SIZE;}//压缩JNIEXPORTjint Java_com_gauss_opus_encode_Opus_encode(JNIEnv *env,jobject thiz, jshortArray lin, jint offset, jbyteArray encoded, jint size){ int err; int i; int nbBytes; unsigned short cbits[480]; unsigned short out[160]; if(encoder == NULL){ return 0; } //读取参数 数组 (*env)->GetShortArrayRegion(env,lin,offset,size,out);nbBytes = opus_encode(encoder,out , size, cbits, 480);////设定压缩完的数据到数组中 (*env)->SetByteArrayRegion(env,encoded, 0, nbBytes, (jshort*)cbits); return nbBytes;}//解压JNIEXPORTjint Java_com_gauss_opus_encode_Opus_decode(JNIEnv *env,jobject thiz, jbyteArray encoded, jshortArray lin, int size){ int err; int i; int frame_size; int nbBytes; unsigned char cbits[MAX_PACKET_SIZE]; unsigned short out[160]; unsigned short deout[160]; if(decoder == NULL){ return 0; } (*env)->GetByteArrayRegion(env, encoded,0,size,out); frame_size = opus_decode(decoder, out, size, deout, MAX_FRAME_SIZE, 0); if(frame_size <0){ return 0; } int nSize = frame_size*CHANNELS; (*env)->SetShortArrayRegion(env,lin, 0, nSize, (jshort*)deout); return nSize;}//释放语音对象JNIEXPORTvoid Java_com_gauss_opus_encode_Opus_close(JNIEnv *env,jobject thiz){ if(encoder !=NULL){ opus_encoder_destroy(encoder); } if(encoder !=NULL){ opus_decoder_destroy(decoder); }}
IOS编译
1.使用build-libopus.sh 脚本编译,修改一下参数
VERSION=1.1.4 #opus库的版本
SDKVERSION=”10.3” #ios sdk版本
MINIOSVERSION=”8.0” #最低版本8.0
2.然后使用终端编译build-libopus.sh
3.然后把libopus.a 和include 加入工程中。
#import "OpusCode1.h"@implementation OpusCode1- (id)init { if (self = [super init]) { codecOpenedTimes = 0; } return self;}/* quality value 1 ~ 10 */#define BITRATE 8000#define MAX_FRAME_SIZE 6*960- (void)open:(int)quality { if ((quality < 1) || (quality > 10)) { return; } if (codecOpenedTimes++ != 0) { return; } else { encodeFrameSize = 160; decodeFrameSize = 160; int bandwidth = OPUS_AUTO; int use_vbr = 0; int cvbr=1; int packet_loss_perc=0; //opus int err; encoder = opus_encoder_create(8000, 1, OPUS_APPLICATION_AUDIO, &err); err = opus_encoder_ctl(encoder, OPUS_SET_BITRATE(BITRATE)); opus_encoder_ctl(encoder, OPUS_SET_BANDWIDTH(bandwidth)); opus_encoder_ctl(encoder, OPUS_SET_VBR(use_vbr)); opus_encoder_ctl(encoder, OPUS_SET_VBR_CONSTRAINT(cvbr)); opus_encoder_ctl(encoder, OPUS_SET_COMPLEXITY(quality)); opus_encoder_ctl(encoder, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc)); decoder = opus_decoder_create(8000, 1, &err); }}- (NSData *)encode:(short *)pcmBuffer length:(int)lengthOfShorts { if (codecOpenedTimes == 0) { return nil; } //opus int nbBytes; unsigned short cbits[480]; NSMutableData *decodedData = [NSMutableData dataWithCapacity:20]; short input_frame[encodeFrameSize]; memset((Byte*)input_frame,0,encodeFrameSize*2); memcpy(input_frame, pcmBuffer, encodeFrameSize * sizeof(short)); nbBytes = opus_encode(encoder, input_frame, encodeFrameSize, cbits, 480); [decodedData appendBytes:cbits length:nbBytes]; return decodedData;}- (int)decode:(unsigned char *)encodedBytes length:(int)lengthOfBytes output:(short *)decoded { if ( ! codecOpenedTimes) return 0; opus_int16 out[MAX_FRAME_SIZE]; char cbits[200]; memcpy(cbits, encodedBytes, lengthOfBytes); int frame_size; frame_size = opus_decode(decoder, (short*)encodedBytes, lengthOfBytes, decoded, MAX_FRAME_SIZE, 0); return decodeFrameSize;}- (void)close { if (--codecOpenedTimes != 0) { return; } if(encoder !=NULL){ opus_encoder_destroy(encoder); } if(decoder !=NULL){ opus_decoder_destroy(decoder); }}- (void)dealloc { [self close];#if !__has_feature(objc_arc)// [super dealloc];#endif}@end
- android ios opus语音编码压缩库编译
- Plumble-android 一次完整的编译过程(Opus语音压缩项目)
- ios的opus编译
- qt creator编译opus库
- ios使用opus压缩和解压缩PCM文件
- AAC终结者Opus音频编码器的瑞士军刀,编译android ios
- opus编译库到arm上面用
- Opus编码解码
- opus在安卓编译下的Android.mk
- opus交叉编译
- 编译静态库遇到的一些问题speex,opus
- android语音录制和压缩
- android语音录制和压缩
- 音频编码之opus(一)
- 音频编码之opus(一)
- 音频编码之opus(一)
- WebRTC中的Opus编码揭秘
- Build Opus Codec for iOS
- 一道有关setTimeout的面试题
- Python三种数据结构
- ajax实战篇---城市select联动----json交互
- 自定义MVC
- 【iOS】基本控件:文本输入框、开关、分段控件、滑块与输入键盘隐藏的问题
- android ios opus语音编码压缩库编译
- sftp服务器搭建
- 容斥原理
- USACO Section 1.2 Name That Number
- java中jar命令打包一个文件夹下的所有文件
- 02_hibernate5快速入门_注解的方式
- List集合常用方法
- Java RandomAccessFile用法
- 二叉树基本结构