当前位置: 首页 > news >正文

音视频处理(二): 一文讲清楚音频处理流程:采样、压缩和播放

一、前言

当前音视频技术很火,在IPC、无人机、手机、直播等各行各业都需要用到音视频技术,本文针对音频处理全流程:采样、数据保存、压缩、播放做一个详细介绍。

  • 音频源端处理流程
mic
采样
pcm
wav文件
压缩
mp3\aac\opus
  • 播放端处理流程
解压
重采样
播放

二、音频采样

2.1 模数转换-量化

音频采集设备产生的是模拟电平数据,计算机中存储的是数字信号,需要进行采样、量化成数字信号。音频采样有如下几个参数:

  • 采样率
  • 位深
  • 通道数

2.1.1 采样率

以一段声音信号为例,我们按固定时间间隔(如每0.25单位)进行采样,采样时间频率就是采样率。

那这里有几个常见的:一个是8K,第二16K,32K,44.1K,48K,这都是我们常见的采样率。采样率越高,我们的数字信号与模拟信号之间的模仿的就越接近,它的误差就越小。采样率越低,有一些很敏感的信息就忽略掉了。对于我们通常打电话来说,一般都是8K的采样率,是有一些失真的。但是如果你是48K的这个采样率,实际基本上就完全还原了人的这个声音,和面对面的说话音质基本接近。
在这里插入图片描述

一般通话时的采样率为8KHz,常用的媒体采样率有44KHz,对于一些蓝光影片采样率高达1MHz。

- 48000 Hz(48k)
- 44100 Hz(44.1k)
- 32000 Hz
- 16000 Hz
- 8000 Hz(最低常用值)

2.1.2 采样大小(位深)

采样大小,或者叫做位深,每个采样值用多少位的数据表示,如8bit、16bit等,位深越大,声音越清晰细腻。最常见的是16位的位深,那表示的范围是-32768到32768。

2.1.3 声道数

声道数分为单声道、双声道和多声道(立体声)

2.2 采集数据的保存

2.2.1 PCM数据格式

采集到的音频原始数据是以二进制形式在计算机中存储传输的,比如音频采集设备和CPU之间就是通过二进制方波进行传输。这些二进制数据其实就是PCM数据,PCM(脉冲编码调制),所谓脉冲:指的是音频原始采样量化后的数据,像一个个脉冲。调制指的是将十进制数据转换成二进制数据传输。

在这里插入图片描述

如果是多通道的数据,PCM数据是交叉排列:

+---------+-----------+-----------+-----------+-----------+----FL 	|     FR    |     FL 	  |     FR    |     FL 	  |    
+---------+-----------+-----------+-----------+-----------+----

PCM数据是原始数据流,是不包含描述信息的比如通道、采样率、位深等信息。在设备之间传输时需要先传输额外的描述信息,比如CPU和MIC直接传输时,音频驱动会设置好采样率等信息。但是通过网络传输,或者跨设备之间传输,描述信息回丢失,导致音频数据无法播放。所以需要文件形式保存,加上额外的描述头信息,这就是WAV数据格式。

2.2.2 WAV文件格式

WAV是文件格式,在PCM的基础上增加描述信息,便于传输。WAV文件一般保存的是未经压缩的数据,所以文件是较大的,当然也可以保存压缩数据,由头部字段控制。但大多数情况下 99% 我们都用WAV来存储PCM原始数据。

头部保存哪些音频关键信息?

在讲解文件格式前,从原理方面先想一下如果让我们设计一个文件头格式,该如何设计,其实就是搞清楚音频解码时需要哪些关键信息:

音频量化信息:
1) 采样率
2)位深
3)通道数4)数据压缩格式
5)数据长度
6) 时长
  • RIFF格式,3个trunk

WAV文件遵循RIFF文件规范,RIFF(Resource Interchange File Format) 是windows平台广泛使用的文件规范。它基本单位是trunk,每个trunk描述一个类型的资源,用ID表示类型,size表示trunk数据的大小。RIFF文件有一个公共的头RIFF头,其中使用asiic码WAVE表示WAV文件类型。 WAV另外还有两个trunk:fmt和trunk

trunk说明
RIFF trunkRIFF文件通用头,WAVE表示WAV文件
fmt trunk音频描述信息,fmt表示音频格式。保存量化信息:采样率、位深、通道数
data trunk音频数据信息,保存PCM数据
在这里插入图片描述

WAV也可以保存音频压缩数据,但是常见的是PCM,文件头中的AutioFormat编码格式取值如下:

