summaryrefslogtreecommitdiff
path: root/LoopbackApp/app/src/main/java/org
diff options
context:
space:
mode:
authorRicardo Garcia <rago@google.com>2015-04-08 18:59:29 -0700
committerRicardo Garcia <rago@google.com>2015-04-08 18:59:29 -0700
commit698bcf06af8a983bf47b3a6bc1682690fe6db13c (patch)
tree7281a4793eb17e655b83b479297a10cfc08b98e7 /LoopbackApp/app/src/main/java/org
parent49721ce2ad40c9c4fecff30e755d5b09e415b4a1 (diff)
downloaddrrickorang-698bcf06af8a983bf47b3a6bc1682690fe6db13c.tar.gz
New microphone selection capabilities.
Now it is possible to select the microphone source. Some notification/error management refactoring. Adding microphone source to the name of the wavefile.
Diffstat (limited to 'LoopbackApp/app/src/main/java/org')
-rw-r--r--LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackActivity.java30
-rw-r--r--LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackApplication.java70
-rw-r--r--LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackAudioThread.java140
-rw-r--r--LoopbackApp/app/src/main/java/org/drrickorang/loopback/NativeAudioThread.java10
-rw-r--r--LoopbackApp/app/src/main/java/org/drrickorang/loopback/SettingsActivity.java40
5 files changed, 223 insertions, 67 deletions
diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackActivity.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackActivity.java
index 2ecc2e2..eac59e4 100644
--- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackActivity.java
+++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackActivity.java
@@ -80,6 +80,12 @@ public class LoopbackActivity extends Activity {
showToast("Java Recording Started");
refreshState();
break;
+ case LoopbackAudioThread.FUN_PLUG_AUDIO_THREAD_MESSAGE_REC_ERROR:
+ log("got message java rec can't start!!");
+ showToast("Java Recording Error. Please try again");
+ refreshState();
+ stopAudioThread();
+ break;
case LoopbackAudioThread.FUN_PLUG_AUDIO_THREAD_MESSAGE_REC_COMPLETE:
if(audioThread != null) {
mWaveData = audioThread.getWaveData();
@@ -243,22 +249,25 @@ public class LoopbackActivity extends Activity {
int samplingRate = getApp().getSamplingRate();
int playbackBuffer = getApp().getPlayBufferSizeInBytes();
int recordBuffer = getApp().getRecordBufferSizeInBytes();
+ int micSource = getApp().getMicSource();
log(" current sampling rate: " + samplingRate);
stopAudioThread();
//select if java or native audio thread
if (getApp().getAudioThreadType() == LoopbackApplication.AUDIO_THREAD_TYPE_JAVA ) {
+ int micSourceMapped = getApp().mapMicSource(LoopbackApplication.AUDIO_THREAD_TYPE_JAVA ,micSource);
audioThread = new LoopbackAudioThread();
audioThread.setMessageHandler(mMessageHandler);
audioThread.mSessionId = sessionId;
- audioThread.setParams(samplingRate, playbackBuffer, recordBuffer);
+ audioThread.setParams(samplingRate, playbackBuffer, recordBuffer,micSourceMapped);
audioThread.start();
} else {
+ int micSourceMapped = getApp().mapMicSource(LoopbackApplication.AUDIO_THREAD_TYPE_NATIVE ,micSource);
nativeAudioThread = new NativeAudioThread();
nativeAudioThread.setMessageHandler(mMessageHandler);
nativeAudioThread.mSessionId = sessionId;
- nativeAudioThread.setParams(samplingRate, playbackBuffer, recordBuffer);
+ nativeAudioThread.setParams(samplingRate, playbackBuffer, recordBuffer,micSourceMapped);
nativeAudioThread.start();
}
mWavePlotView.setSamplingRate( samplingRate);
@@ -302,7 +311,13 @@ public class LoopbackActivity extends Activity {
//create filename with date
String date = (String) DateFormat.format("yyyy_MM_dd_kk_mm", System.currentTimeMillis());
- String fileName = "loopback_"+date+".wav";
+ String micSource = getApp().getMicSourceString( getApp().getMicSource());
+ String fileName = "loopback_"+micSource+"_"+date+".wav";
+
+ //MIC
+ //VERSION?
+ //hardware?
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// browser.
@@ -433,7 +448,14 @@ public class LoopbackActivity extends Activity {
s.append(" Audio: NATIVE");
break;
}
- mTextInfo.setText(s.toString());
+
+ //mic source
+ int micSource = getApp().getMicSource();
+ String micSourceName = getApp().getMicSourceString(micSource);
+ if(micSourceName != null) {
+ s.append(String.format(" Mic: %s", micSourceName));
+ mTextInfo.setText(s.toString());
+ }
}
private static void log(String msg) {
diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackApplication.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackApplication.java
index 736e64a..6af44a6 100644
--- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackApplication.java
+++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackApplication.java
@@ -23,6 +23,7 @@ import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
+import android.media.MediaRecorder;
import android.os.Build;
public class LoopbackApplication extends Application {
@@ -31,6 +32,7 @@ public class LoopbackApplication extends Application {
private int mPlayBufferSizeInBytes = 0;
private int mRecordBuffSizeInBytes = 0;
private int mAudioThreadType = 0; //0:Java, 1:Native (JNI)
+ private int mMicSource = 3; //maps to MediaRecorder.AudioSource.VOICE_RECOGNITION;
public static final int AUDIO_THREAD_TYPE_JAVA = 0;
public static final int AUDIO_THREAD_TYPE_NATIVE = 1;
@@ -64,6 +66,74 @@ public class LoopbackApplication extends Application {
mAudioThreadType = audioThreadType;
}
+ int getMicSource() { return mMicSource; }
+ int mapMicSource(int threadType, int source) {
+ int mappedSource = 0;
+// <item>DEFAULT</item>
+// <item>MIC</item>
+// <item>CAMCORDER</item>
+// <item>VOICE_RECOGNITION</item>
+// <item>VOICE_COMMUNICATION</item>
+
+ if(threadType == AUDIO_THREAD_TYPE_JAVA) {
+
+ switch (source) {
+ default:
+ case 0: //DEFAULT
+ mappedSource = MediaRecorder.AudioSource.DEFAULT;
+ break;
+ case 1: //MIC
+ mappedSource = MediaRecorder.AudioSource.MIC;
+ break;
+ case 2: //CAMCORDER
+ mappedSource = MediaRecorder.AudioSource.CAMCORDER;
+ break;
+ case 3: //VOICE_RECOGNITION
+ mappedSource = MediaRecorder.AudioSource.VOICE_RECOGNITION;
+ break;
+ case 4: //VOICE_COMMUNICATION
+ mappedSource = MediaRecorder.AudioSource.VOICE_COMMUNICATION;
+ break;
+ }
+ } else if (threadType == AUDIO_THREAD_TYPE_NATIVE ) {
+
+ //taken form OpenSLES_AndroidConfiguration.h
+ switch (source) {
+ default:
+ case 0: //DEFAULT
+ mappedSource = 0x00; //SL_ANDROID_RECORDING_PRESET_NONE
+ break;
+ case 1: //MIC
+ mappedSource = 0x01; //SL_ANDROID_RECORDING_PRESET_GENERIC
+ break;
+ case 2: //CAMCORDER
+ mappedSource = 0x02; //SL_ANDROID_RECORDING_PRESET_CAMCORDER
+ break;
+ case 3: //VOICE_RECOGNITION
+ mappedSource = 0x03; //SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION
+ break;
+ case 4: //VOICE_COMMUNICATION
+ mappedSource = 0x04; //SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION
+ break;
+ }
+ }
+
+ return mappedSource;
+ }
+
+ String getMicSourceString(int source) {
+
+ String name = null;
+
+ String[] myArray = getResources().getStringArray(R.array.mic_source_array);
+ if(myArray != null && source>=0 && source < myArray.length) {
+ name = myArray[source];
+ }
+ return name;
+ }
+
+ void setMicSource(int micSource) { mMicSource = micSource; }
+
int getPlayBufferSizeInBytes() {
return mPlayBufferSizeInBytes;
}
diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackAudioThread.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackAudioThread.java
index ae2c0ca..e7ed9c2 100644
--- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackAudioThread.java
+++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackAudioThread.java
@@ -35,6 +35,7 @@ import android.os.Message;
public class LoopbackAudioThread extends Thread {
public boolean isRunning = false;
+ // private boolean isInitialized = false;
double twoPi = 6.28318530718;
public AudioTrack mAudioTrack;
@@ -59,6 +60,7 @@ public class LoopbackAudioThread extends Thread {
private short[] mAudioShortArrayOut;
int mMinPlayBufferSizeSamples = 0;
int mMinRecordBufferSizeSamples = 0;
+ int mMicSource = 0;
boolean isPlaying = false;
private Handler mMessageHandler;
@@ -68,11 +70,12 @@ public class LoopbackAudioThread extends Thread {
static final int FUN_PLUG_AUDIO_THREAD_MESSAGE_REC_COMPLETE = 994;
static final int FUN_PLUG_AUDIO_THREAD_MESSAGE_REC_COMPLETE_ERROR = 995;
- public void setParams(int samplingRate, int playBufferInBytes, int recBufferInBytes) {
+ public void setParams(int samplingRate, int playBufferInBytes, int recBufferInBytes, int micSource) {
mSamplingRate = samplingRate;
mMinPlayBufferSizeInBytes = playBufferInBytes;
mMinRecordBuffSizeInBytes = recBufferInBytes;
+ mMicSource = micSource;
}
@@ -96,7 +99,7 @@ public class LoopbackAudioThread extends Thread {
mAudioShortArrayOut = new short[mMinPlayBufferSizeSamples];
recorderRunnable = new RecorderRunnable(mPipe, mSamplingRate, mChannelConfigIn,
- mAudioFormat, mMinRecordBuffSizeInBytes);
+ mAudioFormat, mMinRecordBuffSizeInBytes, mMicSource);
mRecorderThread = new Thread(recorderRunnable);
mRecorderThread.start();
@@ -114,58 +117,66 @@ public class LoopbackAudioThread extends Thread {
double fr = 440.0f;
double phase = 0.0;
- isPlaying = false;
- isRunning = true;
+ if(recorderRunnable != null && mAudioTrack != null) {
- while (isRunning) {
- if (isPlaying)
- {
- //using PIPE
- // int bytesAvailable = mPipe.availableToRead();
- int samplesAvailable = mPipe.availableToRead();
+
+ isPlaying = false;
+ isRunning = true;
+
+ while (isRunning) {
+ if (isPlaying) {
+ //using PIPE
+ // int bytesAvailable = mPipe.availableToRead();
+ int samplesAvailable = mPipe.availableToRead();
// if (bytesAvailable>0 ) {
- if (samplesAvailable>0) {
+ if (samplesAvailable > 0) {
// int bytesOfInterest = bytesAvailable;
- int samplesOfInterest = samplesAvailable;
+ int samplesOfInterest = samplesAvailable;
// if ( mMinPlayBufferSizeInBytes < bytesOfInterest )
// bytesOfInterest = mMinPlayBufferSizeInBytes;
//
- if (mMinPlayBufferSizeSamples < samplesOfInterest)
- samplesOfInterest = mMinPlayBufferSizeSamples;
+ if (mMinPlayBufferSizeSamples < samplesOfInterest)
+ samplesOfInterest = mMinPlayBufferSizeSamples;
// mPipe.read( mAudioByteArrayOut, 0 , bytesOfInterest);
- int samplesRead = mPipe.read( mAudioShortArrayOut, 0, samplesOfInterest);
+ int samplesRead = mPipe.read(mAudioShortArrayOut, 0, samplesOfInterest);
// int bytesAvailableAfter = mPipe.availableToRead();
// int samplesAvailableAfter = mPipe.availableToRead();
- //output
+ //output
// mAudioTrack.write(mAudioByteArrayOut, 0, bytesOfInterest);
- mAudioTrack.write(mAudioShortArrayOut, 0, samplesRead);
+ mAudioTrack.write(mAudioShortArrayOut, 0, samplesRead);
- if ( !recorderRunnable.isStillRoomToRecord()) {
- //stop
- endTest();
+ if (!recorderRunnable.isStillRoomToRecord()) {
+ //stop
+ endTest();
+ }
}
- }
- }
- else
- {
- if (isRunning)
- {
- try {
- sleep(1);
- } catch (InterruptedException e) {
- e.printStackTrace();
+ } else {
+ if (isRunning) {
+ try {
+ sleep(1);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
}
- }
+ }
+ } //end is running
+ } else {
+ //something went wrong, didn't run
+ log("Loopback Audio Thread couldn't run!");
+ if (mMessageHandler != null) {
+ Message msg = Message.obtain();
+ msg.what = FUN_PLUG_AUDIO_THREAD_MESSAGE_REC_ERROR;
+ mMessageHandler.sendMessage(msg);
}
- } //end is running
+ }
}
public void setMessageHandler(Handler messageHandler) {
@@ -178,33 +189,36 @@ public class LoopbackAudioThread extends Thread {
public void runTest() {
- // start test
- if (mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING )
- {
- log("...run test, but still playing...");
- endTest();
- }
- else
- {
- //erase output buffer
- if (mvSamples != null)
- mvSamples = null;
+ if(isRunning) {
+ // start test
+ if (mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) {
+ log("...run test, but still playing...");
+ endTest();
+ } else {
+ //erase output buffer
+ if (mvSamples != null)
+ mvSamples = null;
- //resize
- int nNewSize = mSamplingRate * 2; //5 seconds!
- mvSamples = new double[nNewSize];
- mSamplesIndex = 0; //reset index
+ //resize
+ int nNewSize = mSamplingRate * 2; //5 seconds!
+ mvSamples = new double[nNewSize];
+ mSamplesIndex = 0; //reset index
- //start playing
- isPlaying = true;
- mAudioTrack.play();
- recorderRunnable.startRecording(mvSamples);
+ //start playing
+ isPlaying = true;
+ mAudioTrack.play();
+ boolean status = recorderRunnable.startRecording(mvSamples);
- log(" Started capture test");
- if (mMessageHandler != null) {
- Message msg = Message.obtain();
- msg.what = FUN_PLUG_AUDIO_THREAD_MESSAGE_REC_STARTED;
- mMessageHandler.sendMessage(msg);
+ log(" Started capture test");
+ if (mMessageHandler != null) {
+ Message msg = Message.obtain();
+ msg.what = FUN_PLUG_AUDIO_THREAD_MESSAGE_REC_STARTED;
+
+ if(!status)
+ msg.what = FUN_PLUG_AUDIO_THREAD_MESSAGE_REC_ERROR;
+
+ mMessageHandler.sendMessage(msg);
+ }
}
}
}
@@ -277,6 +291,8 @@ public class LoopbackAudioThread extends Thread {
private AudioRecord mRecorder;
+
+
private int mSelectedRecordSource = MediaRecorder.AudioSource.MIC;
public int mSamplingRate = 48000;
private int mChannelConfig = AudioFormat.CHANNEL_IN_MONO;
@@ -294,13 +310,14 @@ public class LoopbackAudioThread extends Thread {
int mSamplesIndex;
RecorderRunnable(PipeShort pipe, int samplingRate, int channelConfig, int audioFormat,
- int recBufferInBytes)
+ int recBufferInBytes, int micSource)
{
mPipe = pipe;
mSamplingRate = samplingRate;
mChannelConfig = channelConfig;
mAudioFormat = audioFormat;
mMinRecordBuffSizeInBytes = recBufferInBytes;
+ mSelectedRecordSource = micSource;
}
//init the recording device
@@ -331,6 +348,7 @@ public class LoopbackAudioThread extends Thread {
mRecorder = new AudioRecord(mSelectedRecordSource, mSamplingRate,
mChannelConfig, mAudioFormat, 2 * mMinRecordBuffSizeInBytes);
} catch (IllegalArgumentException e) {
+ e.printStackTrace();
return false;
}
if (mRecorder.getState() != AudioRecord.STATE_INITIALIZED) {
@@ -345,7 +363,7 @@ public class LoopbackAudioThread extends Thread {
return true;
}
- void startRecording(double vCapture[]) {
+ boolean startRecording(double vCapture[]) {
synchronized (sRecordingLock) {
mIsRecording = true;
}
@@ -353,8 +371,8 @@ public class LoopbackAudioThread extends Thread {
mvSamples = vCapture;
mSamplesIndex = 0;
- boolean successful = initRecord();
- if (successful) {
+ boolean status = initRecord();
+ if (status) {
log("Ready to go.");
startRecordingForReal();
} else {
@@ -363,6 +381,8 @@ public class LoopbackAudioThread extends Thread {
mIsRecording = false;
}
}
+
+ return status;
}
void startRecordingForReal() {
diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/NativeAudioThread.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/NativeAudioThread.java
index f8760a3..da6610f 100644
--- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/NativeAudioThread.java
+++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/NativeAudioThread.java
@@ -51,6 +51,8 @@ public class NativeAudioThread extends Thread {
int mMinRecordBuffSizeInBytes = 0;
private int mChannelConfigOut = AudioFormat.CHANNEL_OUT_MONO;
+ int mMicSource = 0;
+
// private double [] samples = new double[50000];
boolean isPlaying = false;
@@ -63,12 +65,14 @@ public class NativeAudioThread extends Thread {
static final int FUN_PLUG_NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE = 894;
static final int FUN_PLUG_NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE_ERRORS = 895;
- public void setParams(int samplingRate, int playBufferInBytes, int recBufferInBytes) {
+ public void setParams(int samplingRate, int playBufferInBytes, int recBufferInBytes, int micSource) {
mSamplingRate = samplingRate;
mMinPlayBufferSizeInBytes = playBufferInBytes;
mMinRecordBuffSizeInBytes = recBufferInBytes;
+ mMicSource = micSource;
+
}
//JNI load
@@ -84,7 +88,7 @@ public class NativeAudioThread extends Thread {
}
//jni calls
- public native long slesInit(int samplingRate, int frameCount);
+ public native long slesInit(int samplingRate, int frameCount, int micSource);
public native int slesProcessNext(long sles_data, double[] samples, long offset);
public native int slesDestroy(long sles_data);
@@ -122,7 +126,7 @@ public class NativeAudioThread extends Thread {
log(String.format("about to init, sampling rate: %d, buffer:%d", mSamplingRate,
mMinPlayBufferSizeInBytes/2 ));
- long sles_data = slesInit(mSamplingRate, mMinPlayBufferSizeInBytes/2);
+ long sles_data = slesInit(mSamplingRate, mMinPlayBufferSizeInBytes/2, mMicSource);
log(String.format("sles_data = 0x%X",sles_data));
if(sles_data == 0 ) {
diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/SettingsActivity.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/SettingsActivity.java
index 06d5299..f27361c 100644
--- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/SettingsActivity.java
+++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/SettingsActivity.java
@@ -19,6 +19,7 @@ package org.drrickorang.loopback;
import android.app.Activity;
import android.content.Intent;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
@@ -34,17 +35,21 @@ import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.AdapterView;
import android.widget.NumberPicker;
import android.widget.NumberPicker.OnValueChangeListener;
+import android.widget.TextView;
public class SettingsActivity extends Activity implements OnItemSelectedListener,
OnValueChangeListener {
/**
* Called with the activity is first created.
*/
+ Spinner mSpinnerMicSource;
Spinner mSpinnerSamplingRate;
Spinner mSpinnerAudioThreadType;
NumberPicker mNumberPickerPlaybackBuffer;
NumberPicker mNumberPickerRecordBuffer;
+ TextView mTextSettingsInfo;
+
ArrayAdapter<CharSequence> adapterSamplingRate;
int bytesPerFrame;
@@ -55,6 +60,25 @@ OnValueChangeListener {
View view = getLayoutInflater().inflate(R.layout.settings_activity, null);
setContentView(view);
+
+ mTextSettingsInfo = (TextView) findViewById(R.id.textSettingsInfo);
+
+
+ int micSource = getApp().getMicSource();
+ mSpinnerMicSource = (Spinner) findViewById(R.id.spinnerMicSource);
+ ArrayAdapter<CharSequence> adapterMicSource = ArrayAdapter.createFromResource(this,
+ R.array.mic_source_array, android.R.layout.simple_spinner_item);
+ // Specify the layout to use when the list of choices appears
+ adapterMicSource.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ // Apply the adapter to the spinner
+ mSpinnerMicSource.setAdapter(adapterMicSource);
+ //set current value
+// String currentValue = String.valueOf(samplingRate);
+// int nPosition = adapter.getPosition(currentValue);
+ mSpinnerMicSource.setSelection(micSource, false);
+ mSpinnerMicSource.setOnItemSelectedListener(this);
+
+
bytesPerFrame = getApp().BYTES_PER_FRAME;
int samplingRate = getApp().getSamplingRate();
//init spinner, etc
@@ -135,6 +159,15 @@ OnValueChangeListener {
String currentValue = String.valueOf(samplingRate);
int nPosition = adapterSamplingRate.getPosition(currentValue);
mSpinnerSamplingRate.setSelection(nPosition);
+
+
+ try {
+ int versionCode = getApplicationContext().getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), 0).versionCode;
+ String versionName = getApplicationContext().getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), 0).versionName;
+ mTextSettingsInfo.setText("SETTINGS - Ver. " +versionCode +"."+ versionName + " | " +Build.MODEL + " | " + Build.FINGERPRINT);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
}
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
@@ -157,6 +190,13 @@ OnValueChangeListener {
log("AudioThreadType:" + audioThreadType);
refresh();
break;
+ case R.id.spinnerMicSource:
+ int micSource = mSpinnerMicSource.getSelectedItemPosition();
+ getApp().setMicSource(micSource);
+ settingsChanged();
+ log("mic Source:" + micSource);
+ refresh();
+ break;
}
}