ALSA音频编程常用参数详细说明

  • ALSA简介
  • 音频采样回放过程
    • 音频采样过程
    • 音频回放过程
  • PCM及其相关参数
    • PCM简介
    • 参数说明
    • 实例分析
  • PCM接口编程
  • WAV音频格式
    • WAV简介
    • WAV格式
  • opus简介及libopus库安装使用
    • 在PC下的配置编译安装
    • 在交叉编译环境下的配置编译安装
    • opus编码的使用约束
    • libopus-1.3.1使用

最近在做ALSA音频采集、编码相关的东西,也是一点点了解这方面的知识,查了挺多资料,当然很多都是大同小异,无非介绍一些ALSA的由来、相关参数以及ALSA编程采样或者回放音频,虽然直接把代码拷贝编译后,可以正常执行音频的采集与回放,但总感觉有的细节没有摸索清楚。

在完成项目的同时,通过网上的资料和自己的理解把ALSA的一些东西梳理一下,一方面给有需要的朋友提供有用的帮助,另一方面,也是自己对ALSA的总结。


ALSA简介

ALSA(Advanced Linux Sound Architecture)高级Linux音频架构,为 Linux 系统提供了统一的音频和MIDI功能和驱动。它由许多声卡的声卡驱动程序组成,同时它也提供一个称为libasound的API库,应用程序开发者应该使用libasound而不是内核中的 ALSA接口,因为libasound提供最高级并且编程方便的编程接口。ALSA提供一系列基于命令行的工具集,比如混音器(mixer),音频文件播放器(aplay),以及控制特定卡特定属性的工具。

ALSA官网链接

ALSA提供的API库可以分解成以下几个主要的接口:

  1. 控制接口:提供管理声卡注册和请求可用设备的通用功能。
  2. PCM接口:管理数字音频回放(playback)和录音(capture)的接口。本文后续总结重点放在这个接口上,因为它是开发数字音频程序最常用到的接口。
  3. Raw MIDI接口:支持MIDI(Musical Instrument Digital Interface),标准的电子乐器。这些API提供对声卡上MIDI总线的访问。这个原始接口基于MIDI事件工作,由程序员负责管理协议以及时间处理。
  4. 定时器(Timer)接口:为同步音频事件提供对声卡上时间处理硬件的访问。
  5. 时序器(Sequencer)接口
  6. 混音器(Mixer)接口

音频采样回放过程

音频采样过程

音频采样过程是一个将麦克风的模拟信号(电压)按一定的周期进行采样(即采样率),并将采样的数据转换为数字信号(0,1)的过程,在数字电路中称之为ADC(Analog-Digital Conversion,模数转换),具体实现是通过逐次逼近电路将模拟信号进行量化,量化时有一个精度,这个精度就是采样长度,量化后得到对应的数字量以便于在数字设备中传输;

音频回放过程

音频回放过程是一个将声卡中的数字信号还原为模拟信号的过程,在数字电路中称之为DAC(Digital -Analog Conversion,数模转换),具体实现是通过数模转换器电路将数字信号还原为模拟信号(电压),最终将转换后的模拟信号传送到喇叭,喇叭根据电信号的特征播放出声音。


PCM及其相关参数

PCM简介

PCM(Pulse Code Modulation----脉冲编码调制)即将音频采样量化过程后变成符号化的脉冲序列,并予以记录。PCM是由数字信号(0,1)未经过任何编码和压缩处理的数字量。与模拟信号比,它不易受传送系统的杂波及失真的影响。动态范围宽,可得到音质相当好的影响效果。PCM数据是最原始的音频数据完全无损。

参数说明

ALSA的API库的PCM接口中有一些参数是需要知道的,这些参数也是音频相关的基本知识:

  1. 采样长度(sample_length):将音频进行采样量化的精度,有8bit/16bit
  2. 采样通道(sample_channels):音频采样的通路数,比如立体声就有2个采样通路数分别进行左右声道的采样,单声道就有1个通路数进行单声道采样;
  3. 采样帧大小(sample_frame):以字节Byte为单位,是采样长度与采样通道的乘积,由于采样长度单位是位,所以这个乘积的单位是位,要想转换为字节,需要将这个乘积再除以8,因此采样帧字节大小公式即sample_frame=sample_length*sample_channels/8;举个栗子,采样长度位16bit,采样通道为立体声,那么帧大小(字节)=16*2/8=4Byte;
  4. 采样周期(sample_period):指多久完成一次采样;
  5. 采样率(sample_rate):指每秒采样的帧数,注意这里是每秒采样的帧数,不是每秒采样的位数/字节数。
  6. 交错模式(interleaved):是一种音频数据的记录方式,在交错模式下,数据以连续桢的形式存放,即首先记录完桢1的左声道样本和右声道样本(假设为立体声格式),再开始桢2的记录。而在非交错模式下,首先记录的是一个周期内所有桢的左声道样本,再记录右声道样本,数据是以连续通道的方式存储。不过多数情况下,我们只需要使用交错模式就可以了。

