Audio部分准备工作alsa移植

2019-07-13 01:44发布

1,audio内核部分的开发,包含codec驱动,cpu的声音驱动和内核alsa驱动等,
这个是完全的嵌入式linux的开发内容,这里跳过,请确保这几部分正确。

2,从alsa的官方网站下载最新的alsa-lib-1.0.23和alsa-utils-1.0.23
官方网站:http://www.alsa-project.org
alsa-lib基于内核alsa驱动,它将对内核alsa接口的操作封装成libasound库
alsa-utils是一个工具包,基于alsa-lib来控制底层alsa驱动,包含aplay/amixer/control等工具
alsa的系统架构如下:
         alsa应用
            |
         alsa-utils
            |
         alsa-lib
            |
         alsa-driver
alsa-driver已经集成在linux内核中,alsa应用直接调用alsa-utils工具包的工具来控制底层驱动以操作声卡

3,在vendor/ardent/merlin目录下新建一个alsa目录,然后将下载的alsa-lib-1.0.23和alsa-utils-1.0.23
解压缩到alsa目录下,将解压缩后的文件夹去掉版本号改成alsa-lib和alsa-utils

4,在vendor/ardent/merlin/AndroidBoard.mk文件中加入如下内容:
L_PATH := $(LOCAL_PATH)
include $(L_PATH)/alsa/Mdroid.mk

5,在vendor/ardent/merlin/alsa目录下新建Mdroid.mk文件,内容如下:
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文件,内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/src/Mdroid.mk

7,在vendor/ardent/merlin/alsa/alsa-lib/src目录下新建Mdroid.mk文件,内容在文章后面。


注:alsa-lib中编译的内容很多,我们可以先将alsa-lib当成普通的linux库来编译,编译完成后通过查找lo文件的方法
看那些文件被编译到了,同而找到需要编译的c文件,通过make install到指定目录找到需要复制的库和其它文件。代码中
的很多部分是不需要用到了,目前暂时未作详细处理,alsa-lib/modules/mixer/simple目录下的内容编译成了另外的几个
动态库(smixer-ac97,smixer-hda.so,smixer-sbase.so),alsa-lib/aserver目录下的内容编译成aserver,
这两部分因为不会用到,所以未加入到android编译系统中。

8,找个目录将alsa-lib当成普通的linux库编译一次,在include目录下会生成config.h文件,将该文件复制到
vendor/ardent/merlin/alsa/alsa-lib/include目录下并修改config.h的部分内容如下:
#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文件,删除如下内容:
#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
改成
#include
类似
#include
改成
#include

11,修改alsa-lib/src/alisp/alisp.c,在obj_type_str函数最后面位置加上如下内容:
        return NULL;

12,将alsa-lib当普通linux库编译时alsa-lib/src/control目录下生成的ctl_symbols_list.c文件和
alsa-lib/src/pcm目录下生成的pcm_symbols_list.c文件复制到android中alsa-lib对应位置。

13,修改alsa-lib/src/pcm/pcm_direct.c文件,删除如下内容:
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 的前面有
#include
没有的自己加上,否则会报告错误说size_t未定义

15,修改alsa-lib/src/pcm/pcm_ladspa.c文件,将
*strrchr (labellocale, '.') = *lc->decimal_point;
改成
*strrchr (labellocale, '.') = ".";
屏蔽掉如下内容:
//lc = localeconv ();
这个是因为android用的C库是bionic,和标准C库不同,对应的locale.h文件中的lconv结构体定义不同所导致。

16,修改alsa-lib/src/pcm/pcm_mmap.c文件中的snd_pcm_mmap函数,将switch (i->type)语句下SND_PCM_AREA_SHM分支的内容
屏蔽掉,同时修改该文件中snd_pcm_munmap函数,将switch (i->type)语句下的SND_PCM_AREA_SHM分支内容屏蔽掉。

17,搜索alsa-lib/src目录下的所有文件,搜索shmctl,shmget,shmat,shmdt等4个函数的调用处,将调用到的地方删除。
这个主要是因为android的bionic libc库不支持System V IPC所导致,具体的可以从头文件中看出来。System V IPC通过共享
内存的方式来实现,GNU C库对应共享内存头文件为linux pc的/usr/include/sys/shm.h文件,在此文件中,你可以看到
shmctl,shmget,shmat,shmdt等4个函数的声明,bionic libc库也有一个同样的头文件,在android源代码目录的
bionic/libc/kernel/common/linux目录下,但是文件中的内容却没有上面4个函数的声明。上面16所作的修改也是基于这个原因。

18,按照16和17的结论,由于bionic libc所引发的System V IPC功能的缺失,导致alsa库中的相关功能不能正常实现,所以最好的
方法是将相关的部分不编译进来,以免找成不必要的错误。据此将一些文件从编译中删除,修改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
删除了这几个模块后要将alsa-lib/src/control目录下的ctl_symbols_list.c文件和
alsa-lib/src/pcm目录下的pcm_symbols_list.c文件中的相关内容删除,否则会编译不过。

19,最后要实现的功能当然是复制alsa-lib的配置文件了,在alsa-lib/src/conf目录下,复制操作在alsa-lib/src/Mdroid.mk中实现,
最终的Mdroid.mk文件内容如下:
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的移植方法也类似,这里就不再介绍,上面的过程只是体验了一下android下开源库的移植方法,
实际上google服务器上已经有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部分复制到vendor/ardent/merlin/alsa目录下参考上面的方法只需对以上
的4和5部分稍作修改即可。