Created
December 24, 2017 20:31
-
-
Save Capotasto/c258e68b976b8025cfe51dc091c22c1c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.funckyhacker.util; | |
import android.media.AudioFormat; | |
import android.media.AudioRecord; | |
import android.media.MediaRecorder; | |
import android.os.Environment; | |
import android.os.SystemClock; | |
import java.io.File; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import rx.Single; | |
import rx.SingleSubscriber; | |
public class AudioRecordUtils { | |
private static final int AUDIO_SOURCE = MediaRecorder.AudioSource.MIC; | |
private static final int SAMPLE_RATE = 16000; // Hz | |
private static final int ENCODING = AudioFormat.ENCODING_PCM_16BIT; | |
private static final int CHANNEL_MASK = AudioFormat.CHANNEL_IN_MONO; | |
private static final int BUFFER_SIZE = 2 * AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_MASK, ENCODING); | |
private File mWavFile; | |
private boolean isRecording; | |
public void startRecording() { | |
isRecording = true; | |
} | |
public void stopRecording() { | |
isRecording = false; | |
} | |
public File getRecordedFile() { | |
return mWavFile; | |
} | |
public boolean isRecording() { | |
return isRecording; | |
} | |
public Single<Long[]> doRecordAudio() { | |
return Single.create((SingleSubscriber<? super Long[]> singleSubscriber) -> { | |
final File file = getNewRecordingFile(); | |
AudioRecord audioRecord = null; | |
FileOutputStream wavOut = null; | |
long startTime = 0; | |
long endTime = 0; | |
try { | |
// Open our two resources | |
audioRecord = new AudioRecord(AUDIO_SOURCE, SAMPLE_RATE, CHANNEL_MASK, ENCODING, BUFFER_SIZE); | |
wavOut = new FileOutputStream(file); | |
// Write out the wav file header | |
FileUtils.writeWavHeader(wavOut, CHANNEL_MASK, SAMPLE_RATE, ENCODING); | |
// Avoiding loop allocations | |
byte[] buffer = new byte[BUFFER_SIZE]; | |
boolean run = true; | |
int read; | |
long total = 0; | |
// Let's go | |
startTime = SystemClock.elapsedRealtime(); | |
audioRecord.startRecording(); | |
while (run && isRecording) { | |
read = audioRecord.read(buffer, 0, buffer.length); | |
// WAVs cannot be > 4 GB due to the use of 32 bit unsigned integers. | |
if (total + read > 4294967295L) { | |
// Write as many bytes as we can before hitting the max size | |
for (int i = 0; i < read && total <= 4294967295L; i++, total++) { | |
wavOut.write(buffer[i]); | |
} | |
run = false; | |
} else { | |
// Write out the entire read buffer | |
wavOut.write(buffer, 0, read); | |
total += read; | |
} | |
} | |
} catch (IOException ex) { | |
singleSubscriber.onError(ex); | |
} finally { | |
if (audioRecord != null) { | |
try { | |
if (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) { | |
audioRecord.stop(); | |
endTime = SystemClock.elapsedRealtime(); | |
} | |
} catch (IllegalStateException ex) { | |
singleSubscriber.onError(ex); | |
} | |
if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) { | |
audioRecord.release(); | |
} | |
} | |
if (wavOut != null) { | |
try { | |
wavOut.close(); | |
} catch (IOException ex) { | |
singleSubscriber.onError(ex); | |
} | |
} | |
} | |
try { | |
// This is not put in the try/catch/finally above since it needs to run | |
// after we close the FileOutputStream | |
FileUtils.updateWavHeader(file); | |
} catch (IOException ex) { | |
singleSubscriber.onError(ex); | |
} | |
singleSubscriber.onSuccess(new Long[]{file.length(), endTime - startTime}); | |
}); | |
} | |
private File getNewRecordingFile() { | |
mWavFile = new File(Environment.getExternalStorageDirectory().getPath(), | |
"recording_" + System.currentTimeMillis() / 1000 + ".wav"); | |
return mWavFile; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment