javaandroidaudio-streamingaudiotrackaudiorecord

Android Java sound recorded with AudioRecord has noise when played


I'm recording voice using AudioRecord, send it to server, receive it on both Android and Web. On Android, I'm playing the audio using AudioTrack, and there's a "tttttt" noise. On web, such noise doesn't seem to exist, maybe web API changes it to another more comfortable noise.

I'm recording voice and sending it so server like this:

recorder = new AudioRecord(audioSource, sampleRateInHz, channelConfig, audioFormat, bufferSize);
int audioSession = recorder.getAudioSessionId();
NoiseSuppressor.create(audioSession);
AutomaticGainControl.create(audioSession);
AcousticEchoCanceler.create(audioSession);
...
try {
    int bytesRead;
    int count = 0;
    byte[] buffer = new byte[bufferSize];

    while (isRecording) {
        bytesRead = recorder.read(buffer, 0, buffer.length);

        // skip first 2 buffers to eliminate "click sound"
        if (bytesRead > 0 && ++count > 2) {

            // I'm manually adding wav header to make it playable on web
            byte[] combined = new byte[wavHeaders.length + buffer.length];
            System.arraycopy(wavHeaders, 0, combined, 0, wavHeaders.length);
            System.arraycopy(buffer, 0, combined, wavHeaders.length, buffer.length);

            socket.emit("voice", combined);
        }
    }
    recorder.stop();
} catch (Exception e) {
    // e.printStackTrace();
}

And this is how I'm playing the audio:

player = new AudioTrack.Builder()
        .setAudioAttributes(new AudioAttributes.Builder()
                // .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
                .setUsage(AudioAttributes.USAGE_MEDIA)
                .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                .build())
        .setAudioFormat(new AudioFormat.Builder()
                .setEncoding(audioFormat)
                .setSampleRate(sampleRateInHz)
                .setChannelMask(outputChannelConfig)
                .build())
        .setBufferSizeInBytes(bufferSize)
        .build();
...
player.play();
...
public void addPlay(byte[] audioBuffer) {
    player.write(audioBuffer, 0, audioBuffer.length, 0);
}
...
try {
    addPlay((byte[]) args[0]);
} catch (Exception e) {
    // TODO: handle exception
}

Update:

I noticed by removing the generated header, the "ttttt" noise goes away, but I need to in order to be playable on web.


Solution

  • You can write audio data without the header by specifying offset in the audioBuffer, something like

    int audioOffset = wavHeaders.length;
    int audioLength = audioBuffer.length - wavHeaders.length;
    player.write(audioBuffer, audioOffset, audioLength, 0);