【ALSA】使用ALSA進行音訊資料擷取 之其二

針對前一篇的 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,進行播放

參考下列程式碼:

  1. <span style="white-space: pre;">    </span>buff_size = frames * channels * 2/* 2 -> sample size */
  2.     buff = (char *) malloc(buff_size); 
  3.  
  4.     snd_pcm_hw_params_get_period_time(params, &tmp, NULL); 
  5.  
  6.     for (loops = (seconds * 1000000) / tmp; loops > 0; loops--) { 
  7.  
  8.         if (pcm = read(0, buff, buff_size) == 0) { 
  9.             printf("Early end of file.\n"); 
  10.             return 0; 
  11.         } 
  12.         if (pcm = snd_pcm_writei(pcm_handle, buff, frames) == -EPIPE) { 
  13.             printf("XRUN.\n"); 
  14.             snd_pcm_prepare(pcm_handle); 
  15.         } else if (pcm < 0) { 
  16.             printf("ERROR. Can't write to PCM device. %s\n", snd_strerror(pcm)); 
  17.         } 
  18.     } 
<span style="white-space: pre;">	</span>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,將資料取出相對應大小放置在此區域,重複使用此空間進行播放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值