2012-03-26 170 views
0

我一直在研究一個可以實時從麥克風播放音頻的應用程序。 它設置了一個AudioRecorder,它沒有任何錯誤。但是,在執行讀取操作時,它只會返回一堆zeors,或者接近short的最大值的很多數字。我真的被卡住了,如果有人能幫助我,我會非常友好。這是我的代碼:Android:AudioRecord.read()返回垃圾

public class AudioIn extends Thread { 
public static final int ERROR_RECORD_INIT = -1; 
public static final int ERROR_RECORD_NOTIFICATION = -2; 
public static final int ERROR_RECORD_READ = -3; 
public static final int SUCCESS = 0; 

public static final int audioFrequency = 44100; 
public static final int channelConfig = AudioFormat.CHANNEL_IN_MONO; 
public static final int audioFormat = AudioFormat.ENCODING_PCM_16BIT; 
final int ShortsReadPerCycle = 1024; 


private boolean capture = true; 
private AudioRecord recorder; 
private int effectiveCaptureBufferSize; 
private short[] buffer; 

private AudioInHandler handler; 

public AudioIn() 
{ 
    int minDeviceBuffer = AudioRecord.getMinBufferSize(audioFrequency, channelConfig, audioFormat); 
    Log.d("AudioIn", "Minimum device capture buffer is: " + Integer.toString(minDeviceBuffer) + " bytes"); 

    effectiveCaptureBufferSize = minDeviceBuffer; 
    Log.d("AudioIn", "Setting capture buffer size to " + effectiveCaptureBufferSize + " bytes"); 
} 

public void close() 
{ 
    capture = false; 
} 

public int samplesPerBuffer() 
{ 
    return effectiveCaptureBufferSize/2; 
} 

@Override 
public void run() { 
    // TODO Auto-generated method stub 
    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO); 
    try 
    { 
     recorder = new AudioRecord(AudioSource.MIC, audioFrequency, channelConfig, audioFormat, effectiveCaptureBufferSize); 
    } 
    catch (Throwable t) 
    { 
     handler.onError(ERROR_RECORD_INIT); 
     return;   
    } 

    recorder.startRecording(); 

    while(capture) 
    { 
     buffer = new short[ShortsReadPerCycle]; 
     int shortsRead = recorder.read(buffer, 0, buffer.length); 
     if (shortsRead < 0) 
     { 
      new Runnable() { 

       @Override 
       public void run() { 
        // TODO Auto-generated method stub 
        handler.onError(ERROR_RECORD_READ); 
       } 
      }.run(); 
      this.close(); 
     } 
     else 
     { 
      new Runnable() { 

       @Override 
       public void run() { 
        // TODO Auto-generated method stub 
        handler.onNewData(buffer); 
       } 
      }.run();  
     } 
    } 
    Log.d("AudioIn.run()", "Stopping AudioRecord..."); 
    recorder.stop(); 
    Log.d("AudioIn.run()", "Stopped AudioRecord, now releasing..."); 
    recorder.release(); 
    Log.d("AudioIn.run()", "AudioRecord released"); 
    recorder = null; 
} 

public void setHandler(AudioInHandler handler) { 
    this.handler = handler; 
} 
} 

回答

3

在AudioRecord上調用read()一次並不能確保填充整個short []。您應該檢查返回的「shortsRead」以獲取實際的短讀數並繼續調用read(),直到short []被填充。示例代碼如下。

private void readFully(short[] data, int off, int length) { 
     int read; 
     while (length > 0) { 
      read = mRec.read(data, off, length); 
      length -= read; 
      off += read; 
     } 
} 

在錄製循環

while (!released) { 
    // fill the pktBuf 
    short[] pktBuf = new short[pktSize]; 
    readFully(pktBuf, 0, pktSize); 
    // Do something 
} 

這樣,每次調用閱讀()製成,我們增加的「讀」偏移量和減少由「讀」剩餘長度,繼續閱讀,直到剩餘長度達到0爲止。然後,您將獲得一個填滿的短片[]和錄製的音頻數據。同樣,當你寫數據到AudioTrack時,你必須做同樣的事情「writeFully()」,以確保整個short []被寫入到AudioTrack中。

希望它有幫助。