美文网首页安卓Rom
Android杂谈:音频调试小计

Android杂谈:音频调试小计

作者: 我在等你回复可你没回 | 来源:发表于2017-04-24 16:27 被阅读0次

经常要搞音频调试,很麻烦,现在记录下。

常用数据结构

/system/media/audio/include/system/audio.h
定义了常用的stream类型,例如3就是音乐的stream。

/* Audio stream types */
typedef enum {
    /* These values must kept in sync with
     * frameworks/base/media/java/android/media/AudioSystem.java
     */
    AUDIO_STREAM_DEFAULT          = -1,
    AUDIO_STREAM_MIN              = 0,
    AUDIO_STREAM_VOICE_CALL       = 0,
    AUDIO_STREAM_SYSTEM           = 1,
    AUDIO_STREAM_RING             = 2,
    AUDIO_STREAM_MUSIC            = 3,
    AUDIO_STREAM_ALARM            = 4,
    AUDIO_STREAM_NOTIFICATION     = 5,
    AUDIO_STREAM_BLUETOOTH_SCO    = 6,
    AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user
                                        * and must be routed to speaker
                                        */
    AUDIO_STREAM_DTMF             = 8,
    AUDIO_STREAM_TTS              = 9,  /* Transmitted Through Speaker.
                                         * Plays over speaker only, silent on other devices.
                                         */
    AUDIO_STREAM_ACCESSIBILITY    = 10, /* For accessibility talk back prompts */
    AUDIO_STREAM_REROUTING        = 11, /* For dynamic policy output mixes */
    AUDIO_STREAM_PATCH            = 12, /* For internal audio flinger tracks. Fixed volume */
    AUDIO_STREAM_PUBLIC_CNT       = AUDIO_STREAM_TTS + 1,
    AUDIO_STREAM_CNT              = AUDIO_STREAM_PATCH + 1,
} audio_stream_type_t;

定义了输出设备id,例如0x4对应设备就是有线耳机

    /* output devices */
    AUDIO_DEVICE_OUT_EARPIECE                  = 0x1,
    AUDIO_DEVICE_OUT_SPEAKER                   = 0x2,
    AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4,
    AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8,

2.常用调试方法

1.查看音量的log

关键tag是AudioMTKGainController
插入耳机,调小音量,出现下面log

01-01 00:29:51.752251   499   906 D AudioMTKGainController: setNormalVolume(), stream 8, devices 0x8, index 8, mode 0x0

上面的log就是把设备耳机的stream 8(DTMF声)的音量设置为8。

拔出耳机,调小音量,出现下面log

AudioMTKGainController: setNormalVolume(), stream 1, devices 0x2, index 13, mode 0x0
AudioMTKGainController: getGainDevice(), input devices = 0x2, return gainDevice = 2
AudioMTKGainController: setSpeakerGain(), gain = 10, spkAnaType = 2, spkLMixerName = Audio_Speaker_PGA_gain, spkRMixerName = Audio_Speaker_PGA_gain

上面的log就是把设备扬声器的stream 1(系统声)的音量设置为13。这里的13只是上层表示的一个音量index,要转换成底层的gain,例如index=13时,gain就是10.
下面是设置speaker音量的流程

