本文Android Studio编译部分参考自:AndroidStudio编译faac的so动态库
在音视频开发中,常常需要将原生音频PCM数据转为AAC、MP3、AC3等音频格式,然后再将音频数据放入到视频编码中进行处理,或者将PCM转为音频格式后,再进行音频调音、优化等处理。不论最后音频呈现的形式是怎么样的,最初处理的还是原生音频PCM数据。
音频格式
PCM
PCM(pulse code modulation,脉码调制录音),所谓的PCM录音就是将声音等模拟信号变成符号化的脉冲列,再予以记录。PCM信号是由[1]、[0]等符号构成的数字信号,而未经过任何编码和压缩处理,与模拟信号相比,不易受传送系统的杂波及失真的影响。动态范围广,可以得到音质相当好的影响效果。
MP3
MP3是一种音频压缩技术,全称是动态影响专家压缩技术标准音频层面3(Moving Picture Experts Group Audio Layer 3),简称MP3。利用MP3技术,可以将音乐以1:10甚至1:12的压缩率,压缩成容量较小的文件,而重放的音质与最初的不压缩音频相比没有明显的下降。MP3利用人耳对高频声音信号不敏感的特性,将时域波形信号换为频域信号,并将划分成多个频段,对不同的频段使用不同的压缩率,如对高频信号采用较大压缩率,或者直接忽略;对低频信号使用较小的压缩率,保证信号不失真。这样就达到较高的压缩率。
AC3
AC3(Audio Coding Version 3),是Dolby实验室所发展 的有损音频编码格式,AC3被广泛应用于5.1声道。AC3普及程度很高,以384-448kb/s的码率应用于激光唱片和DVD,也以640kb/s的码率广泛应用于电影院。
AAC
AAC是高级编码(Advanced Audio Coding)的缩写,一种专为声音数据设计的文件压缩格式。最初基于MPEG-2的音频编码技术,后来MPEG-4出现,AAC又重新集成了新技术,称为MPEG-4 AAC。与MP3相比,AAC采用了全新的算法进行编码,在感觉声音质量没有明显减低的前提下,文件格式更加小巧。缺点在于:AAC属于有损编码,与其他编码格式有实质上的区别。
AAC有如下规格,以适应不用的场合需要:
- MPEG-2 AAC LC: 低复杂度规格(low complexity),比较简单,没有增益控制,但是提高了编码效率。
- MPEG-2 AAC Main:主规格
- MPEG-2 AAC SSR:可变采样率规格(Scaleable Sample Rate)
- MPEG-4 AAC LC:低复杂度规格(low complexity),手机中常见的Mp4文件的音频部分就使用该规格的音频文件
- MPEG-4 AAC Main:主规格,包含了除增益控制之外的全部功能,其音质最好
- MPEG-4 AAC SSR:可变采样率规格(Scaleable Sample Rate)
- MPEG-4 AAC LTP:长时其的预测规格(Long Term Predicition)
- MPEG-4 AAC LD:低延迟规格(Low Delay)
- MPEG-4 AAC HE:高效率规格(High Efficieney),这种规格适用于低码率编码,有Nero ACC编码器支持。
总的来说,AAC规格,主要分为MPEG2、MPEG4两代,每代中又有主规格、可变采样率规格、低复杂度及效率类规格。
FAAC
FAAC和FAAD2分别是开源的MPEG-2和MPEG-4 AAC音频编码和解码器。FAAC的主要目的是将原声PCM音频数据编码成AAC格式的音频数据;而FAAD2则相反,是将AAC格式的音频数据解码成原生PCM音频数据。
FAAC编译
想要在Android系统中使用FAAC编码,就需要将FAAC这个库编译成动态库(.so)。编译FAAC需要NDK的环境,可以在Linux下进行通过Shell脚本编译,也可以通过Android Studio进行编译。
到官网下载源码包,这里下载的是faac-1.29.9.2.tar.gz版本
Android Studio编译
-
创建一个支持NDK的Android项目,然后将所有源代码导入到JNI目录中,并将config.h.in文件的配置名修改为config.h,否则会报错。
- 然后在Jni目录中创建Android.mk和Application.mk文件
- Android.mk
LOCAL_PATH := $(call my-dir)
FAAC_TOP := $(LOCAL_PATH)
include $(CLEAR_VARS)
include $(FAAC_TOP)/libfaac/Android.mk
- Application.mk:标注要构建的动态库的类型,all表示全平台
APP_ABI := all`
- 在libfaac目录中创建Android.mk文件,表明编译时需要用到哪些源码和依赖工具。
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libfaac
LOCAL_SRC_FILES:= \
aacquant.c \
backpred.c \
bitstream.c \
channels.c \
fft.c \
filtbank.c \
frame.c \
huffman.c \
ltp.c \
midside.c \
psychkni.c \
tns.c \
util.c \
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(FAAC_TOP) \
$(FAAC_TOP)/include
LOCAL_CFLAGS:= -DHAVE_CONFIG_H
include $(BUILD_SHARED_LIBRARY)
- 在module的build.gradle中加入ndkBuild的配置
sourceSets { main { jni.srcDirs = ['src/main/jni/'] } }
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
-
最后一步,rebuild Project后,就会生成全平台的libfaac.so文件
Linux编译
- 同样下载源码包,然后进行解压
tar -zxvf faac-1.29.9.2.tar.gz
- 创建一个build_faac.sh文件,并通过Vim写入如下内容:ndk路径、编译平台、编译依赖、生成目标地址等。
#!/bin/bash
CPU=arm
NDK=/usr/ndk/android-ndk-r14b
export PLATFORM=$NDK/platforms/android-9/arch-arm
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin
export PREFIX="$(pwd)/android/arm"
export CROSS_COMPILE=$PREBUILT/arm-linux-androideabi-
export CFLAGS="-DANDROID -fPIC -ffunction-sections -funwind-tables -fstack-protector -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300"
export CPPFLAGS="$CFLAGS"
export CFLAGS="$CFLAGS"
export CXXFLAGS="$CFLAGS"
export CXX="${CROSS_COMPILE}g++ --sysroot=${PLATFORM}"
export LDFLAGS="$LDFLAGS"
export CC="${CROSS_COMPILE}gcc --sysroot=${PLATFORM}"
export NM="${CROSS_COMPILE}nm"
export STRIP="${CROSS_COMPILE}strip"
export RANLIB="${CROSS_COMPILE}ranlib"
export AR="${CROSS_COMPILE}ar"
./configure --program-prefix=$PREFIX --without-mp4v2 --host=arm-linux
make
cp ./libfaac/.libs/*.a $PREFIX/lib
cp ./libfaac/.libs/*.so $PREFIX/lib
cp ./include/*.h $PREFIX/include
- 给build_faac.sh添加执行权限,然后执行
chmod +x build_faac.sh
./build_faac.sh
- 执行完毕后,就会在android/arm/lib中找到libfaac.so动态库文件。注意此动态库只支持armv7-a的架构,如果需要支持arm64-v8a、x86、x86_64等架构,就需要对编译脚本中PREBUILT、CFLAGS等进行相应的修改,再进行编译。
FAAC的编译就到此结束了,至于他的使用会在后续文章中和其他开源库的使用一同讲诉。