Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 4.4 Kitkat 音頻實現及簡要分析

Android 4.4 Kitkat 音頻實現及簡要分析

編輯:關於Android編程

在 Android 4.4 上實現錄放音


背景

Android 自 ICS 開始,音頻系統就有了很大的變化,先是拋棄了 alsalib,然後是采用了 AIO,各級框架上,都有了自己的特色,與 Linux 的音頻應用漸行漸遠,形成了自己獨特的音頻管理和音頻配置功能。總的來說改進還是非常大,至少在用戶體驗上已經大大的超越了之前的版本。我們就從 4.4 的音頻實現上來分析其中的一些變化和實現機制。

要求


首先是硬件功能正常,這個不表。 Linux 支持 alsa 驅動,生成 alsa 子系統,最好是能夠在 buildroot 等其他文件系統上事先測試音頻的播放和錄制。

HAL

音頻的 HAL 簡單實現,參考 device/asus/grouper/audio , 如果沒有太復雜的音頻配置,基本上可以在這個代碼基礎上稍微修改,主要是一些播放和錄制的參數。這個 HAL 已經實現了通用的接口,並且調用的也是標准的 tinyalsa 的接口,移植性非常高。我們這裡使用的 wm8904,功能不多,直接使用即可。

Android 的配置


主要是4個文件 audio_policy.conf media_profiles.xml media_codecs.xml mixer_paths.xml 參考 asus ,不必大改,基本照抄,完全可以直接使用,開源萬歲。
做好文件系統,這個時候系統應該就不使用 default 的 stub 音頻 HAL , 而是用我們添加的 audio HAL 了。 但是能否發聲,這個多半還是不能。

調試


audio 系統調用了 libtinyalsa libaudioutils libaudioroute 幾個底層庫。 這幾個移植了一些通用的 alsa 設備打開配置功能,但是具體平台卻並不一定都能正常執行,主要是這些庫實現都很簡單,沒有考慮全面,你的硬件細節可能剛好被他們忽略了,同樣以我們的 wm8904 來說,我們不支持 time stamp ,但是 tinyalsa 是默認打開的必須將其關掉。
    disable tstamp for wm8904.
    
    Change-Id: Ia22aa6ed39ede6214657487344d0488be93e5544

diff --git a/pcm.c b/pcm.c
index 4501777..94cf6ee 100644
--- a/pcm.c
+++ b/pcm.c
@@ -691,7 +691,7 @@ struct pcm *pcm_open(unsigned int card, unsigned int device,
 
 
     memset(&sparams, 0, sizeof(sparams));
-    sparams.tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE;
+    sparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
     sparams.period_step = 1;
 
     if (!config->start_threshold) {

具體哪些參數不對,或者不合適,就需要 Android 驅動工程師根據硬件設計和芯片手冊,逐個查證,配置到一個音頻系統工作的最佳狀態。那麼用戶體驗才能最好。


Android 音頻系統分析

以下分析基於 4.4.2

audio HAL


tinyalsa 與 audioroute

Android 音頻系統基於 Linux 的 ALSA 驅動, tinyalsa 在 alsa 的驅動基礎上封裝音頻接口,提供給 audio HAL, audio HAL 提供接口給 Android audioflinger 等 framework。 HAL 需要實現 audio 硬件的打開與關閉(這裡是 android 認為的硬件)。
static inline int audio_hw_device_open(const struct hw_module_t* module,
                                       struct audio_hw_device** device)
{
    return module->methods->open(module, AUDIO_HARDWARE_INTERFACE,
                                 (struct hw_device_t**)device);
}

static inline int audio_hw_device_close(struct audio_hw_device* device)
{
    return device->common.close(&device->common);
}

需要實現 in 和 out 的 數據流 struct audio_stream_out struct audio_stream_in
in 主要有 read 方法用於讀取音頻數據, out 主要有 write 方法,寫入數據到設備,分別實現錄音和放音。 詳見: hardware/libhardware/include/hardware/audio.h
其中的方法又是調用的 tinyalsa 的接口,關於 pcm 的操作:
/* Open and close a stream */
struct pcm *pcm_open(unsigned int card, unsigned int device,
                     unsigned int flags, struct pcm_config *config);
int pcm_close(struct pcm *pcm);
int pcm_is_ready(struct pcm *pcm);

/* Obtain the parameters for a PCM */
struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
                                  unsigned int flags);
void pcm_params_free(struct pcm_params *pcm_params);
unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
                                enum pcm_param param);
unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
                                enum pcm_param param);

/* Set and get config */
int pcm_get_config(struct pcm *pcm, struct pcm_config *config);
int pcm_set_config(struct pcm *pcm, struct pcm_config *config);

/* Returns a human readable reason for the last error */
const char *pcm_get_error(struct pcm *pcm);

/* Returns the sample size in bits for a PCM format.
 * As with ALSA formats, this is the storage size for the format, whereas the
 * format represents the number of significant bits. For example,
 * PCM_FORMAT_S24_LE uses 32 bits of storage.
 */
