Linux-音频应用编程

news2025/2/24 14:17:14

ALPHA I.MX6U 开发板支持音频,板上搭载了音频编解码芯片 WM8960,支持播放以及录音功能!本章我们来学习 Linux 下的音频应用编程,音频应用编程相比于前面几个章节所介绍的内容、其难度有所上升,但是笔者仅向大家介绍 Linux 音频应用编程中的基础知识,而更多细节、更加深入的内容需要大家自己去学习。

本章将会讨论如下主题内容。

Linux ALSA 框架概述;

alsa-lib 库介绍;

alsa-lib 库移植;

alsa-lib 库的使用;

音频应用编程之播放;

音频应用编程之录音。


ALSA 概述

ALSA Advanced Linux Sound Architecture(高级的 Linux 声音体系)的缩写,目前已经成为了 linux下的主流音频体系架构,提供了音频和 MIDI 的支持,替代了原先旧版本中的 OSS(开发声音系统);学习过 Linux 音频驱动开发的读者肯定知道这个;事实上,ALSA Linux 系统下一套标准的、先进的音频驱动框架,那么这套框架的设计本身是比较复杂的,采用分离、分层思想设计而成,具体的细节便不给大家介绍了!作为音频应用编程,我们不用去研究这个。

在应用层,ALSA 为我们提供了一套标准的 API,应用程序只需要调用这些 API 就可完成对底层音频硬件设备的控制,譬如播放、录音等,这一套 API 称为 alsa-lib。如下图所示:


alsa-lib 简介

如上所述,alsa-lib 是一套 Linux 应用层的 C 语言函数库,为音频应用程序开发提供了一套统一、标准的接口,应用程序只需调用这一套 API 即可完成对底层声卡设备的操控,譬如播放与录音。

用户空间的 alsa-lib 对应用程序提供了统一的 API 接口,这样可以隐藏驱动层的实现细节,简化了应用程序的实现难度、无需应用程序开发人员直接去读写音频设备节点。所以本章,对于我们来说,学习音频应用编程其实就是学习 alsa-lib 库函数的使用、如何基于 alsa-lib 库函数开发音频应用程序。

ALSA 提供了关于 alsa-lib 的使用说明文档,其链接地址为:https://www.alsa-project.org/alsa-doc/alsa-lib/

进入到该链接地址后,如下所示:

alsa-lib 库支持功能比较多,提供了丰富的 API 接口供应用程序开发人员调用,根据函数的功能、作用将这些 API 进行了分类,可以点击上图中 Modules 按钮查看其模块划分,如下所示:

一个分类就是一个模块(module),有些模块下可能该包含了子模块,譬如上图中,模块名称前面有三角箭头的表示该模块包含有子模块。

Global defines and functions:包括一些全局的定义,譬如函数、宏等;

Constants for Digital Audio Interfaces:数字音频接口相关的常量;

Input Interface:输入接口;

Output Interface:输出接口;

Error handling:错误处理相关接口;

Configuration Interface:配置接口;

Control Interface:控制接口;

PCM InterfacePCM 设备接口;

RawMidi InterfaceRawMidi 接口;

Timer Interface:定时器接口;

Hardware Dependant Interface:硬件相关接口;

MIDI SequencerMIDI 音序器;

External PCM plugin SDK:外部 PCM 插件 SDK

External Control Plugin SDK:外部控制插件 SDK

Mixer Interface:混音器接口;

Use Case Interface:用例接口;

Topology Interface:拓扑接口。

可以看到,alsa-lib 提供的接口确实非常多、模块很多,以上所列举出来的这些模块,很多模块笔者也不是很清楚它们的具体功能、作用,但是本章我们仅涉及到三个模块下的 API 函数,包括:PCM Interface、Error Interface 以及 Mixer Interface

PCM Interface

PCM Interface,提供了 PCM 设备相关的操作接口,譬如打开/关闭 PCM 设备、配置 PCM 设备硬件或软件参数、控制 PCM 设备(启动、暂停、恢复、写入/读取数据),该模块下还包含了一些子模块,如下所示:

点击模块名称可以查看到该模块提供的API接口有哪些以及相应的函数说明,这里就不给大家演示了!

Error Interface

该模块提供了关于错误处理相关的接口,譬如函数调用发生错误时,可调用该模块下提供的函数打印错误描述信息。

Mixer Interface

提供了关于混音器相关的一系列操作接口,譬如音量、声道控制、增益等等。


sound 设备节点

Linux 内核设备驱动层、基于 ALSA 音频驱动框架注册的 sound 设备会在/dev/snd 目录下生成相应的设备节点文件,譬如 ALPHA I.MX6U 开发板出厂系统/dev/snd 目录下有如下文件:

Tips:注意,Mini I.MX6U 开发板出厂系统/dev/snd 目录下是没有这些文件的,因为 Mini 板不支持音频、没有板载音频编解码芯片,所以本章实验例程无法在 Mini 板上进行测试,请悉知!

从上图可以看到有如下设备文件:

controlC0用于声卡控制的设备节点,譬如通道选择、混音器、麦克风的控制等,C0 表示声卡 0(card0);

pcmC0D0c用于录音的 PCM 设备节点。其中 C0 表示 card0,也就是声卡 0;而 D0 表示 device0,也就是设备 0;最后一个字母 c capture 的缩写,表示录音;所以 pcmC0D0c 便是系统的声卡0 中的录音设备 0

pcmC0D0p用于播放(或叫放音、回放)的 PCM 设备节点。其中 C0 表示 card0,也就是声卡 0;而 D0 表示 device 0,也就是设备 0;最后一个字母 p playback 的缩写,表示播放;所以 pcmC0D0p便是系统的声卡 0 中的播放设备 0

pcmC0D1c用于录音的 PCM 设备节点。对应系统的声卡 0 中的录音设备 1

pcmC0D1p用于播放的 PCM 设备节点。对应系统的声卡 0 中的播放设备 1

timer定时器。

本章我们编写的应用程序,虽然是调用 alsa-lib 库函数去控制底层音频硬件,但最终也是落实到对 sound设备节点的 I/O 操作,只不过 alsa-lib 已经帮我们封装好了。在 Linux 系统的/proc/asound 目录下,有很多的文件,这些文件记录了系统中声卡相关的信息,如下所示:

cards

通过"cat /proc/asound/cards"命令、查看 cards 文件的内容,可列出系统中可用的、注册的声卡,如下所示:

cat /proc/asound/cards

我们的阿尔法板子上只有一个声卡(WM8960 音频编解码器),所以它的编号为 0,也就是 card0。系统中注册的所有声卡都会在/proc/asound/目录下存在一个相应的目录,该目录的命名方式为 cardXX 表示 声卡的编号),譬如图 28.3.2 中的 card0card0 目录下记录了声卡 0 相关的信息,譬如声卡的名字以及声卡注册的 PCM 设备,如下所示:

devices

列出系统中所有声卡注册的设备,包括 controlpcmtimerseq 等等。如下所示:

cat /proc/asound/devices

pcm

列出系统中的所有 PCM 设备,包括 playback capture

cat /proc/asound/pcm


alsa-lib 移植

因为 alsa-lib ALSA 提供的一套 Linux 下的 C 语言函数库,需要将 alsa-lib 移植到开发板上,这样基于 alsa-lib 编写的应用程序才能成功运行,除了移植 alsa-lib 库之外,通常还需要移植 alsa-utilsalsa-utils 包含了一些用于测试、配置声卡的工具。

事实上,ALPHA I.MX6U 开发板出厂系统中已经移植了 alsa-lib alsa-utils,本章我们直接使用出厂系统移植好的 alsa-lib alsa-utils 进行测试,笔者也就不再介绍移植过程了。其实它们的移植方法也非常简单,如果你想自己尝试移植,网上有很多参考,大家可以自己去看看。

alsa-utils 提供了一些用于测试、配置声卡的工具,譬如 aplayarecordalsactlalsaloopalsamixer、amixer 等,在开发板出厂系统上可以直接使用这些工具,这些应用程序也都是基于 alsa-lib 编写的。

aplay

aplay 是一个用于测试音频播放功能程序,可以使用 aplay 播放 wav 格式的音频文件,如下所示:

程序运行之后就会开始播放音乐,因为 ALPHA 开发板支持喇叭和耳机自动切换,如果不插耳机默认从喇叭播放音乐,插上耳机以后喇叭就会停止播放,切换为耳机播放音乐,这个大家可以自己进行测试。

需要注意的是,aplay 工具只能解析 wav 格式音频文件,不支持 mp3 格式解码,所以无法使用 aplay 工具播放 mp3 音频文件。稍后笔者会向大家介绍如何基于 alsa-lib 编写一个简单地音乐播放器,实现与 aplay相同的效果。

更多命令参考正电原子应用开发手册即可。

暂略。


编写一个简单的alsa-lib应用程序

本小节开始,我们来学习如何基于 alsa-lib 编写音频应用程序,alsa-lib 提供的库函数也别多,笔者肯定不会全部给大家介绍,只介绍基础的使用方法,关于更加深入、更加详细的使用方法需要大家自己去研究、学习。

对于 alsa-lib 库的使用,ALSA 提供了一些参考资料来帮助应用程序开发人员快速上手 alsa-lib、基于alsa-lib 进行应用编程,以下笔者给出了链接:

https://users.suse.com/~mana/alsa090_howto.html

https://www.alsa-project.org/alsa-doc/alsa-lib/examples.html

第一份文档向用户介绍了如何使用 alsa-lib 编写简单的音频应用程序,包括 PCM 播放音频、PCM 录音等,笔者也是参考了这份文档来编写本章教程,对应初学者,建议大家看一看。

第二个链接地址是 ALSA 提供的一些示例代码,如下所示:

点击对应源文件即可查看源代码。

以上便是 ALSA 提供的帮助文档以及参考代码,链接地址已经给出了,大家有兴趣可以看一下。

本小节笔者将向大家介绍如何基于 alsa-lib 编写一个简单地音频应用程序,譬如播放音乐、录音等;但在此之前,首先我们需要先来了解一些基本的概念,为后面的学习打下一个坚实的基础!

一些基本概念

主要是与音频相关的基本概念,因为在 alsa-lib 应用编程中会涉及到这些概念,所以先给大家进行一个简单地介绍。

样本长度(Sample

样本是记录音频数据最基本的单元,样本长度就是采样位数,也称为位深度(Bit DepthSample Size、Sample Width)。是指计算机在采集和播放声音文件时,所使用数字声音信号的二进制位数,或者说每个采样样本所包含的位数(计算机对每个通道采样量化时数字比特位数),通常有 8bit16bit24bit 等。

声道数(channel

分为单声道(Mono)和双声道/立体声(Stereo)1 表示单声道、2 表示立体声。

帧(frame

帧记录了一个声音单元,其长度为样本长度与声道数的乘积,一段音频数据就是由苦干帧组成的。

把所有声道中的数据加在一起叫做一帧,对于单声道:一帧 = 样本长度 * 1;双声道:一帧 = 样本长度 * 2。譬如对于样本长度为 16bit 的双声道来说,一帧的大小等于:16 * 2 / 8 = 4 个字节。

更多命令参考正电原子应用开发手册即可。

暂略。

关于音频,先了解吧。

后面如果要接触,再来深入学习。


补充

什么是PCM设备?

脉冲编码调制(Pulse Code Modulation,简称PCM)是一种将模拟信号转换为数字信号的技术。这种转换过程是通过测量模拟信号的特征点(例如电压或电流)并将其编码为二进制数字数据来实现的。

在通信系统中,PCM设备的作用主要体现在以下几个方面:

  • 低速业务转换:PCM设备可以将各种低速业务转换成数字信号,并装入64kbit/s通道。这些低速业务包括但不限于语音电话、热线电话、磁石电话等,以及2W/4W模拟音频、RS-232、RS-422、RS-485、V.35、G.703同向64kbit/s以太网等。

  • 多路复用:PCM设备具有将30路64kbit/s通道复接成2Mbit/s的能力,从而实现了多路复用的功能。这意味着在同一条物理线路上可以同时传输多路信号,提高了线路的利用率和通信效率。

  • 信号传输:在光纤通信系统中,PCM设备发挥着重要作用。光纤中传输的二进制光脉冲“0”码和“1”码,就是由二进制数字信号对光源进行通断调制产生的,而数字信号正是通过对连续变化的模拟信号进行抽样、量化和编码得到的,这就是PCM的过程。

  • 接口类型多样:PCM设备的接口类型丰富多样,包括环路中继接口、用户线接口、二线音频接口、四线音频接口、异步RS232/V.24接口、同步RS232、RS422接口、RS485接口、V.35接口、G.703 64Kb/s同向数据接口等。

总的来说,PCM设备在现代通信系统中扮演着重要角色,它不仅能够实现模拟信号到数字信号的转换,还能够通过多路复用技术提高通信效率,满足不同用户对数据传输速率的需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2256484.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySQL】数据库 Navicat 可视化工具与 MySQL 命令行基本操作

💯 欢迎光临清流君的博客小天地,这里是我分享技术与心得的温馨角落 💯 🔥 个人主页:【清流君】🔥 📚 系列专栏: 运动控制 | 决策规划 | 机器人数值优化 📚 🌟始终保持好奇心&…

UG NX二次开发(Python)-UIStyler-选取点

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、设计一个UI界面3、创建长方体的代码4、需要引入的库5、测试验证1、前言 采用Python语言进行UG NX二次开发的资料比较少,我本来不是很认可采用Python进行二次开发的,但是近期有读者咨询…

策略模式实战 - 猜拳游戏

**可以整体的替换一套算法,这就是策略模式。**这样对于同一个问题,可以有多种解决方案——算法实现的时候,可以通过策略模式来非常方便的进行算法的整体替换,而各种算法是独立封装好的,不用修改其内部逻辑。 具体的实…

中建海龙:科技创新引领建筑业革新,铸就行业影响力

在建筑业这个古老而又充满活力的行业中,中建海龙科技有限公司(以下简称“中建海龙”)凭借其卓越的科技实力和一系列荣誉奖项,正逐步确立其在建筑工业化领域的领导地位,并对整个行业产生了深远影响。 中建海龙自成立以来…

混合云策略在安全领域受到青睐

Genetec 发布了《2025 年物理安全状况报告》,该报告根据超过 5,600 名该领域领导者(其中包括 100 多名来自澳大利亚和新西兰的领导者)的回应,揭示了物理安全运营的趋势。 报告发现,澳大利亚和新西兰的组织采用混合云策…

小程序 —— Day1

组件 — view和scroll-view view 类似于HTML中的div,是一个块级元素 案例:通过view组件实现页面的基础布局 scroll-view 可滚动的视图区域,用来实现滚动列表效果 案例:实现纵向滚动效果 scroll-x属性:允许横向滚动…

DemoFusion 技术浅析(四):跳跃残差

跳跃残差模块(Skip Residual Module) 是 DemoFusion 框架中用于图像去噪和细节保留的核心组件。该模块通过引入跳跃连接(skip connections)和残差学习(residual learning),在图像去噪过程中有效…

电机功率、电压与电流的换算方法

在电气工程和相关行业中,电机的功率、电压和电流是三个重要的基本参数。它们之间有着密切的关系,而理解这些关系对于电机的选型、设计和应用至关重要。本文将详细阐述这三者之间的换算关系,以及相关公式的应用。 一、电机功率的定义 电机功…

k8s 之 Deployment

(1)Deployment 作用是确保 Pod 副本数量,能够保证 Pod 数量与期望值一样,会有自恢复功能。简洁地说:具有 水平扩展 / 收缩 功能。 可能好奇的是在 kubernetes 中是谁在执行这些控制器的,它就是 kube-contr…

浅谈FRTC8563M实时时钟芯片

FRTC8563M是NYFEA徕飞公司推出的一款实时时钟芯片和日历芯片,采用MSOP-8封装形式。它具有低功耗特性,适用于电池供电的便携式设备。该芯片提供年、月、日、星期、小时、分钟和秒的计时功能,并且具有闹钟功能。FRTC8563M通过I2C总线与微控制器…

SpringBoot 主导家乡特色推荐系统升级,无缝对接多元数据源

2系统相关技术 2.1 Java技术 Java是由SUN公司推出,该公司于2010年被oracle公司收购。Java本是印度尼西亚的一个叫做爪洼岛的英文名称,也因此得来java是一杯正冒着热气咖啡的标识。Java语言在移动互联网的大背景下具备了显著的优势和广阔的前景&#xff0…

Flink如何基于数据版本使用最新离线数据

业务场景 假设批量有一张商户表,表字段中有商户名称和商户分类两个字段。 批量需要将最新的商户名称和分类的映射关系推到hbase供实时使用。 原实现方案 a.原方案内容 为解决批量晚批问题,批量推送hbase表时一份数据产生两类rowkey:T-1和…

【集群划分】含分布式光伏的配电网集群电压控制【33节点】

目录 主要内容 模型研究 1.节点电压灵敏度的计算 2.Kmeans聚类划分 3.集群K值 部分代码 运行结果 下载链接 主要内容 该程序参考文献《含分布式光伏的配电网集群划分和集群电压协调控制》,基于社团检测算法,实现基于电气距离和区域电压调节能…

Elasticsearch 单节点安全配置与用户认证

Elasticsearch 单节点安全配置与用户认证 安全扫描时发现了一个高危漏洞:Elasticsearch 未授权访问 。在使用 Elasticsearch 构建搜索引擎或处理大规模数据时,需要启用基本的安全功能来防止未经授权的访问。本文将通过简单的配置步骤,为单节…

Docker打包SpringBoot项目

一、项目打成jar包 在进行docker打包之前,先确定一下,项目能够正常的打成JAR包,并且启动之后能够正常的访问。这一步看似是可有可无,但是能避免后期的一些无厘头问题。 二、Dockerfile 项目打包成功之后,需要编写Doc…

用OpenCV改变图像的对比度和亮度

两个常用的函数是常数的乘法和加法: 参数α>0和β通常被称为增益和偏置参数;有时这些参数分别控制对比度和亮度。 你可以想到f(x)作为源图像像素和g(x)作为输出图像像素。那么,更方便的是,我们可以将表达式写为: 这…

基于阻塞队列的生产者消费者模型动画演示

一个基于阻塞队列的生产者消费者模型的动画演示: 这是打包好的程序。程序是用 QT 写的。 通过网盘分享的文件:CP模型.7z 链接: https://pan.baidu.com/s/1YjC7YiSqHGqdr6bbffaDWg?pwde6g5 提取码: e6g5 CP模型

李沐动手学深度学习无法动态绘制损失和准确率曲线,输出 <Figure size 350x250 with 1 Axes>

在网上搜了两个解决方案 1.这个方法我试了不好用 d2l.plt.savefig(E:\pycharmProject) 2 修改封装好的函数 ,ctrl加鼠标左键点击进入Animator类,修改里面的add函数 def add(self, x, y):# Add multiple data points into the figureif not hasattr(y,…

在idea中使用mysql(超详细)

一、连接mysql 在IDE开发工具中也是可以使用mysql的,这里以开发java常用的IntelliJ IDEA为例。 1. 打开idea,右上角有数据库侧边栏,打开侧边栏点击加号->数据源,可以看到支持很多数据库,选择mysql。 2. 首次使用需…

scss文件内引入其他scss文件报错

1、今天在编译一些老项目的时候,老是提示下面信息 2、而且有很多Sass import rules are deprecated and will be removed in Dart Sass 3.0.0.警告 3、用npm view sass versions看,其中sass的最新版本是1.82.0 4、经过测试"sass": "1.75…