Unity 工具-Opus音频压缩(安卓篇)
来源:互联网 发布:windows家庭版升级 编辑:程序博客网 时间:2024/06/03 15:46
现在很多游戏开始注重社交,因此语音成了游戏中不可或缺的部分。很多公司由于各种限制,可能使用第三方的SDK。虽然方便使用,但是费用挺高,而且不开源,不方便控制细节。
Opus编码器 是一个有损声音编码的格式,由互联网工程任务组(IETF)近来开发Opus 格式是一个开放格式,使用上没有任何专利或限制,应该算是Speex的升级吧,在压缩质量和效率上有了很大的提升。
具体的对比:官网对比说明
在Unity中使用Opus,首先要自己编译成对应Win、Android、IOS的支持库,网上关于Win和Android的网上有很多。我是自己写了简单的接口函数,然后分别对应编译成.dll、.so和.o,导入到Unity中用C#调用。(过去没有接触过编译,因此说的都是入门的,可能有些也不对,大神可以不用看下面的)
其中有几个坑:
- Opus源码在Win有对应的解决方案,因此直接VS打开就可以,写完接口函数,直接编译就好,但是如果编译IOS,就需要自己新建工程,然后导入Opus源码,注意只导入C文件和头文件,其他的都不要导进去,并且所有的X86文件夹都不要导入,IOS只有ARM的CPU。
- IOS必须在真机上测试,Unity中不能调用静态库。
- 安卓的是按照网上的教程,使用NDK编译,感觉很好用,写好MK,就不用管了,我只把接口函数写入,它会自动将以来的方法编译进去。
其中安卓的编译,参考 前人的经验,接口函数不同,需要写C#调用的,而不是JAVA
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_SRC_FILES := opusmain.cpp\ #封装接口opusmain.cpp
接口文件按照自己写的改,而且要写成可以C#访问的,而不是JAVA,网上的很多都只是Android使用,要自己写接口函数。
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.cpp\ #封装接口opusmain.cpp$(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) #编译动态库设置
其中include celt_sources.mk include silk_sources.mk include opus_sources.mk为官方自带的MK,里面有需要的编译规则,cilt主要处理音乐,silk处理声音(skype开发)
4.配置Application.mk
APP_ABI := armeabi armeabi-v7a #编译运行的系统,平台NDK_TOOLCHAIN_VERSION=4.9 #指定交叉编译器APP_PLATFORM := android-19 #设定ndk编译的版本
5.接口函数
头文件opusmain.h
int frame_size;int channels = 1;opus_int32 opus_num;opus_int32 pcm_num;float* pcm_dataFloat_encoder = NULL;opus_int16* pcm_dataInt_encoder = NULL;unsigned char* opus_dataInt_decoder = NULL;unsigned char* opus_dataFloat_decoder = NULL;OpusEncoder *enc = NULL;OpusDecoder *dec = NULL;int error;//必须带有extern "C",否则在Unity中找不到以下方法extern "C" { int nMyOpus; int fnMyOpus(void); void opusEncoderInit(int Fs, int _channels); void opusEncoderSet(int _frame_size, bool isFloat, int quality, int signal); void opusDecoderInit(int Fs, int _channels, int max_len, bool isFloat); int opusEncoder(opus_int16 *encoder_insrc, int in_offset, unsigned char *encoder_out, int max_len); int opusDecoder(int len, unsigned char *decoder_insrc, int in_offset, opus_int16 *decoder_out); int opusEncoderFloat(float *encoder_insrc, int in_offset, unsigned char *encoder_out, int max_len); int opusDecoderFloat(int len, unsigned char *decoder_insrc, int in_offset, float *decoder_out); void opusEncoderDispose(); void opusDecoderDispose();}
C++文件opusmain.cpp
#include <jni.h>#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <string.h>#include "arch.h"#include "opus_multistream.h"#include "opus.h"#include "opusmain.h"#include "../src/opus_private.h"#ifdef VALGRIND#include <valgrind/memcheck.h>#define VG_UNDEF(x,y) VALGRIND_MAKE_MEM_UNDEFINED((x),(y))#define VG_CHECK(x,y) VALGRIND_CHECK_MEM_IS_DEFINED((x),(y))#endif// 这是导出函数的一个示例。这个函数没逻辑,就是测试Unity是否能够连接到静态库int MyOpus(){ return 2;}OpusEncoder* OpusEncoderInit(int Fs){ OpusEncoder *enc = NULL; int complexity = 1; int signal = OPUS_SIGNAL_VOICE; int application = OPUS_APPLICATION_AUDIO; int bitrate_bps = 32000; int bandwidth = OPUS_AUTO; int use_vbr = 1; int cvbr = 0; int packet_loss_perc = 0; enc = opus_encoder_create(Fs, channels, application, &error); opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal)); opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps)); opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth)); opus_encoder_ctl(enc, OPUS_SET_VBR(use_vbr)); opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr)); opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity)); opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc)); return enc;}void OpusEncoderSet(OpusEncoder *enc, int complexity, int signal, int bitrate, int frame_size, int cvbr){ opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal)); opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate)); opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity)); opus_encoder_ctl(enc, OPUS_SET_VBR(1 - cvbr)); opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));}OpusDecoder* OpusDecoderInit(int Fs){ OpusDecoder *dec = opus_decoder_create(Fs, channels, &error); return dec;}int OpusEncoderInt(OpusEncoder *enc, int frame_size, opus_int16 *encoder_insrc, unsigned char *encoder_out, int max_len){ opus_int32 opus_num = opus_encode( enc, encoder_insrc, frame_size, encoder_out, max_len); return opus_num;}int OpusDecoderInt(OpusDecoder *dec, int frame_size, int len, unsigned char *decoder_insrc, opus_int16 *decoder_out){ opus_int32 pcm_num = opus_decode( dec, decoder_insrc, len, decoder_out, frame_size, 0); return pcm_num;}
编译过程很简单
进入到Opus文件夹,在里面打开命令行,输入ndk-build,就可以,他会自动找到MK文件,并按规则编译。
在生成Lib文件夹,在里面就能找到.so文件
安卓的先到这,IOS和Win的,以及Unity怎么使用,在下篇博客
- Unity 工具-Opus音频压缩(安卓篇)
- Unity 工具-Opus音频压缩(Win篇)
- 音频(四) - 音频压缩(Speex使用&Opus简介)
- 音频编码之opus(二)
- 音频编码之opus(二)
- 音频编码之opus(一)
- Xiph opus音频编码器试用
- 音频编码之opus(一)
- 音频调研之opus speex
- 音频编码之opus(一)
- 使用opus音频编码流程简介
- OPUS/SILK/SPEEX 音频编码比较
- 优于AAC的音频编码格式opus
- Plumble-android 一次完整的编译过程(Opus语音压缩项目)
- unity 实现另一个unity软件的安装工具(3)——压缩解压安装工程
- AAC音频压缩(转载)
- 音频转码(压缩)
- 取代资源管理器的工具 Directory Opus
- mysql性能优化-慢查询分析、优化索引和配置
- 分布交互式CosiMate 8.1 2016.04多学科协同仿真计算平台
- 九大排序算法
- HDU-1005(基础题)
- HTML5中关于文件的上传
- Unity 工具-Opus音频压缩(安卓篇)
- VMware10.0.1下CentOS6.5的图文安装教程
- 哈工大LTP部署及测试Demo
- Mybatis+spring+springmvc+swagger
- informix datetime数据类型存储内容详解
- js引擎的使用
- leetcode 37. Sudoku Solver 一个经典的DFS深度优先搜索的做法
- Hadoop学习-错误记录:namenode、datanode、secondarynamenode未启动
- 51Nod-1412-AVL树的种类(树形dp)