Created
December 6, 2017 12:39
-
-
Save MensObscura/8e08f1b80ce3f1350f4aa19e1de7c9ec to your computer and use it in GitHub Desktop.
AudioRecorder
This file contains 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
import android.media.AudioFormat; | |
import android.media.AudioRecord; | |
import android.media.AudioTrack; | |
import android.media.MediaRecorder; | |
import android.util.Log; | |
import java.nio.ByteBuffer; | |
import java.nio.ByteOrder; | |
/** | |
* See: http://stackoverflow.com/questions/5774104/android-audio-fft-to-retrieve-specific-frequency-magnitude-using-audiorecord | |
* Created from https://github.com/synaptik-/SoundWave/blob/master/app/src/main/java/com/synaptik/soundwave/AudioMonitor.java | |
*/ | |
public class AudioRecorder implements Runnable { | |
private static final String TAG = AudioRecorder.class.getSimpleName(); | |
private int mBufferSize; | |
private byte[] bufferByte; | |
private short[] bufferShort; | |
private AudioTrack at; | |
public boolean done = false; | |
private AudioRecord mAudio; | |
private OnUpdateListener mListener; | |
private static final int REQUIRED_FREQUENCY = 16000; | |
private static final int REQUIRED_CHANNEL = AudioFormat.CHANNEL_IN_MONO; | |
private static final int REQUIRED_FORMAT = AudioFormat.ENCODING_PCM_16BIT; | |
public AudioRecorder(OnUpdateListener listener) { | |
this.mListener = listener; | |
this.initialize(); | |
} | |
private void initialize() { | |
mBufferSize = AudioRecord.getMinBufferSize(REQUIRED_FREQUENCY, REQUIRED_CHANNEL, REQUIRED_FORMAT) * 2; | |
Log.d(TAG, "Recommended bufferSize: " + mBufferSize); | |
if (mBufferSize > 0) { | |
bufferShort = new short[mBufferSize / 2]; | |
bufferByte = new byte[mBufferSize]; | |
mAudio = new AudioRecord(MediaRecorder.AudioSource.MIC, REQUIRED_FREQUENCY, REQUIRED_CHANNEL, REQUIRED_FORMAT, mBufferSize); | |
if (mAudio.getState() == AudioRecord.STATE_UNINITIALIZED) { | |
Log.d(TAG, "Unable to initializeAudioMonitor AudioRecord. Ensure nothing else is using the microphone."); | |
if (mListener != null) { | |
this.mListener.quit(OnUpdateListener.ERROR_CODE_MICROPHONE_LOCKED); | |
} | |
mAudio = null; | |
} | |
} | |
} | |
public boolean isInitialized() { | |
return this.mAudio != null; | |
} | |
@Override | |
public void run() { | |
Log.d(TAG, "run"); | |
if (mAudio != null) { | |
mAudio.startRecording(); | |
while (!done) { | |
int count = mAudio.read(bufferByte, 0, mBufferSize); | |
int j =0; | |
for (int i = 0; i < bufferShort.length; i++) { | |
ByteBuffer bb = ByteBuffer.allocate(2); | |
bb.order(ByteOrder.LITTLE_ENDIAN); | |
bb.put(bufferByte[j]); | |
bb.put(bufferByte[j+1]); | |
short shortVal = bb.getShort(0); | |
bufferShort[i] = shortVal; | |
j+=2; | |
} | |
if (count > 0) { | |
if (mListener != null) { | |
float sampleLength = 1.0f / ((float) REQUIRED_FREQUENCY / (float) count); | |
mListener.update(bufferByte, bufferShort, count, sampleLength); | |
} | |
} else { | |
done = true; | |
} | |
} | |
mAudio.stop(); | |
mAudio.release(); | |
Log.d(TAG, "released"); | |
mAudio = null; | |
} else { | |
Log.d(TAG, "mAudio was null!"); | |
} | |
} | |
public void setListener(OnUpdateListener listener) { | |
mListener = listener; | |
} | |
} |
This file contains 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
public class MyFragment extends Fragment implements OnUpdateListener { | |
AudioRecorder mAudioRecorder; | |
Thread mAudioThread; | |
@Override | |
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { | |
super.onViewCreated(view, savedInstanceState); | |
// Don't forget to ask permission Manifest.permission.RECORD_AUDIO; | |
mAudioRecorder = new AudioRecorder(this); | |
if (mAudioRecorder.isInitialized()) { | |
mAudioThread = new Thread(mAudioRecorder); | |
mAudioThread.start(); | |
} | |
} | |
public void stopRecording() { | |
if (mAudioRecorder != null && mAudioRecorder.isInitialized()) { | |
mAudioRecorder.setListener(null); | |
mAudioRecorder.done = true; | |
} | |
} | |
// region AUDIO_MONITOR | |
@Override | |
public void update(final byte[] bytes, final short[] bufferShort, final int length, final float sampleLength) { | |
//Do you stuff | |
} | |
@Override | |
Public void quit(int errorCode) { | |
if (errorCode == OnUpdateListener.ERROR_CODE_MICROPHONE_LOCKED) { | |
new AlertDialog.Builder(getContext()) | |
.setTitle("ERROR") | |
.setMessage("Can't use microphone") | |
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { | |
@Override | |
public void onClick(DialogInterface dialog, int which) { | |
onBackPressed(); | |
} | |
}) | |
.show(); | |
} | |
} | |
} |
This file contains 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
public interface OnUpdateListener { | |
int ERROR_CODE_MICROPHONE_LOCKED = 1; | |
void update(byte[] bytes, short[] bufferShort, int length, float sampleLength); | |
void quit(int errorCode); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment