0

マイクで取得した音声サンプルをスピーカーに渡そうとしていますこれは、ここで取得した提案を
使用して、使用しているコードです

public class MainActivity extends Activity {
    AudioManager am = null;
    AudioRecord record =null;
    AudioTrack track =null;
    final int SAMPLE_FREQUENCY = 44100;
    final int SIZE_OF_RECORD_ARRAY = 1024;  // 1024 ORIGINAL
    final int WAV_SAMPLE_MULTIPLICATION_FACTOR = 1;
    int i= 0;
    boolean isPlaying = true;
    class MyThread extends Thread{
        private boolean passThroughMode = true;
        /*
        @Override
        public void run(){
            recordAndPlay(passThroughMode);
        }
        */

        MyThread(){
            super();
        }

        MyThread(boolean newPTV){
            this.passThroughMode = newPTV;
        }

        @Override
        public void run(){
            short[] lin = new short[SIZE_OF_RECORD_ARRAY];
            int num = 0;
            // am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
            // am.setMode(AudioManager.MODE_IN_COMMUNICATION);
            record.startRecording();
            track.play();
            // while (passThroughMode) {
            while (!isInterrupted()) {
                num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
                for(i=0;i<lin.length;i++)
                    lin[i] *= WAV_SAMPLE_MULTIPLICATION_FACTOR; 
                track.write(lin, 0, num);
            }
        }
        /*
        public void stopThread(){
            passThroughMode = false;
        }
        */
    }

    MyThread newThread;

    private void init() {
        int min = AudioRecord.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO,
                                 AudioFormat.ENCODING_PCM_16BIT, min);
        int maxJitter = AudioTrack.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
        track = new AudioTrack(AudioManager.MODE_IN_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO,
                               AudioFormat.ENCODING_PCM_16BIT, maxJitter, AudioTrack.MODE_STREAM);
     }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setVolumeControlStream(AudioManager.MODE_IN_COMMUNICATION);
        init();
        newThread = new MyThread(true);
        newThread.start();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
/*  
    private void recordAndPlay(boolean pTM) {
        short[] lin = new short[SIZE_OF_RECORD_ARRAY];
        int num = 0;
        am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
        am.setMode(AudioManager.MODE_IN_COMMUNICATION);
        record.startRecording();
        track.play();
        while (pTM) {
            num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
            for(i=0;i<lin.length;i++)
                lin[i] *= WAV_SAMPLE_MULTIPLICATION_FACTOR; 
            track.write(lin, 0, num);
        }
    }
*/  
    public void passStop(View view){
        Button playBtn = (Button) findViewById(R.id.playBtn);  
        // /*
        if(!isPlaying){
            record.startRecording();
            track.play();
            isPlaying = true;
            playBtn.setText("Pause");
        }
        else{
           record.stop();
           track.pause();
           isPlaying=false;
           playBtn.setText("Pass through");
        }
        // */
    }

/*
    @SuppressWarnings("deprecation")
    @Override
    public void onDestroy(){
        newThread.stop();
    }
    */

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // android.os.Process.killProcess(android.os.Process.myPid());
        // killProcess(android.os.Process.myPid());
        // newThread.stopThread();
        newThread.interrupt();
    }
}

最初の実行中、プログラムは正常に実行され、マイクの音がスピーカーに渡され、戻るボタンを押すとスレッドも停止するように見えるため、アプリが終了するとパススルーが停止します。ただし、アプリを再度実行すると、パススルーは発生しません。は

newThread = new MyThread(true);
newThread.start();  

アプリが実行されるたびに新しいスレッドを開始します (つまり、onCreate() が呼び出されます)、または何らかの理由で古いスレッドの状態を覚えていますか? このアプリを完全にリセットして、実行するたびに完全に新しいアプリが開始されるようにするにはどうすればよいですか?

- - 編集 - -

割り込みなしの代替バージョン:

public class MainActivity extends Activity {
    AudioManager am = null;
    AudioRecord record =null;
    AudioTrack track =null;
    final int SAMPLE_FREQUENCY = 44100;
    final int SIZE_OF_RECORD_ARRAY = 1024;  // 1024 ORIGINAL
    final int WAV_SAMPLE_MULTIPLICATION_FACTOR = 1;
    int i= 0;
    boolean isPlaying = true;
    class MyThread extends Thread{
        private volatile boolean passThroughMode = true;
         /*
        @Override
        public void run(){
            recordAndPlay(passThroughMode);
        }
        // */


        // /*
        MyThread(){
            super();
        }

        MyThread(boolean newPTV){
            this.passThroughMode = newPTV;
        }
        // */

        // /*
        @Override
        public void run(){
            short[] lin = new short[SIZE_OF_RECORD_ARRAY];
            int num = 0;
            // am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
            // am.setMode(AudioManager.MODE_IN_COMMUNICATION);
            record.startRecording();
            track.play();
            while (passThroughMode) {
            // while (!isInterrupted()) {
                num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
                for(i=0;i<lin.length;i++)
                    lin[i] *= WAV_SAMPLE_MULTIPLICATION_FACTOR; 
                track.write(lin, 0, num);
            }
            record.stop();
            track.stop();
            record.release();
            track.release();
        }
        // */

        // /*
        public void stopThread(){
            passThroughMode = false;
        }
        // */
    }

    MyThread newThread;

    private void init() {
        int min = AudioRecord.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO,
                                 AudioFormat.ENCODING_PCM_16BIT, min);
        int maxJitter = AudioTrack.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
        track = new AudioTrack(AudioManager.MODE_IN_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO,
                               AudioFormat.ENCODING_PCM_16BIT, maxJitter, AudioTrack.MODE_STREAM);
     }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setVolumeControlStream(AudioManager.MODE_IN_COMMUNICATION);
        init();
        Log.d("MYLOG", "onCreate() called");

        //Toast.makeText(getApplicationContext(), "HERE", Toast.LENGTH_SHORT).show();
        // newThread = new MyThread(true); // -> Moved this to onResume();
        // newThread = new MyThread();
        // newThread.start(); // -> Moved this to onResume()
        // newThread.run();
    }

    @Override
    protected void onResume(){
        super.onResume();
        // newThread.stopThread();
        Log.d("MYLOG", "onResume() called");
        newThread = new MyThread(true);
        newThread.start(); 
    }

    @Override
    protected void onPause(){
        super.onPause();
        Log.d("MYLOG", "onPause() called");
        newThread.stopThread();
        // android.os.Process.killProcess(android.os.Process.myPid());
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

     /* 
    private void recordAndPlay(boolean pTM) {
        short[] lin = new short[SIZE_OF_RECORD_ARRAY];
        int num = 0;
        am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
        am.setMode(AudioManager.MODE_IN_COMMUNICATION);
        record.startRecording();
        track.play();
        while (pTM) {
            num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
            for(i=0;i<lin.length;i++)
                lin[i] *= WAV_SAMPLE_MULTIPLICATION_FACTOR; 
            track.write(lin, 0, num);
        }
    }
// */   
    public void passStop(View view){
        Button playBtn = (Button) findViewById(R.id.playBtn);  
        // /*
        if(!isPlaying){
            record.startRecording();
            track.play();
            isPlaying = true;
            playBtn.setText("Pause");
        }
        else{
           record.stop();
           track.pause();
           isPlaying=false;
           playBtn.setText("Pass through");
        }
        // */
    }

     /*
    @SuppressWarnings("deprecation")
    @Override
    public void onDestroy(){
        // newThread.stop();
        newThread.stopThread();
    }
    // */

    // /*
    @Override
    protected void onDestroy() {
        super.onDestroy();
        newThread.stopThread();
        // android.os.Process.killProcess(android.os.Process.myPid());
        // killProcess(android.os.Process.myPid());
        // newThread.interrupt();
         Log.d("MYLOG", "onDestroy() called");
    }
    // */
}  

