2012-03-26 167 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中。

希望它有帮助。