android Audio 詳解( 二 )
2018年01月04日 15:57:45 韓半仙 閱讀數:302更多
個人分類: linux驅動
2 tinyalsa
tinyalsa是Google在Android 4.0之後推的基於alsa內核的用戶層音頻接口。在Android 4.0之前還一直是使用這alsa-lib接口。Google之所以推出tinyalsa,可能是因爲alsa使用了GPL許可證的緣故,也有可能是因爲alsa-lib的庫過於複雜繁瑣而大部分功能在Android平臺沒有實際實用意義卻依然佔用屈指可數的內存空間。Google在Android4.0之後推出了tinyalsa 。
tinyalsa的源代碼位於 external/tinyalsa/目錄下。
tinyalsa的源代碼包括兩部分,tinyalsa庫文件和小工具。
tinyalsa庫文件的源代碼有兩個,是mixer.c pcm.c。其中mixer.c提供了控制接口。pcm.c提供了PCM播放、錄音的接口。
tinyalsa工具包括了四個文件,tinyplay.c、tinycap.c、tinymix.c、tinypcminfo.c。每個文件對應一個可執行文件。tinyplay 是一個簡單的播放器,可以播放WAV文件。tinycap是一個簡單的錄音程序,可以進行錄音並保存到一個wav文件中。tinymix用於配置control,例如切換音頻通道等等。tinypcminfo獲取PCM的參數的示例,例如採樣率的範圍、通道數的範圍等等。
2.1 PCM播放錄音說明。
重要的數據結構
struct pcm_config {
unsigned int channels;
unsigned int rate;
unsigned int period_size;
unsigned int period_count;
enum pcm_format format;
/* Values to use for the ALSA start, stop and silence thresholds. Setting
* any one of these values to 0 will cause the default tinyalsa values to be
* used instead. Tinyalsa defaults are as follows.
*
* start_threshold : period_count * period_size
* stop_threshold : period_count * period_size
* silence_threshold : 0
*/
unsigned int start_threshold;
unsigned int stop_threshold;
unsigned int silence_threshold;
/* Minimum number of frames available before pcm_mmap_write() will actually
* write into the kernel buffer. Only used if the stream is opened in mmap mode
* (pcm_open() called with PCM_MMAP flag set). Use 0 for default.
*/
int avail_min;
};
.channels :通道數
.rate : 採樣率
.period_size : 每次傳輸的數據長度。值越小,時延越小,cpu佔用就越高。
.period_count: 緩衝區period的個數。緩衝區越多,發生XRUN的機會就越少。
.format : 定義數據格式,如數據寬度
.start_threshold : 緩衝區的數據超過該值時,硬件開始啓動數據傳輸。
.stop_threshold : 緩衝區空閒區大於該值時,硬件停止傳輸。默認情況下,這個數 爲整個緩衝區的大小,即整個緩衝區空了,就停止傳輸。
.avail_min : 緩衝區空閒區大於該值時,pcm_mmap_write()往緩衝寫數據。
播放和錄音的調用可以參考tinyplay.c、tinycap.c裏面的示例。
2.1 mix使用說明。
2.1.1 打開mixer設備
struct mixer *mixer = mixer_open(card);
card是一個整型的變量。是聲卡的控制器的編號。mixer_open會打開controlCX,card就是對應X的數值。
我們在/dev/snd/目錄下用ls命令就可以看到相關的聲卡設備。
2.1.2 mixer的讀寫
首先獲得mixer_ctl的指針。
mixer_ctl ctl =mixer_get_ctl_by_name(mixer, name);
參數name就是control的名稱,就是要和我們前面介紹的snd_kcontrol_new結構中name相匹配。
也可以通過id來得到mixer_ctl的指針。
mixer_ctl ctl =mixer_get_ctl(mixer, id);
這個id和驅動中添加control的順序是一樣的,例如第一個control的id是0,第二個是1...
設置control的值。
mixer_ctl_set_value(ctl, index, value);
前面講過control的名稱相同,則通過index來區分,這個index就是和snd_kcontrol_new結構中index相匹配的。如果沒有同名的control,那麼index就直接設爲0。value爲要設置的值。
讀control的值
mixer_ctl_get_value(ctl, index);
詳細的代碼可以參考tinymix.c。