diff --git a/apps/OboeTester/app/src/main/cpp/FullDuplexAnalyzer.cpp b/apps/OboeTester/app/src/main/cpp/FullDuplexAnalyzer.cpp index 243c647c8..db8f0b0af 100644 --- a/apps/OboeTester/app/src/main/cpp/FullDuplexAnalyzer.cpp +++ b/apps/OboeTester/app/src/main/cpp/FullDuplexAnalyzer.cpp @@ -45,10 +45,13 @@ oboe::DataCallbackResult FullDuplexAnalyzer::onBothStreamsReadyFloat( (void) getLoopbackProcessor()->process(inputFloat, inputStride, numInputFrames, outputFloat, outputStride, numOutputFrames); - // write the first channel of output and input to the stereo recorder + // Save data for later analysis or for writing to a WAVE file. if (mRecording != nullptr) { float buffer[2]; int numBoth = std::min(numInputFrames, numOutputFrames); + // Offset to the selected channels that we are analyzing. + inputFloat += getLoopbackProcessor()->getInputChannel(); + outputFloat += getLoopbackProcessor()->getOutputChannel(); for (int i = 0; i < numBoth; i++) { buffer[0] = *outputFloat; outputFloat += outputStride; diff --git a/apps/OboeTester/app/src/main/cpp/analyzer/BaseSineAnalyzer.h b/apps/OboeTester/app/src/main/cpp/analyzer/BaseSineAnalyzer.h index b9ae220fc..6adb115be 100644 --- a/apps/OboeTester/app/src/main/cpp/analyzer/BaseSineAnalyzer.h +++ b/apps/OboeTester/app/src/main/cpp/analyzer/BaseSineAnalyzer.h @@ -58,22 +58,6 @@ class BaseSineAnalyzer : public LoopbackProcessor { return mMagnitude; } - void setInputChannel(int inputChannel) { - mInputChannel = inputChannel; - } - - int getInputChannel() const { - return mInputChannel; - } - - void setOutputChannel(int outputChannel) { - mOutputChannel = outputChannel; - } - - int getOutputChannel() const { - return mOutputChannel; - } - void setNoiseAmplitude(double noiseAmplitude) { mNoiseAmplitude = noiseAmplitude; } @@ -113,7 +97,7 @@ class BaseSineAnalyzer : public LoopbackProcessor { // ALOGD("sin(%f) = %f, %f\n", mOutputPhase, sinOut, kPhaseIncrement); } for (int i = 0; i < channelCount; i++) { - frameData[i] = (i == mOutputChannel) ? output : 0.0f; + frameData[i] = (i == getOutputChannel()) ? output : 0.0f; } return RESULT_OK; } @@ -232,8 +216,6 @@ class BaseSineAnalyzer : public LoopbackProcessor { InfiniteRecording mInfiniteRecording; private: - int32_t mInputChannel = 0; - int32_t mOutputChannel = 0; float mTolerance = 0.10; // scaled from 0.0 to 1.0 float mNoiseAmplitude = 0.00; // Used to experiment with warbling caused by DRC. diff --git a/apps/OboeTester/app/src/main/cpp/analyzer/LatencyAnalyzer.h b/apps/OboeTester/app/src/main/cpp/analyzer/LatencyAnalyzer.h index 8ef3123fb..165ba140f 100644 --- a/apps/OboeTester/app/src/main/cpp/analyzer/LatencyAnalyzer.h +++ b/apps/OboeTester/app/src/main/cpp/analyzer/LatencyAnalyzer.h @@ -428,10 +428,41 @@ class LoopbackProcessor { reset(); } + /** + * Some analyzers may only look at one channel. + * You can optionally specify that channel here. + * + * @param inputChannel + */ + void setInputChannel(int inputChannel) { + mInputChannel = inputChannel; + } + + int getInputChannel() const { + return mInputChannel; + } + + /** + * Some analyzers may only generate one channel. + * You can optionally specify that channel here. + * + * @param outputChannel + */ + void setOutputChannel(int outputChannel) { + mOutputChannel = outputChannel; + } + + int getOutputChannel() const { + return mOutputChannel; + } + protected: int32_t mResetCount = 0; private: + + int32_t mInputChannel = 0; + int32_t mOutputChannel = 0; int32_t mSampleRate = kDefaultSampleRate; int32_t mResult = 0; }; diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/BaseAutoGlitchActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/BaseAutoGlitchActivity.java index 0c462a68c..46ec12a4e 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/BaseAutoGlitchActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/BaseAutoGlitchActivity.java @@ -22,9 +22,11 @@ import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.os.Bundle; +import android.os.Environment; import androidx.annotation.Nullable; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Locale; @@ -377,13 +379,13 @@ protected TestResult testCurrentConfigurations() throws InterruptedException { appendFailedSummary(" " + getConfigText(actualInConfig) + "\n"); appendFailedSummary(" " + getConfigText(actualOutConfig) + "\n"); appendFailedSummary(" " + resultText + "\n"); + saveRecordingAsWave(); mAutomatedTestRunner.incrementFailCount(); result = TEST_RESULT_FAILED; } else { mAutomatedTestRunner.incrementPassCount(); result = TEST_RESULT_PASSED; } - } mAutomatedTestRunner.flushLog(); @@ -397,6 +399,17 @@ protected TestResult testCurrentConfigurations() throws InterruptedException { return testResult; } + private void saveRecordingAsWave() { + File recordingDir = getExternalFilesDir(Environment.DIRECTORY_MUSIC); + File waveFile = new File(recordingDir, String.format("glitch_%03d.wav", getTestCount())); + int saveResult = saveWaveFile(waveFile.getAbsolutePath()); + if (saveResult > 0) { + appendFailedSummary("Saved in " + waveFile.getAbsolutePath() + "\n"); + } else { + appendFailedSummary("saveWaveFile() returned " + saveResult + "\n"); + } + } + protected int getTestCount() { return mAutomatedTestRunner.getTestCount(); }