2

画面のようなダイヤル パッドを表示する必要があり、ユーザーがダイヤル パッドのボタンを押すたびに 1khz トーン (DTMF トーンではなく) を生成する必要があります。

以下のリンクのコードを使用して、1 khz トーンを生成しました。

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) を取得しています。状態が変化する理由がわかりません。

アプリでこのフロスクローズの問題を防ぐために必要な変更を教えてください。またはこれを行うための代替手段があるかどうか提案してください。

4

4 に答える 4

4

トーンの生成に成功し、次に失敗する 21 の数については、以前に作成したインスタンス呼び出しメソッドを解放する必要があると思いますaudioTrack.release()

を回避するにはIllegalStateException:
のインスタンスを作成した後、AudioTrack適切に初期化されているかどうかをテストする必要があります。
モードを使用MODE_STATICして、正しく初期化されていない場合、状態は次のようになります。STATE_UNINITIALIZED代わりに、正しく初期化されている場合: 。STATE_NO_STATIC_DATA書き込みメソッドを呼び出すと、状態は に変更されSTATE_INITIALIZEDます。
モードを使用MODE_STREAMして、正しく初期化されていない場合、状態は次のようになります:STATE_UNINITIALIZED代わりに、正しく初期化された場合: STATE_INITIALIZED.
ソースの読み取りAudioTrack私はそれを見ました。コンストラクターから返されたオブジェクトは、構築後に初期化できないため使用できないため、これは非常に奇妙だと思います。

于 2014-01-13T14:34:00.413 に答える
3

アプリの で1 つのシングルAudioTrackを作成し、アプリの開始時にonCreate呼び出しaudioTrack.play()、ボタンを押してデータを書き込むことができます。

また、 での私の経験ではAudioTrack、複数の AudioTrack を同時に再生しようとすると、非常に悪い途切れ途切れのサウンドが作成され、遅延が発生します。

複数のサウンドを同時に再生できるため、事前にサウンドを録音し、Sound Poolを使用することを検討できます。

または、API レベル 9 以降、セッション ID をAudioTrackに割り当てることができます。これにより、私が正しく理解している場合、SoundPool でオーディオ トラックを再生できるようになり、理想的には STATIC AudioTracks を作成する必要があります。

于 2011-09-25T20:58:31.477 に答える
1

同様の問題が発生し、マニフェストファイルに次のアクセス許可を追加することで解決しました。

    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
于 2012-10-15T08:59:39.030 に答える
1

AudioTrack.MODE_STATIC を AudioTrack.MODE_STREAM に変更します。それはそれを行う必要があります:)

于 2011-09-30T17:54:12.780 に答える