格式编码格式名称fmt 块长度fact 块
0x01PCM / 非压缩格式16
0x02Microsoft ADPCM18
0x03IEEE float18
0x06ITU G.711 a-law18√
0x07ITU G.711 μ-law18√
0x031GSM 6.1020
0x040ITU G.721 ADPCM
0xFFFE见子格式块中的编码格式40

音频的量化参数使用fmt trunk来表示,那么时间长度是如何保存的呢?

音频时长参数不用额外记录,根据采样频率,按照采样频率顺序往下播放就可以。

  • 查看原始数据
hd /home/share/samba/sample-15s.wav -n 128
00000000  52 49 46 46 24 9c 33 00  57 41 56 45 66 6d 74 20  |RIFF$.3.WAVEfmt |
00000010  10 00 00 00 01 00 02 00  44 ac 00 00 10 b1 02 00  |........D.......|
00000020  04 00 10 00 64 61 74 61  00 9c 33 00 0f f8 0f f8  |....data..3.....|
00000030  f3 fb f3 fb 66 0a 66 0a  49 09 49 09 83 fc 83 fc  |....f.f.I.I.....|
00000040  fd fd fd fd b2 06 b2 06  b1 03 b1 03 86 02 86 02  |................|
00000050  f5 0c f5 0c 85 0d 85 0d  fc 02 fc 02 8f 06 8f 06  |................|
00000060  d2 12 d2 12 11 0e 11 0e  02 01 02 01 a9 02 a9 02  |................|
00000070  9b 09 9b 09 2e 05 2e 05  4c 02 4c 02 53 09 53 09  |........L.L.S.S.|
00000080

说明:

- 52 49 46 46:对应的 ASCII 字符为 `RIFF`
- 24 9c 33 00:ChunkSize,对应的十六进制是 0x339c24=3382308 + 8 和上面的文件大小一致
- 57 41 56 45:对应的 ASCII 字符为 `WAVE`
- 66 6d 74 20:对应的 ASCII 字符为 `fmt`
- 10 00 00 00:FmtSize 0x10=16 代表 PCM 编码方式
- 01 00:对应为 1,代表 PCM 编码方式
- 02 00:通道个数,通道数为 2
- 44 ac 00 00:采样频率 0xac44=44100=44.1KHz
- 10 b1 02 00:传输速率,转化为十六进制为: 0x2b110=176400 通过此值可以计算该音频的时长:3382308/176400 = 19.174s
- 04 00:数据对齐单位
- 10 00:采样位数 0x10=16
- 64 61 74 61:对应的 ASCII 字符为 `data`
- 00 9c 33 00:对应该音频的 raw 数据的大小,转化为十六进制为 0x339c00=3382272,此值等于 0x339c24 - 44

三、音频压缩

3.1 码率

码率bitrate指的是音频播放时的数据吞吐量速率,实时直播的场景时也表示网络传输的数据量大小,PCM未经压缩的数据,码率是比较大的。可以根据位深、采样率和通道数计算出码率信息。

码率 = 采样率x位深x通道数

例如,采样率44.1k,位深为16bit,通道数是2,那么码率=44.1k x 16 x 2 = 1411.2kb/s。已经是1.4Mbps的速率,是很大的,比如实时直播的场景,再加上视频数据,网络带宽占用很大,所以需要对音频数据进行压缩。

3.2 音频压缩

音频压缩技术是保证人耳听觉效果不失真的情况尽可能的压缩数据,分为:

  • 有损压缩
  • 无损压缩

音频压缩的本质是消除两种冗余信息:

  • 统计冗余:音频信号在时域和频域上的相关性
  • 感知冗余:人耳听觉特性无法感知的音频信息

3.2.1 有损压缩

有损压缩的核心是根据人耳的听觉效应,从原始数据中去掉一些人耳无法辨识的一些冗余信息。比如人耳有以下特性,以及对应的压缩算法处理。

心理声学基础:

1)人耳只能听到20-20KHz之间的声音,其他的听不到。 => 去掉低频和高频数据。

2)多个人说话只能听到声音大,高频会覆盖低频。=> 频率掩蔽。

3)人耳对不同频率的敏感度不同(如2-4kHz最敏感)。=> 其他频率低于阈值的信号可忽略。

4)短时间内出现的弱信号可能被强信号掩盖。=> 时域掩蔽。

下面重点讲一下频率掩蔽和时域掩蔽技术。

3.2.1.1 频域掩蔽

下图描述了频域遮蔽,音频数据是时域的,但是可以使用傅里叶变换转成频域的,频域上高频遮蔽低频信号。低于遮蔽源会产生一个遮罩门槛,低于遮蔽门槛的信号都被遮蔽掉,这些信号进行压缩时可以去掉。

在这里插入图片描述

3.2.1.2 时域掩蔽

时域遮蔽表示遮蔽源的高频声音对时间前后的数据做一定影响,导致人耳听不到。前后时间内越靠近遮蔽源时间越容易被遮蔽,下图是时域遮蔽示意图。

在这里插入图片描述

3.2.1.3 核心有损压缩算法

下表对比了主流有损压缩算法的特点:

算法压缩比主要特点应用场景
MP3 (MPEG-1 Audio Layer III)10:1-12:1使用MDCT变换和心理声学模型,兼容性极佳音乐存储、网络音频传输
AAC (Advanced Audio Coding)优于MP3(尤其在低码率下)MDCT变换、预测编码、噪声整形,MP3的继任者iTunes、YouTube、iOS系统默认音频格式
Ogg Vorbis比MP3高约30%完全开源,灵活的块大小和真VBR支持开源软件、视频游戏
Opus可变(支持低比特率语音到高保真音频)结合SILK(语音)和CELT(音频)算法,低延迟实时通信、WebRTC默认音频编码
3.2.1.4 关键技术实现
  1. 感知编码:利用掩蔽效应,在强信号附近减少或删除弱信号的编码精度。
  2. 频域变换:通过MDCT(改进型离散余弦变换)将时域信号转换为频域表示,便于按频率子带分别处理。
  3. 量化与比特分配:根据心理声学模型动态分配比特资源,对重要频段高精度量化,次要频段粗量化。
  4. 立体声编码:利用左右声道的相关性,采用联合立体声、强度立体声等技术减少冗余。

3.2.2 无损压缩

无损压缩式是不会丢失原数据信息,常见的zip、gz都是属于无损压缩。音频无损压缩技术主要利用huffman编码,将高频出现的信息使用小的值表示建立查找表,减少占用空间。核心技术原理如下:

  1. 线性预测编码:利用音频信号的短时相关性,用过去样本预测当前样本,编码预测残差而非原始信号。 预测公式为:x1=∑i=1paix[n−i] 残差计算公式为:e[n]=x[n]−x2。这里和视频压缩h264编码中的I帧和P帧的概念类似,都是基于时间相关性保存差值的。
  2. 熵编码:根据符号出现概率分配变长码字,常见方法包括: Rice编码:专为小整数优化的Golomb-Rice编码,FLAC主要采用 霍夫曼编码:构造最优前缀码,用于ALAC、WAVPACK等格式。huffman编码主要是利用信息出现的频率进行
  3. 通道去相关:对立体声信号采用Mid/Side编码: Mid(中) = (L + R) / 2 Side(边) = (L - R) / 2。
3.2.2.1 主要无损格式对比
格式压缩率特点应用领域
FLAC30%-50%开源免费,硬件支持广泛,使用线性预测+Rice编码音乐流媒体(Tidal)、数字音乐商店(Bandcamp)
ALAC近似FLACApple专属格式,兼容苹果生态系统iOS、macOS设备
WAVPACK可调支持混合模式(有损+无损)特殊需求的音频归档
APE较高高压缩率但编解码效率较低个人音乐收藏

3.2.3 音频压缩算法性能对比

实际应用中,算法选择需综合考虑多种因素:

3.2.3.1 音质与码率关系
  • 有损压缩在128kbps以上码率通常能达到透明音质(大多数人无法区分与原始音频的差别)
  • 无损压缩保持100%音质,但文件体积通常比同源有损压缩大3-5倍
3.2.3.2 计算复杂度比较
  • 低复杂度:G.711、ADPCM(适合嵌入式系统和实时通信)
  • 中复杂度:MP3、AAC(平衡压缩效率与计算需求)
  • 高复杂度:Opus、无损编码(需要较高计算性能)
3.2.3.3 延迟特性
  • 电话语音编码(G.723、G.729):延迟最低(5-30ms)
  • 普通音频编码(MP3、AAC):中等延迟(50-100ms)
  • 高质量无损编码:延迟较高(100ms以上)

3.2.4 音频压缩技术发展轨迹与趋势

了解技术演进历史有助于把握未来发展方向:

