背景知识
- 对于音乐类型的音频资源,可以通过MediaPlayer来播放;
- 对于音调,可以通过ToneGenerator来播放;
- 对于提示音,可以通过Ringtone来播放;
- 对于游戏中的音频资源,可以通过SoundPool来播放。
ToneGenerator提供了对DTMF音(ITU-T Q.23),以及呼叫监督音(3GPP TS 22.001)、专用音(3GPP TS 31.111)中规定的音频的支持,根据呼叫状态和漫游状态,该文件产生的音频路径为下行音频或者传输给扬声器或耳机。需要说明的是,DTMF音为WAV格式,相关的音频类型定义位于ToneGenerator.h文件中
代码分析
1. java上层调用,每次new都会重新创建一个AudioTrack
ToneGenerator.java (frameworks\base\media\java\android\media)
android_media_ToneGenerator.cpp (frameworks\base\core\jni)
比如:
mToneGenerator = new ToneGenerator(AudioManager.STREAM_DTMF, 80);
2. ToneGenerator.cpp (frameworks\av\media\libaudioclient)
//每个按键音的定义,主要是频率,因为这是自动生成的PCM数据
const ToneGenerator::ToneDescriptor ToneGenerator::sToneDescriptors[] = {
{ .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1336, 941, 0 }, 0, 0},
{ .duration = 0 , .waveFreq = { 0 }, 0, 0}},
.repeatCnt = ToneGenerator::TONEGEN_INF,
.repeatSegment = 0 }, // TONE_DTMF_0
...
}
ToneGenerator::ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava) {
//获取对应audio流的采样率
if (AudioSystem::getOutputSamplingRate(&mSamplingRate, streamType) != NO_ERROR) {
// Generate tone by chunks of 20 ms to keep cadencing precision
mProcessSize = (mSamplingRate * 20) / 1000;
if (initAudioTrack()) {
}
bool ToneGenerator::initAudioTrack() { //初始化播放tone的audiotrack
// Open audio track in mono, PCM 16bit, default sampling rate.
mpAudioTrack = new AudioTrack();
attr = AudioSystem::streamTypeToAttributes(streamType); //streamType = STREAM_DTMF
status_t status = mpAudioTrack->set(
AUDIO_STREAM_DEFAULT,
0, // sampleRate
AUDIO_FORMAT_PCM_16_BIT,