status_t AudioMTKGainController::setNormalVolume(int stream, int index, int devices, audio_mode_t mode)
{
    ALOGD("setNormalVolume(), stream %d, devices 0x%x, index %d, mode 0x%x", stream, devices, index, mode);
    // get gain device
    GAIN_DEVICE gainDevice = getGainDevice(devices); //获取要设置增益的设备,2是speaker
    if (isSpeakerCategory(gainDevice))
    {
        if (mSpec.spkAnaType >= 0 && mSpec.spkAnaType < NUM_GAIN_ANA_TYPE)
        {
            unsigned char gain = mGainTable.streamGain[stream][gainDevice][index].analog[mSpec.spkAnaType];   //把index转换成底层的gain增益
            setSpeakerGain(gain);         //设置speaker的增益
        }
    }

2.查看设置Parameter的log

在音频控制中,常常有一种比较粗暴的设置方法,就是直接设置参数Parameter,这个可以在java层直接设置,然后在hal层进行处理。例如在fm中,在java层设置参数
/packages/apps/FMRadio/src/com/android/fmradio/FmService.java

mAudioManager.setParameters("AudioFmPreStop=1");

在AudioSystem中进行处理
/frameworks/av/media/libmedia/AudioSystem.cpp

status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
{
    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    if (af == 0) return PERMISSION_DENIED;
    return af->setParameters(ioHandle, keyValuePairs);
}

String8 AudioSystem::getParameters(audio_io_handle_t ioHandle, const String8& keys)
{
    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    String8 result = String8("");
    if (af == 0) return result;

    result = af->getParameters(ioHandle, keys);
    return result;
}

上面是原生的代码,是在AudioFlinger中处理,而在mtk中,往往是有AudioPolicy处理

 aps->SetPolicyManagerParameters (POLICY_SET_FM_PRESTOP,value,0,0);

3.了解路由规则

下面的log表示路由到耳机

01-03 06:44:36.621514   570  1265 D AudioALSAStreamOut: +setParameters(): routing=8

定义是在
http://androidxref.com/6.0.0_r1/xref/frameworks/base/media/java/android/media/AudioSystem.java#122

    /* Routing bits for the former setRouting/getRouting API */
    /** @deprecated */
    @Deprecated public static final int ROUTE_EARPIECE          = (1 << 0);
    /** @deprecated */
    @Deprecated public static final int ROUTE_SPEAKER           = (1 << 1);
    /** @deprecated use {@link #ROUTE_BLUETOOTH_SCO} */
    @Deprecated public static final int ROUTE_BLUETOOTH = (1 << 2);
    /** @deprecated */
    @Deprecated public static final int ROUTE_BLUETOOTH_SCO     = (1 << 2);
    /** @deprecated */
    @Deprecated public static final int ROUTE_HEADSET           = (1 << 3);
    /** @deprecated */
    @Deprecated public static final int ROUTE_BLUETOOTH_A2DP    = (1 << 4);
    /** @deprecated */
    @Deprecated public static final int ROUTE_ALL               = 0xFFFFFFFF;

3.了解Audio Patch

Audio Patch是一个通路,包含源source和目标sink。例如FM就是源,耳机就是目标sink。

4.了解Audio Mode

Audio的模式,例如正常模式,通话模式等
/frameworks/base/media/java/android/media/AudioSystem.java

    /* modes for setPhoneState, must match AudioSystem.h audio_mode */
    public static final int MODE_INVALID            = -2;
    public static final int MODE_CURRENT            = -1;
    public static final int MODE_NORMAL             = 0;
    public static final int MODE_RINGTONE           = 1;
    public static final int MODE_IN_CALL            = 2;
    public static final int MODE_IN_COMMUNICATION   = 3;
    public static final int NUM_MODES               = 4;

5.了解Audio Trace

看看下面的log

01-03 08:26:37.051925  5353  5353 V ToneGenerator: AudioTrack(0xf2f36700) created
01-03 08:26:37.051999  5353  5353 D AudioTrack: set(): 0xf2f36700, streamType 8, sampleRate 44100, format 0x1, channelMask 0x1, frameCount 882, flags #4, notificationFrames 0, sessionId 0, transferType 1, uid -1, pid -1

上面的log是点击拨号盘,发出声音打出来的。0xf2f36700是AudioTrack对象的ID。streamType 是按键音。

6.关于SessionId

抄自网上:
一个Session就是一个会话。每个会话都有一个独一无二的Id来标识。该Id的最终管理在AudioFlinger中。
一个会话可以被多个AudioTrack对象和MediaPlayer共用。
共用一个Session的AudioTrack和MediaPlayer共享相同的AudioEffect。

相关文章

网友评论

    本文标题:Android杂谈:音频调试小计

    本文链接:https://www.haomeiwen.com/subject/ahdpzttx.html