Entrée Et Sortie Audio Immédiate Android

dans mon application Android, je voudrais prendre un peu d'audio du micro du smartphone et le lire immédiatement, en direct, comme un microphone, sans décalage. Je suis actuellement en train de penser à l'aide de AudioRecord et AudioTrack classes (d'après ce que j'ai lu), mais je ne sais pas trop comment procéder.

j'ai vérifié d'autres questions sur le débordement de la pile, mais elles ne répondent pas exactement à ce que j'aimerais faire. Et la plupart datent de 2012.

alors comment puis-je utiliser ces classes pour entrer et produire l'audio simultanément?

ALSO: j'ai eu un coup d'oeil à l' MediaRecorder API, mais d'après ce que j'ai lu, cela exige que vous sauvegardiez l'audio dans un fichier, ce que je ne veux pas faire. Peut-il être retouché pour répondre à mes exigences? Ou est-ce que je devrais juste utiliser AudioRecord?

Merci

EDIT:

Voici mon code mis à jour ci-dessous comme @Pradip Pramanick l'a suggéré:

final Thread record = new Thread(new Runnable() {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                MediaRecorder microphone = new MediaRecorder();
                microphone.setAudioSource(MediaRecorder.AudioSource.MIC);
                    microphone.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                microphone.setOutputFile(filename);
                microphone.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                try {
                    microphone.prepare();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                microphone.start();
            }
        }
    });

    final Thread play = new Thread(new Runnable() {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                player = new MediaPlayer();
                try {
                    player.setDataSource(filename);
                    player.prepare();
                    player.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    });

je suis Illegal State Exception | Start failed: -38. Mais je suis appel de microphone.start après microphone.prepare... Ce qui semble être le problème? J'ai cherché d'autres threads qui ont dit qu'il pourrait y avoir d'autres applications de fond en utilisant le microphone. J'ai cherché sur mon appareil: Moto X Play (3ème génération) et je n'en ai trouvé aucun. (J'ai même désactivé la reconnaissance vocale "Ok Google", mais l'erreur a continué).

JOURNAL DES ERREURS:

voici le log-cat montrant les erreurs les plus récentes:

01-31 09:37:21.064 344-3339/? E/MediaPlayerService: offset error
01-31 09:37:21.065 1835-1922/com.synerflow.testapp E/MediaPlayer: Unable to create media player

01-31 09:37:21.065 1835-1922/com.synerflow.testapp I/Player: player.prepare() has failed
01-31 09:37:21.065 1835-1922/com.synerflow.testapp W/System.err: java.io.IOException: setDataSourceFD failed.: status=0x80000000

Le IO Exception semble être à l' player.setDataSource(filename), le la variable filename est une chaîne de caractères:Environment.getExternalStorageDirectory().getAbsolutePath() + "voice.3gp"

18
demandé sur Adifyr 2015-12-28 10:27:11

3 réponses

dans la mesure où je peux penser que cela peut être fait d'une manière très simple. Je n'ai pas essayé,mais vous l'essayez. Je pense que ça va marcher:

créer deux threads l'un pour enregistrer l'autre pour jouer. Disons que les fils sont TRecord et TPlay.

dans la méthode run de TRecord faites ceci:

public void run(){
        MediaRecorder mRecorder = null;
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mRecorder.setOutputFile(mFileName);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            mRecorder.prepare();
        } catch (IOException e) {
            //todo
        }

        mRecorder.start();
}

Et il TPlay méthode run du faire ceci :

public void run() {
MediaPlayer   mPlayer = null;
mPlayer = new MediaPlayer();
        try {
            mPlayer.setDataSource(mFileName);
            mPlayer.prepare();
            mPlayer.start();
        } catch (IOException e) {
            //todo
        }
}

maintenant sur la mainactivity il suffit de créer deux threads. D'abord démarrer le fil TRecord puis Tplay . Essayer.

ici est le code de l'extension de fichier:

mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
 mFileName += "/audiorecordtest.3gp";
3
répondu Pradip Pramanick 2016-01-27 18:16:43

C'est en fait très délicat sur Android. Google eux-mêmes ont un très bon (mais légèrement long) vidéo expliquer les enjeux.

Ils ont aussi une page expliquant leur test de latence méthodes et de critères d' pour les différents appareils.

essentiellement, Android stock ne peut pas faire l'audio à latence zéro, mais rien n'empêche les partenaires matériels d'ajouter le matériel requis et les extensions de plate-forme pour le faire.

2
répondu Kas Hunt 2016-01-27 14:33:13

essayez ceci. Je n'ai pas l'exécuter.

      recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
      RECORDER_SAMPLERATE, RECORDER_CHANNELS,
      RECORDER_AUDIO_ENCODING, bufferSize * BytesPerElement);

    recorder.startRecording();

    isRecording = true;

    recordingThread = new Thread(new Runnable() {

     public void run() {

      try {
          int intSize = android.media.AudioTrack.getMinBufferSize(RECORDER_SAMPLERATE,AudioFormat.CHANNEL_OUT_MONO , RECORDER_AUDIO_ENCODING);
          byte[] sData = new byte[bufferSize];
          AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, RECORDER_SAMPLERATE, AudioFormat.CHANNEL_OUT_MONO, RECORDER_AUDIO_ENCODING, intSize, AudioTrack.MODE_STREAM);
          while(isRecording){
          recorder.read(sData, 0, bufferSize);  //isRecording = false; onStop button

          if (at!=null) { 
              at.play();
              // Write the byte array to the track
              at.write(sData, 0, sData.length); 
              at.stop();
              at.release();
          }
          }
    } catch (IOException e) {
        e.printStackTrace();
    }
 }
  }, "AudioRecorder Thread");
    recordingThread.start();
0
répondu kAmol 2016-01-28 06:44:02