I am using Java Android AudioRecorder (Code as below). When I start recording, rms is normal value larger than 0. Several seconds after recording, rms only gets 0.0 value, which means audioBuffer is a zero buffer. How can I fix it? Thanks.
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelConfig, audioFormat, bufferSize);
while (isRecording) {
int read = recorder.read(audioBuffer, 0, bufferSize);
if (read > 0) {
long currentTime = System.currentTimeMillis();
// Calculate the RMS (root mean square) value of the audio buffer
double sum = 0;
for (int i = 0; i < read; i += 2) {
short sample = (short) ((audioBuffer[i + 1] << 8) | (audioBuffer[i] & 0xFF));
sum += sample * sample;
}
double rms = Math.sqrt(sum / (read / 2));
And here is a more detailed version of my code:
private void writeAudioDataToFile(String filePath, int bufferSize) {
byte[] audioBuffer = new byte[bufferSize];
FileOutputStream os = null;
while (isRecording) {
int read = recorder.read(audioBuffer, 0, bufferSize);
if (read > 0) {
long currentTime = System.currentTimeMillis();
// Calculate the RMS (root mean square) value of the audio buffer
double sum = 0;
for (int i = 0; i < read; i += 2) {
short sample = (short) ((audioBuffer[i + 1] << 8) | (audioBuffer[i] & 0xFF));
sum += sample * sample;
}
double rms = Math.sqrt(sum / (read / 2));
// Check if the audio level is above the silence threshold
if (rms > SILENCE_THRESHOLD) {
lastVoiceTimestamp = currentTime;
Log.i(Config.TAG, "Loud.");
// If the output stream is null, create a new file
if (os == null) {
try {
os = new FileOutputStream(filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
// Write audio data to file
try {
os.write(audioBuffer, 0, read);
} catch (IOException e) {
e.printStackTrace();
}
} else {
Log.i(Config.TAG, "Silent "+ String.valueOf(rms)+" "+String.valueOf(recorder.getState()));
// Check if silence duration has exceeded the threshold
if (currentTime - lastVoiceTimestamp > SILENCE_DURATION) {
Log.i(Config.TAG, "Silent Time Out "+ String.valueOf(rms)+" "+ String.valueOf(lastVoiceTimestamp));
// Close the current file and prepare for a new one
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
os = null;
// Encode the recorded PCM data to M4A
String m4aFilePath = filePath.replace(".pcm", ".m4a");
convertPcmToM4a(filePath, m4aFilePath);
filePath = audioDir + "/" + "record_" + System.currentTimeMillis() + ".pcm";
// Trigger transcription and translation
new Thread(() -> {
triggerTranscriptionAndTranslation(m4aFilePath);
}).start();
Log.i(Config.TAG, "New audio "+ filePath);
}
} else {
// If within silence duration, continue writing silence (optional)
if (os != null) {
try {
os.write(audioBuffer, 0, read);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
// Clean up when recording stops
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
os = null;
// Encode the last recorded PCM data to M4A
String m4aFilePath = filePath.replace(".pcm", ".m4a");
convertPcmToM4a(filePath, m4aFilePath);
// Trigger transcription and translation
new Thread(() -> {
triggerTranscriptionAndTranslation(m4aFilePath);
}).start();
}
}
I have logged the rms. At the beginning it is normal value larger than 0. Then suddenly it becomes 0.
It's hard to tell what exactly is wrong based on the information given. But here are a few tips:
writeAudioDataToFile
doesn't run on the main (UI) thread.recorder.read()
and handle possible errors (e.g. AudioRecord.ERROR_BAD_VALUE
, AudioRecord.ERROR_INVALID_OPERATION
, etc.)