在Android中从麦克风录制wav文件 - 问题

时间:2010-12-15 17:14:55

标签: java android wav audio-recording

我需要能够在Android中使用麦克风创建WAV文件。目前,我遇到了很多麻烦。到目前为止,这是我的情况。我正在使用micDroid项目代码的一部分进行记录:

//read thread


int sampleRate = 44100;
int bufferSize = AudioRecord.getMinBufferSize(sampleRate,android.media.AudioFormat.CHANNEL_CONFIGURATION_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT);
AudioRecord ar = new AudioRecord(AudioSource.MIC,sampleRate,android.media.AudioFormat.CHANNEL_CONFIGURATION_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT,bufferSize);
short[] buffer = new short[bufferSize];

ar.startRecording();
while(isRunning){
    try{
        int numSamples = ar.read(buffer, 0, buffer.length);
        queue.put(new Sample(buffer, numSamples));
    } catch (InterruptedException e){
        e.printStackTrace();
    }
}


//write thread


int sampleRate = 44100;
WaveWriter writer = new WaveWriter("/sdcard","recOut.wav",sampleRate,android.media.AudioFormat.CHANNEL_CONFIGURATION_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT);
try {
    writer.createWaveFile();
} catch (IOException e) {
    e.printStackTrace();
}
while(isRunning){
    try {
        Sample sample = queue.take();
        writer.write(sample.buffer, sample.bufferSize);
    } catch (IOException e) {
        //snip
    }
}

这似乎工作正常,但最终结果可识别地包含我所说的,但它是可怕的扭曲。这是大胆的屏幕上限(WMP拒绝播放文件)。

alt text

如果您需要更多代码/信息,请随时与我们联系。

更新

根据马库斯的建议,这是我更新的代码:

int sampleRate = 16000;

writer = new WaveWriter("/sdcard","recOut.wav",sampleRate,android.media.AudioFormat.CHANNEL_IN_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT);

int bufferSize = AudioRecord.getMinBufferSize(sampleRate,android.media.AudioFormat.CHANNEL_IN_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT);
AudioRecord ar = new AudioRecord(AudioSource.MIC,sampleRate,android.media.AudioFormat.CHANNEL_IN_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT,bufferSize);

byte[] buffer = new byte[bufferSize]; //all references changed from short to byte type

...和另一个大胆的屏幕截图: alt text

4 个答案:

答案 0 :(得分:5)

据我所知,

CHANNEL_CONFIGURATION_MONO已弃用,请使用CHANNEL_IN_MONO。考虑查看rehearsalassistant项目,他们也使用AudioRecord类。应选择样本率以符合标准样本率,如本wikipedia article中所述。

答案 1 :(得分:4)

您可以使用以下命令将缓冲区设置为little-endian:

buffer.order(ByteOrder.LITTLE_ENDIAN);

答案 2 :(得分:2)

我有很多理论:

  1. 如果你有一个饱和的噪音信号,你无法理解任何东西,或者你可以理解某些东西。可能是你有大端和小端的问题。当您记录16位(2字节)时可以像AB一样存储或像BA一样存储(其中A和B是一个字节)。在java中,所有都是big endian(http://mindprod.com/jgloss/endian.html)所以你在大端存储一个16位的样本,然后你尝试构造一个wav,但是wav需要将数据存储在little endian({{ 3}})。那么结果很清楚,你有截图。解决方案是始终使用字节,你已经完成了,现在可能一切都好了
  2. 如果没有检查queue.put和queue.take我认为你不需要它们,因为你存储了音频和数组就足够了。在第一次,我会用一个函数替换queue.put,将缓冲区存储在一个包含所有字节的大量字节中。然后你可以把wav的标题。

    记住wav有标题和音频的字节,也许你已经忘记了标题,而你正在使用的程序正在发明一个标题来播放它。

    另一个选项是:你有44个字节的wav头问题。检查你的WaveWriter功能。如果你在上面写了不好的代码,你可以听到很多不同的声音。

    注意:我在android的源代码中看到了WaveWriter或类似的功能,但三个月前还没有准备好使用它。一些关于waveheader的新内容?

答案 3 :(得分:1)

很明显,Audacity认为你的文件是浮点数。 WAV标题被搞砸了,否则就是你打开它的方式。

录制。 在Audacity中,使用项目/导入原始数据打开它 设置您认为录制方式的参数。 我敢打赌它可以回放。