針對前一篇的 main (int argc, char *argv[]) 裡面的argc以及argv[]參數做個簡單解釋,
argc 代表命令列的參數數量
argv[] 將資料參數 記錄的位置,
範例: target# > ./MiniCapture default
那麼argc = 2 , argv[0] = MiniCapture ,argv[1] = default ,以上為主程式參數簡易說明。
底下就目前所了解的 ALSA API 程式碼,做一個簡單說明:
使用ALSA播放/錄製大概是這樣一個流程,
1、開啟設備
2、參數設定
3、資料擷取/播放
4、關閉/釋放空間等..
以下是簡易說明:
1、開啟設備--
snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
**pcm: 似乎是設定擋的名稱!?
name: 是硬體裝置,目前使用default,另外有 plughw:0,0或是hw:0,0等,細部仍不甚了解
steam: 錄音為 SND_PCM_STREAM_CAPTURE,放音則為 SND_PCM_STREAM_PLAYBACK等
mode: 0為標準模式,另外有SND_PCM_NONBLOCK以及SND_PCM_ASYNC參數,
NONBLOCK為立即的讀寫,ASYNC當做完一個周期讀寫後會使用SIGIO(不懂!?)
2、參數設定--
需要設定的參數有: a、記憶體空間配置-使用malloc或alloca進行空間配置
b、使用snd_pcm_hw_params_any 建立 對應硬體結構 的 完整參數定義
c、access type-設定交錯/非交錯的處理模式
d、sample format- 設定取樣的資料格式,SND_PCM_FORMAT_S16_LE格式為16bit資料(=2bytes),應該還有其他種格式,未查明。
e、sample rate-取樣率,一般CD音質使用44100Hz,若僅做語音辨識,可設定為32000或16000即可,
映體不見得可完全依照所設定的取樣率,可使用snd_pcm_hw_params_set_rate_near進行做接近的設置。
f、channel 可定通道數量,一般為單聲道或雙聲道,在交錯式雙聲道的設定下,一次取聲音(1 frame)將有 L(2Bytes)R(2Bytes)=1 word長度的資料
g、snd_pcm_hw_params()指令會將參數資料寫入硬體進行設置。
3、資料擷取/播放:
擷取交錯式資料使用 snd_pcm_readi,而非交錯式則為snd_pcm_readn,
播放交錯式資料使用 snd_pcm_writei,而非交錯式則為snd_pcm_writen,
4、關閉/釋放空間:
使用snd_pcm_close、snd_pcm_drop、snd_pcm_drain等命令進行PCM設備的關閉,並free(buf)釋放掉相關空間。
其中較為複雜的部分,在規劃buffer空間,以及檔案資料的讀取,
假設使用 16bit的資料格式,雙通道模式,frame數量為 frames,進行播放
參考下列程式碼:
buff_size = frames * channels * 2 /* 2 -> sample size */;
buff = (char *) malloc(buff_size);
snd_pcm_hw_params_get_period_time(params, &tmp, NULL);
for (loops = (seconds * 1000000) / tmp; loops > 0; loops--) {
if (pcm = read(0, buff, buff_size) == 0) {
printf("Early end of file.\n");
return 0;
}
if (pcm = snd_pcm_writei(pcm_handle, buff, frames) == -EPIPE) {
printf("XRUN.\n");
snd_pcm_prepare(pcm_handle);
} else if (pcm < 0) {
printf("ERROR. Can't write to PCM device. %s\n", snd_strerror(pcm));
}
}
buffer_size=frame數量*4byte,並使用malloc()配置buff空間,用來放要播放的資料,
seconds為要播放的秒數,用ger_period_time取得播放一個週期所需時間,計算出需要loop的次數,
然後將讀取的資料使用snd_pcm_writei寫到pcm_handle設定的機器,資料由buff指向的位置取資料,
一次取1frames(=16bit LR=4bytes),取的次數為frames次,這樣為一個period,
依據'設定的sample rate,若44100的取樣率,一秒則需要44100筆frame(4byte),
一次period若為100筆frame,那麼計算出來loop就會是441次,
buffer_size就會是100*4Bytes,將資料取出相對應大小放置在此區域,重複使用此空間進行播放。