Linux ALSA声卡介绍及使用

一. 介绍 ALSA 标准是一个先进的linux声音体系。它包含内核驱动集合,API库和工具对Linux声音进行支持。ALSA 包含一系列内核驱动对不同的声卡进行支持,还提供了libasound的API库。用这些进行写程序不需要打开设备等操作,所以编程人员在写程序的时候不 会被底层的东西困扰。与此相反OSS/Free 驱动在内核层次调用,需要指定设备名和调用ioctl。为提供向后兼容, ALSA 提供内核模块模仿 OSS/Free 驱动,所以大多数的程序不需要改动。 ALSA 拥有调用插件的能力对新设备提供扩展,包括那些用软件模拟出来的虚拟设备。 ALSA 还提供一组命令行工具包括 mixer, sound file player 和工具控制一些特别的声卡的特别的作用。二.ALSA 体系:ALSA API 被主要分为以下几种接口:l 控制接口:提供灵活的方式管理注册的声卡和对存在的声卡进行查询。l PCM接口:提供管理数字音频的捕捉和回放。l 原始 MIDI 接口: 支持 MIDI (Musical Instrument Digital Interface), 一种标准电子音乐指令集。 这些 API 提供访问声卡上的 MIDI 总线。这些原始借口直接工作在 The MIDI 事件上,程序员只需要管理协议和时间。l 记时接口: 为支持声音的同步事件提供访问声卡上的定时器。l 音序器接口:一个比原始MIDI接口高级的MIDI编程和声音同步高层接口。它可以处理很多的MIDI协议和定时器。l 混音器接口:控制发送信号和控制声音大小的声卡上的设备。三.声卡的缓存和数据的传输: 一块声卡有一个声卡内存用来存储记录的样本。当它被写满时就产生中断。内核驱动就使用DMA将数据传输到内存中。同样地,当在播放时就将内存中的声音样本 使用DMA传到声卡的内存中! 声卡的缓存是环状的,这里只讨论应用程序中的内存结构:ALSA将数据分成连续的片段然后传到按单元片段传输。四:典型的声音程序结 构: open interface for capture or playback set hardware parameters (access mode, data format, channels, rate, etc.) while there is data to be processed: read PCM data (capture) or write PCM data (playback) close interface五.一些例子:1.显示一些PCM的类型和格式:

    #include<iostream>#include<alsa/asoundlib.h>intmain(){std::cout<<"ALSAlibraryversion:"<<SND_LIB_VERSION_STR<<std::endl;std::cout<<"PCMstreamtypes:"<<std::endl;for(intval=0;val<=SND_PCM_STREAM_LAST;++val)std::cout<<snd_pcm_stream_name((snd_pcm_stream_t)val)<<std::endl;std::cout<<std::endl;std::cout<<"PCMaccesstypes:"<<std::endl;for(intval=0;val<=SND_PCM_ACCESS_LAST;++val)std::cout<<snd_pcm_access_name((snd_pcm_access_t)val)<<std::endl;std::cout<<std::endl;std::cout<<"PCMsubformats:"<<std::endl;for(intval=0;val<=SND_PCM_SUBFORMAT_LAST;++val)std::cout<<snd_pcm_subformat_name((snd_pcm_subformat_t)val)<<"("<<snd_pcm_subformat_description((snd_pcm_subformat_t)val)<<")"<<std::endl;std::cout<<std::endl;std::cout<<"PCMstates:"<<std::endl;for(intval=0;val<=SND_PCM_STATE_LAST;++val)std::cout<<snd_pcm_state_name((snd_pcm_state_t)val)<<std::endl;std::cout<<std::endl;std::cout<<"PCMformats:"<<std::endl;for(intval=0;val<=SND_PCM_FORMAT_LAST;++val)std::cout<<snd_pcm_format_name((snd_pcm_format_t)val)<<"("<<snd_pcm_format_description((snd_pcm_format_t)val)<<")"<<std::endl;std::cout<<std::endl;}

