I have been messing around with the AudioRecord feature of the Android API and found some strange behaviors with it.
Background info: My phone is a HTC Incredible I
It's been a while since this question was asked, so I don't know if answering it is relevant any more.
The reason you're getting values from -127 to 128 is that you're reading into an array of bytes, each of which hold a signed 8-bit number. For 16-bit audio, read into an array of shorts.
I'm afraid I can't help with the noise issue.
When you read bytes from a "AudioFormat.ENCODING_PCM_16BIT" stream, it actually gives you both the upper and lower bytes of each sample as 2 sequential bytes. This will seem extremely noisy if you just take each byte to be a sample (instead of the half sample it actually is), plus the signing will be wrong for the first byte (it's in little endian order).
To get meaningful data out of the stream, read via shorts, e.g.
public void run() {
while(isRecording) {
audioRecord.startRecording();
short[] data = new short[bufferSize/2];
audioRecord.read(data, 0, bufferSize/2);
listener.setData(data);
handleData(data);
}
audioRecord.release();
}
This open source project has a good amount of helper classes to help you acquire the audio data and experiment with analyzing it:
https://github.com/gast-lib/gast-lib
It has an AsyncTask
It has something that controls AudioRecorder
It even has a simple frequency estimation algorithm
I might be able to help a tiny bit. However, I am in the same situation as you so I can only tell you about my experiences.
I believe you can get your device's preferred sampleRate like so:
int sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM);
The 16Bit encoding mode is the only one that works with AudioRecord. I am unsure why you are getting 8Bit like output (right?). Maybe someone knows.
I am also unsure how you pull the amplitude from the retrieved bytes, did you do this?
Finally, I believe you need to use the periodic listener functions, like so:
int sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM);
int channelMode = AudioFormat.CHANNEL_IN_MONO;
int encodingMode = AudioFormat.ENCODING_PCM_16BIT;
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelMode, encodingMode);
AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelMode, encodingMode, bufferSize);
recorder.setPositionNotificationPeriod(intervalFrames);
recorder.setRecordPositionUpdateListener(recordListener);
recorder.startRecording();
private RecordListener recordListener = new RecordListener();
private class RecordListener implements AudioRecord.OnRecordPositionUpdateListener {
public void onMarkerReached(AudioRecord recorder) {
Log.v("MicInfoService", "onMarkedReached CALL");
}
public void onPeriodicNotification(AudioRecord recorder) {
Log.v("MicInfoService", "onPeriodicNotification CALL");
}
}
There are two big questions here which I cannot answer and want to know the answer of myself as well:
I wish I could help more.