---編集2---

08-20 20:57:58.266: D/MYLOG(21936): onResume() called
08-20 20:57:58.266: W/dalvikvm(21936): threadid=11: thread exiting with uncaught exception (group=0x416f5700)
08-20 20:57:58.266: E/AndroidRuntime(21936): FATAL EXCEPTION: Thread-897
08-20 20:57:58.266: E/AndroidRuntime(21936): java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.
08-20 20:57:58.266: E/AndroidRuntime(21936):    at android.media.AudioRecord.startRecording(AudioRecord.java:517)
08-20 20:57:58.266: E/AndroidRuntime(21936):    at com.example.mypassthrough.MainActivity$MyThread.run(MainActivity.java:54)
08-20 20:57:58.286: D/MYLOG(21936): onPause() called
08-20 20:57:58.366: D/MYLOG(21936): onDestroy() called
4

2 に答える 2

1

いいえ、インスタンスThread間でのオブジェクトの状態の永続性はありません。ただし、アプリを実行するたびに新しいアクティビティが取得されると想定するのは間違いです。アクティビティは、Android OS が削除を決定するまで保持されます。その後、アプリに再度入ると、新しいインスタンスが作成されます。それ以外の場合は、以前と同じアクティビティが取得され、この場合は再度呼び出されませんActivityonCreate()

つまり、代わりに init/deinit にonResume()andを使用する必要があります。onPause()詳細については、ライフサイクル ページをご覧ください。

編集:別の問題はinterrupt()、スレッドのフローを制御するために使用していることです。いくつかの副作用があり、スレッドの状況によっては割り込みステータスを に設定することさえできないinterrupt()ためこれは常に良い考えとは限りません。セマンティクスはユーザーが設定するため、代わりに「shouldStop」フィールドを使用する必要があります。true

この「shouldStop」フィールドは field である必要があり引数として渡しても機能しないことに注意してください。に次のようなものが必要ですMyThread

    @Override
    public void run(){
        short[] lin = new short[SIZE_OF_RECORD_ARRAY];
        int num = 0;
        record.startRecording();
        track.play();
        while (passThroughMode) {
            num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
            for(i=0;i<lin.length;i++)
                lin[i] *= WAV_SAMPLE_MULTIPLICATION_FACTOR; 
            track.write(lin, 0, num);
        }
    }

そして、でonPause()

@Override
protected void onPause() {
    super.onPause();
    newThread.stopThread();
}

それでもスレッドが停止しない場合は、呼び出しによってスレッドがブロックされています。これは、I/O 操作では一般的です。

EDIT 2:さらに別の問題は、プレーヤースレッドがシャットダウンされている間(ループ後)、stop()andを実行しないことです。I/O に関連するものを使用するときの経験則は、多くの場合、明示的な「手動」リリース (および場合によっては割り当て) が必要な「ネイティブ」リソースにアタッチされることです。このような場合は、常にクラス API を確認する必要があります。release()AudioTrackAudioRecordwhile

EDIT 3: ...そして、MyThreadインスタンスは、他のすべてのリソースと同様に、で完全に初期化する必要があります。これには、 onではなくonResume()、そこに新しいインスタンスを作成することが含まれます。onCreate()

于 2013-08-20T10:13:34.637 に答える
0

あなたのスレッドは、外部クラスへの参照を持ち、使用する内部クラスですMainActivity。そうすれば、新しいスレッド オブジェクト自体が前のインスタンスから何も継承していなくても、スレッドの 2 番目のインスタンスは最初のインスタンスとは異なる方法で実行される可能性があります。@TheTerribleSwiftTomato が言うように、あなたの活動は続くかもしれません。

于 2013-08-20T10:15:21.597 に答える