最近移植Android,当Android能够在设备上面运行之后,首先想到的是让音频设备跑起来。“没有声音,再好的戏也出不来”。本文简单介绍一下Android音频适配层。
这个世界音频设备千变万化,Android也不可能为每种设备都提供支持。Android定义了一个框架,这个框架来适配底层的音频设备。该适配层的定义位于:
hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h
要想视频底层的音频设备必须要继承该文件中定义的AudioStreamOut,AudioStreamIn,AudioHardwareInterface等类,并实现createAudioHardware函数。
下面我们看一下Android创建音频设备的代码,代码位于:
frameworks/base/libs/audioflinger/AudioHardwareInterface.cpp
该文件有如下代码:
AudioHardwareInterface* AudioHardwareInterface::create()
{
/*
* FIXME: This code needs to instantiate the correct audio device
* interface. For now - we use compile-time switches.
*/
AudioHardwareInterface* hw = 0;
char value[PROPERTY_VALUE_MAX];
#ifdef GENERIC_AUDIO
hw = new AudioHardwareGeneric();
#else
// if running in emulation - use the emulator driver
if (property_get("ro.kernel.qemu", value, 0)) {
LOGD("Running in emulation - using generic audio driver");
hw = new AudioHardwareGeneric();
}
else {
LOGV("Creating Vendor Specific AudioHardware");
hw = createAudioHardware();
}
#endif
if (hw->initCheck() != NO_ERROR) {
LOGW("Using stubbed audio hardware. No sound will be produced.");
delete hw;
hw = new AudioHardwareStub();
}
#ifdef WITH_A2DP
hw = new A2dpAudioInterface(hw);
#endif
#ifdef ENABLE_AUDIO_DUMP
// This code adds a record of buffers in a file to write calls made by AudioFlinger.
// It replaces the current AudioHardwareInterface object by an intermediate
one which
// will record buffers in a file (after sending them to hardware) for testing purpose.
// This feature is enabled by defining symbol ENABLE_AUDIO_DUMP.
// The output file is set with setParameters("test_cmd_file_name="). Pause are not recorded in the file.
LOGV("opening PCM dump interface");
hw = new AudioDumpInterface(hw); // replace interface
#endif
return hw;
}
从代码中我们可以看出如果定义了GENERIC_AUDIO的宏,则会创建 AudioHardwareGeneric,如果是模拟器的话,AudioHardwareGeneric会不能初始化,进而创建 AudioHardwareStub。这两个类都是Audio设备的适配层,是Android默认提供的。模拟器都是用 AudioHardwareStub,不会有声音输出。设备都是用AudioHardwareGeneric,因为默认GENERIC_AUDIO是设置的。
一般我们只关心AudioHardwareGeneric实现,谁会去给模拟器去调试声音呢,反正我没这个闲心。首先说明一下这个音频适配层是 Android自带的,可以保证你的音频设备正常运行,但是不能发挥设备的最佳性能。通过后面的描述你将会了解。 AudioHardwareGeneric的定义位于:
frameworks/base/libs/audioflinger/AudioHardwareGeneric.cpp
查看源码你会发现这个适配层需要实现设备/dev/eac,并且该设备只输出44.1khz采样率的音频数据给 /dev/eac设备,如果不是44.1khz的采样率的数据,AudioHardwareGeneric会经过Resample过程把它转换成 44.1kHZ的音频数据,然后再输出给音频设备。44.1kHZ音频数据是最普遍的音频采样率,大部分Mp3都是以这个采样率压缩的,所以选择这个采样 率做为默认采样率还是有一定的合理性的。AudioHardwareGeneric是软件实现Resample过程是,效率会比较低。很多音频设备支持不 同采样率的数据,可以理解成硬件实现Resample过程。
通过上面的描述我们可以知道这个通用音频适配层只是让你的设备可以用而已,不能发挥设备的性能优势,如果你的设备对音频质量有更高的要求,必须要自己实现音频适配层。谷歌只能保证你的音频可以播放,但是不能保证效率(他也没有办法保证效率)。
本文只是粗略的对Android音频系统进行了简单介绍。如果有错误之处请不吝指教。