2015-12-28 6 views
18

In meiner Android App möchte ich etwas Audio vom Mikrofon des Smartphones aufnehmen und es sofort, live, wie ein Mikrofon, ohne Verzögerung abspielen. Ich denke gerade an die Verwendung von AudioRecord und AudioTrack Klassen (von dem, was ich gelesen habe), aber ich bin mir nicht sicher, wie es weiter geht.Sofortiger Audio-Eingang und -Ausgang Android

Ich habe einige andere Fragen zu Stack Overflow ausgecheckt, aber sie antworten nicht genau, was ich gerne machen würde. Und die meisten sind von 2012.

Also wie kann ich diese Klassen verwenden, um Audio gleichzeitig einzugeben und auszugeben?

AUCH: hatte ich einen Blick auf den MediaRecorder API, aber von dem, was ich lese, dass erfordert, dass Sie die Audio-Datei zu speichern, die ich nicht tun will. Kann es angepasst werden, um meine Anforderungen zu erfüllen? Oder verwende ich besser AudioRecord?

Dank

EDIT:

Hier ist meine aktualisierte Code unten als @Pradip Pramanick vorgeschlagen:

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(); 
       } 
      } 
     } 
    }); 

Ich bin ein Illegal State Exception | Start failed: -38 bekommen. Aber ich rufe microphone.start nach microphone.prepare ... Was scheint das Problem zu sein? Ich suchte andere Threads, die sagten, dass es andere Hintergrund-Apps gibt, die das Mikrofon verwenden. Ich habe mein Gerät gesucht: Moto X Play (3. Generation) und keine gefunden. (Ich habe sogar "Ok Google" Spracherkennung ausgeschaltet, aber der Fehler kam immer wieder).

ERROR LOG:

ist die Log-Katze die letzten Fehler zeigt:

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 

Der IO-Ausnahme bei player.setDataSource(filename) zu sein scheint, ist der Dateiname Variable a string: Environment.getExternalStorageDirectory().getAbsolutePath() + "\voice.3gp"

+0

Können Sie sagen, warum Sie das tun möchten? –

+0

@ ste-fu Probier mal was aus. Weißt du wie das geht? – SynerFlow

+1

Sollte nur in der Lage sein, Streams so etwas zu übertragen http://stackoverflow.com/questions/5381969/android-how-to-record-mp3-radio-audio-stream/5384161#5384161. Vielleicht auch mit einem kleinen Puffer. Ich frage mich nur, warum wirklich - und ob Sie Audio-Feedback sehr schlecht leiden würden, wenn Sie es taten. –

Antwort

3

Soweit ich denken kann, kann es auf sehr einfache Weise getan werden. Ich habe es nicht versucht, aber Sie versuchen es. Ich denke, es wird funktionieren:

Erstellen Sie zwei Threads für die Aufnahme einer anderen zum Spielen. Sagen wir, die Threads sind TRecord und TPlay.

In TRecord der run-Methode dies zu tun:

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(); 
} 

Und es TPlay die run-Methode dies zu tun:

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

Jetzt auf mainactivity einfach zwei Threads erstellen. Starten Sie zuerst den TRecord-Thread und dann Tplay. Versuch es.

hier ist der Code für die Dateiendung:

mFileName = Environment.getExternalStorageDirectory().getAbsolutePath(); 
mFileName += "/audiorecordtest.3gp"; 
+0

Hi, was ist der mFileName in diesem Fall? Ist es eine vordefinierte Datei? Außerdem möchte ich die Datei loswerden, nachdem ich fertig gesprochen habe. Wie kann das gemacht werden? – SynerFlow

+0

Auch, was sollte die Erweiterung der Datei in diesem Fall sein? Können Sie den Code einschließen, der die Ausgabedatei/Datenquelle einrichtet? – SynerFlow

+0

ok Ich habe es bearbeitet. –

2

Das auf Android eigentlich wirklich schwierig ist. Google selbst hat eine sehr gute (aber etwas lange) video Erklärung der Probleme.

Sie haben auch a page explaining their latency testing methods and benchmarks für verschiedene Geräte.

Im Grunde genommen kann Android keine Zero-Latency-Audio machen, aber es gibt nichts, was Hardware-Partner davon abhält, die erforderliche Hardware und Plattform-Erweiterungen dafür hinzuzufügen.

0

versuchen Sie dies. Ich habe das nicht ausgeführt.

 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

Sein Teil von einem meiner Projekt früher, und funktioniert gut. Sie müssen es richtig zusammenbauen und Variablen wie Beispielrate 44100 usw. initialisieren :) – kAmol

+0

So funktioniert es. Aber die Stimme ist sehr cracky und extrem merkwürdig. Irgendein Grund, warum das passieren könnte? Wie viel kostet 'BytesPerElement'? – SynerFlow

+0

Versuchen Sie die Abtastrate 44100 und 'RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT'. Ich hoffe, Sie haben buffersize = 'AudioRecord.getMinBufferSize (RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING)' Wenn es funktioniert, vergessen Sie nicht, als Antwort zu markieren. :) – kAmol

Verwandte Themen