Opus从入门到精通(三)手撸一个Opus编码程序

Opus从入门到精通(三)手撸一个Opus编码程序

前面Opus从入门到精通(二):编解码器使用介绍了opus编解码器的API,这边文章介绍编码API的具体使用示例.分Android,ios,Linux三个系统进行实现.

编码是我们对脉冲编码调制(Pulse Code Modulation,PCM)的数据进行压缩操作,我们通常通过操作系统麦克风API获取PCM数据,或者从存储的现成的文件的PCM数据:

  1. 麦克风回调二进制:

     - Android的AudioRecorder
     - IOS的Audio Unit
    
  2. 麦克风存储到文件:

     - Android的MediaRecorder
     - IOS的AVFoundation AVAudioRecorder
    

PCM数据大小怎么计算呢?根据采样率采样格式,声道数计算.根据前面文章音视频之音频知识入门介绍:
PCM文件大小 = 采样率 * 采样格式 * 声道数 * 录制时长
采样率即一秒多少采样,采样格式指一个采用占多少字节,通常一个采用使用一个字节或者两个字节,所以采样率*采样格式计算出一秒钟一个声道PCM多少字节,乘以声道数,算出一秒钟PCM大小,再乘以时长就可以计算出PCM文件大小.

下面分别使用Android平台的麦克风二进制回调方式和IOS平台的麦克风文件回调方式采集,并使用OPUS编码器进行编码.

Android平台编码程序实现

配置工程

AndroidStudio新建工程,在见一个Andorid Library模块library,在library下面新建类OpusUtil,并写好native方法:

public class OpusUtil {
  static {
    System.loadLibrary("opusutil-lib");
  }
  //创建编码器
  public static native long _createOpusEncoder(int sampleRateInHz, int channel, int bitrate,
      int complexity);
  //编码一帧PCM数据
  public static native int _encodeOpus(long enc, short[] buffer, int offset, byte[] encoded);
  //释放编码器
  public static native void _destroyOpusEncoder(long enc);
}

在src/main下面新建cpp目录,把从官网下载的opus编码器拷贝到cpp下,新建media_jni.c用于实现JNI方法
在library根目录下创建我们的CMakeLists.txt,并在build.gradle下面配置cmake文件:

externalNativeBuild {
    cmake {
      path file('CMakeLists.txt')
    }

CMakeLists.txt将opus编码器文件配置好:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")

set(libs_include_opus_DIR src/main/cpp/libopus)
include_directories(
        ${libs_include_opus_DIR}/include
        ${libs_include_opus_DIR}/celt
        ${libs_include_opus_DIR}/silk
        ${libs_include_opus_DIR}/silk/float
        ${libs_include_opus_DIR}/src)

add_library(
        opusutil-lib

        SHARED

        src/main/cpp/util.c
        src/main/cpp/media_jni.c
        src/main/cpp/jni_utils.c
        src/main/cpp/libopus/src/opus_multistream_decoder.c
        src/main/cpp/libopus/src/opus_multistream_encoder.c
        src/main/cpp/libopus/src/opus_multistream.c
        src/main/cpp/libopus/src/opus_encoder.c
        src/main/cpp/libopus/celt/celt_encoder.c
        src/main/cpp/libopus/celt/bands.c
        src/main/cpp/libopus/celt/entcode.c
        src/main/cpp/libopus/celt/entdec.c
        src/main/cpp/libopus/celt/entenc.c
        src/main/cpp/libopus/celt/mathops.c
        src/main/cpp/libopus/celt/vq.c
        src/main/cpp/libopus/celt/cwrs.c
        src/main/cpp/libopus/celt/celt.c
        src/main/cpp/libopus/celt/mdct.c
        src/main/cpp/libopus/celt/kiss_fft.c
        src/main/cpp/libopus/celt/bands.c
        src/main/cpp/libopus/celt/pitch.c
        src/main/cpp/libopus/celt/celt_lpc.c
        src/main/cpp/libopus/celt/quant_bands.c
        src/main/cpp/libopus/celt/laplace.c
        src/main/cpp/libopus/celt/modes.c
        src/main/cpp/libopus/celt/rate.c
        src/main/cpp/libopus/silk/lin2log.c
        src/main/cpp/libopus/silk/enc_API.c
        src/main/cpp/libopus/silk/resampler.c
        src/main/cpp/libopus/silk/resampler_private_IIR_FIR.c
        src/main/cpp/libopus/silk/resampler_private_up2_HQ.c
        src/main/cpp/libopus/silk/resampler_private_down_FIR.c
        src/main/cpp/libopus/silk/resampler_private_AR2.c
        src/main/cpp/libopus/silk/resampler_rom.c
        src/main/cpp/libopus/silk/float/encode_frame_FLP.c
        src/main/cpp/libopus/silk/gain_quant.c
        src/main/cpp/libopus/silk/log2lin.c
        src/main/cpp/libopus/silk/encode_pulses.c
        src/main/cpp/libopus/silk/code_signs.c
        src/main/cpp/libopus/silk/tables_pulses_per_block.c
        src/main/cpp/libopus/silk/tables_other.c
        src/main/cpp/libopus/silk/shell_coder.c
        src/main/cpp/libopus/silk/encode_indices.c
        src/main/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

轻口味

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值