android ios opus语音编码压缩库编译

据说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就可以直接编译了。

android ios opus语音编码压缩库编译_第1张图片

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的 mk
include silk_sources.mk  #加载silk 所有.c 的mk
include opus_sources.mk #加载opus 所有.c 的mk
MY_MODULE_DIR       := newopus  #库的名称
LOCAL_MODULE        := $(MY_MODULE_DIR)
SILK_SOURCES += $(SILK_SOURCES_FIXED)
#编译的源代码.c
CELT_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=64
LOCAL_CFLAGS        += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT=1 -DDISABLE_FLOAT_API -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -O3 -fno-math-errno
LOCAL_CPPFLAGS      := -DBSD=1
LOCAL_CPPFLAGS      += -ffast-math -O3 -funroll-loops
include $(BUILD_SHARED_LIBRARY)  #编译动态库设置

4.配置Application.mk

APP_ABI := armeabi armeabi-v7a  #编译运行的系统,平台
NDK_TOOLCHAIN_VERSION=4.9 #指定交叉编译器
APP_PLATFORM := android-19   #设定ndk编译的版本

5.以上配置完编译
android ios opus语音编码压缩库编译_第2张图片
Cmd 到项目中 有jni文件夹 进行ndk-build编译就ok了 把libopus复制到项目libs对应的armeabi armeabi-v7a 目录下

封装接口源代码:

Opusmain.c
#include 
#include 
#include 

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#if (!defined WIN32 && !defined _WIN32) || defined(__MINGW32__)
#include 
#else
#include 
#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;

}
JNIEXPORT
jint Java_com_gauss_opus_encode_Opus_getFrameSize(JNIEnv *env,jobject thiz)
{
    return  FRAME_SIZE;
}
//压缩
JNIEXPORT
jint 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;

}
//解压
JNIEXPORT
jint 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;

}


//释放语音对象
JNIEXPORT
void 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,C++,网络)