2011-09-21 21 views
2

語氣我有我需要顯示撥號盤,如屏幕的要求,我不得不產生1kHz的音(不DTMF音),只要在撥號盤上的按鈕用戶按下。未初始化AudioTrack例外,當我嘗試生成的第22次

我用的代碼從下面的鏈接,產生1 kHz音調:

Playing an arbitrary tone with Android

當我開始我的撥號盤屏幕上的撥號按鈕,直到21按下它成功地產生基調,但後22日嘗試我我得到了應用程序不響應(ANR)錯誤,我需要關閉應用程序。

下面是我的代碼:

final float duration = 0.3f; // seconds 
final int sampleRate = 4000; 
final int numSamples = (int)duration * sampleRate + 100; 
final double sample[] = new double[numSamples]; 
final double freqOfTone = 1000; // hz 
final byte generatedSnd[] = new byte[2 * numSamples]; 

final Handler handler = new Handler(); 


     public void onClick(View v) { 
    // TODO Auto-generated method stub 

    int id = v.getId(); 

    playSound(); 
    } 


    private void playSound() 
{ 

    final Thread thread = new Thread(new Runnable() { 
     public void run() { 
      genTone(); 
      handler.post(new Runnable() { 

       public void run() { 
        playSound1(); 
       } 
      }); 
     } 
    }); 
    thread.start(); 


} 

void playSound1(){ 
    final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 
      sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
      AudioFormat.ENCODING_PCM_16BIT, numSamples, 
      AudioTrack.MODE_STATIC); 
     audioTrack.write(generatedSnd, 0, generatedSnd.length); 


     audioTrack.play(); 
} 

void genTone(){ 
    // fill out the array 
    for (int i = 0; i < numSamples; ++i) { 
     sample[i] = Math.sin(2 * Math.PI * i/(sampleRate/freqOfTone)); 
    } 

    // convert to 16 bit pcm sound array 
    // assumes the sample buffer is normalised. 
    int idx = 0; 
    for (final double dVal : sample) { 
     // scale to maximum amplitude 
     final short val = (short) ((dVal * 32767)); 
     // in 16 bit wav PCM, first byte is the low order byte 
     generatedSnd[idx++] = (byte) (val & 0x00ff); 
     generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8); 

    } 
} 

的onClick()方法,將每次當我按撥號盤上的按鈕時調用。

與上面的代碼我在logcat的收到這個輸出:即我正在值後

05.500 E/AudioFlinger( 85): no more track names available 

09-21 05:20:05.500 E/AudioTrack( 133): AudioFlinger could not create track, status: -12 

09-21 05:20:05.503 E/SoundPool( 133): Error creating AudioTrack 

09-21 05:20:05.535 E/AudioFlinger( 85): no more track names available 

09-21 05:20:05.535 E/AudioTrack(6080): AudioFlinger could not create track, status: -12 

09-21 05:20:05.535 E/AudioTrack-JNI(6080): Error initializing AudioTrack 

09-21 05:20:05.535 E/AudioTrack-Java(6080): [ android.media.AudioTrack ] Error code -20 when initializing AudioTrack. 

09-21 05:20:05.535 D/AndroidRuntime(6080): Shutting down VM 

09-21 05:20:05.535 W/dalvikvm(6080): threadid=1: thread exiting with uncaught exception (group=0x40015578) 

09-21 05:20:05.539 E/AndroidRuntime(6080): FATAL EXCEPTION: main 

09-21 05:20:05.539 E/AndroidRuntime(6080): java.lang.IllegalStateException: play() called on uninitialized AudioTrack. 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at android.media.AudioTrack.play(AudioTrack.java:824) 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at com.android.dial.DialPadScreen.playSound1(DialPadScreen.java:274) 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at com.android.dial.DialPadScreen$1$1.run(DialPadScreen.java:248) 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at android.os.Handler.handleCallback(Handler.java:587) 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at android.os.Handler.dispatchMessage(Handler.java:92) 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at android.os.Looper.loop(Looper.java:123) 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at android.app.ActivityThread.main(ActivityThread.java:3687) 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at java.lang.reflect.Method.invokeNative(Native Method) 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at java.lang.reflect.Method.invoke(Method.java:507) 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842) 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600) 

09-21 05:20:05.539 E/AndroidRuntime(6080):  at dalvik.system.NativeStart.main(Native Method) 

09-21 05:20:05.542 E/  ( 133): Dumpstate > /data/log/dumpstate_app_error 

09-21 05:20:05.542 W/ActivityManager( 133): Force finishing activity com.android.dial/.DialPadScreen 

我打印「audioTrack」直到21時我正在值1(STATE_INITIALIZED)的狀態'0'(STATE_UNINITIALIZED)。不知道爲什麼國家正在發生變化。

請幫我什麼是我需要做的防止這種力的確定關閉問題在我的應用程序的變化。 或請建議是否有其他方法來做到這一點。

回答

2

你可以在你的應用程序的創建onCreate單一AudioTrack,然後調用audioTrack.play()上的應用開始,然後只將數據寫入到其上的按鈕按下。

而且,在我和AudioTrack的經驗,如果我嘗試同時播放多個AudioTrack,它創建了一個非常糟糕的,波濤洶涌聲有滯後性。

你可以考慮預錄製的聲音和使用Sound Pool,因爲這是能夠同時播放多個聲音。

或者,由於API 9級,你可以在會話ID分配給AudioTrack,這應該允許您使用的Soundpool播放音軌,如果我理解正確的話,然後你會非常想創建靜態AudioTracks

1

變化AudioTrack.MODE_STATIC到AudioTrack.MODE_STREAM。應該這樣做:)

1

我也有類似的問題,我加入這個權限清單文件解決了這個問題:

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> 
4

關於21個成功生成樂音數和明年失敗,我想你必須釋放以前創建的實例,調用audioTrack.release()方法。

爲了避免IllegalStateException
創建的AudioTrack你要測試是否良好初始化實例後。
使用MODE_STATIC模式,如果它沒有正確初始化,狀態將爲:STATE_UNINITIALIZED, 而不是正確初始化:STATE_NO_STATIC_DATA,當您調用寫入方法時,狀態將更改爲STATE_INITIALIZED
使用MODE_STREAM模式,如果它沒有正確初始化,則狀態將爲:STATE_UNINITIALIZED, 而不是正確初始化:STATE_INITIALIZED
閱讀AudioTrack的來源我看到了。我認爲這很奇怪,因爲構造函數返回的對象不可用,因爲在構造之後不可能初始化。

相關問題