How can on Android the bits per sample be changed from 16 bit to 8 bit (or other bitrates) in a AudioRecord object when recording in wav format?
This doesn't work (as discussed for example here: Using AudioRecord with 8-bit encoding in android):
private static int RECORDER_AUDIO_ENCODING =
AudioFormat.ENCODING_PCM_8BIT; -->ERROR: Invalid Audio Format.
bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING);
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,RECORDER_SAMPLERATE,
RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize);
With the header:
private void WriteWaveFileHeader(
FileOutputStream out, long totalAudioLen,
long totalDataLen, long longSampleRate, int channels,
long byteRate) throws IOException {
byte[] header = new byte[44];
header[0] = 'R'; // RIFF/WAVE header
...header content...
header[32] = (byte) (2 * 16 / 8); // block align
header[33] = 0;
header[34] = (byte)RECORDER_BPP; // bits per sample, set to 8
...header content...
out.write(header, 0, 44);
}
You need to record 16 Bit samples by using AudioFormat.ENCODING_PCM_16BIT
because 8 Bit encoding is not generally working on Android devices.
Then convert your 16 Bit buffer to 8 Bit on the fly prior to writing it into a wave sound file. But because 8 Bit wave files use unsigned integers (0-255) with silence being 128 instead of 0, my suggested conversion corrects for that. The following is just a code skeleton:
// Your source above already defined a value for bufferSize and the recorder object
sampleBufferShorts = new short[bufferSize];
sampleBufferBytes = new short[bufferSize];
int numberOfShortsRead = recorder.read(samleBufferShorts, 0, bufferSize);
if (numberOfShortsRead != ERROR_INVALID_OPERATION && numberOfShortsRead != ERROR_BAD_VALUE) {
for (int i = 0 ; i < numberOfShortsRead ; ++i)
sampleBufferBytes[i] = (byte)((sampleBufferShorts[i]>>8)+128);
}
See https://stackoverflow.com/a/18777515/1986583 for a useful explanation why additional dithering would improve the resulting quality.