Alsa是Linux高级音频接口。面对众多的音频设备,Alsa为Linux音频开发人员提供了一套标准的访问机制,使得音频开发变得十分容易。不信?下面我们就利用它编写一个简单的录音/播音程序,不过这需要你有一定的计算机语言基础。

一个典型的音频程序应该具有以下结构:

打开音频设备

为设备设置读写参数

向音频设备读/写音频数据

关闭设备

Alsa库为我们实现这些操作提供了丰富的接口。

首先让我们封装一个打开音频设备的函数:

1.  snd_pcm_t *pcm_handle;

2.

3.  bool device_open(int mode){

4.  if (snd_pcm_open (&pcm_handle, “default” , mode , 0) < 0)

5.  return false;

6.  return true;

7.  }

snd_pcm_open是Alsa库提供的打开设备调用函数,这里我们指定打开缺省的音频设备,并根据参数mode将设备置为录音或是播放状态,如果设备打开成功,pcm_handle便指向该设备句柄,我们用全局变量保存起来,方便以后使用。

第二步是设置参数,参数设置不当将会导致音频设备无法正常工作。在设置参数前,我们需要了解一下各个参数的含义以及一些基本概念。

样本长度(sample):样本是记录音频数据最基本的单位,常见的有8位和16位。

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

桢(frame):桢记录了一个声音单元,其长度为样本长度与通道数的乘积。

采样率(rate):每秒钟采样次数,该次数是针对桢而言。

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

交错模式(interleaved):是一种音频数据的记录方式,在交错模式下,数据以连续桢的形式存放,即首先记录完桢1的左声道样本和右声道样本(假设为立体声格式),再开始桢2的记录。而在非交错模式下,首先记录的是一个周期内所有桢的左声道样本,再记录右声道样本,数据是以连续通道的方式存储。不过多数情况下,我们只需要使用交错模式就可以了。

明白了各参数含义及关系后,我们开始设置参数:

1.  int bit_per_sample; //样本长度(bit)

2.  int period_size; //周期长度(桢数)

3.  int chunk_byte; //周期长度(字节数)

4.  snd_pcm_hw_params_t *params; //定义参数变量

5.

6.  bool device_setparams()

7.  {

8.  snd_pcm_hw_params_t *hw_params;

9.  snd_pcm_hw_params_malloc (&hw_params); //为参数变量分配空间

10.snd_pcm_hw_params_malloc (&params);

11.snd_pcm_hw_params_any ( pcm_handle, hw_params ); //参数初始化

12.snd_pcm_hw_params_set_access ( pcm_handle, hw_params,

13. SND_PCM_ACCESS_RW_INTERLEAVED); //设置为交错模式

14.snd_pcm_hw_params_set_format( pcm_handle, hw_params,

15. SND_FORMAT_S16_LE); //使用用16位样本

16.snd_pcm_hw_params_set_rate_near( pcm_handle, hw_params,

17. 44100, 0); //设置采样率为44.1KHz

18.snd_pcm_hw_params_set_channels( pcm_handle, hw_params, 2); //设置为立体声

19.snd_pcm_hw_params_get_period_size( hw_params, &period_size); //获取周期长度

20.bit_per_sample = snd_pcm_hw_format_physical_width( hw_params.format );

21. //获取样本长度

22.chunk_byte = period_size * bit_per_sample * hw_params.channels / 8;

23.//计算周期长度(字节数(bytes) = 每周期的桢数 * 样本长度(bit) * 通道数 / 8 )

24.snd_pcm_hw_params( pcm_handle, hw_params); //设置参数

25.params = hw_params; //保存参数,方便以后使用

26.snd_pcm_hw_params_free( hw_params); //释放参数变量空间

27.return true;

28.

29.}

这里先使用了Alsa提供的一系列snd_pcm_hw_params_set_函数为参数变量赋值。最后才通过snd_pcm_hw_params将参数传递给设备。需要说明的是正式的开发中需要处理参数设置失败的情况,这里仅做为示例程序而未作考虑。

设置好参数后便可以开始录音了。录音过程实际上就是从音频设备中读取数据信息并保存。

1.  char *wave_buf;

2.  int wave_buf_len;

3.  bool device_capture( int dtime ){

4.   wave_buf_len = dtime * params.rate * bit_per_sample * params.channels / 8 ;

5.   //计算音频数据长度(秒数 * 采样率 * 桢长度)

6.   char *data = wave_buf = (char*)malloc( wave_buf_len ); //分配空间

7.

8.  int r = 0;

9.  while ( data ?C wave_buf <= wave_buf_len ?C chunk_size ){

10.r = snd_pcm_readi( pcm_handle, data , chunk_size);

11.if ( r>0 ) data += r * chunk_byte;

12.else

13.return false

14.}

15.return true;

16.}

形参dtime用来确定录音时间,根据录音时间分配数据空间,再调用snd_pcm_readi从音频设备读取音频数据,存放到wave_buf中。

同样的原理,我们再添加一个播放函数,向音频设备写入数据:

1.  bool device_play(){

2.  char *data = wave_buf;

3.  int r = 0;

4.  while ( data ?C wave_buf <= wave_buf_len ?C chunk_size ){

5.  r = snd_pcm_writei( pcm_handle, data , chunk_size);

6.  if ( r>0 ) data += r * chunk_byte;

7.  else

8.  return false

9.  }

10.return true;

11.}

最后我们给这个示例程序加上main函数

1.  #include <alsa/asoundlib.h>

2.

3.  bool device_open( int mode);

4.  bool device_setparams();

5.  bool device_capture( int dtime );

6.  bool device_play();

7.  char *wave_buf;

8.  int wave_buf_len;

9.  int bit_per_sample;

10.int period_size;

11.int chunk_byte;

12.int chunk_size;

13.snd_pcm_hw_params_t *params;

14.