3.2.4.1 技术演进历程
  1. 早期波形编码(1980s前):G.711(64kbps)、ADPCM(32kbps)
  2. 第一代感知编码(1990s):MP3、MP2(MPEG-1 Layer 2)
  3. 第二代感知编码(2000s):AAC、Ogg Vorbis
  4. 现代通用编码(2010s至今):Opus(融合语音与音频编码)
3.2.4.2 未来发展趋势
  1. AI驱动编码:基于神经网络的音频编码器(如Lyra、SoundStream)
  2. 自适应码率:根据网络条件动态调整音频质量
  3. 沉浸式音频:支持三维声场的下一代编码技术
  4. 端侧智能编码:在设备端实现更高效的智能压缩
3.2.4.3 总结与工程实践建议

作为音视频开发工程师,在选择音频压缩算法时需要考虑以下因素:

  1. 应用场景需求:实时通信优先低延迟编码器(Opus),音乐存储考虑音质与体积平衡(AAC/FLAC)
  2. 目标平台兼容性:移动端考虑硬件解码支持,跨平台需测试兼容性
  3. 计算资源约束:嵌入式设备选择低复杂度算法,服务器端可考虑高质量但高复杂度编码
  4. 系统集成复杂度:评估编码器集成、许可协议、专利费用等非技术因素

四、音频播放

4.1 重采样-多退少补

音频播放设备支持的采样率等信息可能跟音频数据不一致,这时就需要重采样。重采样的的核心策略是“多退少补”。对于音频数据采样率低于播放设备的,采用插帧处理,copy一份相同数据播放。对于对于音频数据采样率高于播放设备的,丢弃一帧数据。

关键原则:保持时长不变

重采样过程中有一个至关重要的原则:音频的总播放时长不应改变 。这意味着,一段 10 秒的音频在经过重采样后,播放时长应该仍然是 10 秒。实现这一点的关键在于正确处理采样率和样本数量的关系。计算公式如下

输出样本数 = 输入样本数 × 输出采样率 / 输入采样率

FFmpeg 提供了 av_rescale_rnd函数来安全高效地完成这个计算,避免整数溢出。

4.2 ffmpeg音频重采样

FFmpeg 提供了强大的工具来进行音频重采样,既可以通过命令行快速完成,也可以通过 API 编程进行集成。

4.2.1 命令行方式

使用 FFmpeg 命令行工具可以非常便捷地完成重采样任务。基本命令格式如下 :

ffmpeg -ar <输入采样率> -ac <输入声道数> -f <输入采样格式> -i <输入文件> -ar <输出采样率> -ac <输出声道数> -f <输出采样格式> <输出文件>

参数说明

  • -ar:指定音频采样率(如 44100, 48000)。
  • -ac:指定音频声道数(如 1 表示单声道,2 表示立体声)。
  • -f:指定采样格式(如 s16le, s32le, f32le)。

实例演示

将名为 44100_s16le_2.pcm的音频文件(44100 Hz, 16位有符号整数, 立体声)转换为 48000_f32le_1.pcm(48000 Hz, 32位浮点数, 单声道):

ffmpeg -ar 44100 -ac 2 -f s16le -i 44100_s16le_2.pcm -ar 48000 -ac 1 -f f32le 48000_f32le_1.pcm

4.2.2 编程方式(使用 Swresample 库)

对于集成到应用程序中的需求,FFmpeg 的 libswresample库是更强大的选择。其核心步骤和关键函数如下 :

  1. 创建并初始化重采样上下文:使用 swr_alloc_set_opts函数创建 SwrContext结构体,并设置输入和输出的音频参数(声道布局、采样格式、采样率),然后调用 swr_init进行初始化 。
  2. 分配输入/输出缓冲区:使用 av_samples_alloc_array_and_samples函数为音频数据分配内存空间 。
  3. 循环读取、转换、写入:在一个循环中,不断从输入源(如文件)读取原始 PCM 数据,然后调用核心函数 swr_convert进行实际的重采样计算。该函数会返回转换后的样本数量,随后将结果写入输出目标 。
  4. 处理延迟(排空重采样器):在所有输入数据转换完毕后,重采样器内部可能还存在一些缓存的数据。需要再次调用 swr_convert,但将输入参数设置为 NULL0,直到没有更多数据输出为止,以确保所有数据都被处理 。
  5. 清理资源:最后,务必释放所有分配的资源,包括缓冲区 (av_freep) 和重采样上下文 (swr_free) 。

下面是一个简化的代码逻辑片段,展示了这一流程:

