s3c6410平台,codec为WM9714(驱动可使用WM9713的),使用ALSA,android版本1.5. MID上移植android以来一直没有声音。

首先确认AC97的硬件连接,AC-LINK通讯是否正常,这里使用到wince中的init寄存器组,在

sound/soc/codecs/wm9713.c中替换static const u16 wm9713_reg[]相应的寄存器,以适配硬件

配置。

做完这部分工作后,应该启动时就会有噗噗声,如果能听到,说明硬件连接正常,软件读写CODEC正常.

在网上查了很多资料,很多说要配置/system/etc/asound.conf,可我也不知道怎么去配,找了一堆的资料学习,然后对照wm9713.c中

的参数和别人的asound.conf,终于弄了一份上去,不过似乎不起说明作用,用alsa_aplay z.wav还是提示错误"Unable to install

hw params:",以下函数出错:

err = snd_pcm_hw_params(handle, params);

也就是说真正要和硬件交互的时候错了。。 终端里用logcat命令查看log信息,发现还是一直打印消息:

I/ServiceManager( 1185): Waiting for sevice media.audio_flinger...

I/ServiceManager( 1185): Waiting for sevice media.audio_flinger...

W/AudioSystem( 1185): AudioFlinger not published, waiting...

I/ServiceManager( 1185): Waiting for sevice media.audio_flinger...

I/ServiceManager( 1185): Waiting for sevice media.audio_flinger...

I/ServiceManager( 1185): Waiting for sevice media.audio_flinger...

I/ServiceManager( 1185): Waiting for sevice media.audio_flinger...

I/ServiceManager( 1185): Waiting for sevice media.audio_flinger...

W/AudioSystem( 1185): AudioFlinger not published, waiting...

I/ServiceManager( 1185): Waiting for sevice media.audio_flinger...

I/ServiceManager( 1185): Waiting for sevice media.audio_flinger...

这说明audio服务还是没有正常启动起来! 于是查android源代码,在frameworks/base/libs/audioflinger/AudioFlinger.cpp中,

void AudioFlinger::instantiate() {

LOGD("*******++AudioFlinger::instantiate()/n");

defaultServiceManager()->addService(

String16("media.audio_flinger"), new AudioFlinger());

LOGD("*******--AudioFlinger::instantiate()/n");

}

有调用此函数将自己添加到服务管理器,但是不知道什么原因,系统的服务管理器并没有

得到media.audio_flinger的管理权,所以就会出现上面的一直等待的情况。

跟进new AudioFlinger()

先创建一个audio硬件对象 mAudioHardware = AudioHardwareInterface::create();

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 DUMP_FLINGER_OUT

// 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 DUMP_FLINGER_OUT.

// The output file is FLINGER_DUMP_NAME. Pause are not recorded in the file.

hw = new AudioDumpInterface(hw); // replace interface

#endif

return hw;

}

这里hw = createAudioHardware();才是真正的初始化主体:

android::AudioHardwareInterface *createAudioHardware(void) {

return new android::AudioHardwareALSA();

}

也就是AudioHardwareInterface::create()返回的是实际的硬件初始化对象AudioHardwareALSA的指针。

接着跟进:

AudioHardwareALSA::AudioHardwareALSA() :

mOutput(0),

mInput(0),

mIPC(0) // sangsu fix : for IPC

{

snd_lib_error_set_handler(&ALSAErrorHandler);

mMixer = new ALSAMixer; //创建混合器对象

mIPC = new AudioHardwareIPC; // sangsu fix : IPC init

}

再看mIPC = new AudioHardwareIPC;

AudioHardwareIPC::AudioHardwareIPC() :

mClient(NULL)

{

LOGD("### %s", __func__);

int err = 0;

mClient = OpenClient_RILD();

if (mClient == NULL){

LOGE("[*] OpenClient_RILD() error/n");

err = 1;

}

if (RegisterRequestCompleteHandler(mClient, RIL_REQUEST_OEM_HOOK_RAW,

onRawReqComplete) != RIL_CLIENT_ERR_SUCCESS){

LOGE("[*] RegisterRequestCompleteHandler() error/n");

err = 1;

}

if (RegisterUnsolicitedHandler(mClient, 11004, onUnsol) !=

RIL_CLIENT_ERR_SUCCESS){

LOGE("[*] RegisterUnsolicitedHandler() error/n");

err = 1;

}

if (Connect_RILD(mClient) != RIL_CLIENT_ERR_SUCCESS){

LOGE("[*] Connect_RILD() error/n");

err = 1;

}

if (!err) LOGD("Success Initializing IPC");

else LOGE("Failed Initializing IPC");

}

在logcat里也确实有打印出这些出错信息,说明RIL服务没有运行。