15.int main( int , char** ){

16.//录音

17.if (!device_open(SND_PCM_STREAM_CAPTURE ) return 1;

18.if (!device_setparams()) return 2;

19.if (!device_capture( 3 )) return 3; //录制3秒

20.snd_pcm_close( pcm_handle );

21.

22.//播放

23.if (!device_open( SND_PCM_STREAM_PLAYBACK ) return 4;

24.if (!device_setparams()) return 5;

25.if (!device_play()) return 6;

26.snd_pcm_close( pcm_handle );

27.

28.return 0;

29.}

这样,我们便完成了一个具有录音,播音的功能的音频程序,因为使用了alsa库,如果你使用的是gcc编译器,最后链接时记得要带上参数——lasound 。

限于篇幅,Alsa接口提供的强大功能不仅于此,有兴趣的读者可以参阅ALSA HOWTO,那上面你一定能够发现Alsa的强大之处。

alsa 麦克风采集音频相关推荐

  1. Linux 下查看麦克风或音频采集设备

    前言 最近需要在树莓派上做音频采集和音频处理,所以第一步得在树莓派系统下查看到当前的音频输入和音频输出设备.树莓派安装了raspberry系统,raspberry系统隶属于debian系统. 一.如何 ...

  2. nanopc-T4 开发板通过USB麦克风采集录制音频

    文章目录 1. 使用 nanopc-T4 开发板采集音频 2. 使用 Tyless外置usb麦克风录制声音 3. 使用 ffrmpeg 将实时视频与音频合并并推流到 rtmp 服务器中 4. 成功实现 ...

  3. 【总结】Linux 下查看麦克风或音频采集设备

    前言 最近需要在树莓派上做音频采集和音频处理,所以第一步得在树莓派系统下查看到当前的音频输入和音频输出设备.树莓派安装了raspberry系统,raspberry系统隶属于debian系统. 一.如何 ...

  4. 如何使用c语言获取麦克风信息,[C#] 如何获取麦克风采集的音频信息 和 如何根据波形播放声音。...

    你好: 我对这方面也不懂,但是我觉得如果想分析音频数据的话首先要知道麦克风采集到的音频是什么格式的,然后需要了解这种格式的音频数据的二进制流的编码规范,比如wav格式的音频,参考一下这篇博客, wav ...

  5. AudioRecord 采集音频PCM数据

    AudioRecord 可以用来采集音频原始数据(PCM)格式,使用起来非常简单. 主要就是构造函数的定义 AudioRecord(int audioSource, int sampleRateInH ...

  6. Android 音视频开发(二):使用 AudioRecord 采集音频PCM并保存到文件(学习笔记)

    关于 AudioRecord Android SDK 提供了两套音频采集的API,分别是:MediaRecorder 和 AudioRecord,前者是一个更加上层一点的API,它可以直接把手机麦克风 ...

  7. 音频-基于Core Audio技术采集音频(版本2)

    上一个版本有个严重的问题,就是 Format-size的值 竟然是40个字节 诡异啊 奇怪啊 不应该是16 或者18吗 怎么会是40呢?? 按理说是16 ,表示一个纯粹的FOTMAT块,如果是18 表 ...

  8. alsa录制pcm音频及fdk-aac编码

    1. 利用alsa库录制PCM音频,并保存为音频文件. (该部分代码摘自网络,原链接不记得了,侵删.但是代码亲测可用,在此做个demo备用) /*** @file record_pcm.c* @bri ...

  9. WebRTC Native M96 SDK接口封装--startAudioMixing播放音乐文件与麦克风采集声音混音

    封装接口 使用WebRTC大概有两种方式,一种是把WebRTC当做一种库来用:另一种是把WebRTC当做一个框架,自己在上层封装代码. 不管怎么,做实时音视频SDK开发的,都需要封装接口,供给上层应用 ...

最新文章

  1. 自然语言推理和数据集
  2. 科学家提出了忆阻性神经混合芯片 这一概念
  3. # JavaScript中的执行上下文和队列(栈)的关系?
  4. Ring3下Dll注入方法整理汇总
  5. 计算机维修英语情景对话大全,快速英语情景对话大全 日常生活对话 7 排除电脑故障...
  6. 牛客网-华为-2020届校园招聘上机考试-软件类机考-1
  7. 机器学习笔记(十二):随机梯度下降
  8. python开发仓库管理系统_tkinter的应用--mini级《仓库管理系统》
  9. opencv学习(二十四)之腐蚀与膨胀
  10. php implode explode,PHP函数implode()与explode()的区别及数组与字符串互转的用法讲解...
  11. 交互式可视化报表怎么弄?看过来!
  12. 一个人在家怎么做自媒体?4个靠谱平台,门槛低、变现很简单
  13. [译] 为什么设计师讨厌政治(如何解决)
  14. Python学习之学校教学(选择结构与循环结构)抓狐狸问题
  15. Sublime3 豆沙绿护眼主题及仿HBuilder绿优主题
  16. 【解决方案】智慧工地AI视频远程集中监控解决方案是如何通过EasyCVR视频平台实现的?
  17. WPF 控件样式之TextBox 输入框
  18. 细分消费市场有4个关键基础
  19. python与sas_python与R(对比SAS),我该选择哪种工具?
  20. 关于Android Studio Button背景无法修改,一直呈现亮紫色

热门文章

  1. Android viewpager+fragment实现无限滚动,左右有前/后一页的部分,并fragment显示的内容是activity传过去的数据
  2. 投影仪应该怎么选择?数码粉总结目前最好的家用投影仪
  3. C#学习笔记 正则表达式
  4. 【简单的密码生成器】
  5. ElectronBot支线项目
  6. PL2303在ARM Linux下驱动的问题及解决方法
  7. C语言的小tips~
  8. Unity:计算两个物体(没有父子关系)的相对坐标
  9. 做程序界的死神,获取自己的斩魂刀
  10. 病毒HEUR:Trojan-Downloader.Win32.Generic