2014-11-21 25 views
5

Mam funkcję, która rejestruje dźwięk i zapisuje go w pliku. To jest to, co wygląda następująco:Odtwarzanie dźwięku z mikrofonu w czasie rzeczywistym

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

    } 

mam inną funkcję, zwaną playrecord, który odtwarza ten nagrany dźwięk:

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

Te dwie funkcje działają bez zarzutu niezależnie. Jeśli zadzwonię do startRecord(), a następnie zadzwonię do playRecord, jestem w stanie usłyszeć dźwięk. Ale chcę odtwarzać dźwięk w CZASIE RZECZYWISTYM, tj. Od razu po rozpoczęciu nagrywania chcę, aby dźwięk był odtwarzany. Co powinienem zrobić, aby to osiągnąć?

Odpowiedz

7

Działa to dla mnie:

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

Należy również dwa przyciski w układzie activity_main z identyfikatorem start_button i stop_button.

Ta próbka zawiera również EchoCanceler!

Powodzenia!

+0

ale ile wynosi opóźnienie? –

+0

To naprawdę wysoka wydajność. Pewne jest pewne opóźnienie, ale myślę, że jest to najlepszy najszybszy sposób na rozwiązanie problemu. Jeśli potrzebujesz więcej informacji, mogę polecić Ci https://www.youtube.com/watch?v=d3kfEeMZ65c. – Xry

+1

Mam wyjątek NullPointer w tej linii: AcousticEchoCanceler echoCancler = AcousticEchoCanceler.create (record.getAudioSessionId()); echoCancler.setEnabled (true); – AlinaBM

Powiązane problemy