Linux音频编程声卡介绍
Posted l-102
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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中的标准接口。
以上是关于Linux音频编程声卡介绍的主要内容,如果未能解决你的问题,请参考以下文章