unsigned int pcm_format_to_bits(enum pcm_format format);

/* Returns the buffer size (int frames) that should be used for pcm_write. */
unsigned int pcm_get_buffer_size(struct pcm *pcm);
unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames);
unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes);

/* Returns the pcm latency in ms */
unsigned int pcm_get_latency(struct pcm *pcm);

/* Returns available frames in pcm buffer and corresponding time stamp.
 * The clock is CLOCK_MONOTONIC if flag PCM_MONOTONIC was specified in pcm_open,
 * otherwise the clock is CLOCK_REALTIME.
 * For an input stream, frames available are frames ready for the
 * application to read.
 * For an output stream, frames available are the number of empty frames available
 * for the application to write.
 */
int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail,
                       struct timespec *tstamp);

/* Write data to the fifo.
 * Will start playback on the first write or on a write that
 * occurs after a fifo underrun.
 */
int pcm_write(struct pcm *pcm, const void *data, unsigned int count);
int pcm_read(struct pcm *pcm, void *data, unsigned int count);

/*
 * mmap() support.
 */
int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count);
int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count);
int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset,
                   unsigned int *frames);
int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames);

/* Start and stop a PCM channel that doesn't transfer data */
int pcm_start(struct pcm *pcm);
int pcm_stop(struct pcm *pcm);

/* Interrupt driven API */
int pcm_wait(struct pcm *pcm, int timeout);

/* Change avail_min after the stream has been opened with no need to stop the stream.
 * Only accepted if opened with PCM_MMAP and PCM_NOIRQ flags
 */
int pcm_set_avail_min(struct pcm *pcm, int avail_min);


值得一提的是 HAL 現在不包含 route 的操作, audio route 交給了 libaudioroute.so , 它也是調用 tinyalsa 的接口,並包含一個 xml 解析器,解析 mixer_paths.xml 裡面的 route 配置數據。這樣系統就可以對 alsa 的 pcm 和 mixer 進行操作了,理論上應該可以放音了,使用 tinyalsa 提供的工具可以進行測試,當然無法測試 HAL 的接口。 tinycap tinymix tinypcminfo tinyplay

tinyplay 可以播放 wav 格式的純音頻數據。 tinymix 可以查看和配置音頻路徑:
root@sama5d3:/ # tinymix                                                       
Mixer name: 'wm8904 @ SAMA5D3EK'
Number of controls: 41
ctl     type    num     name                                     value
0       INT     1       EQ1 Volume                               12
1       INT     1       EQ2 Volume                               12
2       INT     1       EQ3 Volume                               12
3       INT     1       EQ4 Volume                               12
4       INT     1       EQ5 Volume                               12
5       INT     2       Digital Capture Volume                   96 96
6       ENUM    1       Left Caputure Mode                       Single-Ended
7       ENUM    1       Right Capture Mode                       Single-Ended
8       INT     2       Capture Volume                           5 5
9       BOOL    2       Capture Switch                           Off Off
10      BOOL    1       High Pass Filter Switch                  On
11      ENUM    1       High Pass Filter Mode                    Hi-fi
12      BOOL    1       ADC 128x OSR Switch                      On
13      INT     1       Digital Playback Boost Volume            0
14      INT     2       Digital Playback Volume                  96 96
15      INT     2       Headphone Volume                         45 45
16      BOOL    2       Headphone Switch                         On On
17      BOOL    2       Headphone ZC Switch                      On On
18      INT     2       Line Output Volume                       57 57
19      BOOL    2       Line Output Switch                       On On
20      BOOL    2       Line Output ZC Switch                    On On
21      BOOL    1       EQ Switch                                Off
22      BOOL    1       DRC Switch                               Off
23      ENUM    1       DRC Path                                 ADC
24      BOOL    1       DAC OSRx2 Switch                         Off
25      BOOL    1       DAC Deemphasis Switch                    Off
26      INT     2       Digital Sidetone Volume                  0 0
27      ENUM    1       LINER Mux                                DAC
28      ENUM    1       LINEL Mux                                DAC
29      ENUM    1       HPR Mux                                  DAC
30      ENUM    1       HPL Mux                                  DAC
31      ENUM    1       Right Sidetone                           None
32      ENUM    1       Left Sidetone                            None
33      ENUM    1       DACR Mux                                 Right
34      ENUM    1       DACL Mux                                 Left
35      ENUM    1       AIFOUTR Mux                              Right
36      ENUM    1       AIFOUTL Mux                              Left
37      ENUM    1       Right Capture Inverting Mux              IN1R
38      ENUM    1       Right Capture Mux                        IN2R
39      ENUM    1       Left Capture Inverting Mux               IN1L
40      ENUM    1       Left Capture Mux                         IN2L


audioflinger


audioflinger 是 audio 音頻服務器,它會加載 audio hal ,並處理 audio 應用發出音頻請求。這個分析的有很多,參考以下: http://blog.csdn.net/DroidPhone/article/details/5941344






  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved