2014-11-21 16 views
5

Bir işlevi var, ses kaydeder ve bir dosyaya kaydeder. Geri bu kaydedilen ses oynar playrecord adlı başka işlevi varOynat Gerçek zamanlı olarak mikrofondan sesi geri al

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

    } 

:

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

Bu iki işlev bağımsız iyi çalışır Bu nedir benzemesidir. StartRecord() işlevini çağırır ve playRecord'u çağırırsam, sesi duyabiliyorum. Ama yapmak istediğim, sesi GERÇEK ZAMANLA çal, yani kayıt yapmaya başladığım anda sesin çalmasını istiyorum. Bunu başarmak için ne yapmalıyım?

cevap

7

Bu benim için çalışıyor:

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

Ayrıca id start_button ve stop_button ile activity_main düzeninde iki düğme gerekir.

Bu örnekte ayrıca bir EchoCanceler içerir!

İyi şanslar!

+0

ama gecikme süresi ne kadar? –

+0

Bu gerçekten yüksek performanslıdır. Elbette biraz gecikme var ama sanırım sorununuzu çözmenin en hızlı yolu. Daha fazla bilgiye ihtiyacınız varsa https://www.youtube.com/watch?v=d3kfEeMZ65c adresini izlemenizi önerebilirim. – Xry

+1

Bu satırlarda bir NullPointer Özel Durum var: AcousticEchoCanceler echoCancler = AcousticEchoCanceler.create (record.getAudioSessionId()); echoCancler.setEnabled (true); – AlinaBM

İlgili konular