I want to record input from the microphone, attach a reverb effect, and persist the result to a file. My use-case is an app that lets you sing a song and select different preset reverb options after recording, and then save your performance and store it on a backend server. The file that I send to the server needs to have a reverb effect applied to it.
So far I've been able to record input using AudioRecord
, and I can add a reverb effect to AudioTrack
to hear the reverb effect, but I'm stuck on figuring out how to save the audio with the reverb effect embedded. Here's what I have so far:
private void startRecording() {
final int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT);
mRecorder = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, bufferSize);
if(NoiseSuppressor.isAvailable()) {
NoiseSuppressor ns = NoiseSuppressor.create(mRecorder.getAudioSessionId());
ns.setEnabled(true);
}
if(AcousticEchoCanceler.isAvailable()) {
AcousticEchoCanceler aec = AcousticEchoCanceler.create(mRecorder.getAudioSessionId());
aec.setEnabled(true);
}
mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AUDIO_FORMAT, bufferSize, AudioTrack.MODE_STREAM);
PresetReverb reverb = new PresetReverb(1, mPlayer.getAudioSessionId());
reverb.setPreset(PresetReverb.PRESET_LARGEHALL);
reverb.setEnabled(true);
mPlayer.setAuxEffectSendLevel(1.f);
mRecorder.startRecording();
mPlayer.play();
new RecordingThread(mRecorder, mPlayer, bufferSize) {
@Override
public void onReleased() {
mRecorder = null;
mPlayer = null;
}
}.start();
}
public class RecordingThread extends Thread {
private static final String TAG = RecordingThread.class.getSimpleName();
private final AudioRecord mRecorder;
private final AudioTrack mPlayer;
private final int mBufferSize;
public RecordingThread(AudioRecord recorder, AudioTrack player, int bufferSize) {
mRecorder = recorder;
mPlayer = player;
mBufferSize = bufferSize;
}
@Override
public void run() {
byte[] buffer = new byte[mBufferSize];
int read;
while ((read = mRecorder.read(buffer, 0, buffer.length)) > 0) {
mPlayer.write(buffer, 0, buffer.length);
}
mRecorder.release();
mPlayer.release();
onReleased();
Timber.tag(TAG);
Timber.i("Exited with code %s", read);
}
public void onReleased() {
}
}
So ideally, it'd be nice to be able to attach the PresetReverb
on the AudioRecord
instead of the AudioTrack
, but when I do I get:
java.lang.RuntimeException: Cannot initialize effect engine for type: 47382d60-ddd8-11db-bf3a-0002a5d5c51b Error: -3
So now I'm thinking I need to pipe the PCM data from AudioRecord
to some external service/library, or to modify the buffer with whatever a reverb algorithm would look like.