再次回到AudioFlinger::AudioFlinger(),创建音频接口对象后,接着打开OutputStream

AudioStreamOut *hwOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);

实际调用函数:

AudioStreamOut *

AudioHardwareALSA::openOutputStream(int format,

int channelCount,

uint32_t sampleRate,

status_t *status)

{

AutoMutex lock(mLock);

LOGD("++AudioHardwareALSA::openOutputStream()/n");

// only one output stream allowed

if (mOutput) {

*status = ALREADY_EXISTS;

return 0;

}

AudioStreamOutALSA *out = new AudioStreamOutALSA(this);

*status = out->set(format, channelCount, sampleRate);

if (*status == NO_ERROR) {

mOutput = out;

// Some information is expected to be available immediately after

// the device is open.

uint32_t routes = mRoutes[mMode];

mOutput->setDevice(mMode, routes);

}

else {

delete out;

}

LOGD("--AudioHardwareALSA::openOutputStream()/n");

return mOutput;

}

进入new AudioStreamOutALSA(this)

AudioStreamOutALSA::AudioStreamOutALSA(AudioHardwareALSA *parent) :

mParent(parent),

mPowerLock(false)

{

static StreamDefaults _defaults = {

devicePrefix : "AndroidPlayback",

direction : SND_PCM_STREAM_PLAYBACK,

format : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT

channels : 2,

sampleRate : DEFAULT_SAMPLE_RATE,

latency : 250000, // Desired Delay in usec

// sangsu fix : optimizing output buffer size

bufferSize : 2048, // Desired Number of samples

};

setStreamDefaults(&_defaults);

}

这里就是设置的默认OutStream参数了。。 再看out->set(format, channelCount, sampleRate);

status_t set(int format = 0,

int channelCount = 0,

uint32_t sampleRate = 0) {

return ALSAStreamOps::set(format, channelCount, sampleRate);

}

status_t ALSAStreamOps::set(int format,

int channels,

uint32_t rate)

{

if (channels != 0)

mDefaults->channels = channels;

if (rate != 0)

mDefaults->sampleRate = rate;

switch(format) {

// format == 0

case AudioSystem::DEFAULT:

break;

case AudioSystem::PCM_16_BIT:

mDefaults->format = SND_PCM_FORMAT_S16_LE;

break;

case AudioSystem::PCM_8_BIT:

mDefaults->format = SND_PCM_FORMAT_S8;

break;

default:

LOGE("Unknown PCM format %i. Forcing default", format);

break;

}

return NO_ERROR;

}

也就是继续设置default参数。 然后调用mOutput->setDevice(mMode, routes);

status_t AudioStreamOutALSA::setDevice(int mode, uint32_t newDevice)

{

AutoMutex lock(mLock);

return ALSAStreamOps::setDevice(mode, newDevice);

}

status_t ALSAStreamOps::setDevice(int mode, uint32_t device)

