音频处理——常用音频编码格式简介(PCM、G726、ADPCM、LPCM、G711、AAC)

PCM

音频处理——详解PCM数据格式
音频处理——解析PCM格式实例(音量调控)

G726

  G.726是ITU-T定义的音频编码算法。1990年 CCITT(ITU前身)在G.721和G.723标准的基础上提出。G.726可将64kbps的PCM信号转换为40kbps、32kbps、24kbps、16kbps的ADPCM信号。

  最为常用的方式是 32 kbit/s,但由于其只是 G.711速率的一半,所以就将网络的可利用空间增加了一倍。G.726具 体规定了一个 64 kbpsA-law 或 μ-law PCM 信号是如何被转化为40, 32, 24或16 kbps 的 ADPCM 通道的。在这些通道中,24和16 kbps 的通道被用于数字电路倍增设备(DCME)中的语音传输,而40 kbps 通道则被用于 DCME 中的数据解调信号(尤其是4800 kbps 或更高的调制解调器)。

  实际上,G.726 encoder 输入一般都是G.711 encoder的输出:64kbit/s 的A-law或µ-law;G.726算法本质就是一个ADPCM, 自适应量化算法,把64kbit/s 压缩到32kbit/s

ADPCM

ADPCM :Adaptive Differential Pulse Code Modulation
自适应差分脉冲编码调制

说到ADPCM, 就得先说下DPCM。
  Differential(差异)或Delta PCM(DPCM)纪录的是目前的值与前一个值的差异值。DPCM对信号的差值进行量化,可以进一步减少量化比特数。与相等的PCM比较,这种编码只需要25%的比特数。这与一些视频的压缩理念类似,用该帧与前一帧的差异来进行记录该帧以达到压缩的目的。
  ADPCM (ADPCM Adaptive Differential Pulse Code Modulation), 是一种针对16bit (或者更高) 声音波形数据的一种有损压缩算法, 它将声音流中每次采样的 16bit 数据以 4bit 存储, 所以压缩比1:4. 而压缩/解压缩算法非常的简单, 所以是一种低空间消耗,高质量声音获得的好途径。

   该算法利用了语音信号样点间的相关性,并针对语音信号的非平稳特点,使用了自适应预测自适应量化,即量化器和预测器的参数能随输入信号的统计特性自适应于或接近于最佳的参数状态,在32kbps◎8khz速率上能够给出网络等级话音质量。

特性:ADPCM综合了APCM的自适应特性和DPCM系统的差分特性,是一种性能比较好的波形编码。它的核心想法是:

  • ①利用自适应的思想改变量化阶的大小,即使用小的量化阶(step-size)去编码小的差值,使用大的量化阶去编码大的差值;

  • ②使用过去的样本值估算下一个输入样本的预测值,使实际样本值和预测值之间的差值总是最小。

  • 优点:算法复杂度低,压缩比小,编解码延时最短(相对其它技术)

  • 缺点:声音质量一般

  简单理解,ADPCM就是对LPCM数据进行有损压缩,压缩过程中量化参数遇小则小,遇大则大,根据差值来自己调整大小;另外它可以对之前的数据统计后来预测后来的数据差值,尽量使差值比较小。

LPCM

LPCM: linear pulse code modulation
   LPCM,即线性脉冲编码调制,是一种非压缩音频数字化技术,是一种未压缩的原音重现,在普通CD、DVD及其他各种要求最高音频质量的场合中已经得到广泛的应用。
   各种应用场合中的LPCM(PCM)原理是一样的,区别在于采样频率和量化精度不同。

   声音之所以能够数字化,是因为人耳所能听到的声音频率不是无限宽的,主要在20kHz以下。按照抽样定理,只有抽样频率大于40kHz,才能无失真地重建原始声音。如CD采用44.1kHz的抽样频率,其他则主要采用48kHz或96kHz。

   PCM(脉冲编码调制)是一种将模拟语音信号变换为数字信号的编码方式。主要经过3个过程:抽样、量化和编码。抽样过程将连续时间模拟信号变为离散时间、连续幅度的抽样信号,量化过程将抽样信号变为离散时间、离散幅度的数字信号,编码过程将量化后的信号编码成为一个二进制码组输出。
   量化分为线性量化和非线性量化。线性量化在整个量化范围内,量化间隔均相等。非线性量化采用不等的量化间隔。量化间隔数由编码的二进制位数决定。例如,CD采用16bit线性量化,则量化间隔数L=65536。位数(n)越多,精度越高,信噪比SNR=6.02n+1.76(dB)也越高。但编码的二进制位数不是无限制的,需要根据所需的数据率确定。比如:CD可以达到的数据率为2×44.1×16=1411.2Kbit/s。
   简单的理解,LPCM就是把原始模拟声音波形经过采样和线性量化后得到的数字信号,这些数据信号还没被压缩

G711

  G711是国际电信联盟ITU-T定制出来的一套语音压缩标准,它代表了对数PCM(logarithmic pulse-code modulation)抽样标准,主要用于电话。它主要用脉冲编码调制对音频采样,采样率为8k每秒。它利用一个 64Kbps 未压缩通道传输语音讯号。 起压缩率为1:2, 即把16位数据压缩成8位。G.711是主流的波形声音编解码器。

   G.711 标准下主要有两种压缩算法。一种是u-law algorithm (又称often u-law, ulaw, mu-law),主要运用于北美和日本;另一种是A-law algorithm,主要运用于欧洲和世界其他地区。其中,后者是特别设计用来方便计算机处理的

  G711的内容是将14bit(uLaw)或者13bit(aLaw)采样的PCM数据编码成8bit的数据流,播放的时候在将此8bit的数据还原成14bit或者13bit进行播放,不同于MPEG这种对于整体或者一段数据进行考虑再进行编解码的做法,G711是波形编解码算法,就是一个sample对应一个编码,所以压缩比固定为:

  • 8/14 = 57% (uLaw)

  • 8/13 = 62% (aLaw)

  简单理解,G.711就是语音模拟信号的一种非线性量化, bitrate 是64kbps。

AAC

  AAC,全称Advanced Audio Coding,中文名:高级音频编码,是一种专为声音数据设计的文件压缩格式。与MP3不同,它采用了全新的算法进行编码,更加高效,具有更高的“性价比”。利用AAC格式,可使人感觉声音质量没有明显降低的前提下,更加小巧。苹果ipod、诺基亚手机支持AAC格式的音频文件。

  • 优点:相对于mp3,AAC格式的音质更佳,文件更小。
  • 不足:AAC属于有损压缩的格式,与时下流行的APE、FLAC等无损格式相比音质存在“本质上”的差距。加之,传输速度更快的USB3.0和16G以上大容量MP3正在加速普及,也使得AAC头上“小巧”的光环不复存在。

  AAC是新一代的音频有损压缩技术,它通过一些附加的编码技术(比如PS,SBR等),衍生出了LC-AAC,HE-AAC,HE-AACv2三种主要的编码,LC-AAC就是比较传统的AAC,相对而言,主要用于中高码率(>=80Kbps),HE-AAC(相当于AAC+SBR)主要用于中低码(<=80Kbps),而新近推出的HE-AACv2(相当于AAC+SBR+PS)主要用于低码率(<=48Kbps),事实上大部分编码器设成<=48Kbps自动启用PS技术,而>48Kbps就不加PS,就相当于普通的HE-AAC。

格式对比

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

音频帧长

  其实,音频的帧的概念没有视频帧那么清晰,几乎所有视频编码格式都可以简单的认为一帧就是编码后的一副图像。但音频帧跟编码格式相关,它是各个编码标准自己实现的。因为如果以PCM(未经编码的音频数据)来说,它根本就不需要帧的概念,根据采样率和采样精度就可以播放了。

  • 比如采样率为44.1kHZ,采样精度为16位的音频,你可以算出bitrate(比特率)是44100 x 16kbps,每秒的音频数据是固定的44100 x 16 / 8 字节。

  对采样率为44.1kHz的AAC(Advanced Audio Coding)音频进行解码时,一帧的解码时间须控制在23.22毫秒内。通常是按1024个采样点一帧。
  以上表G.711的帧长为480为例,那么一帧的时间长度即为480 / 8khz = 0.06s = 60ms

音频播放过程

  播放音乐时,应用程序从存储介质中读取音频数据(MP3、WMA、AAC),进过解码后,最终送到音频驱动程序中的就是PCM数据,反过来,在录音是,音频驱动不停地把采样所得到的PCM数据送回给应用程序,有应用程序完成压缩、存储等任务。所以,音频驱动的两大核心任务就是:

  • playback:如何把用户空间的应用程序发货来的PCM数据,转化为人耳可以辨别的模拟音频
  • capture:把mic拾取得到的模拟信号,经过采样、量化,转化为PCM信号送回给用户空间的应用程序。
  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现将 PCM 音频转换为 G.726 LE 编码格式的过程可以分为以下几个步骤: 1. 初始化 FFmpeg 库,并找到 G.726 LE 编码器。 ```python import ffmpeg # 初始化 FFmpeg 库 ffmpeg.init() # 查找 G.726 LE 编码器 codec = ffmpeg.avcodec_find_encoder(ffmpeg.AV_CODEC_ID_ADPCM_G726LE) ``` 2. 创建 AVCodecContext 对象,并设置编码参数。 ```python # 创建 AVCodecContext 对象 codec_context = ffmpeg.avcodec_alloc_context3(codec) # 设置编码参数 codec_context.bits_per_coded_sample = 2 codec_context.sample_rate = 8000 codec_context.channels = 1 codec_context.frame_size = 320 codec_context.bit_rate = 40000 ``` 其中,bits_per_coded_sample 表示每个采样的编码位数,这里是 2;sample_rate 表示采样率,这里是 8000;channels 表示通道数,这里是 1;frame_size 表示编码帧大小,这里是 320;bit_rate 表示比特率,这里是 40000。 3. 打开编码器,并分配编码器数据包和缓冲区。 ```python # 打开编码器 ffmpeg.avcodec_open2(codec_context, codec) # 分配编码器数据包和缓冲区 pkt = ffmpeg.av_packet_alloc() frame = ffmpeg.av_frame_alloc() frame.data[0] = ffmpeg.av_malloc(codec_context.frame_size) frame.nb_samples = codec_context.frame_size // 2 ``` 其中,pkt 表示编码器的数据包,frame 表示编码器的帧数据,frame.data[0] 表示帧数据的缓冲区,frame.nb_samples 表示帧数据采样数,这里是 320 // 2 = 160。 4. 读取 PCM 音频数据,并将其转换为 G.726 LE 编码格式。 ```python # 读取 PCM 音频数据 pcm_data = open("audio.pcm", "rb").read() # 将 PCM 音频数据转换为 G.726 LE 编码格式 while len(pcm_data) >= codec_context.frame_size * 2: # 将 PCM 数据写入帧数据缓冲区 ffmpeg.swig_opaque(frame.data[0], pcm_data[:codec_context.frame_size * 2]) pcm_data = pcm_data[codec_context.frame_size * 2:] # 编码帧数据为 G.726 LE 格式 ret = ffmpeg.avcodec_send_frame(codec_context, frame) while ret >= 0: ret = ffmpeg.avcodec_receive_packet(codec_context, pkt) if ret == ffmpeg.AVERROR_EAGAIN or ret == ffmpeg.AVERROR_EOF: break elif ret < 0: raise Exception("Error during encoding") # 将编码后的数据写入文件 open("audio.g726", "ab").write(pkt.data[:pkt.size]) ``` 其中,pcm_data 表示待编码的 PCM 音频数据,每次从 PCM 数据中读取 codec_context.frame_size * 2 个字节的数据,将其写入帧数据缓冲区 frame.data[0] 中,并调用 avcodec_send_frame 函数将帧数据送入编码器中编码。编码器编码完成后,通过 avcodec_receive_packet 函数获取编码后的数据包 pkt,将其写入文件中。 5. 释放资源。 ```python # 释放资源 ffmpeg.av_packet_unref(pkt) ffmpeg.av_frame_free(frame) ffmpeg.av_freep(frame.data) ffmpeg.avcodec_close(codec_context) ffmpeg.avcodec_free_context(codec_context) ``` 最后,需要释放编码器数据包、帧数据和编码器上下文等资源。 完整代码如下: ```python import ffmpeg # 初始化 FFmpeg 库 ffmpeg.init() # 查找 G.726 LE 编码器 codec = ffmpeg.avcodec_find_encoder(ffmpeg.AV_CODEC_ID_ADPCM_G726LE) # 创建 AVCodecContext 对象 codec_context = ffmpeg.avcodec_alloc_context3(codec) # 设置编码参数 codec_context.bits_per_coded_sample = 2 codec_context.sample_rate = 8000 codec_context.channels = 1 codec_context.frame_size = 320 codec_context.bit_rate = 40000 # 打开编码器 ffmpeg.avcodec_open2(codec_context, codec) # 分配编码器数据包和缓冲区 pkt = ffmpeg.av_packet_alloc() frame = ffmpeg.av_frame_alloc() frame.data[0] = ffmpeg.av_malloc(codec_context.frame_size) frame.nb_samples = codec_context.frame_size // 2 # 读取 PCM 音频数据 pcm_data = open("audio.pcm", "rb").read() # 将 PCM 音频数据转换为 G.726 LE 编码格式 while len(pcm_data) >= codec_context.frame_size * 2: # 将 PCM 数据写入帧数据缓冲区 ffmpeg.swig_opaque(frame.data[0], pcm_data[:codec_context.frame_size * 2]) pcm_data = pcm_data[codec_context.frame_size * 2:] # 编码帧数据为 G.726 LE 格式 ret = ffmpeg.avcodec_send_frame(codec_context, frame) while ret >= 0: ret = ffmpeg.avcodec_receive_packet(codec_context, pkt) if ret == ffmpeg.AVERROR_EAGAIN or ret == ffmpeg.AVERROR_EOF: break elif ret < 0: raise Exception("Error during encoding") # 将编码后的数据写入文件 open("audio.g726", "ab").write(pkt.data[:pkt.size]) # 释放资源 ffmpeg.av_packet_unref(pkt) ffmpeg.av_frame_free(frame) ffmpeg.av_freep(frame.data) ffmpeg.avcodec_close(codec_context) ffmpeg.avcodec_free_context(codec_context) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Spark!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值