Android AudioRecord计算PCM缓冲区的持续时间

时间:2014-09-15 04:33:22

标签: android buffer duration audiorecord

我很抱歉,如果这是一个微不足道的问题,但我是Android的新手并且花了几天时间搜索,但没有答案或信息让我满意。

我希望使用Android手机每隔30秒录制一段长度约为3秒的录音。每条记录都会发送到我的PC(使用TCP / IP协议)进行进一步处理。

以下是Android方面的代码(我在这个问题中引用了@TechEnd的代码:Android AudioRecord example):

private final int AUD_RECODER_SAMPLERATE = 44100; // 44.1 kHz
private final int AUD_RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
private final int AUD_RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private final int AUD_RECORDER_BUFFER_NUM_ELEMENTS = 131072; // ~~ 1.486 second ???
private final int AUD_RECORDER_BUFFER_BYTES_PER_ELEMENT = 2;

private AudioRecord audioRecorder = null;
private boolean isAudioRecording = false;
private Runnable runnable = null;
private Handler handler = null;
private final int AUD_RECORDER_RECORDING_PERIOD = 30000; // one fire every 30 seconds

private byte[] bData = new byte[AUD_RECORDER_BUFFER_NUM_ELEMENTS*AUD_RECORDER_BUFFER_BYTES_PER_ELEMENT];

public void start() {
    audioRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, AUD_RECODER_SAMPLERATE, AUD_RECORDER_CHANNELS, AUD_RECORDER_AUDIO_ENCODING, AUD_RECORDER_BUFFER_NUM_ELEMENTS*AUD_RECORDER_BUFFER_BYTES_PER_ELEMENT);
    audioRecorder.startRecording();
    isAudioRecording = true;

    handler = new Handler();
    runnable = new Runnable() {
        @Override
        public void run() {
            if (isAudioRecording) {
                int nElementRead = audioRecorder.read(bData, 0, bData.length);
                net_send(bData, 0, nElementRead);
            }
            handler.postDelayed(this, AUD_RECORDER_RECORDING_PERIOD);
        }
    };
    handler.postDelayed(runnable, AUD_RECORDER_RECORDING_PERIOD);
}

public void stop() {
    isAudioRecording = false;
    if (audioRecorder != null) {
        audioRecorder.stop();
        audioRecorder.release();
        audioRecorder = null;
    }
    handler.removeCallbacks(runnable);
}

public void net_send(byte[] data, int nbytes) {
    try {
        dataOutputStream.writeInt(nbytes);
        dataOutputStream.write(data,0,nbytes);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

在PC端(用C编写的服务器),收到一条记录后(我检查了它们都是262144字节),我首先将字节数组写入二进制文件(扩展名为.raw)并用Free Audio打开编辑器(http://www.free-audio-editor.com/)并获得持续时间为1.486秒的结果 https://www.dropbox.com/s/xzml51jzvagl6dy/aud1.PNG?dl=0

然后我使用此函数将每两个连续字节转换为2字节整数

short bytes2short( const char num_buf[2] )
{
    return( 
        ( ( num_buf[1] & 0xFF ) << 8 ) | 
          ( num_buf[0] & 0xFF )
    );
}

并用Excel写入文件(长度为131072字节)和绘图(标准化的),得到类似的图形。

根据我的计算,一秒钟内记录的字节数为44100(样本/秒)* 1(秒)* 2(字节/样本/通道)* 1(通道)= 88200字节。 因此,对于长度为131072 * 2(字节)的缓冲区,相应的持续时间应为262144/88200 = 2.97秒。但我得到的结果只有一半。我尝试了三个运行Android OS版本2.3.3,2.3.4和4.3的不同设备,并获得了相同的结果。因此,这是我自己的问题。

在我的计算或代码中,有人能告诉我问题出在哪里吗?我的理解是正确的吗? 任何意见或建议将不胜感激。

0 个答案:

没有答案