自学内容网 自学内容网

Linux-音频应用编程

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


原文地址:https://blog.csdn.net/qq_28576837/article/details/144306135

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!