{

// Close off previously opened device.

// It would be nice to determine if the underlying device actually

// changes, but we might be manipulating mixer settings (see asound.conf).

//

close();

const char *stream = streamName();

status_t status = open (mode, device);

int err;

if (status != NO_ERROR)

return status;

err = snd_pcm_hw_params_any(mHandle, mHardwareParams);

if (err < 0) {

LOGE("Unable to configure hardware: %s", snd_strerror(err));

return NO_INIT;

}

status = setPCMFormat(mDefaults->format);

// Set the interleaved read and write format.

err = snd_pcm_hw_params_set_access(mHandle, mHardwareParams,

SND_PCM_ACCESS_RW_INTERLEAVED);

if (err < 0) {

LOGE("Unable to configure PCM read/write format: %s",

snd_strerror(err));

return NO_INIT;

}

//

// Some devices do not have the default two channels. Force an error to

// prevent AudioMixer from crashing and taking the whole system down.

//

// Note that some devices will return an -EINVAL if the channel count

// is queried before it has been set. i.e. calling channelCount()

// before channelCount(channels) may return -EINVAL.

//

status = channelCount(mDefaults->channels);

if (status != NO_ERROR)

return status;

// Don't check for failure; some devices do not support the default

// sample rate.

sampleRate(mDefaults->sampleRate);

// Disable hardware resampling.

status = setHardwareResample(false);

if (status != NO_ERROR)

return status;

snd_pcm_uframes_t bufferSize = mDefaults->bufferSize;

unsigned int latency = mDefaults->latency;

// Make sure we have at least the size we originally wanted

err = snd_pcm_hw_params_set_buffer_size(mHandle, mHardwareParams, bufferSize);

if (err < 0) {

LOGE("Unable to set buffer size to %d: %s",

(int)bufferSize, snd_strerror(err));

return NO_INIT;

}

// Setup buffers for latency

err = snd_pcm_hw_params_set_buffer_time_near (mHandle, mHardwareParams,

&latency, NULL);

if (err < 0) {

/* That didn't work, set the period instead */

unsigned int periodTime = latency / 4;

err = snd_pcm_hw_params_set_period_time_near (mHandle, mHardwareParams,

&periodTime, NULL);

if (err < 0) {

LOGE("Unable to set the period time for latency: %s", snd_strerror(err));

return NO_INIT;

}

snd_pcm_uframes_t periodSize;

err = snd_pcm_hw_params_get_period_size (mHardwareParams, &periodSize, NULL);

if (err < 0) {

LOGE("Unable to get the period size for latency: %s", snd_strerror(err));

return NO_INIT;

}

bufferSize = periodSize * 4;

if (bufferSize < mDefaults->bufferSize)

bufferSize = mDefaults->bufferSize;

err = snd_pcm_hw_params_set_buffer_size_near (mHandle, mHardwareParams, &bufferSize);

if (err < 0) {

LOGE("Unable to set the buffer size for latency: %s", snd_strerror(err));

return NO_INIT;

}

} else {

// OK, we got buffer time near what we expect. See what that did for bufferSize.

err = snd_pcm_hw_params_get_buffer_size (mHardwareParams, &bufferSize);

if (err < 0) {

LOGE("Unable to get the buffer size for latency: %s", snd_strerror(err));

return NO_INIT;

}

// Does set_buffer_time_near change the passed value? It should.

err = snd_pcm_hw_params_get_buffer_time (mHardwareParams, &latency, NULL);

if (err < 0) {

LOGE("Unable to get the buffer time for latency: %s", snd_strerror(err));

return NO_INIT;

}

unsigned int periodTime = latency / 4;

err = snd_pcm_hw_params_set_period_time_near (mHandle, mHardwareParams,

&periodTime, NULL);

if (err < 0) {

LOGE("Unable to set the period time for latency: %s", snd_strerror(err));

return NO_INIT;

}

}

LOGD("Buffer size: %d", (int)bufferSize);

LOGD("Latency: %d", (int)latency);

mDefaults->bufferSize = bufferSize;

mDefaults->latency = latency;

// Commit the hardware parameters back to the device.

err = snd_pcm_hw_params(mHandle, mHardwareParams);

if (err < 0) {

LOGE("Unable to set hardware parameters: %s", snd_strerror(err));

return NO_INIT;

}

status = setSoftwareParams();

return status;

}

在调用了一系列设置参数的函数后,最后调用err = snd_pcm_hw_params(mHandle, mHardwareParams);

将参数写入到硬件。

完成这个过程后,接着创建 MixerThread ,AudioRecordThread ,至此media.audio_flinger服务初始化完毕。

在我们的MID上,wince6.0下有调试WM9714通过,可正常发声和录音。可android下使用alsa_aplay测试总是出现问题。

一气之下重新解压android包,编译,烧写ramdisk-uboot.img,system.img,userdata.img,偶然在android界面点开music player,找

到SD卡上的音乐,竟然能发出不连续的声音,欣喜若狂! 赶紧在kernel中关掉打印信息,再次进入播放,悠扬的声音出来了!

晕~~~ 竟然不用动什么东西! 也不需要配asound.conf,所需要注意的是测试在android界面里用music player播放就好,

alsa_aplay还是在这种场合不合适,因为android加载,占用了音频设备。每次烧写也应该带上ramdisk-uboot.img,这个很重要。

我的alsa_aplay版本:

# alsa_aplay --version

aplay: version 1.0.19 by Jaroslav Kysela <[email protected]>

更多相关文章

  1. android中Activity传递参数之onActivityResult
  2. 使用Kotlin开发Android 扩展函数(Extensions)
  3. Android2.3 中如何使用GPU硬件加速
  4. android调用高版本api函数的兼容性问题
  5. Android O system函数执行reboot命令失败
  6. Android下使用dlopen函数动态调用.so链接库 [转]
  7. java代码控制layout_Margin参数
  8. Android Log及其参数的使用

随机推荐

  1. 当我们按下电源键,Android 究竟做了些什么
  2. 改造 Android(安卓)官方架构组件 ViewMod
  3. ArcGIS for Android Runtime100 基本操作
  4. Android、js&html5的基础资料&书籍
  5. 刚进入Android终端即可使用busybox的命令
  6. pc 应用 通过 usb adb 与 android客户端
  7. 第1章 Android图像概述
  8. 我也分享一下我Android的收入数据
  9. Android 6.x 新的运行时权限
  10. Android 开发之关于 drawable 你必须知道