一、原理简介

在Linux下,记录——从dsp读取数据。播放——至dsp设备写入数据。

开发板採用声卡UDA1341实现音频编解码,完毕A/D和D/A转换,芯片UDA1341与CPU的连接图例如以下:

为了实现全双工,传输数据须要使用两个DMA通道。以音频回放为例,传输数据先由内部总线送到内存。 然后传到DMA控制器通道1,再通过IIS控制器写入IIS总线并传输给音频芯片,通道2用来录音。

二、WAV文件

WAVE是录音时用的标准的Windows文件格式,文件的扩展名为“wav”。数据本身的格式为PCM或压缩型。属于无损音乐格式的一种,符合RIFF(Resource Interchange File Format)规范。全部的WAV都有一个文件头,这个文件头音频流的编码參数。

数据块的记录方式是小端(little-endian)字节顺序,标志符并非字符串而是单独的符号

採样率为8kHz,量化位数为16,单通道的record.wav文件为例,文件前三行信息例如以下:

第一列表示地址,一行表示16个字节。

0x52,0x49,0x46,0x46   //“RIFF”4个字符相应的ASCII码值

0x57,0x41,0x56,0x45,0x66,0x6D,0x74,0x20  //“WAVEfmt ”各个字符相应的ASCII码值

0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00//sizeof(PCMWAVEFORMAT)4Byte,格式类别2B,通道数1B(声道)

0x40,0x1F,0x00,0x00,0x80,0x3E,0x00,0x00, //採样频率0X0001F40= 8kHZ(8000Hz)4B。0x00003E80B/s=16kB/s 4B

0x02,0x00,0x10,0x00,0x64,0x61,0x74,0x61};//数据调整数0x0002(1*16/8)2B,即一个採样点所占的字节数。样本数据位数0x10(16位)2B,即一个採样点所表示的位数    “data”4B

地址000014H~000017H的值:2400 01 00即十六进制0x00010024,相应十进制65572(65536+36),表示从0x08開始到文件尾的总字节数;

地址000028H~00002BH的值:0080 0C 00即十六进制0x00010000,相应十进制65536,表示採样数据总数。

录音測试命令:cat  /dev/sound/dsp > audio.wav

使用cat命令生成的audio.wav是一个PCM纯音频文件:

通过加入wav文件头,能够生成一个标准的wav音频文件:

三、Linux下实现录放音

注意驱动程序中的默认參数,应用程序能够通过ioctl()函数设置新的取值。

Open()函数:採用何种模式对声卡进行操作也必须在打开设备时指定,对于不支持全双工的声卡来说,应该使用仅仅读或者仅仅写的方式打开。仅仅有那些支持全双工的声卡。才干以读写的方式打开,这还依赖于驱动程序的详细实现。open_mode有三种选择:O_RDONLY。O_WRONLY和O_RDWR,分别表示仅仅读、仅仅写和读写。

OSS建议尽量使用仅仅读或仅仅写。仅仅有在全双工的情况下(即录音和放音同一时候)才使用读写模式。Linux
同意应用程序多次打开或者关闭与声卡相应的设备文件,从而可以非常方便地在放音状态和录音状态之间进行切换。

注意,用户始终要读/写一个完整的採样。比如一个16-bit的立体声模式下。每一个採样有4个字节。所以应用程序每次必须读/写4的倍数个字节。

源代码例如以下:

  1. #include<unistd.h>
  2. #include<fcntl.h>
  3. #include<sys/types.h>
  4. #include<sys/ioctl.h>
  5. #include<stdlib.h>
  6. #include<stdio.h>
  7. #include<linux/soundcard.h>
  8.  
  9. #define LENGTH 3 // 存储秒数
  10. #define RATE 44100 // 採样频率
  11. #define SIZE 16 // 量化位数
  12. #define CHANNELS 2 // 声道数目
  13. /* 用于保存数字音频数据的内存缓冲区*/
  14. unsigned charbuf[LENGTH*RATE*SIZE*CHANNELS/8];
  15. int main()
  16. {
  17. intfd; // 声音设备的文件描写叙述符
  18. intarg; // 用于ioctl调用的參数
  19. intstatus; // 系统调用的返回值
  20. /*打开声音设备 */
  21. fd= open("/dev/sound/dsp", O_RDONLY);
  22. if(fd< 0)
  23. {
  24. perror("openof /dev/sound/dsp failed");
  25. exit(1);
  26. }
  27.  
  28. /*设置採样时的量化位数 */
  29. arg= SIZE;
  30. status= ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
  31. if(status== -1)
  32. perror("SOUND_PCM_WRITE_BITSioctl failed");
  33. if(arg!= SIZE)
  34. perror("unableto set sample size");
  35. /*设置採样时的声道数目 */
  36. arg= CHANNELS;
  37. status= ioctl(fd, SNDCTL_DSP_STEREO, &arg);
  38. if(status== -1)
  39. perror("SNDCTL_DSP_STEREOioctl failed");
  40. if(arg!= CHANNELS)
  41. perror("unableto set number of channels");
  42. /*设置採样时的採样频率 */
  43. arg= RATE;
  44. status= ioctl(fd, SNDCTL_DSP_SPEED, &arg);
  45. if(status== -1)
  46. perror("SNDCTL_DSP_SPEEDioctl failed");
  47. if(arg!= RATE)
  48. perror("unableto set rate");
  49.  
  50. printf("Saysomething:\n");
  51. status= read(fd, buf, sizeof(buf)); //recording
  52. if(status!= sizeof(buf))
  53. perror("readwrong number of bytes");
  54. printf("Yousaid:\n");
  55. close(fd);
  56. fd= open("/dev/sound/dsp", O_WRONLY);
  57. if(fd< 0)
  58. {
  59. perror("openof /dev/sound/dsp failed");
  60. exit(1);
  61. }
  62.  
  63. /*设置採样时的量化位数 */
  64. arg= SIZE;
  65. status= ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
  66. if(status == -1)
  67. perror("SOUND_PCM_WRITE_BITS ioctl failed");
  68. if(arg != SIZE)
  69. perror("unable toset sample size");
  70. /*设置採样时的声道数目 */
  71. arg = CHANNELS;
  72. status = ioctl(fd, SNDCTL_DSP_STEREO,&arg);
  73. if(status == -1)
  74. perror("SNDCTL_DSP_STEREO ioctl failed");
  75. if(arg != CHANNELS)
  76. perror("unable toset number of channels");
  77. /* 设置採样时的採样频率 */
  78. arg = RATE;
  79. status = ioctl(fd,SNDCTL_DSP_SPEED, &arg);
  80. if(status == -1)
  81. perror("SNDCTL_DSP_SPEED ioctl failed");
  82. if(arg != RATE)
  83. perror("unable toset rate");
  84.  
  85. status= write(fd, buf, sizeof(buf)); //playing
  86. if(status!= sizeof(buf))
  87. perror("wrotewrong number of bytes");
  88. close(fd);
  89. return0;
  90. }

程序中的注意点是open()函数的參数设置,之前採用參数O_RDWR,结果放音时总是出现错误。详细出错原因可能与驱动程序的设置有关。本设计中。正确的设置是当recording时,选择O_RDONLY,什么时候playing时间。选择O_WRONLY。

Linux对于录音的更多相关文章

  1. linux声卡录音和播放(alsa方法)

    前言 客户购买多台UNO-2184,使用fedora23系统进行视频监控,视频监控的同时,也要同步采集现场画面的声音,原来系统采用的是fedora 14,之前是通过操作/dev/bsp,对声卡进行操作 ...

  2. Linux 应用笔记

    Linux 应用笔记 Linux 应用笔记 小书匠 Raspberry Pi 常用命令 CentOs Raspberry Ubuntu python 实用教程 Vim 权限问题 内存分配 shell ...

  3. 转载-好用的linux软件合集

    音频 Airtime – Airtime 是一款用于调度和远程站点管理的开放广播软件  Ardour – 在 Linux 上录音,编辑,和混音  Audacious – 开源音频播放器,按你想要的方式 ...

  4. Linux 软件大全

    应用 音频 Airtime - Airtime 是一款用于调度和远程站点管理的开放广播软件   Ardour - 在 Linux 上录音,编辑,和混音  Audacious - 开源音频播放器,按你想 ...

  5. 海量的超赞 Linux 软件 (转载)

    海量的超赞 Linux 软件 作者: VoLuong 译者: LCTT Mo | 2016-08-24 16:01   评论: 27 收藏: 38 这个仓库收集了对任何用户/开发者都超赞的 Linux ...

  6. 超赞的Linux软件分享(持续更新)

    开发 Android studio - Android 的官方 IDE:Android Studio 提供在各种类型的安卓设备上构建应用最快的工具. Aptana - Aptana Studio 利用 ...

  7. Linux 驱动开发

    linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...

  8. 微信录音文件上传到服务器以及amr转化成MP3格式,linux上转换简单方法

    微信公众号音频接口开发 根据业务需求,我们可能需要将微信录音保存到服务器,而通过微信上传语音接口上传到微信服务器的语音文件的有效期只有3天,所以需要将文件下载到我们自己的服务器. 上传语音接口 wx. ...

  9. 〖Linux〗录像桌面视频同时录音

    1. 安装依赖的包 sudo apt-get install -y ffmpeg oss-compat alsa-oss 2. 录制桌面视频并录音 aoss ffmpeg -f oss -i /dev ...

随机推荐

  1. sql时间比较

  2. 【Android开发经验】使用反射,得到的类的字段、方法、并实现了简单的调用

    本文后推出Android的ICO框架做准备,所以,假设你想要一个最近的一项研究Android的ICO学生框架.你可以稍微看一下. 首先,简介一下Java里面的反射. JAVA反射机制是在执行状态中,对 ...

  3. 给Ubuntu安装KDE桌面 [转]

    自ubuntu5.10发布以来,我非常难得的让她在我的硬盘上顽强生存了近3个月,仔细想想就连当年我第一个接触的红旗Linux也不过坚持了一个月,呵呵,又写了一段废话── 所 谓的“重回Kununtu” ...

  4. 高速理解掌握node.js 字符编码,确码过程 以及base64编解码原理

    var buf1 = new Buffer('a','ascii'); // 字符'a' -> ascii编码 -> 61 存在计算机中 console.log(buf1); var b ...

  5. 返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .net 4.5 带来的更方便的异步操作

    原文:返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, ...

  6. T-SQL中default值的使用

    今天介绍一下通过T-SQL语句来创建表时使用default的关键字来自动使用默认值,这个关键字和其它的如:identity,primary key ,not null ,unique等不是相同,这里简 ...

  7. android使用XmlPullParser来解析XML文件

    解析下面的一个XML: <?xml version="1.0" encoding="utf-8" ?> <rss><sid> ...

  8. Cookie概念

    ASP.NET Cookie概念.CURD操作.原理.实际运用   会话就WEB开发来说,一个会话就是你通过浏览器与服务器之间的一次通话,只不过这种通话是以用浏览器浏览的方式来实现的. 就会话的应用来 ...

  9. GitLab 之 Linux十分钟快装(转)

    先把 Shell 命令贴出来,楼主以 CentOS release 6.5 (Final) 64位 为例: //配置系统防火墙,把HTTP和SSH端口开放. sudo yum install curl ...

  10. Scilab 的画图函数(1)

    Scilab 的画图函数 plot 函数 最主要的是 plot 函数,与 matlab 中的plot 函数类似. xdata = linspace(1,10,50); ydata = sin(xdat ...