diff options
author | Glenn Kasten <gkasten@google.com> | 2017-05-22 16:50:01 -0700 |
---|---|---|
committer | Glenn Kasten <gkasten@google.com> | 2017-05-22 16:52:14 -0700 |
commit | adaa3c6c8bf4acfe1f547d15a18c03a823eebdea (patch) | |
tree | c86a1649cdf9ed2032a4912dd4a8f70ec120e3f4 | |
parent | 9e72ade37314f00216313b2cdcbbf5c16c5252e8 (diff) | |
download | drrickorang-adaa3c6c8bf4acfe1f547d15a18c03a823eebdea.tar.gz |
Version 19
Snap to commit b200b95a3aff6a2d5b9c59343c29a806bc00d0f1
Improve auto calibration
Keep track of average and RMS energy levels
Fix race condition during systrace collection
Allow systrace during latency test
Update to latest build tools
Display simulated load threads
Fix memory leak
Add privacy policy
12 files changed, 202 insertions, 78 deletions
diff --git a/LoopbackApp/app/build.gradle b/LoopbackApp/app/build.gradle index b1e114a..ff69f81 100644 --- a/LoopbackApp/app/build.gradle +++ b/LoopbackApp/app/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'com.android.model.application' model { android { compileSdkVersion = 23 - buildToolsVersion = "23.0.1" + buildToolsVersion = "25.0" defaultConfig.with { applicationId = "org.drrickorang.loopback" diff --git a/LoopbackApp/app/src/main/AndroidManifest.xml b/LoopbackApp/app/src/main/AndroidManifest.xml index 508f37f..a057e02 100644 --- a/LoopbackApp/app/src/main/AndroidManifest.xml +++ b/LoopbackApp/app/src/main/AndroidManifest.xml @@ -23,8 +23,8 @@ xmlns:android="http://schemas.android.com/apk/res/android" package="org.drrickorang.loopback" - android:versionCode="17" - android:versionName="0.9.74"> + android:versionCode="19" + android:versionName="0.9.75"> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/CaptureHolder.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/CaptureHolder.java index 774310b..99143f2 100644 --- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/CaptureHolder.java +++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/CaptureHolder.java @@ -140,7 +140,14 @@ public class CaptureHolder { /** * Send signal to listener script to terminate and stop atrace **/ - public static void stopLoopbackListenerScript() { + public void stopLoopbackListenerScript() { + if (mCaptureThread == null || !mCaptureThread.stopLoopbackListenerScript()) { + // The capture thread is unable to execute this operation. + stopLoopbackListenerScriptImpl(); + } + } + + static void stopLoopbackListenerScriptImpl() { try { OutputStream outputStream = new FileOutputStream(SIGNAL_FILE); outputStream.write(TERMINATE_SIGNAL.getBytes()); @@ -204,6 +211,8 @@ public class CaptureHolder { private CapturedState mNewCapturedState; private int mIndexToPlace; + private boolean mIsRunning; + private boolean mSignalScriptToQuit; /** * Create new thread with capture state struct for captured systrace, bugreport and wav @@ -217,6 +226,9 @@ public class CaptureHolder { @Override public void run() { + synchronized (this) { + mIsRunning = true; + } // Write names of desired captures to signal file, signalling // the listener script to write systrace and/or bugreport to those files @@ -287,6 +299,13 @@ public class CaptureHolder { for (CapturedState cs:mCapturedStates) log += "\n...." + cs; Log.d(TAG, log); + synchronized (this) { + if (mSignalScriptToQuit) { + CaptureHolder.stopLoopbackListenerScriptImpl(); + mSignalScriptToQuit = false; + } + mIsRunning = false; + } Log.d(TAG, "Completed capture thread terminating"); } @@ -294,5 +313,14 @@ public class CaptureHolder { public synchronized void updateRank(int rank) { mNewCapturedState.rank = Math.max(mNewCapturedState.rank, rank); } + + public synchronized boolean stopLoopbackListenerScript() { + if (mIsRunning) { + mSignalScriptToQuit = true; + return true; + } else { + return false; + } + } } } diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/Correlation.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/Correlation.java index d12cd7b..6c59bd9 100644 --- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/Correlation.java +++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/Correlation.java @@ -37,6 +37,8 @@ public class Correlation implements Parcelable { public double mEstimatedLatencySamples = 0; public double mEstimatedLatencyMs = 0; public double mEstimatedLatencyConfidence = 0.0; + public double mAverage = 0.0; + public double mRms = 0.0; private double mAmplitudeThreshold = 0.001; // 0.001 = -60 dB noise @@ -90,6 +92,9 @@ public class Correlation implements Parcelable { mDataAutocorrelated.length, data.length, minIndex)); log(String.format(" average : %.3f rms: %.3f", average, rms)); + mAverage = average; + mRms = rms; + mEstimatedLatencyConfidence = 0.0; if (average > 0) { double factor = 3.0; @@ -199,6 +204,8 @@ public class Correlation implements Parcelable { bundle.putDouble("mEstimatedLatencySamples", mEstimatedLatencySamples); bundle.putDouble("mEstimatedLatencyMs", mEstimatedLatencyMs); bundle.putDouble("mEstimatedLatencyConfidence", mEstimatedLatencyConfidence); + bundle.putDouble("mAverage", mAverage); + bundle.putDouble("mRms", mRms); } dest.writeBundle(bundle); } @@ -211,6 +218,8 @@ public class Correlation implements Parcelable { mEstimatedLatencySamples = bundle.getDouble("mEstimatedLatencySamples"); mEstimatedLatencyMs = bundle.getDouble("mEstimatedLatencyMs"); mEstimatedLatencyConfidence = bundle.getDouble("mEstimatedLatencyConfidence"); + mAverage = bundle.getDouble("mAverage"); + mRms = bundle.getDouble("mRms"); } } 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 9cfa768..d3acd03 100644 --- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackActivity.java +++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackActivity.java @@ -93,6 +93,8 @@ public class LoopbackActivity extends Activity private static final int LATENCY_TEST_ENDED = 301; private static final int BUFFER_TEST_STARTED = 302; private static final int BUFFER_TEST_ENDED = 303; + private static final int CALIBRATION_STARTED = 304; + private static final int CALIBRATION_ENDED = 305; // 0-100 controls compression rate, currently ignore because PNG format is being used private static final int EXPORTED_IMAGE_QUALITY = 100; @@ -163,6 +165,7 @@ public class LoopbackActivity extends Activity private int mPlayerBufferSizeInBytes; private int mRecorderBufferSizeInBytes; private int mIgnoreFirstFrames; // TODO: this only applies to native mode + private CaptureHolder mCaptureHolder; // for buffer test private int[] mGlitchesData; @@ -280,7 +283,7 @@ public class LoopbackActivity extends Activity break; } if (getApp().isCaptureEnabled()) { - CaptureHolder.stopLoopbackListenerScript(); + mCaptureHolder.stopLoopbackListenerScript(); } stopAudioTestThreads(); if (mIntentRunning && mIntentFileName != null && mIntentFileName.length() > 0) { @@ -379,11 +382,10 @@ public class LoopbackActivity extends Activity } mIntentRunning = false; - - } - if (getApp().isCaptureEnabled()) { - CaptureHolder.stopLoopbackListenerScript(); - } + if (getApp().isCaptureEnabled()) { + mCaptureHolder.stopLoopbackListenerScript(); + } + } // mNativeAudioThread != null refreshSoundLevelBar(); break; default: @@ -428,6 +430,16 @@ public class LoopbackActivity extends Activity LOOPBACK_NATIVE_AUDIO_THREAD_MESSAGE_BUFFER_REC_COMPLETE_ERRORS: setTransportButtonsState(BUFFER_TEST_ENDED); break; + + // Sound Calibration started + case CALIBRATION_STARTED: + setTransportButtonsState(CALIBRATION_STARTED); + break; + + // Sound Calibration ended + case CALIBRATION_ENDED: + setTransportButtonsState(CALIBRATION_ENDED); + break; } } }; @@ -803,7 +815,7 @@ public class LoopbackActivity extends Activity mBufferTestDurationInSeconds = getApp().getBufferTestDuration(); mBufferTestWavePlotDurationInSeconds = getApp().getBufferTestWavePlotDuration(); - CaptureHolder captureHolder = new CaptureHolder(getApp().getNumStateCaptures(), + mCaptureHolder = new CaptureHolder(getApp().getNumStateCaptures(), getFileNamePrefix(), getApp().isCaptureWavSnippetsEnabled(), getApp().isCaptureSysTraceEnabled(), getApp().isCaptureBugreportEnabled(), this, mSamplingRate); @@ -822,20 +834,20 @@ public class LoopbackActivity extends Activity / (Constant.BYTES_PER_FRAME * mSamplingRate)); mRecorderBufferPeriod.prepareMemberObjects( Constant.MAX_RECORDED_LATE_CALLBACKS_PER_SECOND * mBufferTestDurationInSeconds, - expectedRecorderBufferPeriod, captureHolder); + expectedRecorderBufferPeriod, mCaptureHolder); int expectedPlayerBufferPeriod = Math.round( (float) (mPlayerBufferSizeInBytes * Constant.MILLIS_PER_SECOND) / (Constant.BYTES_PER_FRAME * mSamplingRate)); mPlayerBufferPeriod.prepareMemberObjects( Constant.MAX_RECORDED_LATE_CALLBACKS_PER_SECOND * mBufferTestDurationInSeconds, - expectedPlayerBufferPeriod, captureHolder); + expectedPlayerBufferPeriod, mCaptureHolder); mAudioThread = new LoopbackAudioThread(mSamplingRate, mPlayerBufferSizeInBytes, mRecorderBufferSizeInBytes, micSourceMapped, /* no performance mode */ mRecorderBufferPeriod, mPlayerBufferPeriod, mTestType, mBufferTestDurationInSeconds, mBufferTestWavePlotDurationInSeconds, getApplicationContext(), - mChannelIndex, captureHolder); + mChannelIndex, mCaptureHolder); mAudioThread.setMessageHandler(mMessageHandler); mAudioThread.mSessionId = sessionId; mAudioThread.start(); @@ -848,7 +860,7 @@ public class LoopbackActivity extends Activity mNativeAudioThread = new NativeAudioThread(mSamplingRate, mPlayerBufferSizeInBytes, mRecorderBufferSizeInBytes, micSourceMapped, performanceModeMapped, mTestType, mBufferTestDurationInSeconds, mBufferTestWavePlotDurationInSeconds, - mIgnoreFirstFrames, captureHolder); + mIgnoreFirstFrames, mCaptureHolder); mNativeAudioThread.setMessageHandler(mMessageHandler); mNativeAudioThread.mSessionId = sessionId; mNativeAudioThread.start(); @@ -910,6 +922,7 @@ public class LoopbackActivity extends Activity private void setTransportButtonsState(int state){ Button latencyStart = (Button) findViewById(R.id.buttonStartLatencyTest); Button bufferStart = (Button) findViewById(R.id.buttonStartBufferTest); + Button calibrationStart = (Button) findViewById(R.id.buttonCalibrateSoundLevel); switch (state) { case LATENCY_TEST_STARTED: @@ -919,6 +932,7 @@ public class LoopbackActivity extends Activity latencyStart.setCompoundDrawablesWithIntrinsicBounds( R.drawable.ic_stop, 0, 0, 0); bufferStart.setEnabled(false); + calibrationStart.setEnabled(false); break; case LATENCY_TEST_ENDED: @@ -926,6 +940,7 @@ public class LoopbackActivity extends Activity latencyStart.setCompoundDrawablesWithIntrinsicBounds( R.drawable.ic_play_arrow, 0, 0, 0); bufferStart.setEnabled(true); + calibrationStart.setEnabled(true); break; case BUFFER_TEST_STARTED: @@ -935,14 +950,39 @@ public class LoopbackActivity extends Activity bufferStart.setCompoundDrawablesWithIntrinsicBounds( R.drawable.ic_stop, 0, 0, 0); latencyStart.setEnabled(false); + calibrationStart.setEnabled(false); break; case BUFFER_TEST_ENDED: findViewById(R.id.zoomAndSaveControlPanel).setVisibility(View.VISIBLE); + findViewById(R.id.resultSummary).setVisibility(View.VISIBLE); + findViewById(R.id.glitchReportPanel).setVisibility(View.VISIBLE); bufferStart.setCompoundDrawablesWithIntrinsicBounds( R.drawable.ic_play_arrow, 0, 0, 0); latencyStart.setEnabled(true); + calibrationStart.setEnabled(true); + break; + + case CALIBRATION_STARTED: + findViewById(R.id.zoomAndSaveControlPanel).setVisibility(View.INVISIBLE); + findViewById(R.id.resultSummary).setVisibility(View.INVISIBLE); + findViewById(R.id.glitchReportPanel).setVisibility(View.INVISIBLE); + bufferStart.setCompoundDrawablesWithIntrinsicBounds( + R.drawable.ic_stop, 0, 0, 0); + latencyStart.setEnabled(false); + bufferStart.setEnabled(false); + calibrationStart.setEnabled(false); + break; + + case CALIBRATION_ENDED: + findViewById(R.id.zoomAndSaveControlPanel).setVisibility(View.VISIBLE); + findViewById(R.id.resultSummary).setVisibility(View.VISIBLE); findViewById(R.id.glitchReportPanel).setVisibility(View.VISIBLE); + bufferStart.setCompoundDrawablesWithIntrinsicBounds( + R.drawable.ic_play_arrow, 0, 0, 0); + latencyStart.setEnabled(true); + bufferStart.setEnabled(true); + calibrationStart.setEnabled(true); break; } } @@ -1134,16 +1174,15 @@ public class LoopbackActivity extends Activity } public void onButtonCalibrateSoundLevel(final View view) { - view.setEnabled(false); + Message m = Message.obtain(); + m.what = CALIBRATION_STARTED; + mMessageHandler.sendMessage(m); Runnable onComplete = new Runnable() { @Override public void run() { - view.post(new Runnable() { - @Override - public void run() { - view.setEnabled(true); - } - }); + Message m = Message.obtain(); + m.what = CALIBRATION_ENDED; + mMessageHandler.sendMessage(m); } }; doCalibration(onComplete); @@ -1649,16 +1688,16 @@ public class LoopbackActivity extends Activity s.append(mTestStartTimeString); s.append("):\n"); - s.append("SR: " + mSamplingRate + " Hz"); - s.append(" ChannelIndex: " + (mChannelIndex < 0 ? "MONO" : mChannelIndex)); + s.append("SR: ").append(mSamplingRate).append(" Hz"); + s.append(" ChannelIndex: ").append(mChannelIndex < 0 ? "MONO" : mChannelIndex); switch (mAudioThreadType) { case Constant.AUDIO_THREAD_TYPE_JAVA: - s.append(" Play Frames: " + playerFrames); - s.append(" Record Frames: " + recorderFrames); + s.append(" Play Frames: " ).append(playerFrames); + s.append(" Record Frames: ").append(recorderFrames); s.append(" Audio: JAVA"); break; case Constant.AUDIO_THREAD_TYPE_NATIVE: - s.append(" Frames: " + playerFrames); + s.append(" Frames: ").append(playerFrames); s.append(" Audio: NATIVE"); break; } @@ -1666,36 +1705,41 @@ public class LoopbackActivity extends Activity // mic source String micSourceName = getApp().getMicSourceString(mMicSource); if (micSourceName != null) { - s.append(String.format(" Mic: %s", micSourceName)); + s.append(" Mic: ").append(micSourceName); } // performance mode String performanceModeName = getApp().getPerformanceModeString(mPerformanceMode); if (performanceModeName != null) { - s.append(String.format(" Performance Mode: %s", performanceModeName)); + s.append(" Performance Mode: ").append(performanceModeName); } // sound level at start of test - s.append(String.format(" Sound Level: %d/%d", mSoundLevel, - mBarMasterLevel.getMax())); + s.append(" Sound Level: ").append(mSoundLevel).append("/").append(mBarMasterLevel.getMax()); + + // load threads + s.append(" Simulated Load Threads: ").append(getApp().getNumberOfLoadThreads()); // Show short summary of results, round trip latency or number of glitches if (mTestType == Constant.LOOPBACK_PLUG_AUDIO_THREAD_TEST_TYPE_LATENCY) { if (mIgnoreFirstFrames > 0) { - s.append(" First Frames Ignored: " + mIgnoreFirstFrames); + s.append(" First Frames Ignored: ").append(mIgnoreFirstFrames); } if (mCorrelation.isValid()) { - mTextViewResultSummary.setText(String.format("Latency: %.2f ms Confidence: %.2f", - mCorrelation.mEstimatedLatencyMs, mCorrelation.mEstimatedLatencyConfidence)); + mTextViewResultSummary.setText(String.format("Latency: %.2f ms Confidence: %.2f" + + " Average = %.4f RMS = %.4f", + mCorrelation.mEstimatedLatencyMs, mCorrelation.mEstimatedLatencyConfidence, + mCorrelation.mAverage, mCorrelation.mRms)); } } else if (mTestType == Constant.LOOPBACK_PLUG_AUDIO_THREAD_TEST_TYPE_BUFFER_PERIOD && mGlitchesData != null) { // show buffer test duration - s.append("\nBuffer Test Duration: " + mBufferTestDurationInSeconds + " s"); + s.append("\nBuffer Test Duration: ").append(mBufferTestDurationInSeconds).append(" s"); // show buffer test wave plot duration - s.append(" Buffer Test Wave Plot Duration: last " + - mBufferTestWavePlotDurationInSeconds + " s"); + s.append(" Buffer Test Wave Plot Duration: last "); + s.append(mBufferTestWavePlotDurationInSeconds); + s.append(" s"); mTextViewResultSummary.setText(getResources().getString(R.string.numGlitches) + " " + estimateNumberOfGlitches(mGlitchesData)); @@ -1704,7 +1748,7 @@ public class LoopbackActivity extends Activity } String info = getApp().getSystemInfo(); - s.append(" " + info); + s.append(" ").append(info); mTextInfo.setText(s.toString()); } @@ -1922,7 +1966,6 @@ public class LoopbackActivity extends Activity log("Error closing ParcelFile Descriptor"); } } - } private StringBuilder getReport() { @@ -1966,6 +2009,9 @@ public class LoopbackActivity extends Activity sb.append(String.format("LatencyConfidence = %.2f", mCorrelation.mEstimatedLatencyConfidence) + endline); + + sb.append(String.format("Average = %.4f", mCorrelation.mAverage) + endline); + sb.append(String.format("RMS = %.4f", mCorrelation.mRms) + endline); break; case Constant.LOOPBACK_PLUG_AUDIO_THREAD_TEST_TYPE_BUFFER_PERIOD: sb.append("Buffer Test Duration (s) = " + mBufferTestDurationInSeconds + endline); 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 ba68780..b4c3b3a 100644 --- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackAudioThread.java +++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackAudioThread.java @@ -27,7 +27,6 @@ import android.util.Log; import android.os.Handler; import android.os.Message; - /** * A thread/audio track based audio synth. */ @@ -172,9 +171,8 @@ public class LoopbackAudioThread extends Thread { // read from the pipe and plays it out int samplesAvailable = mLatencyTestPipe.availableToRead(); if (samplesAvailable > 0) { - int samplesOfInterest = samplesAvailable; - if (mMinPlayerBufferSizeSamples < samplesOfInterest) - samplesOfInterest = mMinPlayerBufferSizeSamples; + int samplesOfInterest = Math.min(samplesAvailable, + mMinPlayerBufferSizeSamples); int samplesRead = mLatencyTestPipe.read(audioShortArrayOut, 0, samplesOfInterest); 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 5a6735f..95d5899 100644 --- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/NativeAudioThread.java +++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/NativeAudioThread.java @@ -292,6 +292,10 @@ public class NativeAudioThread extends Thread { endDetecting(); } + if (mTestType == Constant.LOOPBACK_PLUG_AUDIO_THREAD_TEST_TYPE_LATENCY) { + mCaptureHolder.captureState(0); + } + runDestroy(sles_data); final int maxTry = 20; diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/SoundLevelCalibration.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/SoundLevelCalibration.java index eca9a82..ed70a09 100644 --- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/SoundLevelCalibration.java +++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/SoundLevelCalibration.java @@ -25,7 +25,7 @@ import android.util.Log; class SoundLevelCalibration { private static final int SECONDS_PER_LEVEL = 1; private static final int MAX_STEPS = 15; // The maximum number of levels that should be tried - private static final double CRITICAL_RATIO = 0.4; // Ratio of input over output amplitude at + private static final double CRITICAL_RATIO = 0.41; // Ratio of input over output amplitude at // which the feedback loop neither decays nor // grows (determined experimentally) private static final String TAG = "SoundLevelCalibration"; @@ -68,34 +68,39 @@ class SoundLevelCalibration { // TODO: Allow stopping in the middle of calibration int calibrate() { final int maxLevel = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - int delta = (maxLevel + MAX_STEPS - 1) / MAX_STEPS; // round up - int level; - // TODO: Use a better algorithm such as binary search. - for(level = maxLevel; level >= 0; level -= delta) { - mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, level, 0); - if (mChangeListener != null) { - mChangeListener.go(level); - } - - mNativeAudioThread.start(); - try { - mNativeAudioThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - double[] data = mNativeAudioThread.getWaveData(); + int levelBottom = 0; + int levelTop = maxLevel + 1; + while(levelTop - levelBottom > 1) { + int level = (levelBottom + levelTop) / 2; + Log.d(TAG, "setting level to " + level); + setVolume(level); + + double amplitude = runAudioThread(mNativeAudioThread); mNativeAudioThread = new NativeAudioThread(mNativeAudioThread); // generate fresh thread - double amplitude = averageAmplitude(data); Log.d(TAG, "calibrate: at sound level " + level + " volume was " + amplitude); if (amplitude < Constant.SINE_WAVE_AMPLITUDE * CRITICAL_RATIO) { - Log.d(TAG, "calibrate: chose sound level " + level); - break; + levelBottom = level; + } else { + levelTop = level; } } + // At this point, levelBottom has the highest proper value, if there is one (0 otherwise) + Log.d(TAG, "Final level: " + levelBottom); + setVolume(levelBottom); + return levelBottom; + } - // Return the maximum level if we can't find a proper one - return level != 0 ? level : maxLevel; + private double runAudioThread(NativeAudioThread thread) { + // runs the native audio thread and returns the average amplitude + thread.start(); + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + double[] data = thread.getWaveData(); + return averageAmplitude(data); } // TODO: Only gives accurate results for an undistorted sine wave. Check for distortion. @@ -110,6 +115,13 @@ class SoundLevelCalibration { return Math.sqrt(2.0 * sumSquare / data.length); // amplitude of the sine wave } + private void setVolume(int level) { + mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, level, 0); + if (mChangeListener != null) { + mChangeListener.go(level); + } + } + void setChangeListener(SoundLevelChangeListener changeListener) { mChangeListener = changeListener; } diff --git a/LoopbackApp/app/src/main/jni/sles.cpp b/LoopbackApp/app/src/main/jni/sles.cpp index 36a096c..159269b 100644 --- a/LoopbackApp/app/src/main/jni/sles.cpp +++ b/LoopbackApp/app/src/main/jni/sles.cpp @@ -45,7 +45,7 @@ int slesInit(sles_data ** ppSles, int samplingRate, int frameCount, int micSourc memset(pSles, 0, sizeof(sles_data)); - SLES_PRINTF("malloc %zu bytes at %p", sizeof(sles_data), pSles); + SLES_PRINTF("pSles malloc %zu bytes at %p", sizeof(sles_data), pSles); //__android_log_print(ANDROID_LOG_INFO, "sles_jni", //"malloc %d bytes at %p", sizeof(sles_data), pSles);//Or ANDROID_LOG_INFO, ... *ppSles = pSles; @@ -70,6 +70,7 @@ int slesDestroy(sles_data ** ppSles) { if (*ppSles != NULL) { + SLES_PRINTF("free memory at %p",*ppSles); free(*ppSles); *ppSles = 0; } @@ -533,9 +534,13 @@ int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount, int mic // Initialize free buffers pSles->freeBuffers = (char **) calloc(pSles->freeBufCount + 1, sizeof(char *)); + SLES_PRINTF(" calloc freeBuffers %zu bytes at %p",pSles->freeBufCount + 1, + pSles->freeBuffers); unsigned j; for (j = 0; j < pSles->freeBufCount; ++j) { pSles->freeBuffers[j] = (char *) malloc(pSles->bufSizeInBytes); + SLES_PRINTF(" buff%d malloc %zu bytes at %p",j, pSles->bufSizeInBytes, + pSles->freeBuffers[j]); } pSles->freeFront = 0; pSles->freeRear = pSles->freeBufCount; @@ -543,11 +548,13 @@ int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount, int mic // Initialize record queue pSles->rxBuffers = (char **) calloc(pSles->rxBufCount + 1, sizeof(char *)); + SLES_PRINTF(" calloc rxBuffers %zu bytes at %p",pSles->rxBufCount + 1, pSles->rxBuffers); pSles->rxFront = 0; pSles->rxRear = 0; // Initialize play queue pSles->txBuffers = (char **) calloc(pSles->txBufCount + 1, sizeof(char *)); + SLES_PRINTF(" calloc txBuffers %zu bytes at %p",pSles->txBufCount + 1, pSles->txBuffers); pSles->txFront = 0; pSles->txRear = 0; @@ -970,8 +977,35 @@ int slesDestroyServer(sles_data *pSles) { (*(pSles->engineObject))->Destroy(pSles->engineObject); SLES_PRINTF("slesDestroyServer 7"); -// free(pSles); -// pSles = NULL; + //free buffers + if (NULL != pSles->freeBuffers) { + for (unsigned j = 0; j < pSles->freeBufCount; ++j) { + if (NULL != pSles->freeBuffers[j]) { + SLES_PRINTF(" free buff%d at %p",j, pSles->freeBuffers[j]); + free (pSles->freeBuffers[j]); + } + } + SLES_PRINTF(" free freeBuffers at %p", pSles->freeBuffers); + free(pSles->freeBuffers); + } else { + SLES_PRINTF(" freeBuffers NULL, no need to free"); + } + + + if (NULL != pSles->rxBuffers) { + SLES_PRINTF(" free rxBuffers at %p", pSles->rxBuffers); + free(pSles->rxBuffers); + } else { + SLES_PRINTF(" rxBuffers NULL, no need to free"); + } + + if (NULL != pSles->txBuffers) { + SLES_PRINTF(" free txBuffers at %p", pSles->txBuffers); + free(pSles->txBuffers); + } else { + SLES_PRINTF(" txBuffers NULL, no need to free"); + } + status = SLES_SUCCESS; } diff --git a/LoopbackApp/app/src/main/res/raw/loopback_listener b/LoopbackApp/app/src/main/res/raw/loopback_listener index bcbce2c..a29b0c9 100644 --- a/LoopbackApp/app/src/main/res/raw/loopback_listener +++ b/LoopbackApp/app/src/main/res/raw/loopback_listener @@ -63,13 +63,6 @@ do echo "LOOPBACK LISTENER: Finished capture" - # Check for case that test has ended while capturing state and exit - if [ -e "$SIGNAL_FILE" ] && [ -s "$SIGNAL_FILE" ] \ - && [ $(cat $SIGNAL_FILE) == $TERMINATE_SIGNAL ] - then - exitListener - fi - rm $SIGNAL_FILE fi fi diff --git a/LoopbackApp/build.gradle b/LoopbackApp/build.gradle index 9d5a7a8..f1cc249 100644 --- a/LoopbackApp/build.gradle +++ b/LoopbackApp/build.gradle @@ -4,7 +4,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle-experimental:0.6.0' + classpath 'com.android.tools.build:gradle-experimental:0.9.0' } } diff --git a/LoopbackApp/gradle/wrapper/gradle-wrapper.properties b/LoopbackApp/gradle/wrapper/gradle-wrapper.properties index 23b4dd3..dde259e 100644 --- a/LoopbackApp/gradle/wrapper/gradle-wrapper.properties +++ b/LoopbackApp/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Apr 19 06:51:07 PDT 2016 +#Tue Mar 21 12:29:44 PDT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip |