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

我需要能够在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拒绝播放文件)。

替代文字

任何帮助将不胜感激,如果您需要更多代码/信息,请告诉我。

更新

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

 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 

…和另一个大胆的屏幕截图: 替代文字

据我所知,CHANNEL_CONFIGURATION_MONO已弃用,请使用CHANNEL_IN_MONO。 考虑看rehearsalassistant项目,afaik他们也使用AudioRecord类。 应该选择样本以符合标准样本率,如本维基百科文章中所述 。

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

 buffer.order(ByteOrder.LITTLE_ENDIAN); 

我有很多理论:

  1. 如果你有一个饱和的噪音信号,你无法理解任何东西,或者你可以理解一些东西。 可能是你有大端和小端的问题。 当您记录16位(2字节)时可以像AB一样存储或像BA一样存储(其中A和B是一个字节)。 在java中都是大端( http://mindprod.com/jgloss/endian.html ),所以你在大端存储一个16位的样本,然后你尝试构建一个wav,但是wav需要有存储在little endian上的数据( https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ )。 那么结果很清楚,你有截图。 解决方案是始终使用byte,你已经完成了,现在可能一切都好了

如果没有检查queue.put和queue.take我认为你不需要它们,因为你存储了音频和数组就足够了。 在第一次,我会用一个函数替换queue.put,将缓冲区存储在一个包含所有字节的大量字节中。 然后你可以把wav的标题。

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

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

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

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

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