Recording a wav file from the mic in Android - pro

2019-03-11 12:00发布

问题:

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:

//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).

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:

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:

回答1:

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



回答2:

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

buffer.order(ByteOrder.LITTLE_ENDIAN);


回答3:

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

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.

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.

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.

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?



回答4:

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.

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.