实例分析

设定采样长度为16bit,采样通道为立体声,采样率为16K,采样周期为20ms,那么采样帧大小是多少?每秒有多少个采样周期?每个采样周期采样到的帧数是多少?需要多少字节的缓存区存放每个周期的数据量?
·
首先 sample_length=16 sample_channels=2 sample_rate=16000 sample_period=20ms
a. 采样帧大小:sample_frame=sample_length*sample_channels/8=4
b. 因为采样周期知道(sample_period=20ms),1秒的采样周期个数=1000/20=50
c. 每个采样周期采样到的帧数:因为每秒钟的采样帧数已知sample_rate=16000,根据b又知道每秒有50个采样周期,所以每个周期的采样帧数=16000/50=320;(当然也可以通过sample_rate*sample_period求得)
d. 由c知道每个采样周期的帧数为320,而由a知道sample_frame=4,所以每帧的数据量为320*4=1280Byte,因此需要1280字节存放每个周期的数据量。

在这里目的不是为了求解,目的在于理解,因为这些东西理解清楚了,在进行音频采集和回放时采用多大的缓冲区就明白了。在利用PCM接口进行音频的采集和回放时,每次读取和写入的数据量是每个采样周期的帧数;在使用PCM接口进行读数据时,读取的数据量是每个采样周期采样到的帧数,读出的数据缓存区大小PCM底层会自动填充至每个采样周期的数据量大小。比如在上述例子中,通过PCM接口读取和写入的数据量大小应该为每个采样周期采样到的帧数即320,而读出的数据buffer会被填充为采样周期的数据量即1280B;


PCM接口编程

参考链接Alsa音频编程
可先参考上面的链接,后续会发布PCM的音视频采集和回放的源码


WAV音频格式

WAV简介

Waveform Audio File Format(WAVE,又或者是因为扩展名而被大众所知的WAV),是微软与IBM公司所开发在个人电脑存储音频流的编码格式,此格式属于资源交换文件格式(RIFF)的应用之一,通常会将采用PCM的音频资存储在区块中。由于此音频格式未经过压缩,所以在音质方面不会出现失真的情况,但文件的体积因而在众多音频格式中较为大。

WAV格式

WAV文件遵守RIFF(Resource Interchange File Format 资源交换文件格式)规则,在文件的前44(或46)字节放置标头(header),使播放器或编辑器能够简单掌握文件的基本信息。标头的前3个区块记录文件格式及长度;接着第一个子区块包含8个区块,记录声道数量、采样率等信息;接着第二个子区块才是真正的音频数据,长度则视音频长度而定。内容如下表所示。须注意的是,每个区块的端序不尽相同,而音频数据本身则是采用小端序1

起始地址(字节) 区块名称 区块大小 端序 区块内容
0 区块编号 4 “RIFF”
4 总区块大小 4 =N+36
8 档案格式 4 “WAVE”
12 子区块标签 4 “fmt”
16 子区块大小 4 16
18 音频格式 2 1(PCM)
20 声道数量 2 1(单声道) 2(立体声)
22 采样频率 4 每秒的采样帧数
26 位元(组)率 4 =采样频率*位元深度/8
30 区块对齐 2 4
32 位元深度 2 指采样长度
36 子区块2标签 4 “data”
40 子区块2大小 4 N(=位元(组)率秒数声道数量)
44 音频数据 =N PCM音频数据

opus简介及libopus库安装使用

opus是有损音频编码的一种适用于网络上的实时声音传输的编码格式。在使用中可以使用opus的开源库,在opus官网可以阅读其相关内容。

在PC下的配置编译安装

  1. 下载libopus 1.3.1
    wget https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz
  2. 解压配置
    tar -zxvf opus-1.3.1.tar.gz
    a.安装路径配置为默认路径./configure
    b.安装路径配置为指定路径./configure --perfix=${path} ${path}替换为指定的安装目录
  3. 编译安装
    a. 编译make
    b. 安装make install

在交叉编译环境下的配置编译安装

  1. 下载libopus 1.3.1
    wget https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz
  2. 解压配置
    tar -zxvf opus-1.3.1.tar.gz
    a.安装路径配置为默认路径./configure --host=交叉工具链名称 CC=gcc CXX=g++
    b.安装路径配置为指定路径./configure --perfix=${path} --host=交叉工具链名称 CC=gcc CXX=g++ ${path}替换为指定的安装目录
  3. 编译安装
    a. 编译make
    b. 安装make install

opus编码的使用约束

  1. 采样率约束:输入信号的采样率(Hz),必须是8000、12000、16000、24000、或48000。
  2. 帧长约束:opus为了对一个帧进行编码,必须正确地用音频数据的帧(2.5, 5, 10, 20, 40 or 60 ms)来调用opus_encode()函数。比如,在16kHz的采样率下,opus_encode()参数中的合法的frame_size(单通道的帧大小)值只有:40, 80, 160, 320, 640, 960m,即:frame_size = 采样率 * 帧时间。
  3. 兼容opus的容器格式:有ogg,ts,mkv。但ts无法播放,mkv只能foobar播放,ogg能用foobar,vlc播放。

libopus-1.3.1使用

opus编码

// 创建编码器
OpusEncoder *opus_encoder_create(opus_int32 Fs,         // 采样率,可以设置的大小为8000, 12000, 16000, 24000, 48000,opus_int32(int)int channels,      // 声道数,网络中实时音频一般为单声道int application,     // 应用场景 OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIOint *error          // 是否创建失败,返回0表示创建成功
)                       // 成功返回OpusEncoder首地址,失败返回NULL// 销毁编码器
void opus_encoder_destroy(OpusEncoder *st       // 创建编码器的返回值
)// 编码器参数设置
int opus_encoder_ctl(OpusEncoder *st,   // 创建编码器的返回值int request,        // 参数设置值...                 // 其他参数
)                       // 成功返回0,失败返回-1// 编码
opus_int32 opus_encode(OpusEncoder *st,         // 创建编码器的返回值const opus_int16 *pcm,      // pcm数据,传入参数,opus_int16(short)int frame_size,            // pcm每个周期的采样帧数unsigned char *data,     // 编码后的数据,传出参数opus_int32 max_data_bytes  // 最大的编码缓存区大小,opus_int32(int)
)                               // 成功返回编码后的数据量大小,失败返回-1

实例:

OpusEncoder *tOpusEncoder;
int OpusEncoderInit(void)
{int opus_err;tOpusEncoder=opus_encoder_create(16000,2,OPUS_APPLICATION_VOIP,&opus_err);if (!m_tOpusEncoder || opus_err < 0){if (!m_tOpusEncoder) {opus_encoder_destroy(tOpusEncoder);}return -1;}  opus_encoder_ctl(tOpusEncoder, OPUS_SET_VBR(0)); //关闭可变码率opus_encoder_ctl(tOpusEncoder, OPUS_SET_BITRATE(128000));//设置固定码率128kreturn 0;
}voidOpusEncoderDeinit(void)
{opus_encoder_destroy(tOpusEncoder);
}opus_int32 OpusEncode(const opus_int16 pcm,int frame_size,unsigned char *opus_data,opus_int32 max_data_bytes)
{return opus_encode(tOpusEncoder,pcm,frame_size,opus_data,opus_data_max_size);
}

opus解码

// 创建解码器
OpusDecoder *opus_decoder_create(opus_int32 Fs,             // 采样率,可以设置的大小为8000, 12000, 16000, 24000, 48000.int channels,                // 声道数,网络中实时音频一般为单声道int *error                   // 是否创建失败,返回0表示创建成功
);                              // 成功返回OpusDecoder首地址,失败返回NULL// 销毁解码器
void opus_decoder_destroy(OpusDecoder *st       // 创建解码器的返回值
)// 编码器参数设置
int opus_decoder_ctl(OpusDecoder *st,   // 创建解码器的返回值int request,        // 参数设置值...                 // 其他参数
)                       // 成功返回0,失败返回-1// opus解码
int opus_decode(OpusDecoder *st,            // 创建解码器的返回值const unsigned char *data,  // 要解码的opus数据opus_int32 len,            // opus数据长度opus_int16 *pcm,             // 解码后的数据,注意是一个以16位长度为基本单位的数组int frame_size,            // pcm每个周期的采样帧数int decode_fec               // 是否需要fec,设置0为不需要,1为需要
)

编程实例见参考链接4


[参考链接]

  1. Alsa音频编程
  2. WAV和PCM的关系和区别
  3. 维基百科
  4. Opus介绍及编译
  5. Opus音频编码的使用约束
  6. 常见的15种音频格式
  7. alsa-lib及alsa-utils成功移植

  1. 大小端序,指数据的高低字节在内存中的存放方式;大端序,也称大端模式,是指数据的高字节存储到内存的低地址,数据的低字节存储到内存的高地址;小端序,也称小端模式,是指数据的高字节存储到内存的高地址,数据的低字节存储到内存的低地址。 ↩︎

ALSA音频编程常用参数详细说明相关推荐

  1. linux下lamealsa进行音频流操作(三)alsa音频编程教程

    1. ALSA音频编程介绍   ALSA 代表高级 Linux 声音架构.它由一组内核驱动程序.一个应用程序编程接口 (API) 库和用于在 Linux 下支持声音的实用程序组成.在本文中,我简要概述 ...

  2. alsa 音频编程简单的例子 (总结)

    1.源代码安装alsa 库,否则编译例子不会通过.原文引用http://apps.hi.baidu.com/share/detail/17289294 2.编译简单的播放和录音的例子.   引用原文h ...

  3. linux内核之alsa,Linux操作系统Alsa音频编程

    一.前序 这里了解一下各个参数的含义以及一些基本概念. 声音是连续模拟量,计算机将它离散化之后用数字表示,就有了以下几个名词术语. 样本长度(sample):样本是记录音频数据最基本的单位,计算机对每 ...

  4. Alsa音频应用编程

    前序:这里了解一下各个参数的含义以及一些基本概念. 样本长度(sample):样本是记录音频数据最基本的单位,常见的有8位和16位. 通道数(channel):该参数为1表示单声道,2则是立体声. 桢 ...

  5. linux+top+常用参数,linux的top命令参数详细说明

    Linux中的top命令是个常用的命令之一,下面由学习啦小编为大家整理了Linux的top命令参数详细说明,希望对大家有帮助! linux的top命令简介 top命令是Linux下常用的性能分析工具, ...

  6. alsa声音编程介绍

    http://blog.csdn.net/q553716434/article/details/7881552 period(周期):硬件中中断间的间隔时间.它表示输入延时. 声卡接口中有一个指针来指 ...

  7. OSS音频编程概述(DSP部分)

    一. 音频概念 音频信号是一种连续变化的模拟信号,但计算机只能处理和记录二进制的数字信号,由自然音源得到的音频信号必须经过一定的变换,成为数字音频信号之后,才能送到计算机中作进一步的处理. 对于OSS ...

  8. Linux ALSA 音频系统:物理链路篇

    原址 1. Overview 硬件平台及软件版本: Kernel - 3.4.5 SoC - Samsung exynos CODEC - WM8994 Machine - goni_wm8994 U ...

  9. 整理下OSS方面的资料,免得到处找,linux音频编程,open sound system

    浅析ASoC-audio驱动oss框架下/dev/dsp与alsa框架下设备节点打开和创建简易流程 http://blog.chinaunix.net/u2/70445/showart_2070710 ...

最新文章

  1. debian下安装LNMP(三)
  2. SQL Server数据库表锁定原理以及如何解除表的锁定转
  3. 价格的格式化 php,价格格式化问题。
  4. CSS_03_04_CSS伪元素选择器
  5. Oracle数据库之事务
  6. 如何基于 SAP CDS view 生成 object page
  7. linux 下opencv安装教程,linux 下 opencv安装
  8. 初学者持续自我提升指南
  9. mybatis3 添加ehcache支持
  10. iOS 14.5新功能:解锁iPhone更方便!
  11. vc中调用其他应用程序的方法(函数) winexec,shellexecute ,createprocess 1
  12. 【操作系统/OS笔记01】课程概要、什么是操作系统
  13. 看代码学知识之(1) 获取当前线程状态
  14. css flex 之 flex-grow | flex-direction
  15. php一行代码实现人脸识别,一行代码搞定人脸识别
  16. excel2016html,excel2016打开不显示内容《2016版本的excel表格》
  17. 马尔可夫和切比雪夫不等式的证明
  18. FORCE_CONSTANTS中3阶力常数大小与原子间距的分析脚本
  19. 如何删除hao123?
  20. bilibili mac客户端 哔哩哔哩 b站mac客户端

热门文章

  1. J2EE高级软件工程师面试题集
  2. 他99年出生,本科身份摘FOCS 2021最佳学生论文奖,曾4刷NOI金牌
  3. 【兼容性】ios上设置overflow: scroll不滚动bug
  4. H265/HEVC视频分层码流分析语义元素解释
  5. html实现文本的查找与替换,在 InDesign 中查找并替换文本
  6. 矩阵的迹以及迹对矩阵求导
  7. java体重指数计算器程序_Android首接触--小程序(体重指数计算器)
  8. 1423. 可获得的最大点数 maxScore
  9. 难怪好人有恶报,原来秘密在这里
  10. 最简单的平面制图用什么软件_建筑绘图用什么软件好?AUTO CAD软件快速制图,工程人必备...