Android的音视频开发是我暂定的一个职业发展的一个方向,通过自学记录一些记了又忘记的知识。
采样率(samplerate)
采用就是把模拟信号数字化的过程,不仅仅是音频需要采样,所有的模拟信号都需要通过采样转换为可以用0101来表示的数字信号。常用的音频采样频率有:8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz、96kHz、192kHz等。
AudioRecord构造参数中的sampleRateInHz。
量化精度(位宽)
上图中,每一个红色的采样点,都需要用一个数值来表示大小,这个数值的数据类型大小可以是:4bit、8bit、16bit、32bit等等,位数越多,表示得就越精细,声音质量自然就越好,当然,数据量也会成倍增大。
AudioRecord构造参数中的audioFormat。
声道数(channels)
由于音频的采集和播放是可以叠加的,因此,可以同时从多个音频源采集声音,并分别输出到不同的扬声器,故声道数一般表示声音录制时的音源数量或回放时相应的扬声器数量。
AudioRecord 构造参数中的channelConfig。
音频帧(frame)
视频我们知道每一帧是一张图片,音频数据是流式的,没有明确的一帧帧的概念,但是在音频处理的时候,一般取2.5ms-60ms为单位数据量的一帧音频。
假设某通道音频信号采样率为8kHz,位宽位16bit,20ms一帧,双通道,那么一帧音频的大小为:
8000*16bit*0.02*2=5120bit=640byte
音频编码
是将音频采样数据(PCM等)压缩成为音频码流,从而降低音频的数据量。模拟的音频信号转换为数字信号需要经过采样和量化,量化的过程被称之为编码,根据不同的量化策略,产生了许多不同的编码方式,常见的编码方式有:PCM 和 ADPCM
为什么要音频编码
存储一秒钟采样率为44.1KHz,位深为16bit,双声道的PCM编码的音频信号,需要
44100*16bit*2 / 8/1024 = 172.2KB的空间,那么1分钟则约为10.09M。
这对大部分用户是不可接受的。
只有2种方法,降低采样指标或者压缩。
Android SDK对于音频采集提供两套API:MediaRecorder和AudioRecorder,前者是偏上层的一个API,可以直接把手机麦克风录入的音频数据进行编码压缩为AMR,MP3等并保存文件。后者接近底层,可以灵活控制,得到原始的一帧帧PCM音频数据。
当要简单的把数据采集为音频文件,就使用MediaRecorder,如果要对音频做进一步的算法处理就使用AudioRecorder。
AudioRecord输出是PCM语音数据,如果保存成音频文件,是不能够被播放器播放的,所以必须先写代码实现数据编码以及压缩。
AudioRecord适用于对采集的音频数据进行二次处理的,我们首先看到代码AudioRecord类的构造函数。
/**
* Class constructor.
* Though some invalid parameters will result in an {@link IllegalArgumentException} exception,
* other errors do not. Thus you should call {@link #getState()} immediately after construction
* to confirm that the object is usable.
* @param audioSource the recording source.
* See {@link MediaRecorder.AudioSource} for the recording source definitions.
* @param sampleRateInHz the sample rate expressed in Hertz. 44100Hz is currently the only
* rate that is guaranteed to work on all devices, but other rates such as 22050,
* 16000, and 11025 may work on some devices.
* {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value
* which is usually the sample rate of the source.
* {@link #getSampleRate()} can be used to retrieve the actual sample rate chosen.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_IN_MONO} and
* {@link AudioFormat#CHANNEL_IN_STEREO}. {@link AudioFormat#CHANNEL_IN_MONO} is guaranteed
* to work on all devices.
* @param audioFormat the format in which the audio data is to be returned.
* See {@link AudioFormat#ENCODING_PCM_8BIT}, {@link AudioFormat#ENCODING_PCM_16BIT},
* and {@link AudioFormat#ENCODING_PCM_FLOAT}.
* @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written
* to during the recording. New audio data can be read from this buffer in smaller chunks
* than this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum
* required buffer size for the successful creation of an AudioRecord instance. Using values
* smaller than getMinBufferSize() will result in an initialization failure.
* @throws java.lang.IllegalArgumentException
*/
public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes)
看这个构造函数的参数的解释可以明白个七七八八。具体的介绍如下:
音频采集的输入源,可选的值以常量的形式定义在 MediaRecorder.AudioSource 类中,常用的值包括:DEFAULT(默认),VOICE_RECOGNITION(用于语音识别,等同于DEFAULT),MIC(由手机麦克风输入),VOICE_COMMUNICATION(用于VoIP应用)等等。
采样率,注意,目前44100Hz是唯一可以保证兼容所有Android手机的采样率。
通道数的配置,可选的值以常量的形式定义在 AudioFormat 类中,常用的是 CHANNEL_IN_MONO(单通道),CHANNEL_IN_STEREO(双通道)
这个参数是用来配置“数据位宽”的,可选的值也是以常量的形式定义在 AudioFormat 类中,常用的是 ENCODING_PCM_16BIT(16bit),ENCODING_PCM_8BIT(8bit),注意,前者是可以保证兼容所有Android手机的。
配置的是 AudioRecord 内部的音频缓冲区的大小,该缓冲区的值不能低于一帧“音频帧”(Frame)的大小,而前一篇文章介绍过,一帧音频帧的大小计算如下:
int size = 采样率 x 位宽 x 采样时间 x 通道数
在Android开发中,AudioRecord 类提供了一个帮助你确定这个 bufferSizeInBytes 的函数,原型如下:
int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat);
不同的厂商的底层实现是不一样的,但无外乎就是根据上面的计算公式得到一帧的大小,音频缓冲区的大小则必须是一帧大小的2~N倍。
操作AudioRecord步骤如下:
示例代码:
注意添加RECORD_AUDIO权限。
点击查看
MediaRecorder可以直接把手机麦克风录入的音频数据进行编码压缩为AMR,MP3等并保存文件。
简单操作使用MediaRecorder类步骤如下:
示例代码:
注意添加权限:
WRITE_EXTERNAL_STORAGE;
RECORD_AUDIO;
点击查看
而AudioRecord录制的是PCM格式的音频文件,需要用AudioTrack来播放,AudioTrack更接近底层。
在用MediaRecorder进行录制音视频时,最终还是会创建AudioRecord用来与AudioFlinger进行交互。
C++层MediaRecorder创建AudioRecord类的代码位于AudioSource类构造函数中.
MediaRecorder录制的数据是 amr MP3 格式;AudioRecorder录制出来的是比较原始的PCM音频格式;PCM经过编码压缩可以为 amr MP3 AAC。
优缺点: