关于ALSA,网上也有介绍,但是我在看的时候看的也是一脸懵逼,不是介绍的不好,是因为我之前对于嵌入式软件这一块实在没什么了解,之前一直学的JAVA,整个体系跟JAVA还是有很大的区别,要学的也完全是我之前没了解过的,所以以下有说错的请及时纠正。

功能

实现在linux中通过编程.C文件播放一个.wav格式的音频文件

播放: 将音频文件进行解码(Decode)生成PCM数据, 并将其送入音频设备中播出.

录音: 本程序暂时不涉及录音功能

ALSA

关于ALSA我不过多介绍,这篇笔记主要是记录我如何成功播放音乐,主要是怕误导别人,在我看来就是向上提供了接口供我们使用,向下控制了硬件播放音乐,跟JAVA中的JDK提供的接口函数类似,你只管使用就可以了。

  • Linux ALSA声卡驱动之一:ALSA架构简介

还有一个是ALSA的官方的教程好像是,播放音乐整体顺序我也是参考的这篇文章来写的。

  • ALSA Programming HOWTO

术语

关于ALSA中有一些术语着实是让我懵逼的一批,有几个术语我到现在还不知道理解的对不对,所以在正式编程之前一定要先知道,等自己编程的时候再理解一下。

因为声音是连续模拟量,计算机将它离散化之后用数字表示,就有了以下几个名词术语

  • 样本长度(sample):样本是记录音频数据最基本的单位,计算机对每个通道采样量化时数字比特位数,常见的有8位和16位。

这个样本长度后面编程时会用到的,按照字面意思理解的话,就是取出来8bit或者16bit的数据做样本;就理解成一个样本就可以,只不过一个样本的大小是8bit或者16bit,或者其他大小。

  • 通道(channel):该参数为1表示单声道,2则是立体声。

这个术语也好理解,单声道应该就是只有一个左耳机或右出声音,而立体就是左右耳机都出声的意思;每一个通道都有一个样本长度,单声道的数据就是一个样本长度(样本),立体声道的话2个样本长度(样本)。

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

帧单位,把所有通道中的数据加在一起叫做一帧,所以单声道:一帧 = 样本长度 * 1;双声道:一帧 = 样本长度 * 2

  • 采样率(rate):每秒钟采样次数,该次数是针对帧而言,常用的采样率如8KHz的人声,44.1KHz的mp3音乐, 96Khz的蓝光音频。

这个在编程时也比较好设置,没什么混淆的,固定的值也就那么几个,一般没有随便乱设置的数值

  • 周期(period):音频设备一次处理所需要的桢数,对于音频设备的数据访问以及音频数据的存储,都是以此为单位。

一个周期用来存放若干个帧的单元,ALSA函数是以一个周期为单位来读取音频数据的,其实这个周期现在我也没很好的理解到底什么个意思,
是说ALSA向硬件输入数据时,是以时间为周期,在这个时间周期中输入若干个帧呢?
还是说就是一个固定存储空间大小叫做周期,然后这个周期大小的空间放入若干个帧? 真是让人头大!!!!!!!

  • 缓冲区(buffer): 用来存放将要被输入到硬件的数据,我这么理解也不知道对还是不对

一个缓冲区一般有两个周期,缓冲区是循环读取的,比如一个缓冲区有两个周期,那么硬件在读取一个缓冲区时便会产生两次中断,当第一个周期的音频数据被取走就准备取第二个周期的音频数据,同时第三个周期的音频数据会填充到第一个音频数据的位置,以此循环

  • 交错模式(interleaved):是一种音频数据的记录方式,分为交错模式和非交错模式

交错模式与非交错模式只是音频数据存放在缓冲区时的一种方式,
在交错模式下,数据以连续桢的形式存放,即首先记录完桢1的左声道样本和右声道样本(假设为立体声格式),再开始桢2的记录。
而在非交错模式下,首先记录的是一个周期内所有桢的左声道样本,再记录右声道样本,数据是以连续通道的方式存储。

看到上面的术语真是让人头大,但是不理解这些,等编程的时候也是瞎子摸象–一通乱摸,所以务必要先理解了这些术语,如果实在看不下去这术语,可以编程的时候走到哪一步时再回过来一一对照理解也可以。

ALSA编程

在用户空间使用ALSA需要安装依赖

alsa-lib: 用户空间函数库, 封装驱动提供的抽象接口, 通过文件libasound.so提供API给应用程序使用

alsa-utils: 实用工具包,通过调用alsa-lib实现播放音频(aplay)、录音(arecord) 等工具

安装

ubuntu 安装

$ sudo apt-get update
$ sudo apt-get install alsa-lib alsa-utils

Arch 安装

$ sudo pacman -Sy alsa-lib alsa-utils glibc

安装好以后需要运行 aplay -l 确认当前用户可以使用声卡设备

$ aplay -l

如果没有显示图片中的内容,可以切换到root用户试一下,或者把当前用户加入到音频组也可以

$ gpasswd -a [user_name] audio
# 记得注销一下,或者切换用户后再切换回来,通过下面的命令可以查看当前用户是否已经加入audio组
$ groups [user_name]
# 再运行查看声卡设备是否有了
$ aplay -l

编程

代码我已经上传到github,可自行下载后运行。

  • GIthub ALSA 源码

文件分为:

  • Makefile:make 的配置文件
  • 1.wav:音频文件
  • alsa-myself-rw-wav-file-paly-music.c:C源码文件
  • const.h:C头文件

C源码文件中我每一步都有注释,使用的函数都可以在参考中的函数接口文档中找到。

在源码中我有一些自己的理解,如果觉得我的注释对你起不到辅助作用可以删除。

buff_size 和 frame 的关系

alsa中有这么两个函数 snd_pcm_hw_params_set_buffer_size函数 和 snd_pcm_writei 函数,在这之前我对这两个函数的第三个参数就特别混淆,不知道该设置什么,现在我有点明白了

首先这两个函数的第三个参数都是传入以 帧 为单位的值,所以根本就是同一个值,第一个函数设置的是每次硬件可以向多大的缓存中拿数据,第二个是应用层向多大的缓存输入多少数据,这里的数据都是 帧,所以我输入的就是你拿的数据,那可不就是一个东西嘛

所以buff_size大小就无所谓了,通常为 buffer_size = period_size * periods

最主要的是第三个参数frame如何计算,也特别好计算,就好像 RMB和美元的换算是一个道理

buffer_size = RMB

frame(帧) = 美元

钱的是1:7,在计算机中按照字节换算,首先要知道一帧(frame)等于到少字节,才能换算,以下使用16bit采样长度换算,如果是其他采样长度换掉采样长度即可。

# 这里除以8 是因为 1字节 = 8bit
1 帧(frame) = 采样长度 * 通道数 = 16 * 2 / 8 = 4
# 知道一帧的大小后,就可以计算总共的帧大小了,右移两位相当于除以4
frames = buffer_size >> 2;

经过计算的frames 就是要传入两个函数的第三个参数的值了。

使用

我自己是在树莓派4上编译使用的,进入到文件夹后,直接运行 make 命令即可在本目录出现可执行文件 alsa

$ git clone https://github.com/ywhs/rpi-arm64.git
$ cd ALSA
$ make
# -m 参数的意思音乐文件,-f 是术语中提到的样本长度,-r 是术语中提到的采样率
$ ./alsa -m 1.wav -f 161 -r 44
# 161 是 S16_LE 162 是 S16_BE,以此类推,或者直接运行 ./alsa 查看都可以设置什么值
$ ./alsa
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Either 1'st, 2'nd, 3'th or all parameters were missing 1'st : -m [music_filename] music_filename.wav 2'nd : -f [format 241bit or 16bit or 32bit] 161 for S16_LE, 162 for S16_BE 241 for S24_LE, 242 for S24_BE 2431 for S24_3LE, 2432 for S24_3BE 321 for S32_LE, 322 for S32_BE 3'th : -r [rate,44 or 88] 44 for 44100hz 82 for 88200hz For example: alsa -m 1.wav -f 161 -r 44
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

一般不报错的话把耳机插入树莓派的耳机插口就可以听到音乐了

参考

  • ALSA project C 函数接口文档
  • Linux音频编程

ALSA应用层编程播放音乐相关推荐

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

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

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

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

  3. alsa声音编程介绍

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

  4. c并非所有的代码路径都返回值_两行C语言代码播放音乐,就这么so easy!你学到了吗?...

    函数介绍 为了实现用C语言播放音乐,我们需要用到windows的一个API,mciSendString. 函数原型为: MCIERROR mciSendStringA( LPCSTR lpstrCom ...

  5. armbian 斐讯n1_尝试使用斐讯N1在armbian终端下播放音乐

    十年前刚开始玩linux的时候,记得用mocp和mplayer在linux终端下播放音乐和视频装过比,现在突然记起这些东西,想在N1上尝试下. N1刷的armbian5.67版本,无桌面,纯终端. 先 ...

  6. 基于arduino的火焰报警蜂鸣器播放音乐(外部中断)实验

    接线 按钮------D3 火焰传感器---D2 蜂鸣器-----D7 led灯-----D13 编程思路及目的 利用火焰传感器检测火焰,然后播放音乐,如果中途有人按下按钮,则停止音乐. 主程序 #i ...

  7. python写音乐_你想过用代码来写音乐吗?我用业余时间开发的一个可以编程写音乐的python库(一)...

    最近几个月学业繁忙,但是业余时间自己开发了很多python库,内容包括数学统计,各种游戏,还有音乐等等.其实还有试着写AI方面的,但是目前还是初期进度.今天我想先介绍一下我正在开发中的一个可以编程写音 ...

  8. 【FPGA】五、蜂鸣器播放音乐

    文章目录 前言 一.蜂鸣器简介 二.音频音符简介 三.任务要求 四.程序设计 1.设计思路 2.程序代码 总结 前言 蜂鸣器(Buzzer)是现代常用的一种电子发声器,主要用于产生声音信号.它是一种一 ...

  9. iPhone开发播放音乐与按钮声音

    1.背景音乐播放,支持mp3格式 循环播放长音乐. 这种播放音乐的方式导入框架#import <AVFoundation/AVFoundation.h>: NSString *musicF ...

最新文章

  1. Python可视化神器Yellowbrick使用
  2. Java Remote Debug(远程调试)
  3. 【bzoj2460】[BeiJing2011]元素 贪心+高斯消元求线性基
  4. 使用apache模块rewrite_module
  5. Python注释缩进不得当导致IndentationError: unexpected indent
  6. 解决IE6下 position的fixed定位问题
  7. RedHat el5.0 搭建 Postfix 邮件服务器系统一
  8. java 数据库 事务 只读_java – odd SQLException – 无法检索转换只读状态服务器
  9. 日出时的画面_如何拍摄日出日落,老摄影家近30年创作经验分享
  10. Terry的学习笔记--ASP.NET MVC 4 HELLO WORLD添加视图(View)
  11. Linux 操作系统下常见信号详解
  12. 我的家乡主题网页设计
  13. 100套Java毕业设计和课程设计项目案例(包含项目源码)
  14. 2016计算机奥林匹克小学,NOIP2016复赛数据
  15. 第三阶段应用层——1.7 数码相册—电子书(4)—select支持多输入
  16. win10系统C盘根目录里文件夹都是干什么的
  17. 六、定语从句和关系代词
  18. 【Java实现】南京地铁导航系统的简单实现(二)—— 最短路径算法的实现
  19. hyperledger java_hyperledger fabric 1.4 使用java开发智能合约
  20. APP加密,ios代码混淆工具,虚拟化技术 适用于移动应用程序的虚拟化加密软件

热门文章

  1. 使用pgloader迁移MySQL至openGauss
  2. 100款最佳英文字体...
  3. SHELL命令里面的EQ、NE、GT、LT、GE、LE分别是什么意思
  4. Browser speed discrepancies
  5. Java 教程 —— 开天辟地
  6. InfoPath与SharePoint之(一) InfoPath和SharePoint List
  7. 2. 网络协议及硬件
  8. 最全的 cadence 元器件库详细说明
  9. oracle代言人,好莱坞巨星布鲁斯南与欧琳正式签约成为代言人
  10. 生成1至10位随机数