Android ToneGenerator startTone() 第一次调用时非常慢
Android ToneGenerator startTone() very slow on the first call
我正在反复呼叫 ToneGenerator.startTone()
以发出短促的声音。但是在第一次调用时,它会阻塞很长时间。所以第一次爆发太长了。这是一个例子:
成员变量:
private ToneGenerator mDTMFPlayer
在构造函数中:
mDTMFPlayer = new ToneGenerator(AudioManager.STREAM_VOICE_CALL, TONE_RELATIVE_VOLUME);
在由 OnClickListener.onClick()
发起的 Thread
中:
long startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 1st: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 2nd: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 3rd: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();
这是输出,执行时间为 startTone()
毫秒:
11-16 18:07:35.885 16927-17977/com.my.project D/Ring: After 1st: 454
11-16 18:07:36.502 16927-17977/com.my.project D/Ring: After 2nd: 0
11-16 18:07:36.672 16927-17977/com.my.project D/Ring: After 3rd: 1
第一个调用阻塞了将近半秒,这对我需要的来说太长了。此后的任何调用都会使阻塞消失一段时间。奇怪的是,如果我稍等一下再试,它又变慢了。似乎有一段时间后阻塞又回来了。
请指教
我认为是 AudioManager.STREAM_VOICE_CALL
造成的。我设计的行为与您的相似。在我 运行 应用程序之后,它对第一个 startTone()
调用进行了长时间的初始化。如果我退出并进入应用程序,所有 3 个调用都可以很快。但如果在应用程序启动之前播放某些系统声音,它会显示相同的 "slow, fast, fast" 结果。
所以我想它与流 switching/blocking 有关,因为 AudioManager.STREAM_NOTIFICATION
在我的设备上只需要 4-10 毫秒。也可以在这里阅读更多信息:What is the difference between AudioManager's stream types at low level?
考虑这段代码:
for (int i = -1; i < 10; i++) {
System.out.println("AudioSystem stream " + i);
mDTMFPlayer = new ToneGenerator(i, TONE_RELATIVE_VOLUME);
long startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG, "After 1st: " + (System.currentTimeMillis() - startTime));
try {Thread.sleep(160);} catch (InterruptedException e) {}
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG, "After 2nd: " + (System.currentTimeMillis() - startTime));
try {Thread.sleep(160);} catch (InterruptedException e) {}
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG, "After 3rd: " + (System.currentTimeMillis() - startTime));
try {Thread.sleep(160);} catch (InterruptedException e) {}
mDTMFPlayer.stopTone();
mDTMFPlayer.release();
}
输出:
I/System.out: AudioSystem stream -1 STREAM_DEFAULT
D/com.example.MainActivity: After 1st: 8
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 0 STREAM_VOICE_CALL
D/com.example.MainActivity: After 1st: 325
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 1 STREAM_SYSTEM
D/com.example.MainActivity: After 1st: 17
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 3
I/System.out: AudioSystem stream 2 STREAM_RING
D/com.example.MainActivity: After 1st: 28
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 3 STREAM_MUSIC
D/com.example.MainActivity: After 1st: 19
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 4 STREAM_ALARM
D/com.example.MainActivity: After 1st: 28
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 5 STREAM_NOTIFICATION
D/com.example.MainActivity: After 1st: 16
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 6 STREAM_BLUETOOTH_SCO
D/com.example.MainActivity: After 1st: 332
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 7 STREAM_SYSTEM_ENFORCED
D/com.example.MainActivity: After 1st: 324
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 8 STREAM_DTMF
D/com.example.MainActivity: After 1st: 26
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 4
I/System.out: AudioSystem stream 9 STREAM_TTS
D/com.example.MainActivity: After 1st: 12
D/com.example.MainActivity: After 2nd: 4
D/com.example.MainActivity: After 3rd: 2
顺便说一句,如果你想研究相关的C源代码,你可以看看android_media_ToneGenerator.cpp, ToneGenerator.h, ToneGenerator.cpp AudioService.java
我正在反复呼叫 ToneGenerator.startTone()
以发出短促的声音。但是在第一次调用时,它会阻塞很长时间。所以第一次爆发太长了。这是一个例子:
成员变量:
private ToneGenerator mDTMFPlayer
在构造函数中:
mDTMFPlayer = new ToneGenerator(AudioManager.STREAM_VOICE_CALL, TONE_RELATIVE_VOLUME);
在由 OnClickListener.onClick()
发起的 Thread
中:
long startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 1st: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 2nd: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 3rd: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();
这是输出,执行时间为 startTone()
毫秒:
11-16 18:07:35.885 16927-17977/com.my.project D/Ring: After 1st: 454
11-16 18:07:36.502 16927-17977/com.my.project D/Ring: After 2nd: 0
11-16 18:07:36.672 16927-17977/com.my.project D/Ring: After 3rd: 1
第一个调用阻塞了将近半秒,这对我需要的来说太长了。此后的任何调用都会使阻塞消失一段时间。奇怪的是,如果我稍等一下再试,它又变慢了。似乎有一段时间后阻塞又回来了。
请指教
我认为是 AudioManager.STREAM_VOICE_CALL
造成的。我设计的行为与您的相似。在我 运行 应用程序之后,它对第一个 startTone()
调用进行了长时间的初始化。如果我退出并进入应用程序,所有 3 个调用都可以很快。但如果在应用程序启动之前播放某些系统声音,它会显示相同的 "slow, fast, fast" 结果。
所以我想它与流 switching/blocking 有关,因为 AudioManager.STREAM_NOTIFICATION
在我的设备上只需要 4-10 毫秒。也可以在这里阅读更多信息:What is the difference between AudioManager's stream types at low level?
考虑这段代码:
for (int i = -1; i < 10; i++) {
System.out.println("AudioSystem stream " + i);
mDTMFPlayer = new ToneGenerator(i, TONE_RELATIVE_VOLUME);
long startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG, "After 1st: " + (System.currentTimeMillis() - startTime));
try {Thread.sleep(160);} catch (InterruptedException e) {}
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG, "After 2nd: " + (System.currentTimeMillis() - startTime));
try {Thread.sleep(160);} catch (InterruptedException e) {}
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG, "After 3rd: " + (System.currentTimeMillis() - startTime));
try {Thread.sleep(160);} catch (InterruptedException e) {}
mDTMFPlayer.stopTone();
mDTMFPlayer.release();
}
输出:
I/System.out: AudioSystem stream -1 STREAM_DEFAULT
D/com.example.MainActivity: After 1st: 8
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 0 STREAM_VOICE_CALL
D/com.example.MainActivity: After 1st: 325
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 1 STREAM_SYSTEM
D/com.example.MainActivity: After 1st: 17
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 3
I/System.out: AudioSystem stream 2 STREAM_RING
D/com.example.MainActivity: After 1st: 28
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 3 STREAM_MUSIC
D/com.example.MainActivity: After 1st: 19
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 4 STREAM_ALARM
D/com.example.MainActivity: After 1st: 28
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 5 STREAM_NOTIFICATION
D/com.example.MainActivity: After 1st: 16
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 6 STREAM_BLUETOOTH_SCO
D/com.example.MainActivity: After 1st: 332
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 7 STREAM_SYSTEM_ENFORCED
D/com.example.MainActivity: After 1st: 324
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 8 STREAM_DTMF
D/com.example.MainActivity: After 1st: 26
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 4
I/System.out: AudioSystem stream 9 STREAM_TTS
D/com.example.MainActivity: After 1st: 12
D/com.example.MainActivity: After 2nd: 4
D/com.example.MainActivity: After 3rd: 2
顺便说一句,如果你想研究相关的C源代码,你可以看看android_media_ToneGenerator.cpp, ToneGenerator.h, ToneGenerator.cpp AudioService.java