也叫做响度(Loudness),人耳对声音强弱的主观感觉就是响度,响度和声波振动的幅度有关。一般说来,声波振动幅度越大则响度也越大。当我们用较大的力量敲鼓时,鼓膜振动的幅度大,发出的声音响;轻轻敲鼓时,鼓膜振动的幅度小,发出的声音弱。
人耳对声音高低的感觉称为音调(也叫音频),音调主要与声波的频率有关。声波的频率高,则音调也高。当我们分别敲击一个小鼓和一个大鼓时,会感觉它们所发出的声音不同。小鼓被敲击后振动频率快,发出的声音比较清脆,即音调较高;而大鼓被敲击后振动频率较慢,发出的声音比较低沉,即音调较低。
一般音调:儿童 > 女生 > 男生
人耳听觉音频范围是 20Hz-20000Hz (若音频压缩时不在这个范围内的数据就可以砍掉)。
同一种乐器,使用不同的材质来制作,所表现出来的音色效果是不一样的,这是由物体本身的结构特性所决定的。
音色与声波的振动波形有关,或者说与声音的频谱结构有关。
日常生活中我们听到的声波波形信号都是时间连续的,我们称这种信号为模拟信号,模拟信号需要量化成数字信号(离散、不连续的)以后才能被我们的计算机识别。音频的量化过程可以简单分为以下 5 个步骤:
现实生活中的声音表现为连续的、平滑的波形,其横坐标为时间轴,纵坐标表示声音的强弱。
按照一定的时间间隔在连续的波上进行采样取值,如下图所示取了 10 个样。
将采样得到的值进行量化处理,也就是给纵坐标定一个刻度,记录下每个采样的纵坐标的值。
将每个量化后的样本值转换成二进制编码,可以看到模拟信号经过采样、量化、编码后形成的二进制序列就是数字音频信号。
将所有样本二进制编码连起来存储在计算机上就形成了数字信号。
每个采样点能够表示的数据范围,用多少个 bit 表示。采样位数通常有 8 bits 或 16 bits 两种,采样位数越大,所能记录声音的变化度就越细腻,相应的数据量就越大。8 位字长量化(低品质)和 16 位字长量化(高品质),16 bit 是最常见的采样精度。
采样位数也被叫做采样精度、量化级、量化数据位数等。
单位时间内对模拟信号的采样次数,也就是采样频率,采样频率越高,声音的还原就越真实越自然,当然数据量就越大。
我们日常生活中常见的采样率:
对于高于 48KHz 的采样频率人耳已无法辨别出来了,所以在电脑上没有多少使用价值。
为了播放声音时能够还原真实的声场,在录制声音时在前后左右几个不同的方位同时获取声音,每个方位的声音就是一个声道。声道数是声音录制时的音源数量或回放时相应的扬声器数量,有单声道、双声道、多声道。
也叫比特率,指每秒传送的数据量,单位为 bps(Bit Per Second),码率代表了压缩质量,码率越高,每秒传送的数据就越多,音质就越好。
公式:
码率 = 采样率 * 采样位数 * 声道数
例如:
CD 音质,采样率 44.1KHz,采样位数 16 bit,立体声(双声道)
码率 = 44.1 * 1000 * 16 * 2 = 1411200 bps = 176400 Bps
根据上面的码率,录制一分钟需要 176400 Bps * 60秒 / 1024 / 1024 = 10.09MB
PCM(Pulse Code Modulation),即脉冲编码调制,对声音进行采样、量化过程,未经过任何编码和压缩处理。
PCM 数据是最原始的音频数据完全无损,所以 PCM 数据虽然音质优秀但体积庞大,为了解决这个问题先后诞生了一系列的音频格式,这些音频格式运用不同的方法对音频数据进行压缩,通常分为无损压缩(ALAC、APE、FLAC)和有损压缩(MP3、AAC、OGG、WMA)两种。
音频数据是流式的,本身没有明确的一帧帧的概念,在实际的应用中,为了音频算法处理/传输的方便,一般约定俗成取 2.5ms~60ms 为单位的数据量为一帧音频。这个时间被称之为 “采样时间”,其长度没有特别的标准,它是根据编解码器和具体应用的需求来决定的。
例如最常见的音频格式 MP3 的数据通常由两部分组成,一部分为 “ID3” 用来存储歌名、演唱者、专辑、音轨数
等信息,另一部分为音频数据。音频数据部分以帧(frame)为单位存储,每个音频都有自己的帧头,如下图所示就是一个 MP3 文件帧结构图。
MP3 中的每一帧都有自己的帧头,其中存储了采样率等解码必须的信息,所以每一个帧都可以独立于文件存在和播放,这个特性加上高压缩比使得 MP3 文件成为了音频流播放的主流格式。帧头之后存储着音频数据,这些音频数据是若干个 PCM 数据帧经过压缩算法压缩得到的。
常见的音频编解码器包括 OPUS、AAC、Vorbis、Speex、iLBC、AMR、G.711 等。目前泛娱乐化直播系统采用 rtmp 协议,支持 AAC 和 Speex。
性能上来看,OPUS > AAC > Vorbis,其它的逐渐被淘汰。
常见的音频相关软件有:音乐播放器、视频播放器、电话、录音软件等等
这部分接口直接提供给 Application 层定制开发 Audio 相关功能,相关代码主要在:
PATH:frameworks/base/media/java/android/media
可供使用的 API 有
AudioRcorder 和 MediaRecorder 主要用于完成音视频数据的采集,而 AudioTrack 和 MediaPlayer 则负责音频数据的输出。
MediaPlayer 能够播放多种格式的声音文件,比如 MP3、AAC、WAV 等,MediaPlayer 的实现包含了 AudioTrack,而 AudioTrack 因为不创建解码器,仅能播放无须解码的 PCM 流(wav 格式)。
PATH: frameworks/av/media/libaudioclient
PATH: frameworks/av/services/audioflinger(audiopolicy)
从整体设计上看,硬件抽象层是 AudioFlinger 直接访问的对象,厂商会在这一层添加自己的实现,桥接硬件驱动和上层框架。
Android Audio 上层设计框架中与硬件抽象层直接交互的只有 AudioFlinger 和 AudioPolicyService。实际上后者并不是一个真实的设备,只是采用虚拟设备的方式让厂商可以方便地定制自己的策略。抽象层的任务就是提供统一的接口来定义它与 AudioFlinger/AudioPolicyService 之间的通信方式,不论 Audio 系统依赖 ALSA-lib 还是 tinyalsa,都不应该对上层框架造成破坏。下面来介绍 Android Audio Hal 的统一接口设计。
在 Android Audio 系统设计中,无论是上层还是下层都是用一个管理类和输入输出两个类来表示 Audio 系统,输入输出两个类负责数据通道,在各个层级间对应关系:
– | Audio 管理类 | Audio 输入 | Audio 输出 |
---|---|---|---|
Java | android.media.AudioSystem | android.media.AudioRecord | android.media.AudioTrack |
native | AudioSystem | AudioRecord | AudioTrack |
AudioFlinger | IAudioFlinger | IAudioRecord | IAudioTrack |
硬件抽象层 | AudioHardwareInterface | AudioStreamOut | AudioStreamIn |
在 Android libhardware_legacy 中定义的音频相关的参考硬件抽象层数据结构:
音频设备描述符:
struct legacy_audio_device {
struct audio_hw_device device;
struct AudioHardwareInterface *hwif;
};
音频输入描述符
struct legacy_stream_in {
struct audio_stream_in stream;
AudioStreamIn *legacy_in;
};
音频输出描述符:
struct legacy_stream_out {
struct audio_stream_out stream;
AudioStreamOut *legacy_out;
};
audio_hw_device 和 AudioHardwareInterface、audio_stream_out 和 AudioStreamOut、audio_stream_in 和 AudioStreamIn 定义的接口基本一致,这是为了兼容 Android 先后版本,下面的分析以 AudioHardwareInterface、AudioStreamIn、AudioStreamOut 作为硬件抽象层音频管理和输入输出结构体定义。
AudioHardwareInterface 负责实现基础类和管理,而 AudioHardwareGeneric.cpp、AudioHardwareStub.cpp、AudioDumpInterface.cpp 和 A2dpAudioInterface.cpp 各自代表一种 Auido 硬件抽象层的实现。
一般情况下用的 ALSA 音频架构