// ... 变量定义(SwrContext*, 输入输出缓冲区等)和参数设置// 1. 创建并初始化重采样上下文
SwrContext *swr_ctx = swr_alloc_set_opts(NULL, out_ch_layout, out_sample_fmt, out_sample_rate,in_ch_layout, in_sample_fmt, in_sample_rate, 0, NULL);
swr_init(swr_ctx);// 2. 分配输入输出缓冲区
av_samples_alloc_array_and_samples(&in_data, &in_linesize, in_channels, in_samples, in_sample_fmt, 0);
av_samples_alloc_array_and_samples(&out_data, &out_linesize, out_channels, out_samples, out_sample_fmt, 0);// 3. 循环读取、转换、写入
while ((read_size = input_file.read(in_data[0], read_size)) > 0) {int ret = swr_convert(swr_ctx, out_data, out_samples, (const uint8_t **)in_data, in_samples);// ... 将转换后的数据(out_data)写入输出文件
}// 4. 排空重采样器,获取缓存的样本
while ((ret = swr_convert(swr_ctx, out_data, out_samples, NULL, 0)) > 0) {// ... 写入排空得到的数据
}// 5. 清理资源
if (in_data) av_freep(&in_data[0]); av_freep(&in_data);
if (out_data) av_freep(&out_data[0]); av_freep(&out_data);
swr_free(&swr_ctx);

4.2.3 重要注意事项

  • 音质影响:重采样,尤其是有理数倍数的采样率转换(如 48 kHz 转 44.1 kHz),可能会引入音质损失。FFmpeg 的重采样器内部使用了高质量的滤波器来尽量减少这种影响,但在对音质要求极高的场合仍需谨慎选择转换参数 。
  • 性能考量:重采样是计算密集型操作,特别是在高采样率和复杂声道布局的情况下。在处理大量音频数据或实时流时,需要关注性能 。
  • 声道布局:除了声道数量,有时还需要指定具体的声道布局(如 AV_CH_LAYOUT_STEREO立体声),可以使用 av_get_channel_layout_nb_channels函数通过声道布局获取声道数 。

五、总结

本文从音频数据采集、保存、压缩、播放等方面讲解音频全流程处理的关键技术,希望对大家有所帮助,有什么疑问也可以在评论区一起探讨,博主定期会进行回复,一起加油,奥利给!

六、参考资料

音频处理——详解PCM数据格式_pcm格式-CSDN博客

RIFF文件格式详解 - 知乎

一文搞懂 wav 文件格式 - 知乎

数字音频基础­­­­­-从PCM说起 - 知乎


  1. n ↩︎

  2. n ↩︎

http://www.dtcms.com/a/532342.html

相关文章:

  • 基于单片机的篮球比赛计时与比分控制系统设计
  • C++容器set
  • 网站建设主机耗电量怎么写代码自己制作网站
  • 超越低功耗:TMS320C6000 DSP的能效架构设计与IoT节点部署实践
  • 西安网站开发工资首都之窗门户网站首页
  • 中药电商平台是什么?主要具有哪些创新特征与应用场景?
  • Python模块(Module)详解:从基础使用到工程化实践
  • DTD 属性详解
  • 随身WiFi助手
  • 安卓网络请求详解:Retrofit + OkHttp 高效通信方案
  • centos建设网站营销系统平台
  • 华为OD机试双机位A卷 - 统计差异值大于相似值二元组个数 (C++ Python JAVA JS GO)
  • bug:realsense-viewer 找不到已识别的设备
  • Mac安装VisualVM 2.2启动闪退
  • 在macOS上搭建C#集成开发环境指南
  • 郑州市城乡建设规划网站苏州园区两学一做网站
  • 音乐网站 模板手游app平台排行榜
  • vue通信加密解密完整方案实现
  • 大模型模板输出与优化技术指南
  • 2026蓝桥杯
  • 让我用一个非常通俗易懂的方式来解
  • 搞一个卖东西的网站怎么做婚庆网站开发计划书
  • 迅雷之家是迅雷做的网站吗学校网站建设的意义和应用
  • 织梦建站教程全集房山营销型网站制作开发
  • 非齐次方程解的结构与几何意义的探讨
  • 【YashanDB】单机版数据库升级测试
  • 张家口百度免费做网站可以做家装设计的网站
  • F-INR: Functional Tensor Decomposition for Implicit Neural Representations
  • 电容的串联、并联
  • 如何解决 pip install -e . 安装报错 后端不支持可编辑安装(PEP 660)问题