2.打开PCM设备和设置参数

    #include<iostream>#include<alsa/asoundlib.h>intmain(){intrc;snd_pcm_t*handle;snd_pcm_hw_params_t*params;unsignedintval,val2;intdir;snd_pcm_uframes_tframes;if((rc=snd_pcm_open(&handle,"default",SND_PCM_STREAM_PLAYBACK,0))<0){std::cerr<<"unabletoopenpcmdevices:"<<snd_strerror(rc)<<std::endl;exit(1);}snd_pcm_hw_params_alloca(&params);snd_pcm_hw_params_any(handle,params);snd_pcm_hw_params_set_access(handle,params,SND_PCM_ACCESS_RW_INTERLEAVED);snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);snd_pcm_hw_params_set_channels(handle,params,2);val=44100;snd_pcm_hw_params_set_rate_near(handle,params,&val,&dir);if((rc=snd_pcm_hw_params(handle,params))<0){std::cerr<<"unabletosethwparameters:"<<snd_strerror(rc)<<std::endl;exit(1);}std::cout<<"PCMhandlename="<<snd_pcm_name(handle)<<std::endl;std::cout<<"PCMstate="<<snd_pcm_state_name(snd_pcm_state(handle))<<std::endl;snd_pcm_hw_params_get_access(params,(snd_pcm_access_t*)&val);std::cout<<"accesstype="<<snd_pcm_access_name((snd_pcm_access_t)val)<<std::endl;snd_pcm_hw_params_get_format(params,(snd_pcm_format_t*)(&val));std::cout<<"format=<<snd_pcm_format_name((snd_pcm_format_t)val)<<("<<snd_pcm_format_description((snd_pcm_format_t)val)<<")"<<std::endl;snd_pcm_hw_params_get_subformat(params,(snd_pcm_subformat_t*)&val);std::cout<<"subformat=<<snd_pcm_subformat_name((snd_pcm_subformat_t)val)<<("<<snd_pcm_subformat_description((snd_pcm_subformat_t)val)<<")"<<std::endl;snd_pcm_hw_params_get_channels(params,&val);std::cout<<"channels="<<val<<std::endl;snd_pcm_hw_params_get_rate(params,&val,&dir);std::cout<<"rate="<<val<<"bps"<<std::endl;snd_pcm_hw_params_get_period_time(params,&val,&dir);std::cout<<"periodtime="<<val<<"us"<<std::endl;snd_pcm_hw_params_get_period_size(params,&frames,&dir);std::cout<<"periodsize="<<static_cast<int>(frames)<<"frames"<<std::endl;snd_pcm_hw_params_get_buffer_time(params,&val,&dir);std::cout<<"buffertime="<<val<<"us"<<std::endl;snd_pcm_hw_params_get_buffer_size(params,(snd_pcm_uframes_t*)&val);std::cout<<"buffersize="<<val<<"frames"<<std::endl;snd_pcm_hw_params_get_periods(params,&val,&dir);std::cout<<"periodsperbuffer="<<val<<"frames"<<std::endl;snd_pcm_hw_params_get_rate_numden(params,&val,&val2);std::cout<<"exactrate="<<val/val2<<"bps"<<std::endl;val=snd_pcm_hw_params_get_sbits(params);std::cout<<"significantbits="<<val<<std::endl;snd_pcm_hw_params_get_tick_time(params,&val,&dir);std::cout<<"ticktime="<<val<<"us"<<std::endl;val=snd_pcm_hw_params_is_batch(params);std::cout<<"isbatch="<<val<<std::endl;val=snd_pcm_hw_params_is_block_transfer(params);std::cout<<"isblocktransfer="<<val<<std::endl;val=snd_pcm_hw_params_is_double(params);std::cout<<"isdouble="<<val<<std::endl;val=snd_pcm_hw_params_is_half_duplex(params);std::cout<<"ishalfduplex="<<val<<std::endl;val=snd_pcm_hw_params_is_joint_duplex(params);std::cout<<"isjointduplex="<<val<<std::endl;val=snd_pcm_hw_params_can_overrange(params);std::cout<<"canoverrange="<<val<<std::endl;val=snd_pcm_hw_params_can_mmap_sample_resolution(params);std::cout<<"canmmap="<<val<<std::endl;val=snd_pcm_hw_params_can_pause(params);std::cout<<"canpause="<<val<<std::endl;val=snd_pcm_hw_params_can_resume(params);std::cout<<"canresume="<<val<<std::endl;val=snd_pcm_hw_params_can_sync_start(params);std::cout<<"cansyncstart="<<val<<std::endl;snd_pcm_close(handle);return0;}

3.一个简单的声音播放程序

    #include<iostream>#include<alsa/asoundlib.h>intmain(){longloops;intrc;intsize;snd_pcm_t*handle;snd_pcm_hw_params_t*params;unsignedintval;intdir;snd_pcm_uframes_tframes;char*buffer;if((rc=snd_pcm_open(&handle,"default",SND_PCM_STREAM_PLAYBACK,0))<0){std::cerr<<"unabletoopenpcmdevice:"<<snd_strerror(rc)<<std::endl;exit(1);}snd_pcm_hw_params_alloca(&params);snd_pcm_hw_params_any(handle,params);snd_pcm_hw_params_set_access(handle,params,SND_PCM_ACCESS_RW_INTERLEAVED);snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);snd_pcm_hw_params_set_channels(handle,params,2);val=44100;snd_pcm_hw_params_set_rate_near(handle,params,&val,&dir); frames=32;snd_pcm_hw_params_set_period_size_near(handle,params,&frames,&dir);if((rc=snd_pcm_hw_params(handle,params))<0){std::cerr<<"unabletosethwparamseters:"<<snd_strerror(rc)<<std::endl;exit(1);}snd_pcm_hw_params_get_period_size(params,&frames,&dir);size=frames*4;buffer=newchar[size];snd_pcm_hw_params_get_period_time(params,&val,&dir);loops=5000000/val;while(loops>0){loops--;if((rc=read(0,buffer,size))==0){std::cerr<<"endoffileoninput"<<std::endl;break;}elseif(rc!=size)std::cerr<<"shortread:read"<<rc<<"bytes"<<std::endl;if((rc=snd_pcm_writei(handle,buffer,frames))==-EPIPE){std::cerr<<"underrunoccurred"<<std::endl;snd_pcm_prepare(handle);}elseif(rc<0)std::cerr<<"errorfromwritei:"<<snd_strerror(rc)<<std::endl;elseif(rc!=(int)frames)std::cerr<<"shortwrite,write"<<rc<<"frames"<<std::endl;}snd_pcm_drain(handle);snd_pcm_close(handle);free(buffer);return0;}

一起吃早餐,午餐,晚餐。或许吃得不好,

Linux ALSA声卡介绍及使用

相关文章:

你感兴趣的文章:

标签云: