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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4452815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 06:26:24  来源:igfitidea点击:

Recording a wav file from the mic in Android - problems

javaandroidwavaudio-recording

提问by fredley

I need to be able to create a WAV file using the mic in Android. Currently, I'm having a lot of trouble. So far, this is my situation. I'm using parts of the micDroid project code to record thus:

我需要能够在 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
    }
}

Which appears to work fine, however the end result recognizably contains whatever I said, but it is horribly distorted. Here's a screen cap of audacity (WMP refuses to play the file).

这似乎工作正常,但最终结果可识别地包含我所说的内容,但它被严重扭曲。这是一个大胆的屏幕截图(WMP 拒绝播放文件)。

alt text

替代文字

Any help would be greatly appreciated, let me know if you need more code / info.

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

Update

更新

Following markus's suggestions, here is my updated code:

按照 markus 的建议,这是我更新的代码:

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

...and another audacity screencap: alt text

...和另一个大胆的截图: 替代文字

回答by mad

CHANNEL_CONFIGURATION_MONO is deprecated as far as i know, use CHANNEL_IN_MONO. consider looking at rehearsalassistantproject, afaik they use AudioRecord class, too. samplerates should be chosen to fit the standard sample rates like explained in this wikipedia article.

据我所知,CHANNEL_CONFIGURATION_MONO 已被弃用,请使用 CHANNEL_IN_MONO。考虑查看排练助理项目,因为他们也使用 AudioRecord 类。应选择采样率以适合标准采样率,如本维基百科文章中所述

回答by netdragon

You can set a buffer to be little-endian by using the following:

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

buffer.order(ByteOrder.LITTLE_ENDIAN);

回答by somebody

I have a lot of theories:

我有很多理论:

  1. if you had a signal saturated of noise and you cannot understand anything or you can understand something. It can be that you have a problem with big endian and little endian. When you record 16bit (2bytes) can be stored like AB or like BA (where A and B it's a byte). In java all is big endian (http://mindprod.com/jgloss/endian.html) so you are storing a sample of 16 bit as short in big endian, then you try to construct a wav, but a wav need to have data stored on little endian (https://ccrma.stanford.edu/courses/422/projects/WaveFormat/). Well the result is clear and you have an screenshot. The solution is to use byte always, you had done and it probably all it's ok now
  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/) 上。结果很清楚,你有一个屏幕截图。解决方案是始终使用字节,你已经完成了,现在可能一切都好了

if not check queue.put and queue.take I think you don't need them because you stored your audio in and array that's enough. In the first while I would replace queue.put by a function to store the buffer in a huge array of bytes with all the bytes. Then you can put the header of the wav.

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

Remember a wav has the header and the bytes of the audio, maybe you have forgot the header and the program you are using is inventing a header to play it.

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

The other option is: you have the problem on the wav header of 44 bytes. check your WaveWriter function. if you write bad code on it, you can heard a lot of different sounds of your voice.

另一种选择是:您在 44 字节的 wav 标头上有问题。检查您的 WaveWriter 函数。如果你在上面写了糟糕的代码,你会听到很多不同的声音。

note: I had seen the function WaveWriter or similar on the source code of android but it had not been ready to use three months ago. Some new about waveheader?

注意:我在android的源代码上看到过WaveWriter或类似的功能,但三个月前还没有准备好使用。波头的一些新东西?

回答by Renate

It's pretty clear, Audacity thinks that your file is floating point. Either the WAV header is screwed up or else it's how you opened it.

很明显,Audacity 认为您的文件是浮点数。要么 WAV 头被搞砸了,要么就是你打开它的方式。

Make a recording. In Audacity, open it using Project / Import Raw Data Set the parameters for how you think that you recorded it. I'll bet it plays back ok.

进行录音。在 Audacity 中,使用 Project/Import Raw Data 将其打开 设置您认为记录它的方式的参数。我敢打赌它可以正常播放。