如题所述
è¿éäºè§£ä¸ä¸å个åæ°çå«ä¹ä»¥åä¸äºåºæ¬æ¦å¿µã
æ ·æ¬é¿åº¦(sample)ï¼æ ·æ¬æ¯è®°å½é³é¢æ°æ®æåºæ¬çåä½ï¼å¸¸è§çæ8ä½å16ä½ã
ééæ°(channel)ï¼è¯¥åæ°ä¸º1表示å声éï¼2åæ¯ç«ä½å£°ã
æ¡¢(frame)ï¼æ¡¢è®°å½äºä¸ä¸ªå£°é³åå ï¼å ¶é¿åº¦ä¸ºæ ·æ¬é¿åº¦ä¸ééæ°çä¹ç§¯ã
éæ ·ç(rate)ï¼æ¯ç§ééæ ·æ¬¡æ°ï¼è¯¥æ¬¡æ°æ¯é对桢èè¨ã
å¨æ(period)ï¼é³é¢è®¾å¤ä¸æ¬¡å¤çæéè¦çæ¡¢æ°ï¼å¯¹äºé³é¢è®¾å¤çæ°æ®è®¿é®ä»¥åé³é¢æ°æ®çåå¨ï¼é½æ¯ä»¥æ¤ä¸ºåä½ã
交é模å¼(interleaved)ï¼æ¯ä¸ç§é³é¢æ°æ®çè®°å½æ¹å¼ï¼å¨äº¤é模å¼ä¸ï¼æ°æ®ä»¥è¿ç»æ¡¢çå½¢å¼åæ¾ï¼å³é¦å è®°å½å®æ¡¢1ç左声éæ ·æ¬åå³å£°éæ ·æ¬ï¼å设为ç«ä½å£°æ ¼å¼ï¼ï¼åå¼å§æ¡¢2çè®°å½ãèå¨é交é模å¼ä¸ï¼é¦å è®°å½çæ¯ä¸ä¸ªå¨æå æææ¡¢ç左声éæ ·æ¬ï¼åè®°å½å³å£°éæ ·æ¬ï¼æ°æ®æ¯ä»¥è¿ç»ééçæ¹å¼åå¨ãä¸è¿å¤æ°æ åµä¸ï¼æ们åªéè¦ä½¿ç¨äº¤é模å¼å°±å¯ä»¥äºã
è±æåæï¼http://www.linuxjournal.com/article/6735
period(å¨æ):硬件ä¸ä¸æé´çé´éæ¶é´ãå®è¡¨ç¤ºè¾å ¥å»¶æ¶ã
声å¡æ¥å£ä¸æä¸ä¸ªæéæ¥æ示声å¡ç¡¬ä»¶ç¼ååºä¸å½åç读åä½ç½®ãåªè¦æ¥å£å¨è¿è¡ï¼è¿ä¸ªæéå°å¾ªç¯å°æåç¼ååºä¸çæ个ä½ç½®ã
frame size = sizeof(one sample) * nChannels
alsaä¸é ç½®çç¼å(buffer)åå¨æ(size)大å°å¨runtimeä¸æ¯ä»¥å¸§(frames)å½¢å¼åå¨çã
period_bytes = frames_to_bytes(runtime, runtime->period_size);
bytes_to_frames()
The period and buffer sizes are not dependent on the sample format because they are measured in frames; you do not need to change them.
ALSA声é³ç¼ç¨ä»ç»
ALSA表示é«çº§Linux声é³ä½ç³»ç»æ(Advanced Linux Sound Architecture)ãå®ç±ä¸ç³»åå æ ¸é©±å¨ï¼åºç¨ç¨åºç¼è¯æ¥å£(API)以åæ¯æLinuxä¸å£°é³çå®ç¨ç¨åºç»æãè¿ç¯æç« éï¼æå°ç®åä»ç»ALSA项ç®çåºæ¬æ¡æ¶ä»¥åå®ç软件ç»æã主è¦éä¸ä»ç»PCMæ¥å£ç¼ç¨ï¼å æ¬æ¨å¯ä»¥èªå¨å®è·µçç¨åºç¤ºä¾ã
æ¨ä½¿ç¨ALSAçåå å¯è½å°±æ¯å 为å®å¾æ°ï¼ä½å®å¹¶ä¸æ¯å¯ä¸å¯ç¨ç声é³APIãå¦ææ¨æ³å®æä½çº§ç声é³æä½ï¼ä»¥ä¾¿è½å¤æ大åå°æ§å¶å£°é³å¹¶æ大åå°æé«æ§è½ï¼æè å¦ææ¨ä½¿ç¨å ¶å®å£°é³API没æçç¹æ§ï¼é£ä¹ALSAæ¯å¾å¥½çéæ©ãå¦ææ¨å·²ç»åäºä¸ä¸ªé³é¢ç¨åºï¼ä½ å¯è½æ³è¦ä¸ºALSA声å¡é©±å¨æ·»å æ¬å°æ¯æãå¦ææ¨å¯¹é³é¢ä¸æå ´è¶£ï¼åªæ¯æ³ææ¾é³é¢æ件ï¼é£ä¹é«çº§çAPIå°æ¯æ´å¥½çéæ©ï¼æ¯å¦SDL,OpenAL以åé£äºæ¡é¢ç¯å¢æä¾çå·¥å ·éãå¦å¤ï¼æ¨åªè½å¨æALSAæ¯æçLinuxç¯å¢ä¸ä½¿ç¨ALSAã
ALSAåå²
ALSA项ç®åèµ·çèµ·å æ¯Linuxä¸ç声å¡é©±å¨(OSS/Free drivers)没æå¾å°ç§¯æçç»´æ¤ã并ä¸è½åäºæ°ç声å¡ææ¯ãJaroslav Kyselaæ©å åäºä¸ä¸ªå£°å¡é©±å¨ï¼å¹¶ç±æ¤å¼å§äºALSA项ç®ï¼é便ï¼æ´å¤çå¼åè å å ¥å°å¼åéä¼ä¸ï¼æ´å¤ç声å¡å¾å°æ¯æï¼APIçç»æä¹å¾å°äºéç»ã
Linuxå æ ¸2.5å¨å¼åè¿ç¨ä¸ï¼ALSA被å并å°äºå®æ¹çæºç æ ä¸ãå¨åå¸å æ ¸2.6åï¼ALSAå·²ç»å 建å¨ç¨³å®çå æ ¸çæ¬ä¸å¹¶å°å¹¿æ³å°ä½¿ç¨ã
æ°åé³é¢åºç¡
声é³ç±ååçæ°åç»æãå®è¢«éº¦å é£è¿æ ·ç转æ¢å¨è½¬æ¢æçµåå½¢å¼ã模/æ°(ADC)转æ¢å¨å°æ¨¡æçµå转æ¢æ离æ£çæ ·æ¬å¼ã声é³ä»¥åºå®çæ¶é´é´é被éæ ·ï¼éæ ·çéç称为éæ ·çãææ ·æ¬è¾åºå°æ°/模(DAC)转æ¢å¨ï¼æ¯å¦æ©é³å¨ï¼æå转æ¢æåæ¥ç模æä¿¡å·ã
æ ·æ¬å¤§å°ä»¥ä½æ¥è¡¨ç¤ºãæ ·æ¬å¤§å°æ¯å½±å声é³è¢«è½¬æ¢ææ°åä¿¡å·ç精确ç¨åº¦çå ç´ ä¹ä¸ãå¦ä¸ä¸ªä¸»è¦çå ç´ æ¯éæ ·çãå¥å¥æ¯ç¹(Nyquist)ç论ä¸ï¼åªè¦ç¦»æ£ç³»ç»çå¥å¥æ¯ç¹é¢çé«äºéæ ·ä¿¡å·çæé«é¢çæ带宽ï¼å°±å¯ä»¥é¿å æ··å ç°è±¡ã
ALSAåºç¡
ALSAç±è®¸å¤å£°å¡ç声å¡é©±å¨ç¨åºç»æï¼åæ¶å®ä¹æä¾ä¸ä¸ªç§°ä¸ºlibasoundçAPIåºãåºç¨ç¨åºå¼åè åºè¯¥ä½¿ç¨libasoundèä¸æ¯å æ ¸ä¸çALSAæ¥å£ãå 为libasoundæä¾æé«çº§å¹¶ä¸ç¼ç¨æ¹ä¾¿çç¼ç¨æ¥å£ã并ä¸æä¾ä¸ä¸ªè®¾å¤é»è¾å½ååè½ï¼è¿æ ·å¼åè çè³ä¸éè¦ç¥é类似设å¤æ件è¿æ ·çä½å±æ¥å£ãç¸åï¼OSS/Free驱å¨æ¯å¨å æ ¸ç³»ç»è°ç¨çº§ä¸ç¼ç¨ï¼å®è¦æ±å¼åè æä¾è®¾å¤æ件å并ä¸å©ç¨ioctrlæ¥å®ç°ç¸åºçåè½ã为äºååå ¼å®¹ï¼ALSAæä¾å æ ¸æ¨¡åæ¥æ¨¡æOSSï¼è¿æ ·ä¹åç许å¤å¨OSSåºç¡ä¸å¼åçåºç¨ç¨åºä¸éè¦ä»»ä½æ¹å¨å°±å¯ä»¥å¨ALSAä¸è¿è¡ãå¦å¤ï¼libaossåºä¹å¯ä»¥æ¨¡æOSSï¼èå®ä¸éè¦å æ ¸æ¨¡åã
ALSAå å«æ件åè½ï¼ä½¿ç¨æ件å¯ä»¥æ©å±æ°ç声å¡é©±å¨ï¼å æ¬å®å ¨ç¨è½¯ä»¶å®ç°çèæ声å¡ãALSAæä¾ä¸ç³»ååºäºå½ä»¤è¡çå·¥å ·éï¼æ¯å¦æ··é³å¨(mixer)ï¼é³é¢æ件ææ¾å¨(aplay)ï¼ä»¥åæ§å¶ç¹å®å£°å¡ç¹å®å±æ§çå·¥å ·ã
ALSAä½ç³»ç»æ
ALSA APIå¯ä»¥å解æ以ä¸å 个主è¦çæ¥å£ï¼
1 æ§å¶æ¥å£ï¼æä¾ç®¡ç声å¡æ³¨åå请æ±å¯ç¨è®¾å¤çéç¨åè½
2 PCMæ¥å£ï¼ç®¡çæ°åé³é¢åæ¾(playback)åå½é³(capture)çæ¥å£ãæ¬æåç»æ»ç»éç¹æ¾å¨è¿ä¸ªæ¥å£ä¸ï¼å 为å®æ¯å¼åæ°åé³é¢ç¨åºæ常ç¨å°çæ¥å£ã
3 Raw MIDIæ¥å£:æ¯æMIDI(Musical Instrument Digital Interface),æ åççµåä¹å¨ãè¿äºAPIæä¾å¯¹å£°å¡ä¸MIDIæ»çº¿ç访é®ãè¿ä¸ªåå§æ¥å£åºäºMIDIäºä»¶å·¥ä½ï¼ç±ç¨åºåè´è´£ç®¡çå议以åæ¶é´å¤çã
4 å®æ¶å¨(Timer)æ¥å£ï¼ä¸ºåæ¥é³é¢äºä»¶æä¾å¯¹å£°å¡ä¸æ¶é´å¤ç硬件ç访é®ã
5 æ¶åºå¨(Sequencer)æ¥å£
6 æ··é³å¨(Mixer)æ¥å£
设å¤å½å
APIåºä½¿ç¨é»è¾è®¾å¤åèä¸æ¯è®¾å¤æ件ã设å¤ååå¯ä»¥æ¯çå®ç硬件ååä¹å¯ä»¥æ¯æ件ååã硬件åå使ç¨hw:i,jè¿æ ·çæ ¼å¼ãå ¶ä¸iæ¯å¡å·ï¼jæ¯è¿å声å¡ä¸ç设å¤å·ã第ä¸ä¸ªå£°é³è®¾å¤æ¯hw:0,0.è¿ä¸ªå«åé»è®¤å¼ç¨ç¬¬ä¸å声é³è®¾å¤å¹¶ä¸å¨æ¬æ示ä¾ä¸ä¸çä¼è¢«ç¨å°ãæ件使ç¨å¦å¤çå¯ä¸ååãæ¯å¦plughw:,表示ä¸ä¸ªæ件ï¼è¿ä¸ªæ件ä¸æä¾å¯¹ç¡¬ä»¶è®¾å¤ç访é®ï¼èæ¯æä¾åéæ ·ç转æ¢è¿æ ·ç软件ç¹æ§ï¼ç¡¬ä»¶æ¬èº«å¹¶ä¸æ¯æè¿æ ·çç¹æ§ã
声é³ç¼ååæ°æ®ä¼ è¾
æ¯ä¸ªå£°å¡é½æä¸ä¸ªç¡¬ä»¶ç¼ååºæ¥ä¿åè®°å½ä¸æ¥çæ ·æ¬ãå½ç¼ååºè¶³å¤æ»¡æ¶ï¼å£°å¡å°äº§çä¸ä¸ªä¸æãå æ ¸å£°å¡é©±å¨ç¶å使ç¨ç´æ¥å å(DMA)访é®ééå°æ ·æ¬ä¼ éå°å åä¸çåºç¨ç¨åºç¼ååºã类似å°ï¼å¯¹äºåæ¾ï¼ä»»ä½åºç¨ç¨åºä½¿ç¨DMAå°èªå·±çç¼ååºæ°æ®ä¼ éå°å£°å¡ç硬件ç¼ååºä¸ã
è¿æ ·ç¡¬ä»¶ç¼ååºæ¯ç¯ç¼åãä¹å°±æ¯è¯´å½æ°æ®å°è¾¾ç¼ååºæ«å°¾æ¶å°éæ°åå°ç¼ååºçèµ·å§ä½ç½®ãALSAç»´æ¤ä¸ä¸ªæéæ¥æå硬件ç¼å以ååºç¨ç¨åºç¼ååºä¸æ°æ®æä½çå½åä½ç½®ãä»å æ ¸å¤é¨çï¼æ们åªå¯¹åºç¨ç¨åºçç¼ååºæå ´è¶£ï¼æ以æ¬æåªè®¨è®ºåºç¨ç¨åºç¼ååºã
åºç¨ç¨åºç¼ååºç大å°å¯ä»¥éè¿ALSAåºå½æ°è°ç¨æ¥æ§å¶ãç¼ååºå¯ä»¥å¾å¤§ï¼ä¸æ¬¡ä¼ è¾æä½å¯è½ä¼å¯¼è´ä¸å¯æ¥åç延è¿ï¼æ们æå®ç§°ä¸ºå»¶æ¶(latency)ã为äºè§£å³è¿ä¸ªé®é¢ï¼ALSAå°ç¼ååºæåæä¸ç³»åå¨æ(period)(OSS/Freeä¸å«çæfragments).ALSA以period为åå æ¥ä¼ éæ°æ®ã
ä¸ä¸ªå¨æ(period)åå¨ä¸äºå¸§(frames)ãæ¯ä¸å¸§å å«æ¶é´ä¸ä¸ä¸ªç¹ææåçæ ·æ¬ã对äºç«ä½å£°è®¾å¤ï¼ä¸ä¸ªå¸§ä¼å å«ä¸¤ä¸ªä¿¡éä¸çæ ·æ¬ãå¾1å±ç¤ºäºå解è¿ç¨ï¼ä¸ä¸ªç¼ååºå解æå¨æï¼ç¶åæ¯å¸§ï¼ç¶åæ¯æ ·æ¬ãå¾ä¸å å«ä¸äºåå®çæ°å¼ãå¾ä¸å·¦å³ä¿¡éä¿¡æ¯è¢«äº¤æ¿å°åå¨å¨ä¸ä¸ªå¸§å ãè¿ç§°ä¸ºäº¤é(interleaved)模å¼ãå¨é交é模å¼ä¸ï¼ä¸ä¸ªä¿¡éçæææ ·æ¬æ°æ®åå¨å¨å¦å¤ä¸ä¸ªä¿¡éçæ°æ®ä¹åã
Over and Under Run
å½ä¸ä¸ªå£°å¡æ´»å¨æ¶ï¼æ°æ®æ»æ¯è¿ç»å°å¨ç¡¬ä»¶ç¼ååºååºç¨ç¨åºç¼ååºé´ä¼ è¾ãä½æ¯ä¹æä¾å¤ãå¨å½é³ä¾åä¸ï¼å¦æåºç¨ç¨åºè¯»åæ°æ®ä¸å¤å¿«ï¼å¾ªç¯ç¼ååºå°ä¼è¢«æ°çæ°æ®è¦çãè¿ç§æ°æ®ç丢失被称为overrun.å¨åæ¾ä¾åä¸ï¼å¦æåºç¨ç¨åºåå ¥æ°æ®å°ç¼ååºä¸çé度ä¸å¤å¿«ï¼ç¼ååºå°ä¼"饿æ»"ãè¿æ ·çé误被称为"underrun"ãå¨ALSAææ¡£ä¸ï¼ææ¶å°è¿ä¸¤ç§æ å½¢ç»ç§°ä¸º"XRUN"ãéå½å°è®¾è®¡åºç¨ç¨åºå¯ä»¥æå°åXRUN并ä¸å¯ä»¥ä»ä¸æ¢å¤è¿æ¥ã
ä¸ä¸ªå ¸åç声é³ç¨åº
使ç¨PCMçç¨åºé常类似ä¸é¢ç伪代ç ï¼
æå¼åæ¾æå½é³æ¥å£
设置硬件åæ°(访é®æ¨¡å¼ï¼æ°æ®æ ¼å¼ï¼ä¿¡éæ°ï¼éæ ·çï¼çç)
while ææ°æ®è¦è¢«å¤çï¼
读PCMæ°æ®(å½é³)
æ åPCMæ°æ®(åæ¾)
å ³éæ¥å£
æ们å°å¨ä¸æä¸çå°ä¸äºå¯ä»¥å·¥ä½ç代ç ãæ建议æ¨å¨ä½ çLinuxç³»ç»ä¸æµè¯è¿è¡è¿äºä»£ç ãæ¥çè¾åºå¹¶å°è¯ä¿®æ¹æ¨èç代ç ãåæ¬æç¸å ³çææå®ä¾æ¸ åå¯ä»¥ä»FTPä¸è·åï¼ftp.ssc.com/pub/lj/listings/issue126/6735.tgzã
Listing 1. Display Some PCM Types and Formats
#include <alsa/asoundlib.h>
int main() {
int val;
printf("ALSA library version: %s/n",
SND_LIB_VERSION_STR);
printf("/nPCM stream types:/n");
for (val = 0; val <= SND_PCM_STREAM_LAST; val++)
printf(" %s/n",
snd_pcm_stream_name((snd_pcm_stream_t)val));
printf("/nPCM access types:/n");
for (val = 0; val <= SND_PCM_ACCESS_LAST; val++)
printf(" %s/n",
snd_pcm_access_name((snd_pcm_access_t)val));
printf("/nPCM formats:/n");
for (val = 0; val <= SND_PCM_FORMAT_LAST; val++)
if (snd_pcm_format_name((snd_pcm_format_t)val)
!= NULL)
printf(" %s (%s)/n",
snd_pcm_format_name((snd_pcm_format_t)val),
snd_pcm_format_description(
(snd_pcm_format_t)val));
printf("/nPCM subformats:/n");
for (val = 0; val <= SND_PCM_SUBFORMAT_LAST;
val++)
printf(" %s (%s)/n",
snd_pcm_subformat_name((
snd_pcm_subformat_t)val),
snd_pcm_subformat_description((
snd_pcm_subformat_t)val));
printf("/nPCM states:/n");
for (val = 0; val <= SND_PCM_STATE_LAST; val++)
printf(" %s/n",
snd_pcm_state_name((snd_pcm_state_t)val));
return 0;
}
æ¸ åä¸æ¾ç¤ºäºä¸äºALSA使ç¨çPCMæ°æ®ç±»åååæ°ãé¦å éè¦åçæ¯å æ¬å¤´æ件ãè¿äºå¤´æ件å å«äºææåºå½æ°ç声æãå ¶ä¸ä¹ä¸å°±æ¯æ¾ç¤ºALSAåºççæ¬ã
è¿ä¸ªç¨åºå©ä¸çé¨åçè¿ä»£ä¸äºPCMæ°æ®ç±»åï¼ä»¥æµç±»åå¼å§ãALSA为æ¯æ¬¡è¿ä»£çæåå¼æä¾ç¬¦å·å¸¸éåï¼å¹¶ä¸æä¾åè½å½æ°ä»¥æ¾ç¤ºæ个ç¹å®å¼çæè¿°å符串ãä½ å°ä¼çå°ï¼ALSAæ¯æ许å¤æ ¼å¼ï¼å¨æç1.0.15çæ¬éï¼æ¯æå¤è¾¾36ç§æ ¼å¼ã
è¿ä¸ªç¨åºå¿ é¡»é¾æ¥å°alsalibåºï¼éè¿å¨ç¼è¯æ¶éè¦å ä¸-lasoundé项ãæäºalsaåºå½æ°ä½¿ç¨dlopenå½æ°ä»¥åæµ®ç¹æä½ï¼æ以æ¨å¯è½è¿éè¦å ä¸-ldl,-lmé项ã
ä¸é¢æ¯è¯¥ç¨åºçMakefile:
CC=gcc
TARGET=test
SRC=$(wildcard *.c)
OBJECT= ${SRC:.c=.o}
INCLUDES=-I/usr/include/alsa
LDFLAGS=-lasound
all:$(TARGET)
$(OBJECT):$(SRC)
$(CC) -c $(INCLUDES) $<
$(TARGET):$(OBJECT)
$(CC) -o $@ $< $(LDFLAGS)
.PHONY:clean
clean:
@rm -rf $(OBJECT) $(TARGET) *~
Listing 2. Opening PCM Device and Setting Parameters
/*
This example opens the default PCM device, sets
some parameters, and then displays the value
of most of the hardware parameters. It does not
perform any sound playback or recording.
*/
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
/* All of the ALSA library API is defined
* in this header */
#include <alsa/asoundlib.h>
int main() {
int rc;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val, val2;
int dir;
snd_pcm_uframes_t frames;
/* Open PCM device for playback. */
rc = snd_pcm_open(&handle, "default",
SND_PCM_STREAM_PLAYBACK, 0);
if (rc < 0) {
fprintf(stderr,
"unable to open pcm device: %s/n",
snd_strerror(rc));
exit(1);
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(¶ms);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params,
SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params,
SND_PCM_FORMAT_S16_LE);
/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(handle, params, 2);
/* 44100 bits/second sampling rate (CD quality) */
val = 44100;
snd_pcm_hw_params_set_rate_near(handle,
params, &val, &dir);
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr,
"unable to set hw parameters: %s/n",
snd_strerror(rc));
exit(1);
}
/* Display information about the PCM interface */
printf("PCM handle name = '%s'/n",
snd_pcm_name(handle));
printf("PCM state = %s/n",
snd_pcm_state_name(snd_pcm_state(handle)));
snd_pcm_hw_params_get_access(params,
(snd_pcm_access_t *) &val);
printf("access type = %s/n",
snd_pcm_access_name((snd_pcm_access_t)val));
snd_pcm_hw_params_get_format(params, &val);
printf("format = '%s' (%s)/n",
snd_pcm_format_name((snd_pcm_format_t)val),
snd_pcm_format_description(
(snd_pcm_format_t)val));
snd_pcm_hw_params_get_subformat(params,
(snd_pcm_subformat_t *)&val);
printf("subformat = '%s' (%s)/n",
snd_pcm_subformat_name((snd_pcm_subformat_t)val),
snd_pcm_subformat_description(
(snd_pcm_subformat_t)val));
snd_pcm_hw_params_get_channels(params, &val);
printf("channels = %d/n", val);
snd_pcm_hw_params_get_rate(params, &val, &dir);
printf("rate = %d bps/n", val);
snd_pcm_hw_params_get_period_time(params,
&val, &dir);
printf("period time = %d us/n", val);
snd_pcm_hw_params_get_period_size(params,
&frames, &dir);
printf("period size = %d frames/n", (int)frames);
snd_pcm_hw_params_get_buffer_time(params,
&val, &dir);
printf("buffer time = %d us/n", val);
snd_pcm_hw_params_get_buffer_size(params,
(snd_pcm_uframes_t *) &val);
printf("buffer size = %d frames/n", val);
snd_pcm_hw_params_get_periods(params, &val, &dir);
printf("periods per buffer = %d frames/n", val);
snd_pcm_hw_params_get_rate_numden(params,
&val, &val2);
printf("exact rate = %d/%d bps/n", val, val2);
val = snd_pcm_hw_params_get_sbits(params);
printf("significant bits = %d/n", val);
snd_pcm_hw_params_get_tick_time(params,
&val, &dir);
printf("tick time = %d us/n", val);
val = snd_pcm_hw_params_is_batch(params);
printf("is batch = %d/n", val);
val = snd_pcm_hw_params_is_block_transfer(params);
printf("is block transfer = %d/n", val);
val = snd_pcm_hw_params_is_double(params);
printf("is double = %d/n", val);
val = snd_pcm_hw_params_is_half_duplex(params);
printf("is half duplex = %d/n", val);
val = snd_pcm_hw_params_is_joint_duplex(params);
printf("is joint duplex = %d/n", val);
val = snd_pcm_hw_params_can_overrange(params);
printf("can overrange = %d/n", val);
val = snd_pcm_hw_params_can_mmap_sample_resolution(params);
printf("can mmap = %d/n", val);
val = snd_pcm_hw_params_can_pause(params);
printf("can pause = %d/n", val);
val = snd_pcm_hw_params_can_resume(params);
printf("can resume = %d/n", val);
val = snd_pcm_hw_params_can_sync_start(params);
printf("can sync start = %d/n", val);
snd_pcm_close(handle);
return 0;
}
æ ·æ¬é¿åº¦(sample)ï¼æ ·æ¬æ¯è®°å½é³é¢æ°æ®æåºæ¬çåä½ï¼å¸¸è§çæ8ä½å16ä½ã
ééæ°(channel)ï¼è¯¥åæ°ä¸º1表示å声éï¼2åæ¯ç«ä½å£°ã
æ¡¢(frame)ï¼æ¡¢è®°å½äºä¸ä¸ªå£°é³åå ï¼å ¶é¿åº¦ä¸ºæ ·æ¬é¿åº¦ä¸ééæ°çä¹ç§¯ã
éæ ·ç(rate)ï¼æ¯ç§ééæ ·æ¬¡æ°ï¼è¯¥æ¬¡æ°æ¯é对桢èè¨ã
å¨æ(period)ï¼é³é¢è®¾å¤ä¸æ¬¡å¤çæéè¦çæ¡¢æ°ï¼å¯¹äºé³é¢è®¾å¤çæ°æ®è®¿é®ä»¥åé³é¢æ°æ®çåå¨ï¼é½æ¯ä»¥æ¤ä¸ºåä½ã
交é模å¼(interleaved)ï¼æ¯ä¸ç§é³é¢æ°æ®çè®°å½æ¹å¼ï¼å¨äº¤é模å¼ä¸ï¼æ°æ®ä»¥è¿ç»æ¡¢çå½¢å¼åæ¾ï¼å³é¦å è®°å½å®æ¡¢1ç左声éæ ·æ¬åå³å£°éæ ·æ¬ï¼å设为ç«ä½å£°æ ¼å¼ï¼ï¼åå¼å§æ¡¢2çè®°å½ãèå¨é交é模å¼ä¸ï¼é¦å è®°å½çæ¯ä¸ä¸ªå¨æå æææ¡¢ç左声éæ ·æ¬ï¼åè®°å½å³å£°éæ ·æ¬ï¼æ°æ®æ¯ä»¥è¿ç»ééçæ¹å¼åå¨ãä¸è¿å¤æ°æ åµä¸ï¼æ们åªéè¦ä½¿ç¨äº¤é模å¼å°±å¯ä»¥äºã
è±æåæï¼http://www.linuxjournal.com/article/6735
period(å¨æ):硬件ä¸ä¸æé´çé´éæ¶é´ãå®è¡¨ç¤ºè¾å ¥å»¶æ¶ã
声å¡æ¥å£ä¸æä¸ä¸ªæéæ¥æ示声å¡ç¡¬ä»¶ç¼ååºä¸å½åç读åä½ç½®ãåªè¦æ¥å£å¨è¿è¡ï¼è¿ä¸ªæéå°å¾ªç¯å°æåç¼ååºä¸çæ个ä½ç½®ã
frame size = sizeof(one sample) * nChannels
alsaä¸é ç½®çç¼å(buffer)åå¨æ(size)大å°å¨runtimeä¸æ¯ä»¥å¸§(frames)å½¢å¼åå¨çã
period_bytes = frames_to_bytes(runtime, runtime->period_size);
bytes_to_frames()
The period and buffer sizes are not dependent on the sample format because they are measured in frames; you do not need to change them.
ALSA声é³ç¼ç¨ä»ç»
ALSA表示é«çº§Linux声é³ä½ç³»ç»æ(Advanced Linux Sound Architecture)ãå®ç±ä¸ç³»åå æ ¸é©±å¨ï¼åºç¨ç¨åºç¼è¯æ¥å£(API)以åæ¯æLinuxä¸å£°é³çå®ç¨ç¨åºç»æãè¿ç¯æç« éï¼æå°ç®åä»ç»ALSA项ç®çåºæ¬æ¡æ¶ä»¥åå®ç软件ç»æã主è¦éä¸ä»ç»PCMæ¥å£ç¼ç¨ï¼å æ¬æ¨å¯ä»¥èªå¨å®è·µçç¨åºç¤ºä¾ã
æ¨ä½¿ç¨ALSAçåå å¯è½å°±æ¯å 为å®å¾æ°ï¼ä½å®å¹¶ä¸æ¯å¯ä¸å¯ç¨ç声é³APIãå¦ææ¨æ³å®æä½çº§ç声é³æä½ï¼ä»¥ä¾¿è½å¤æ大åå°æ§å¶å£°é³å¹¶æ大åå°æé«æ§è½ï¼æè å¦ææ¨ä½¿ç¨å ¶å®å£°é³API没æçç¹æ§ï¼é£ä¹ALSAæ¯å¾å¥½çéæ©ãå¦ææ¨å·²ç»åäºä¸ä¸ªé³é¢ç¨åºï¼ä½ å¯è½æ³è¦ä¸ºALSA声å¡é©±å¨æ·»å æ¬å°æ¯æãå¦ææ¨å¯¹é³é¢ä¸æå ´è¶£ï¼åªæ¯æ³ææ¾é³é¢æ件ï¼é£ä¹é«çº§çAPIå°æ¯æ´å¥½çéæ©ï¼æ¯å¦SDL,OpenAL以åé£äºæ¡é¢ç¯å¢æä¾çå·¥å ·éãå¦å¤ï¼æ¨åªè½å¨æALSAæ¯æçLinuxç¯å¢ä¸ä½¿ç¨ALSAã
ALSAåå²
ALSA项ç®åèµ·çèµ·å æ¯Linuxä¸ç声å¡é©±å¨(OSS/Free drivers)没æå¾å°ç§¯æçç»´æ¤ã并ä¸è½åäºæ°ç声å¡ææ¯ãJaroslav Kyselaæ©å åäºä¸ä¸ªå£°å¡é©±å¨ï¼å¹¶ç±æ¤å¼å§äºALSA项ç®ï¼é便ï¼æ´å¤çå¼åè å å ¥å°å¼åéä¼ä¸ï¼æ´å¤ç声å¡å¾å°æ¯æï¼APIçç»æä¹å¾å°äºéç»ã
Linuxå æ ¸2.5å¨å¼åè¿ç¨ä¸ï¼ALSA被å并å°äºå®æ¹çæºç æ ä¸ãå¨åå¸å æ ¸2.6åï¼ALSAå·²ç»å 建å¨ç¨³å®çå æ ¸çæ¬ä¸å¹¶å°å¹¿æ³å°ä½¿ç¨ã
æ°åé³é¢åºç¡
声é³ç±ååçæ°åç»æãå®è¢«éº¦å é£è¿æ ·ç转æ¢å¨è½¬æ¢æçµåå½¢å¼ã模/æ°(ADC)转æ¢å¨å°æ¨¡æçµå转æ¢æ离æ£çæ ·æ¬å¼ã声é³ä»¥åºå®çæ¶é´é´é被éæ ·ï¼éæ ·çéç称为éæ ·çãææ ·æ¬è¾åºå°æ°/模(DAC)转æ¢å¨ï¼æ¯å¦æ©é³å¨ï¼æå转æ¢æåæ¥ç模æä¿¡å·ã
æ ·æ¬å¤§å°ä»¥ä½æ¥è¡¨ç¤ºãæ ·æ¬å¤§å°æ¯å½±å声é³è¢«è½¬æ¢ææ°åä¿¡å·ç精确ç¨åº¦çå ç´ ä¹ä¸ãå¦ä¸ä¸ªä¸»è¦çå ç´ æ¯éæ ·çãå¥å¥æ¯ç¹(Nyquist)ç论ä¸ï¼åªè¦ç¦»æ£ç³»ç»çå¥å¥æ¯ç¹é¢çé«äºéæ ·ä¿¡å·çæé«é¢çæ带宽ï¼å°±å¯ä»¥é¿å æ··å ç°è±¡ã
ALSAåºç¡
ALSAç±è®¸å¤å£°å¡ç声å¡é©±å¨ç¨åºç»æï¼åæ¶å®ä¹æä¾ä¸ä¸ªç§°ä¸ºlibasoundçAPIåºãåºç¨ç¨åºå¼åè åºè¯¥ä½¿ç¨libasoundèä¸æ¯å æ ¸ä¸çALSAæ¥å£ãå 为libasoundæä¾æé«çº§å¹¶ä¸ç¼ç¨æ¹ä¾¿çç¼ç¨æ¥å£ã并ä¸æä¾ä¸ä¸ªè®¾å¤é»è¾å½ååè½ï¼è¿æ ·å¼åè çè³ä¸éè¦ç¥é类似设å¤æ件è¿æ ·çä½å±æ¥å£ãç¸åï¼OSS/Free驱å¨æ¯å¨å æ ¸ç³»ç»è°ç¨çº§ä¸ç¼ç¨ï¼å®è¦æ±å¼åè æä¾è®¾å¤æ件å并ä¸å©ç¨ioctrlæ¥å®ç°ç¸åºçåè½ã为äºååå ¼å®¹ï¼ALSAæä¾å æ ¸æ¨¡åæ¥æ¨¡æOSSï¼è¿æ ·ä¹åç许å¤å¨OSSåºç¡ä¸å¼åçåºç¨ç¨åºä¸éè¦ä»»ä½æ¹å¨å°±å¯ä»¥å¨ALSAä¸è¿è¡ãå¦å¤ï¼libaossåºä¹å¯ä»¥æ¨¡æOSSï¼èå®ä¸éè¦å æ ¸æ¨¡åã
ALSAå å«æ件åè½ï¼ä½¿ç¨æ件å¯ä»¥æ©å±æ°ç声å¡é©±å¨ï¼å æ¬å®å ¨ç¨è½¯ä»¶å®ç°çèæ声å¡ãALSAæä¾ä¸ç³»ååºäºå½ä»¤è¡çå·¥å ·éï¼æ¯å¦æ··é³å¨(mixer)ï¼é³é¢æ件ææ¾å¨(aplay)ï¼ä»¥åæ§å¶ç¹å®å£°å¡ç¹å®å±æ§çå·¥å ·ã
ALSAä½ç³»ç»æ
ALSA APIå¯ä»¥å解æ以ä¸å 个主è¦çæ¥å£ï¼
1 æ§å¶æ¥å£ï¼æä¾ç®¡ç声å¡æ³¨åå请æ±å¯ç¨è®¾å¤çéç¨åè½
2 PCMæ¥å£ï¼ç®¡çæ°åé³é¢åæ¾(playback)åå½é³(capture)çæ¥å£ãæ¬æåç»æ»ç»éç¹æ¾å¨è¿ä¸ªæ¥å£ä¸ï¼å 为å®æ¯å¼åæ°åé³é¢ç¨åºæ常ç¨å°çæ¥å£ã
3 Raw MIDIæ¥å£:æ¯æMIDI(Musical Instrument Digital Interface),æ åççµåä¹å¨ãè¿äºAPIæä¾å¯¹å£°å¡ä¸MIDIæ»çº¿ç访é®ãè¿ä¸ªåå§æ¥å£åºäºMIDIäºä»¶å·¥ä½ï¼ç±ç¨åºåè´è´£ç®¡çå议以åæ¶é´å¤çã
4 å®æ¶å¨(Timer)æ¥å£ï¼ä¸ºåæ¥é³é¢äºä»¶æä¾å¯¹å£°å¡ä¸æ¶é´å¤ç硬件ç访é®ã
5 æ¶åºå¨(Sequencer)æ¥å£
6 æ··é³å¨(Mixer)æ¥å£
设å¤å½å
APIåºä½¿ç¨é»è¾è®¾å¤åèä¸æ¯è®¾å¤æ件ã设å¤ååå¯ä»¥æ¯çå®ç硬件ååä¹å¯ä»¥æ¯æ件ååã硬件åå使ç¨hw:i,jè¿æ ·çæ ¼å¼ãå ¶ä¸iæ¯å¡å·ï¼jæ¯è¿å声å¡ä¸ç设å¤å·ã第ä¸ä¸ªå£°é³è®¾å¤æ¯hw:0,0.è¿ä¸ªå«åé»è®¤å¼ç¨ç¬¬ä¸å声é³è®¾å¤å¹¶ä¸å¨æ¬æ示ä¾ä¸ä¸çä¼è¢«ç¨å°ãæ件使ç¨å¦å¤çå¯ä¸ååãæ¯å¦plughw:,表示ä¸ä¸ªæ件ï¼è¿ä¸ªæ件ä¸æä¾å¯¹ç¡¬ä»¶è®¾å¤ç访é®ï¼èæ¯æä¾åéæ ·ç转æ¢è¿æ ·ç软件ç¹æ§ï¼ç¡¬ä»¶æ¬èº«å¹¶ä¸æ¯æè¿æ ·çç¹æ§ã
声é³ç¼ååæ°æ®ä¼ è¾
æ¯ä¸ªå£°å¡é½æä¸ä¸ªç¡¬ä»¶ç¼ååºæ¥ä¿åè®°å½ä¸æ¥çæ ·æ¬ãå½ç¼ååºè¶³å¤æ»¡æ¶ï¼å£°å¡å°äº§çä¸ä¸ªä¸æãå æ ¸å£°å¡é©±å¨ç¶å使ç¨ç´æ¥å å(DMA)访é®ééå°æ ·æ¬ä¼ éå°å åä¸çåºç¨ç¨åºç¼ååºã类似å°ï¼å¯¹äºåæ¾ï¼ä»»ä½åºç¨ç¨åºä½¿ç¨DMAå°èªå·±çç¼ååºæ°æ®ä¼ éå°å£°å¡ç硬件ç¼ååºä¸ã
è¿æ ·ç¡¬ä»¶ç¼ååºæ¯ç¯ç¼åãä¹å°±æ¯è¯´å½æ°æ®å°è¾¾ç¼ååºæ«å°¾æ¶å°éæ°åå°ç¼ååºçèµ·å§ä½ç½®ãALSAç»´æ¤ä¸ä¸ªæéæ¥æå硬件ç¼å以ååºç¨ç¨åºç¼ååºä¸æ°æ®æä½çå½åä½ç½®ãä»å æ ¸å¤é¨çï¼æ们åªå¯¹åºç¨ç¨åºçç¼ååºæå ´è¶£ï¼æ以æ¬æåªè®¨è®ºåºç¨ç¨åºç¼ååºã
åºç¨ç¨åºç¼ååºç大å°å¯ä»¥éè¿ALSAåºå½æ°è°ç¨æ¥æ§å¶ãç¼ååºå¯ä»¥å¾å¤§ï¼ä¸æ¬¡ä¼ è¾æä½å¯è½ä¼å¯¼è´ä¸å¯æ¥åç延è¿ï¼æ们æå®ç§°ä¸ºå»¶æ¶(latency)ã为äºè§£å³è¿ä¸ªé®é¢ï¼ALSAå°ç¼ååºæåæä¸ç³»åå¨æ(period)(OSS/Freeä¸å«çæfragments).ALSA以period为åå æ¥ä¼ éæ°æ®ã
ä¸ä¸ªå¨æ(period)åå¨ä¸äºå¸§(frames)ãæ¯ä¸å¸§å å«æ¶é´ä¸ä¸ä¸ªç¹ææåçæ ·æ¬ã对äºç«ä½å£°è®¾å¤ï¼ä¸ä¸ªå¸§ä¼å å«ä¸¤ä¸ªä¿¡éä¸çæ ·æ¬ãå¾1å±ç¤ºäºå解è¿ç¨ï¼ä¸ä¸ªç¼ååºå解æå¨æï¼ç¶åæ¯å¸§ï¼ç¶åæ¯æ ·æ¬ãå¾ä¸å å«ä¸äºåå®çæ°å¼ãå¾ä¸å·¦å³ä¿¡éä¿¡æ¯è¢«äº¤æ¿å°åå¨å¨ä¸ä¸ªå¸§å ãè¿ç§°ä¸ºäº¤é(interleaved)模å¼ãå¨é交é模å¼ä¸ï¼ä¸ä¸ªä¿¡éçæææ ·æ¬æ°æ®åå¨å¨å¦å¤ä¸ä¸ªä¿¡éçæ°æ®ä¹åã
Over and Under Run
å½ä¸ä¸ªå£°å¡æ´»å¨æ¶ï¼æ°æ®æ»æ¯è¿ç»å°å¨ç¡¬ä»¶ç¼ååºååºç¨ç¨åºç¼ååºé´ä¼ è¾ãä½æ¯ä¹æä¾å¤ãå¨å½é³ä¾åä¸ï¼å¦æåºç¨ç¨åºè¯»åæ°æ®ä¸å¤å¿«ï¼å¾ªç¯ç¼ååºå°ä¼è¢«æ°çæ°æ®è¦çãè¿ç§æ°æ®ç丢失被称为overrun.å¨åæ¾ä¾åä¸ï¼å¦æåºç¨ç¨åºåå ¥æ°æ®å°ç¼ååºä¸çé度ä¸å¤å¿«ï¼ç¼ååºå°ä¼"饿æ»"ãè¿æ ·çé误被称为"underrun"ãå¨ALSAææ¡£ä¸ï¼ææ¶å°è¿ä¸¤ç§æ å½¢ç»ç§°ä¸º"XRUN"ãéå½å°è®¾è®¡åºç¨ç¨åºå¯ä»¥æå°åXRUN并ä¸å¯ä»¥ä»ä¸æ¢å¤è¿æ¥ã
ä¸ä¸ªå ¸åç声é³ç¨åº
使ç¨PCMçç¨åºé常类似ä¸é¢ç伪代ç ï¼
æå¼åæ¾æå½é³æ¥å£
设置硬件åæ°(访é®æ¨¡å¼ï¼æ°æ®æ ¼å¼ï¼ä¿¡éæ°ï¼éæ ·çï¼çç)
while ææ°æ®è¦è¢«å¤çï¼
读PCMæ°æ®(å½é³)
æ åPCMæ°æ®(åæ¾)
å ³éæ¥å£
æ们å°å¨ä¸æä¸çå°ä¸äºå¯ä»¥å·¥ä½ç代ç ãæ建议æ¨å¨ä½ çLinuxç³»ç»ä¸æµè¯è¿è¡è¿äºä»£ç ãæ¥çè¾åºå¹¶å°è¯ä¿®æ¹æ¨èç代ç ãåæ¬æç¸å ³çææå®ä¾æ¸ åå¯ä»¥ä»FTPä¸è·åï¼ftp.ssc.com/pub/lj/listings/issue126/6735.tgzã
Listing 1. Display Some PCM Types and Formats
#include <alsa/asoundlib.h>
int main() {
int val;
printf("ALSA library version: %s/n",
SND_LIB_VERSION_STR);
printf("/nPCM stream types:/n");
for (val = 0; val <= SND_PCM_STREAM_LAST; val++)
printf(" %s/n",
snd_pcm_stream_name((snd_pcm_stream_t)val));
printf("/nPCM access types:/n");
for (val = 0; val <= SND_PCM_ACCESS_LAST; val++)
printf(" %s/n",
snd_pcm_access_name((snd_pcm_access_t)val));
printf("/nPCM formats:/n");
for (val = 0; val <= SND_PCM_FORMAT_LAST; val++)
if (snd_pcm_format_name((snd_pcm_format_t)val)
!= NULL)
printf(" %s (%s)/n",
snd_pcm_format_name((snd_pcm_format_t)val),
snd_pcm_format_description(
(snd_pcm_format_t)val));
printf("/nPCM subformats:/n");
for (val = 0; val <= SND_PCM_SUBFORMAT_LAST;
val++)
printf(" %s (%s)/n",
snd_pcm_subformat_name((
snd_pcm_subformat_t)val),
snd_pcm_subformat_description((
snd_pcm_subformat_t)val));
printf("/nPCM states:/n");
for (val = 0; val <= SND_PCM_STATE_LAST; val++)
printf(" %s/n",
snd_pcm_state_name((snd_pcm_state_t)val));
return 0;
}
æ¸ åä¸æ¾ç¤ºäºä¸äºALSA使ç¨çPCMæ°æ®ç±»åååæ°ãé¦å éè¦åçæ¯å æ¬å¤´æ件ãè¿äºå¤´æ件å å«äºææåºå½æ°ç声æãå ¶ä¸ä¹ä¸å°±æ¯æ¾ç¤ºALSAåºççæ¬ã
è¿ä¸ªç¨åºå©ä¸çé¨åçè¿ä»£ä¸äºPCMæ°æ®ç±»åï¼ä»¥æµç±»åå¼å§ãALSA为æ¯æ¬¡è¿ä»£çæåå¼æä¾ç¬¦å·å¸¸éåï¼å¹¶ä¸æä¾åè½å½æ°ä»¥æ¾ç¤ºæ个ç¹å®å¼çæè¿°å符串ãä½ å°ä¼çå°ï¼ALSAæ¯æ许å¤æ ¼å¼ï¼å¨æç1.0.15çæ¬éï¼æ¯æå¤è¾¾36ç§æ ¼å¼ã
è¿ä¸ªç¨åºå¿ é¡»é¾æ¥å°alsalibåºï¼éè¿å¨ç¼è¯æ¶éè¦å ä¸-lasoundé项ãæäºalsaåºå½æ°ä½¿ç¨dlopenå½æ°ä»¥åæµ®ç¹æä½ï¼æ以æ¨å¯è½è¿éè¦å ä¸-ldl,-lmé项ã
ä¸é¢æ¯è¯¥ç¨åºçMakefile:
CC=gcc
TARGET=test
SRC=$(wildcard *.c)
OBJECT= ${SRC:.c=.o}
INCLUDES=-I/usr/include/alsa
LDFLAGS=-lasound
all:$(TARGET)
$(OBJECT):$(SRC)
$(CC) -c $(INCLUDES) $<
$(TARGET):$(OBJECT)
$(CC) -o $@ $< $(LDFLAGS)
.PHONY:clean
clean:
@rm -rf $(OBJECT) $(TARGET) *~
Listing 2. Opening PCM Device and Setting Parameters
/*
This example opens the default PCM device, sets
some parameters, and then displays the value
of most of the hardware parameters. It does not
perform any sound playback or recording.
*/
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
/* All of the ALSA library API is defined
* in this header */
#include <alsa/asoundlib.h>
int main() {
int rc;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val, val2;
int dir;
snd_pcm_uframes_t frames;
/* Open PCM device for playback. */
rc = snd_pcm_open(&handle, "default",
SND_PCM_STREAM_PLAYBACK, 0);
if (rc < 0) {
fprintf(stderr,
"unable to open pcm device: %s/n",
snd_strerror(rc));
exit(1);
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(¶ms);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params,
SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params,
SND_PCM_FORMAT_S16_LE);
/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(handle, params, 2);
/* 44100 bits/second sampling rate (CD quality) */
val = 44100;
snd_pcm_hw_params_set_rate_near(handle,
params, &val, &dir);
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr,
"unable to set hw parameters: %s/n",
snd_strerror(rc));
exit(1);
}
/* Display information about the PCM interface */
printf("PCM handle name = '%s'/n",
snd_pcm_name(handle));
printf("PCM state = %s/n",
snd_pcm_state_name(snd_pcm_state(handle)));
snd_pcm_hw_params_get_access(params,
(snd_pcm_access_t *) &val);
printf("access type = %s/n",
snd_pcm_access_name((snd_pcm_access_t)val));
snd_pcm_hw_params_get_format(params, &val);
printf("format = '%s' (%s)/n",
snd_pcm_format_name((snd_pcm_format_t)val),
snd_pcm_format_description(
(snd_pcm_format_t)val));
snd_pcm_hw_params_get_subformat(params,
(snd_pcm_subformat_t *)&val);
printf("subformat = '%s' (%s)/n",
snd_pcm_subformat_name((snd_pcm_subformat_t)val),
snd_pcm_subformat_description(
(snd_pcm_subformat_t)val));
snd_pcm_hw_params_get_channels(params, &val);
printf("channels = %d/n", val);
snd_pcm_hw_params_get_rate(params, &val, &dir);
printf("rate = %d bps/n", val);
snd_pcm_hw_params_get_period_time(params,
&val, &dir);
printf("period time = %d us/n", val);
snd_pcm_hw_params_get_period_size(params,
&frames, &dir);
printf("period size = %d frames/n", (int)frames);
snd_pcm_hw_params_get_buffer_time(params,
&val, &dir);
printf("buffer time = %d us/n", val);
snd_pcm_hw_params_get_buffer_size(params,
(snd_pcm_uframes_t *) &val);
printf("buffer size = %d frames/n", val);
snd_pcm_hw_params_get_periods(params, &val, &dir);
printf("periods per buffer = %d frames/n", val);
snd_pcm_hw_params_get_rate_numden(params,
&val, &val2);
printf("exact rate = %d/%d bps/n", val, val2);
val = snd_pcm_hw_params_get_sbits(params);
printf("significant bits = %d/n", val);
snd_pcm_hw_params_get_tick_time(params,
&val, &dir);
printf("tick time = %d us/n", val);
val = snd_pcm_hw_params_is_batch(params);
printf("is batch = %d/n", val);
val = snd_pcm_hw_params_is_block_transfer(params);
printf("is block transfer = %d/n", val);
val = snd_pcm_hw_params_is_double(params);
printf("is double = %d/n", val);
val = snd_pcm_hw_params_is_half_duplex(params);
printf("is half duplex = %d/n", val);
val = snd_pcm_hw_params_is_joint_duplex(params);
printf("is joint duplex = %d/n", val);
val = snd_pcm_hw_params_can_overrange(params);
printf("can overrange = %d/n", val);
val = snd_pcm_hw_params_can_mmap_sample_resolution(params);
printf("can mmap = %d/n", val);
val = snd_pcm_hw_params_can_pause(params);
printf("can pause = %d/n", val);
val = snd_pcm_hw_params_can_resume(params);
printf("can resume = %d/n", val);
val = snd_pcm_hw_params_can_sync_start(params);
printf("can sync start = %d/n", val);
snd_pcm_close(handle);
return 0;
}
温馨提示:答案为网友推荐,仅供参考