2014-11-21 40 views
5

Ho una funzione che registra l'audio e lo memorizza in un file. Questo è ciò che è appare come:Riproduzione audio dal microfono in tempo reale

private void startRecord(){ 

     File file = new File(Environment.getExternalStorageDirectory(), "test.pcm"); 

     int sampleFreq = (Integer)spFrequency.getSelectedItem(); 

     try { 
     file.createNewFile(); 

     OutputStream outputStream = new FileOutputStream(file); 
     BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream); 
     DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream); 

     int minBufferSize = AudioRecord.getMinBufferSize(sampleFreq, 
     AudioFormat.CHANNEL_CONFIGURATION_MONO, 
     AudioFormat.ENCODING_PCM_16BIT); 

     short[] audioData = new short[minBufferSize]; 

     AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 
     sampleFreq, 
     AudioFormat.CHANNEL_CONFIGURATION_MONO, 
     AudioFormat.ENCODING_PCM_16BIT, 
     minBufferSize); 

     audioRecord.startRecording(); 

     while(recording){ 
     int numberOfShort = audioRecord.read(audioData, 0, minBufferSize); 
     for(int i = 0; i < numberOfShort; i++){ 
     dataOutputStream.writeShort(audioData[i]); 
     } 

     } 

     audioRecord.stop(); 
     dataOutputStream.close(); 

     } catch (IOException e) { 
     e.printStackTrace(); 
     } 

    } 

Ho un'altra funzione, chiamata playrecord, che riproduce l'audio registrato:

void playRecord(){ 

     File file = new File(Environment.getExternalStorageDirectory(), "test.pcm"); 

      int shortSizeInBytes = Short.SIZE/Byte.SIZE; 

     int bufferSizeInBytes = (int)(file.length()/shortSizeInBytes); 
     short[] audioData = new short[bufferSizeInBytes]; 

     try { 
     InputStream inputStream = new FileInputStream(file); 
     BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); 
     DataInputStream dataInputStream = new DataInputStream(bufferedInputStream); 

     int i = 0; 
     while(dataInputStream.available() > 0){ 
     audioData[i] = dataInputStream.readShort(); 
     i++; 
     } 

     dataInputStream.close(); 

     int sampleFreq = (Integer)spFrequency.getSelectedItem(); 

     AudioTrack audioTrack = new AudioTrack(
     AudioManager.STREAM_MUSIC, 
     sampleFreq, 
     AudioFormat.CHANNEL_CONFIGURATION_MONO, 
     AudioFormat.ENCODING_PCM_16BIT, 
     bufferSizeInBytes, 
     AudioTrack.MODE_STREAM); 

     audioTrack.play(); 
     audioTrack.write(audioData, 0, bufferSizeInBytes); 


     } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
     } catch (IOException e) { 
     e.printStackTrace(); 
     } 
    } 

Queste due funzioni funzionare bene in modo indipendente. Se chiamo startRecord(), e poi chiamo playRecord, sono in grado di sentire l'audio. Ma quello che voglio fare è, riprodurre il suono in REAL TIME, cioè non appena inizio la registrazione, voglio che l'audio suoni. Cosa devo fare per raggiungere questo obiettivo?

risposta

7

Questo funziona per me:

boolean isRecording = false; 
AudioManager am = null; 
AudioRecord record = null; 
AudioTrack track = null; 

@Override 
protected void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    setVolumeControlStream(AudioManager.MODE_IN_COMMUNICATION); 

    initRecordAndTrack(); 

    am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE); 
    am.setSpeakerphoneOn(true); 

    (new Thread() 
    { 
     @Override 
     public void run() 
     { 
      recordAndPlay(); 
     } 
    }).start(); 

    Button startButton = (Button) findViewById(R.id.start_button); 
    startButton.setOnClickListener(new OnClickListener() 
    { 
     @Override 
     public void onClick(View v) 
     { 
      if (!isRecording) 
      { 
       startRecordAndPlay(); 
      } 
     } 
    }); 
    Button stopButton = (Button) findViewById(R.id.stop_button); 
    stopButton.setOnClickListener(new OnClickListener() 
    { 
     @Override 
     public void onClick(View v) 
     { 
      if (isRecording) 
      { 
       stopRecordAndPlay(); 
      } 
     } 
    }); 
} 

private void initRecordAndTrack() 
{ 
    int min = AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); 
    record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 
          min); 
    if (AcousticEchoCanceler.isAvailable()) 
    { 
     AcousticEchoCanceler echoCancler = AcousticEchoCanceler.create(record.getAudioSessionId()); 
     echoCancler.setEnabled(true); 
    } 
    int maxJitter = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); 
    track = new AudioTrack(AudioManager.MODE_IN_COMMUNICATION, 8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, maxJitter, 
          AudioTrack.MODE_STREAM); 
} 

private void recordAndPlay() 
{ 
    short[] lin = new short[1024]; 
    int num = 0; 
    am.setMode(AudioManager.MODE_IN_COMMUNICATION); 
    while (true) 
    { 
     if (isRecording) 
     { 
      num = record.read(lin, 0, 1024); 
      track.write(lin, 0, num); 
     } 
    } 
} 

private void startRecordAndPlay() 
{ 
    record.startRecording(); 
    track.play(); 
    isRecording = true; 
} 

private void stopRecordAndPlay() 
{ 
    record.stop(); 
    track.pause(); 
    isRecording = false; 
} 

è necessario anche due pulsanti nel layout activity_main con l'id start_button e stop_button.

Questo esempio contiene anche un EchoCanceler!

Buona fortuna!

+0

ma quanto costa la latenza? –

+0

È davvero ad alte prestazioni. Certo, c'è un po 'di latenza, ma immagino che sia il modo migliore per risolvere il tuo problema. Se hai bisogno di maggiori informazioni, ti suggerisco di guardare https://www.youtube.com/watch?v=d3kfEeMZ65c. – Xry

+1

Ho ottenuto un'eccezione NullPointer in questo modo: AcousticEchoCanceler echoCancler = AcousticEchoCanceler.create (record.getAudioSessionId()); echoCancler.setEnabled (true); – AlinaBM

Problemi correlati