播放生成Android4.0.3中的提示音
題記:寫這篇博客要主是加深自己對(duì)播放生成的認(rèn)識(shí)和總結(jié)實(shí)現(xiàn)算法時(shí)的一些驗(yàn)經(jīng)和訓(xùn)教,如果有錯(cuò)誤請(qǐng)指出,萬(wàn)分感謝。
????
一、ToneGenerator的應(yīng)用
????參照com.android.contacts.dialpad.DialpadFragment
????ToneGenerator只能播放在ToneGenerator中定義好的TONE_TYPE。
????
1、常量申明
/** Tone音的長(zhǎng)度,單位:milliseconds */ private static final int TONE_LENGTH_MS = 150; /** 主音量的比例:以80%的主音量播放Tone音 */ private static final int TONE_RELATIVE_VOLUME = 80; /** 主音量的音頻種別 */ private static final int DIAL_TONE_STREAM_TYPE =AudioManager.STREAM_MUSIC;????
2、變量申明
// Tone音播放器 private ToneGenerator mToneGenerator; // Tone相干的同步鎖 private Object mToneGeneratorLock = new Object(); // 設(shè)定中的Tone音播放設(shè)置 private boolean mDTMFToneEnabled;????
3、Tone的初始化
public void onResume() {super.onResume();// 讀取設(shè)定的值mDTMFToneEnabled =Settings.System.getInt(getActivity().getContentResolver(),Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;// 失敗了也無(wú)所謂,不是啥重要的貨色synchronized (mToneGeneratorLock) {if (mToneGenerator == null) {try {// we want the user to be ableto control the volume of the dial tones// outside of a call, so we usethe stream type that is also mapped to the// volume control keys for thisactivitymToneGenerator = newToneGenerator(DIAL_TONE_STREAM_TYPE, TONE_RELATIVE_VOLUME);getActivity().setVolumeControlStream(DIAL_TONE_STREAM_TYPE);} catch (RuntimeException e) {Log.w(TAG, "Exceptioncaught while creating local tone generator: " + e);mToneGenerator = null;}}} }????
4、釋放Tone資源
public voidonPause() {super.onPause();synchronized (mToneGeneratorLock) {if (mToneGenerator != null) {mToneGenerator.release();mToneGenerator = null;}} }????
5、播放Tone音
每日一道理那蝴蝶花依然花開花落,而我心中的蝴蝶早已化作雄鷹飛向了廣闊的藍(lán)天。
/*** 播放TONE_LENGTH_MS milliseconds的Tone音.* 只有在設(shè)定中選擇了播放Tone,并且不是靜音模式才會(huì)播放Tone音。* @param tone a tone code from {@linkToneGenerator}*/ void playTone(int tone) {// 設(shè)定中沒(méi)有選中的話,就不播if (!mDTMFToneEnabled) {return;}// 靜音模式的時(shí)候也不播,需要每次都檢查,因?yàn)闆](méi)有Activity切換也能設(shè)成靜音模式// 設(shè)定中的那個(gè)就不需要,因?yàn)橐O(shè)定必須要先切入設(shè)定Activity才行AudioManager audioManager =(AudioManager)getActivity().getSystemService(Context.AUDIO_SERVICE);int ringerMode =audioManager.getRingerMode();if ((ringerMode == AudioManager.RINGER_MODE_SILENT)|| (ringerMode ==AudioManager.RINGER_MODE_VIBRATE)) {return;}synchronized (mToneGeneratorLock) {if (mToneGenerator == null) {Log.w(TAG, "playTone:mToneGenerator == null, tone: " + tone);return;}// Start the new tone (will stop anyplaying tone)mToneGenerator.startTone(tone,TONE_LENGTH_MS);} }
????
????
?二、ToneGenerator的實(shí)現(xiàn)
????相干代碼位置:
????ToneGenerator.java:ICS/frameworks/base/media/java/
????Android_media_ToneGenerator.cpp:ICS/frameworks/base/core/jni/
????ToneGenerator.cpp:ICS/frameworks/base/media/libmedia/
????
1、ToneGenerator.java
????定義了多種ToneType,供給了java的接口
????
2、Android_media_ToneGenerator.cpp
????將Java層的請(qǐng)求轉(zhuǎn)發(fā)給Native層。
????android_media_ToneGenerator_native_setup中的有句話看不懂:
ToneGenerator *lpToneGen= new ToneGenerator(streamType,????
????AudioSystem::linearToLog(volume)
????
????,true); // change this value tochange volume scaling static const float dBPerStep= 0.5f; // shouldn't need totouch these static const floatdBConvert = -dBPerStep * 2.302585093f / 20.0f; static const floatdBConvertInverse = 1.0f / dBConvert; floatAudioSystem::linearToLog(int volume) { // float v = volume ? exp(float(100 -volume) * dBConvert) : 0; // LOGD("linearToLog(%d)=%f",volume, v); // return v; return volume ? exp(float(100 - volume) *dBConvert) : 0; }
????算出來(lái)的值會(huì)直接設(shè)到AudioTrack中,可是AudioTrack中的音量應(yīng)該是個(gè)0~1.0f的百分比才對(duì),為啥需要這么個(gè)公式呢,難道是Bug。應(yīng)該測(cè)試一下!!
????
3、ToneGenerator.cpp
????根據(jù)定義的Tone因的頻率,長(zhǎng)度等信息生成音頻數(shù)據(jù),最后交給AudioTrack播放。
????
三、AudioPolicyService中的mTonePlaybackThread
? 本來(lái)認(rèn)為這個(gè)線程是專門處置Tone音設(shè)備的,可是根據(jù)下面一看本來(lái)是直接走AudioTrack的。這就奇怪了,并且AudioSystem中也沒(méi)有供給對(duì)應(yīng)的接口,這就更奇怪了,難道它沒(méi)預(yù)備讓表面的人用。再一檢索,發(fā)現(xiàn)本來(lái)它是供給給AudioPolicyManagerBase應(yīng)用的一個(gè)非同期播放Tone音的接口。
? 經(jīng)過(guò)AudioCommandThread的處置,最終還是交給ToneGenerator來(lái)處置。
????
四、RingtoneManager與Ringtone
????播放鈴聲的類,沒(méi)具體看,最后是通過(guò)MediaPlayer來(lái)播放的。
????
五、論斷
????本來(lái)還認(rèn)為會(huì)有個(gè)獨(dú)自硬件來(lái)處置Tone音的,最后發(fā)現(xiàn)竟然是自動(dòng)生成后,通過(guò)AudioTrack來(lái)處置的。
????據(jù)說(shuō)是因?yàn)橛布傻腡one音很難聽(tīng),所以才用軟件來(lái)生成的。
文章結(jié)束給大家分享下程序員的一些笑話語(yǔ)錄: 程序員打油詩(shī)
寫字樓里寫字間,寫字間里程序員;
程序人員寫程序,又拿程序換酒錢。
酒醒只在網(wǎng)上坐,酒醉還來(lái)網(wǎng)下眠;
酒醉酒醒日復(fù)日,網(wǎng)上網(wǎng)下年復(fù)年。
但愿老死電腦間,不愿鞠躬老板前;
奔馳寶馬貴者趣,公交自行程序員。
別人笑我忒瘋癲,我笑自己命太賤;
不見(jiàn)滿街漂亮妹,哪個(gè)歸得程序員。
轉(zhuǎn)載于:https://www.cnblogs.com/jiangu66/archive/2013/05/20/3089275.html
總結(jié)
以上是生活随笔為你收集整理的播放生成Android4.0.3中的提示音的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 订阅广告一个微博大号的微信生存记
- 下一篇: Android 编程下帧动画在 Acti