Android:AudioRecord.read()返回垃圾

时间:2012-03-26 17:26:50

标签: android audiorecord

我一直在开发一款可以实时播放麦克风音频的应用。 它设置了一个AudioRecorder,它没有任何错误。但是,在执行读取操作时,它只返回一堆zeors,或者接近short的最大值的大量数字。我真的被困了,如果有人能帮助我,那将是非常友好的。这是我的代码:

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

1 个答案:

答案 0 :(得分: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
}

这样,每当调用read()时,我们将偏移量增加“read”并减去“read”的剩余长度,继续读取直到剩余长度达到0.然后你将得到一个填充短[]录制音频数据。

类似地,当您将数据写入AudioTrack时,您必须执行相同的操作“writeFully()”,以确保将整个short []写入AudioTrack。

希望它有所帮助。