javaandroidbackendaudio-recording

Why does the AudioRecord output only zeros?


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.


Solution

  • It's hard to tell what exactly is wrong based on the information given. But here are a few tips:

    1. Make sure that writeAudioDataToFile doesn't run on the main (UI) thread.
    2. Make sure the recording happens in the foreground (in Activity or a foreground service).
    3. Increase the buffer size (e.g. 2 times the minimum size).
    4. You should check the result of recorder.read() and handle possible errors (e.g. AudioRecord.ERROR_BAD_VALUE, AudioRecord.ERROR_INVALID_OPERATION, etc.)
    5. You might want to acquire a Wake Lock while recording.