android系統(tǒng)開(kāi)發(fā)(九)-Audio部分準(zhǔn)備工作alsa移植
1,audio內(nèi)核部分的開(kāi)發(fā),包含codec驅(qū)動(dòng),cpu的聲音驅(qū)動(dòng)和內(nèi)核alsa驅(qū)動(dòng)等,
這個(gè)是完全的嵌入式linux的開(kāi)發(fā)內(nèi)容,這里跳過(guò),請(qǐng)確保這幾部分正確。
2,從alsa的官方網(wǎng)站下載最新的alsa-lib-1.0.23和alsa-utils-1.0.23
官方網(wǎng)站:
http://www.alsa-project.orgalsa-lib基于內(nèi)核alsa驅(qū)動(dòng),它將對(duì)內(nèi)核alsa接口的操作封裝成libasound庫(kù)
alsa-utils是一個(gè)工具包,基于alsa-lib來(lái)控制底層alsa驅(qū)動(dòng),包含aplay/amixer/control等工具
alsa的系統(tǒng)架構(gòu)如下:
alsa應(yīng)用
|
alsa-utils
|
alsa-lib
|
alsa-driver
alsa-driver已經(jīng)集成在linux內(nèi)核中,alsa應(yīng)用直接調(diào)用alsa-utils工具包的工具來(lái)控制底層驅(qū)動(dòng)以操作聲卡
3,在vendor/ardent/merlin目錄下新建一個(gè)alsa目錄,然后將下載的alsa-lib-1.0.23和alsa-utils-1.0.23
解壓縮到alsa目錄下,將解壓縮后的文件夾去掉版本號(hào)改成alsa-lib和alsa-utils
4,在vendor/ardent/merlin/AndroidBoard.mk文件中加入如下內(nèi)容:
L_PATH := $(LOCAL_PATH)
include $(L_PATH)/alsa/Mdroid.mk
5,在vendor/ardent/merlin/alsa目錄下新建Mdroid.mk文件,內(nèi)容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
ALSA_PATH := $(LOCAL_PATH)
include $(ALSA_PATH)/alsa-lib/Mdroid.mk
include $(ALSA_PATH)/alsa-utils/Mdroid.mk
6,在vendor/ardent/merlin/alsa/alsa-lib目錄下新建Mdroid.mk文件,內(nèi)容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/src/Mdroid.mk
7,在vendor/ardent/merlin/alsa/alsa-lib/src目錄下新建Mdroid.mk文件,內(nèi)容在文章后面。
注:alsa-lib中編譯的內(nèi)容很多,我們可以先將alsa-lib當(dāng)成普通的linux庫(kù)來(lái)編譯,編譯完成后通過(guò)查找lo文件的方法
看那些文件被編譯到了,同而找到需要編譯的c文件,通過(guò)make install到指定目錄找到需要復(fù)制的庫(kù)和其它文件。代碼中
的很多部分是不需要用到了,目前暫時(shí)未作詳細(xì)處理,alsa-lib/modules/mixer/simple目錄下的內(nèi)容編譯成了另外的幾個(gè)
動(dòng)態(tài)庫(kù)(smixer-ac97,smixer-hda.so,smixer-sbase.so),alsa-lib/aserver目錄下的內(nèi)容編譯成aserver,
這兩部分因?yàn)椴粫?huì)用到,所以未加入到android編譯系統(tǒng)中。
8,找個(gè)目錄將alsa-lib當(dāng)成普通的linux庫(kù)編譯一次,在include目錄下會(huì)生成config.h文件,將該文件復(fù)制到
vendor/ardent/merlin/alsa/alsa-lib/include目錄下并修改config.h的部分內(nèi)容如下:
#define ALOAD_DEVICE_DIRECTORY "/dev/snd"
#define ALSA_CONFIG_DIR "/etc"
#define ALSA_DEVICE_DIRECTORY "/dev/snd/"
//#define HAVE_WORDEXP_H 1
//#define VERSIONED_SYMBOLS
9,修改alsa-lib/include/global.h文件,刪除如下內(nèi)容:
#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE)
struct timeval {
time_t tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#endif
10,將源代碼中所有的
#include <sys/shm.h>
改成
#include <linux/shm.h>
類(lèi)似
#include <sys/sem.h>
改成
#include <linux/sem.h>
11,修改alsa-lib/src/alisp/alisp.c,在obj_type_str函數(shù)最后面位置加上如下內(nèi)容:
return NULL;
12,將alsa-lib當(dāng)普通linux庫(kù)編譯時(shí)alsa-lib/src/control目錄下生成的ctl_symbols_list.c文件和
alsa-lib/src/pcm目錄下生成的pcm_symbols_list.c文件復(fù)制到android中alsa-lib對(duì)應(yīng)位置。
13,修改alsa-lib/src/pcm/pcm_direct.c文件,刪除如下內(nèi)容:
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO (Linux specific) */
};
14,查找alsa-lib源代碼所有文件,確保
#include <linux/shm.h>的前面有
#include <stdlib.h>
沒(méi)有的自己加上,否則會(huì)報(bào)告錯(cuò)誤說(shuō)size_t未定義
15,修改alsa-lib/src/pcm/pcm_ladspa.c文件,將
*strrchr (labellocale, '.') = *lc->decimal_point;
改成
*strrchr (labellocale, '.') = ".";
屏蔽掉如下內(nèi)容:
//lc = localeconv ();
這個(gè)是因?yàn)閍ndroid用的C庫(kù)是bionic,和標(biāo)準(zhǔn)C庫(kù)不同,對(duì)應(yīng)的locale.h文件中的lconv結(jié)構(gòu)體定義不同所導(dǎo)致。
16,修改alsa-lib/src/pcm/pcm_mmap.c文件中的snd_pcm_mmap函數(shù),將switch (i->type)語(yǔ)句下SND_PCM_AREA_SHM分支的內(nèi)容
屏蔽掉,同時(shí)修改該文件中snd_pcm_munmap函數(shù),將switch (i->type)語(yǔ)句下的SND_PCM_AREA_SHM分支內(nèi)容屏蔽掉。
17,搜索alsa-lib/src目錄下的所有文件,搜索shmctl,shmget,shmat,shmdt等4個(gè)函數(shù)的調(diào)用處,將調(diào)用到的地方刪除。
這個(gè)主要是因?yàn)閍ndroid的bionic libc庫(kù)不支持System V IPC所導(dǎo)致,具體的可以從頭文件中看出來(lái)。System V IPC通過(guò)共享
內(nèi)存的方式來(lái)實(shí)現(xiàn),GNU C庫(kù)對(duì)應(yīng)共享內(nèi)存頭文件為linux pc的/usr/include/sys/shm.h文件,在此文件中,你可以看到
shmctl,shmget,shmat,shmdt等4個(gè)函數(shù)的聲明,bionic libc庫(kù)也有一個(gè)同樣的頭文件,在android源代碼目錄的
bionic/libc/kernel/common/linux目錄下,但是文件中的內(nèi)容卻沒(méi)有上面4個(gè)函數(shù)的聲明。上面16所作的修改也是基于這個(gè)原因。
18,按照16和17的結(jié)論,由于bionic libc所引發(fā)的System V IPC功能的缺失,導(dǎo)致alsa庫(kù)中的相關(guān)功能不能正常實(shí)現(xiàn),所以最好的
方法是將相關(guān)的部分不編譯進(jìn)來(lái),以免找成不必要的錯(cuò)誤。據(jù)此將一些文件從編譯中刪除,修改alsa-lib/src/Mdroid.mk文件即可
alsa-lib/src/control/control_shm.c
alsa-lib/src/pcm/pcm_direct.c
alsa-lib/src/pcm/pcm_dmix.c
alsa-lib/src/pcm/pcm_dshare.c
alsa-lib/src/pcm/pcm_dsnoop.c
alsa-lib/src/pcm/pcm_ladspa.c
alsa-lib/src/pcm/pcm_shm.c
alsa-lib/src/shmarea.c
刪除了這幾個(gè)模塊后要將alsa-lib/src/control目錄下的ctl_symbols_list.c文件和
alsa-lib/src/pcm目錄下的pcm_symbols_list.c文件中的相關(guān)內(nèi)容刪除,否則會(huì)編譯不過(guò)。
19,最后要實(shí)現(xiàn)的功能當(dāng)然是復(fù)制alsa-lib的配置文件了,在alsa-lib/src/conf目錄下,復(fù)制操作在alsa-lib/src/Mdroid.mk中實(shí)現(xiàn),
最終的Mdroid.mk文件內(nèi)容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
async.c conf.c confmisc.c dlmisc.c error.c input.c \
names.c output.c socket.c userfile.c \
alisp/alisp.c \
control/cards.c control/control.c control/control_ext.c \
control/control_hw.c control/control_symbols.c \
control/hcontrol.c control/namehint.c control/setup.c control/tlv.c \
hwdep/hwdep.c hwdep/hwdep_hw.c hwdep/hwdep_symbols.c \
mixer/bag.c mixer/mixer.c mixer/simple.c mixer/simple_abst.c mixer/simple_none.c \
pcm/atomic.c pcm/interval.c pcm/mask.c pcm/pcm.c pcm/pcm_adpcm.c \
pcm/pcm_alaw.c pcm/pcm_asym.c pcm/pcm_copy.c pcm/pcm_empty.c \
pcm/pcm_extplug.c pcm/pcm_file.c pcm/pcm_generic.c pcm/pcm_hooks.c \
pcm/pcm_hw.c pcm/pcm_iec958.c pcm/pcm_ioplug.c \
pcm/pcm_lfloat.c pcm/pcm_linear.c pcm/pcm_meter.c pcm/pcm_misc.c \
pcm/pcm_mmap.c pcm/pcm_mmap_emul.c pcm/pcm_mulaw.c pcm/pcm_multi.c \
pcm/pcm_null.c pcm/pcm_params.c pcm/pcm_plug.c pcm/pcm_plugin.c \
pcm/pcm_rate.c pcm/pcm_rate_linear.c pcm/pcm_route.c pcm/pcm_share.c \
pcm/pcm_simple.c pcm/pcm_softvol.c pcm/pcm_symbols.c \
rawmidi/rawmidi.c rawmidi/rawmidi_hw.c rawmidi/rawmidi_symbols.c \
rawmidi/rawmidi_virt.c \
seq/seq.c seq/seq_event.c seq/seq_hw.c seq/seqmid.c \
seq/seq_midi_event.c seq/seq_old.c seq/seq_symbols.c \
timer/timer.c timer/timer_hw.c timer/timer_query.c \
timer/timer_query_hw.c timer/timer_symbols.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../include
LOCAL_SHARED_LIBRARIES := libdl
LOCAL_ARM_MODE := arm
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libasound
include $(BUILD_SHARED_LIBRARY)
TARGET_ALSA_CONF_DIR := $(TARGET_OUT)/usr/share/alsa
LOCAL_ALSA_CONF_DIR := $(LOCAL_PATH)/conf
copy_from := \
alsa.conf \
pcm/dsnoop.conf \
pcm/modem.conf \
pcm/dpl.conf \
pcm/default.conf \
pcm/surround51.conf \
pcm/surround41.conf \
pcm/surround50.conf \
pcm/dmix.conf \
pcm/center_lfe.conf \
pcm/surround40.conf \
pcm/side.conf \
pcm/iec958.conf \
pcm/rear.conf \
pcm/surround71.conf \
pcm/front.conf \
cards/aliases.conf
copy_to := $(addprefix $(TARGET_ALSA_CONF_DIR)/,$(copy_from))
copy_from := $(addprefix $(LOCAL_ALSA_CONF_DIR)/,$(copy_from))
$(copy_to) : $(TARGET_ALSA_CONF_DIR)/% : $(LOCAL_ALSA_CONF_DIR)/% | $(ACP)
$(transform-prebuilt-to-target)
ALL_PREBUILT += $(copy_to)
20,alsa-utils的移植方法也類(lèi)似,這里就不再介紹,上面的過(guò)程只是體驗(yàn)了一下android下開(kāi)源庫(kù)的移植方法,
實(shí)際上google服務(wù)器上已經(jīng)有alsa的代碼,直接下載下載便可用,下載方法如下:
git clone git://android.git.kernel.org/platform/external/alsa-lib.git
git clone git://android.git.kernel.org/platform/external/alsa-utils.git
將下載的alsa-lib和alsa-utils部分復(fù)制到vendor/ardent/merlin/alsa目錄下參考上面的方法只需對(duì)以上
的4和5部分稍作修改即可。