Linux音频编程(二)声卡介绍

一、声卡

1、声卡是audio interface,它含有hardware buffer,而这个hardware buffer是在声卡里面,不是内存。声卡的缓存是环状的,则ALSA中是将数据分成连续的片段然后传到按单元片段传输。

2、当我们通过麦克风讲话的声音搜集到声卡里之后,将内存从声卡设备文件中读取声音数据的过程就是录音过程;把内存中的声音数据写入到声卡的设备文件中可以实现音频文件。

3、我们在/dev/snd/目录下用ls命令就可以看到相关的声卡设备。

4、模/数(ADC)转换器将模拟电压转换成离散的样本值。声音以固定的时间间隔被采样,采样的速率称为采样率。把样本输出到数/模(DAC)转换器,比如扩音器,最后转换成原来的模拟信号。

二、相关设备文件介绍

1、/dev/dsp

用于数字采样(sampling)和数字录音(recording)的设备文件,向该设备写数据时使用声卡上的D/A转换器进行放音,而向该设备读数据时使用声卡上的A/D转换器进行录音。

声卡使用DSP(数字信号处理器)来实现模拟信号和数字信号之间的转换(有D/A和A/D转换)。声卡中的DSP设备在以只读方式打开/dev/dsp时,使用A/D转换器变成数字采样后的样本,通过read系统调用从声卡读取数据进行声音的输入;以只写方式打开/dev/dsp时,数字信号经过D/A转换器变成模拟信号,通过write进行声音的输出。以读写的方式打开 /dev/dsp可同时进行声音的输入和输出。

2、/dev/sequencer合成器

3、/dev/mixer混音器

三、使用

1、在打开声卡之后可通过ioctl函数来设置声卡参数,函数如下所示:

int ioctl(int fd, int request, ...);

//参数fd是打开的文件的描述符,它是在设备打开时获得的;如果设备比较复杂,那么对它的控制请求相应地也会有很多种。

//参数request是命令,它的目的就是用来区分不同的控制请求;通常说来,在对设备进行控制时还需要有其它参数,这要根据不同的控制请求才能确定,并且可能是与硬件设备直接相关的。

//第三个参数是完成命令的操作需要的参数或返回的结果。它的意义取决于命令参数,可以是单个数,或是指向复杂的数据结构的指针。(由于ioctl函数面向所有设备文件,不同的设备又是千差万别,所以,第三个参数的意义、函数的返回值、错误代码等等都取决于command。并且,不同的设备,即使是相同的command也有不同的含义,需要的参数和返回值、错误代码等也不同。)

//ioctl函数中相关的命令如下:

SOUND_PCM_WRITE_BITS:设置声卡的量化位数,8或者16,有些声卡不支持16位;

SOUND_PCM_READ_BITS:获取当前声卡的量化位数;

SOUND_PCM_WRITE_CHANNELS:设置声卡的声道数目,1或者2,1为单声道,2为立体声;

SOUND_PCM_READ_CHANNELS:获取当前声卡的声道数;

SOUND_PCM_WRITE_RATE:设置声卡的采样频率,8K,16K等等;

SOUND_PCM_READ_RATE:获取声卡的采样频率

(1)声卡读取数据和向声卡写入数据时,具有特定的格式,默认为8位无符号数据、单声道、8KHz采样率,可通过ioctl系统调用来改变格式,可调节运行在Linux内核中的声卡驱动程序中缓冲区的大小,进而达到放音和录音想要的效果。例如:

//缓冲区大小设置

int setting = 0xnnnnssss;
int result = ioctl(handle, SNDCTL_DSP_SETFRAGMENT, &setting);

//参数setting实际上由两部分组成,其低16位标明缓冲区的尺寸,相应的计算公式为buffer_size = 2^ssss;

//若参数setting低16位的值为16,那么相应的缓冲区的大小会被设置为65536字节。参数setting的高16位则用来标明分片(fragment)的最大序号,它的取值范围从2一直到0x7FFF,其中0x7FFF表示没有任何限制。

//设置声卡声道数目

int channels = 0; //0=mono 1=stereo

int result = ioctl(handle, SNDCTL_DSP_STEREO, &channels);

//设置采样格式

int format = AFMT_U8;

int result = ioctl(handle, SNDCTL_DSP_SETFMT, &format);

//设置采样频率

int rate = 22050;
int result = ioctl(handle, SNDCTL_DSP_SPEED, &rate);

//调用ioctl时将第二个参数的值设置为SNDCTL_DSP_SPEED,同时在第三个参数中指定采样频率的数值。

//在 Linux下进行音频编程时最常用到的几种采样频率是11025Hz、16000Hz、22050Hz、32000Hz和44100Hz。

2、直接使用系统调用控制声卡的是tinyalsa库,位于目录/external/tinyalsa下,编译生成库文件libtinyalsa.so(只涉及两个文件mixer.c,pcm.c),编译生成工具 tinycap,tinymix,tinypcminfo,tinyplay,可用于直接控制音频通道,进行录音播音测试。tinyalsa中使用:
pcm_open()来打开声卡;
pcm_write()来播放音乐;
pcm_read()来录音。

3、config 的配置很重要,tinyalsa直接从wav文件把channels,rate,等读出来并配置进声卡。

//转换成config

config.channels = channels;  //声道数目

config.rate = rate;  //采样频率

config.period_size = 1024; //周期

config.period_count = 4;  //count

if (bits == 32)

config.format = PCM_FORMAT_S32_LE;  //

else if (bits == 16)

config.format = PCM_FORMAT_S16_LE;

config.start_threshold = 0;

config.stop_threshold = 0;

config.silence_threshold = 0;

//

pcm = pcm_open(card, device, PCM_IN, &config);

if (!pcm || !pcm_is_ready(pcm)) {

printf("Unable to open PCM device (%s)\n",pcm_get_error(pcm));

return 0;

}

四、

1、spdif接口支持rawdata和pcmdata模式。

当音频channel设置成channels=4的时候,spdif会相应设置成rawdata模式。当音频channel设置成channels=2或者1的时候,spdif会设置成pcmdata模式。spdif是一个独立的音频驱动,接口支持alsalib中的标准接口。

2、Hdmiaudio支持rawdata和pcmdata模式。

当音频channel设置成channels=4的时候,hdmiaudio会相应设置成rawdata模式。当音频channel设置成channels=2或者1的时候,hdmiaudio会设置成pcmdata模式。Hdmiaudio是一个独立的音频驱动,接口支持alsalib中的标准接口。

原文地址:https://www.cnblogs.com/L-102/p/11488030.html

时间: 2024-07-31 07:56:06

Linux音频编程(二)声卡介绍的相关文章

Linux音频编程指南

Linux音频编程指南 虽然目前Linux的优势主要体现在网络服务方面,但事实上同样也有着非常丰富的媒体功能,本文就是以多媒体应用中最基本的声音为对象,介绍如何在Linux平台下开发实际的音频应用程序,同时还给出了一些常用的音频编程框架. 一.数字音频 音频信号是一种连续变化的模拟信号,但计算机只能处理和记录二进制的数字信号,由自然音源得到的音频信号必须经过一定的变换,成为数字音频信号之后,才能送到计算机中作进一步的处理. 数字音频系统通过将声波的波型转换成一系列二进制数据,来实现对原始声音的重

Linux音频编程指南(转)

转自: http://www.ibm.com/developerworks/cn/linux/l-audio/ Linux音频编程指南 虽然目前Linux的优势主要体现在网络服务方面,但事实上同样也有着非常丰富的媒体功能,本文就是以多媒体应用中最基本的声音为对象,介绍如何在Linux平台下开发实际的音频应用程序,同时还给出了一些常用的音频编程框架. 1 评论: 肖文鹏 ([email protected]), 自由软件爱好者 2004 年 2 月 01 日 内容 一.数字音频 音频信号是一种连续

[转] - Linux网络编程 -- 网络知识介绍

(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端        在网络程序中,如果一个程序主动和外面的程序通信,那么我们把这个程序称为客户端程序. 比如我们使用ftp程序从另外一        个地方获取文件的时候,是我们的ftp程序主动同外面进行通信(获取文件), 所以这个地方我们的ftp程序就是客户端程序. 服务端        和客户端相

Linux网络编程(二)

服务套和客户机的信息函数 1.字节转换函数 在网络上面有着许多类型的机器,这些机器在表示数据的字节顺序是不同的, 比如i386芯片是低字节在内存地址的低端,高字节在高端,而alpha芯片却相反. 为了统一起来,在Linux下面,有专门的字节转换函数. unsigned long int htonl(unsigned long int hostlong)     unsigned short int htons(unisgned short int hostshort)     unsigned

深入理解Linux文件系统编程(二)

Linux文件系统编程实战 一.创建文件 <span style="font-size:14px;">#include<stdio.h> #include<stdlib.h> #include<sys/stat.h> #include<fcntl.h> //创建文件子函数 void creat_file(char *filename) { int fd; //系统调用描述文件的文件描述符(为非负数) if(fd=creat(f

Linux网络编程二、tcp连接API

一.服务端 1.创建套接字: int socket(int domain, int type, int protocol); domain:指定协议族,通常选用AF_INET. type:指定socket类型,TCP通信下使用SOCK_STREAM. protocol:指定协议,通常为0. 返回值:成功则返回新socket的文件描述符,失败返回-1. 头文件:sys/socket.h     sys/types.h 2.绑定套接字 int bind(int sockfd, struct sock

Linux Shell编程二

以"``"符号包含的内容不是字符串,而是代表这是一个shell命令. echo "today is" `date` 前面是字符,后面`date`表示执行date这个命令. PDATE=`date` 代表定义一个变量PDATE,将date执行完成输出的结果放入变量PDATE中. 以单引号,双引号包含的字符全部会被shell认为是字符串 echo "today is " 'date' #打印 today is date "expr"

Linux系统编程——进程的介绍

http://my.9ku.com/fuyin/daogaoo.asp?dgid=564516 http://my.9ku.com/fuyin/daogaoo.asp?dgid=564608 http://my.9ku.com/fuyin/daogaoo.asp?dgid=564687 http://my.9ku.com/fuyin/daogaoo.asp?dgid=564782 http://my.9ku.com/fuyin/daogaoo.asp?dgid=564867 http://my.

【Linux网络编程】广播地址介绍

概述广播地址(Broadcast Address)是专门用于同时向网络中(通常指同一子网)所有工作站进行发送的一个地址.在使用TCP/IP 协议的网络中,主机标识段host ID(简称主机 ID) 为全 1 的 IP 地址为广播地址,广播的分组传送给同一个子网的所有计算机.例如,对于10.1.1.0 (255.255.255.0 )网段,其广播地址为10.1.1.255 (255 即为 2 进制的 11111111 ),当发出一个目的地址为10.1.1.255 的数据包时,它将被分发给该网段上的