經(jīng)常要搞音頻調(diào)試偎窘,很麻煩蔫巩,現(xiàn)在記錄下鸣驱。
常用數(shù)據(jù)結(jié)構(gòu)
/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;
定義了輸出設(shè)備id,例如0x4對應(yīng)設(shè)備就是有線耳機
/* 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.常用調(diào)試方法
1.查看音量的log
關(guān)鍵tag是AudioMTKGainController
插入耳機圈暗,調(diào)小音量粥鞋,出現(xiàn)下面log
01-01 00:29:51.752251 499 906 D AudioMTKGainController: setNormalVolume(), stream 8, devices 0x8, index 8, mode 0x0
上面的log就是把設(shè)備耳機的stream 8(DTMF聲)的音量設(shè)置為8缘挽。
拔出耳機,調(diào)小音量呻粹,出現(xiàn)下面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就是把設(shè)備揚聲器的stream 1(系統(tǒng)聲)的音量設(shè)置為13壕曼。這里的13只是上層表示的一個音量index,要轉(zhuǎn)換成底層的gain等浊,例如index=13時腮郊,gain就是10.
下面是設(shè)置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); //獲取要設(shè)置增益的設(shè)備,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轉(zhuǎn)換成底層的gain增益
setSpeakerGain(gain); //設(shè)置speaker的增益
}
}
2.查看設(shè)置Parameter的log
在音頻控制中筹燕,常常有一種比較粗暴的設(shè)置方法轧飞,就是直接設(shè)置參數(shù)Parameter,這個可以在java層直接設(shè)置撒踪,然后在hal層進行處理过咬。例如在fm中,在java層設(shè)置參數(shù)
/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.了解路由規(guī)則
下面的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和目標(biāo)sink忍捡。例如FM就是源集漾,耳機就是目標(biāo)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是點擊撥號盤,發(fā)出聲音打出來的凌埂。0xf2f36700是AudioTrack對象的ID驱显。streamType 是按鍵音。
6.關(guān)于SessionId
抄自網(wǎng)上:
一個Session就是一個會話。每個會話都有一個獨一無二的Id來標(biāo)識埃疫。該Id的最終管理在AudioFlinger中伏恐。
一個會話可以被多個AudioTrack對象和MediaPlayer共用。
共用一個Session的AudioTrack和MediaPlayer共享相同的AudioEffect栓霜。