OboeTester: major refactoring of NativeAudioContext
Use a different class for each test activity.
diff --git a/apps/OboeTester/app/src/main/cpp/FullDuplexStream.h b/apps/OboeTester/app/src/main/cpp/FullDuplexStream.h
index d892016..98cf5b7 100644
--- a/apps/OboeTester/app/src/main/cpp/FullDuplexStream.h
+++ b/apps/OboeTester/app/src/main/cpp/FullDuplexStream.h
@@ -43,6 +43,7 @@
}
virtual oboe::Result start();
+
virtual oboe::Result stop();
/**
diff --git a/apps/OboeTester/app/src/main/cpp/NativeAudioContext.cpp b/apps/OboeTester/app/src/main/cpp/NativeAudioContext.cpp
index db563b6..d113028 100644
--- a/apps/OboeTester/app/src/main/cpp/NativeAudioContext.cpp
+++ b/apps/OboeTester/app/src/main/cpp/NativeAudioContext.cpp
@@ -30,12 +30,50 @@
}
}
-NativeAudioContext::NativeAudioContext()
- : sineOscillators(MAX_SINE_OSCILLATORS)
- , sawtoothOscillators(MAX_SINE_OSCILLATORS) {
+bool ActivityContext::useCallback = true;
+bool ActivityContext::callbackReturnStop = false;
+int ActivityContext::callbackSize = 0;
+
+oboe::AudioStream * ActivityContext::getOutputStream() {
+ for (int32_t i = 0; i < kMaxStreams; i++) {
+ oboe::AudioStream *oboeStream = mOboeStreams[i];
+ if (oboeStream != nullptr) {
+ if (oboeStream->getDirection() == oboe::Direction::Output) {
+ return oboeStream;
+ }
+ }
+ }
+ return nullptr;
}
-void NativeAudioContext::close(int32_t streamIndex) {
+oboe::AudioStream * ActivityContext::getInputStream() {
+ for (int32_t i = 0; i < kMaxStreams; i++) {
+ oboe::AudioStream *oboeStream = mOboeStreams[i];
+ if (oboeStream != nullptr) {
+ if (oboeStream->getDirection() == oboe::Direction::Input) {
+ return oboeStream;
+ }
+ }
+ }
+ return nullptr;
+}
+
+void ActivityContext::freeStreamIndex(int32_t streamIndex) {
+ mOboeStreams[streamIndex] = nullptr;
+}
+
+int32_t ActivityContext::allocateStreamIndex() {
+ int32_t streamIndex = -1;
+ for (int32_t i = 0; i < kMaxStreams; i++) {
+ if (mOboeStreams[i] == nullptr) {
+ streamIndex = i;
+ break;
+ }
+ }
+ return streamIndex;
+}
+
+void ActivityContext::close(int32_t streamIndex) {
stopBlockingIOThread();
LOGD("%s() delete stream %d ", __func__, streamIndex);
@@ -44,15 +82,9 @@
delete mOboeStreams[streamIndex];
freeStreamIndex(streamIndex);
}
-
- LOGD("%s() delete nodes", __func__);
- manyToMulti.reset(nullptr);
- monoToMulti.reset(nullptr);
- mSinkFloat.reset();
- mSinkI16.reset();
}
-bool NativeAudioContext::isMMapUsed(int32_t streamIndex) {
+bool ActivityContext::isMMapUsed(int32_t streamIndex) {
oboe::AudioStream *oboeStream = getStream(streamIndex);
if (oboeStream != nullptr && oboeStream->usesAAudio()) {
if (mAAudioStream_isMMap == nullptr) {
@@ -76,39 +108,162 @@
return false;
}
-void NativeAudioContext::connectTone() {
-// if (monoToMulti != nullptr) {
-// LOGI("%s() mToneType = %d", __func__, mToneType);
-// switch (mToneType) {
-// case ToneType::SawPing:
-// sawPingGenerator.output.connect(&(monoToMulti->input));
-// monoToMulti->output.connect(&(mSinkFloat.get()->input));
-// monoToMulti->output.connect(&(mSinkI16.get()->input));
-// break;
-// case ToneType::Sine:
-// for (int i = 0; i < mChannelCount; i++) {
-// sineOscillators[i].output.connect(manyToMulti->inputs[i].get());
-// }
-// manyToMulti->output.connect(&(mSinkFloat.get()->input));
-// manyToMulti->output.connect(&(mSinkI16.get()->input));
-// break;
-// case ToneType::Impulse:
-// impulseGenerator.output.connect(&(monoToMulti->input));
-// monoToMulti->output.connect(&(mSinkFloat.get()->input));
-// monoToMulti->output.connect(&(mSinkI16.get()->input));
-// break;
-// case ToneType::Sawtooth:
-// for (int i = 0; i < mChannelCount; i++) {
-// sawtoothOscillators[i].output.connect(manyToMulti->inputs[i].get());
-// }
-// manyToMulti->output.connect(&(mSinkFloat.get()->input));
-// manyToMulti->output.connect(&(mSinkI16.get()->input));
-// break;
-// }
-// }
+oboe::Result ActivityContext::pause() {
+ LOGD("NativeAudioContext::%s() called", __func__);
+ oboe::Result result = oboe::Result::OK;
+ stopBlockingIOThread();
+ for (int32_t i = 0; i < kMaxStreams; i++) {
+ oboe::AudioStream *oboeStream = mOboeStreams[i];
+ if (oboeStream != nullptr) {
+ result = oboeStream->requestPause();
+ printScheduler();
+ }
+ }
+ return result;
}
-void NativeAudioContext::setChannelEnabled(int channelIndex, bool enabled) {
+oboe::Result ActivityContext::stopAllStreams() {
+ oboe::Result result = oboe::Result::OK;
+ stopBlockingIOThread();
+
+ for (int32_t i = 0; i < kMaxStreams; i++) {
+ oboe::AudioStream *oboeStream = mOboeStreams[i];
+ if (oboeStream != nullptr) {
+ result = oboeStream->requestStop();
+ printScheduler();
+ }
+ }
+ return result;
+}
+
+
+void ActivityContext::configureBuilder(bool isInput, oboe::AudioStreamBuilder &builder) {
+ // We needed the proxy because we did not know the channelCount when we setup the Builder.
+ if (useCallback) {
+ LOGD("ActivityContext::open() set callback to use oboeCallbackProxy, size = %d",
+ callbackSize);
+ builder.setCallback(&oboeCallbackProxy);
+ builder.setFramesPerCallback(callbackSize);
+ }
+}
+
+int ActivityContext::open(
+ jint nativeApi,
+ jint sampleRate,
+ jint channelCount,
+ jint format,
+ jint sharingMode,
+ jint performanceMode,
+ jint deviceId,
+ jint sessionId,
+ jint framesPerBurst,
+ jboolean isInput) {
+
+ oboe::AudioApi audioApi = oboe::AudioApi::Unspecified;
+ switch (nativeApi) {
+ case NATIVE_MODE_UNSPECIFIED:
+ case NATIVE_MODE_AAUDIO:
+ case NATIVE_MODE_OPENSLES:
+ audioApi = convertNativeApiToAudioApi(nativeApi);
+ break;
+ default:
+ return (jint) oboe::Result::ErrorOutOfRange;
+ }
+
+ int32_t streamIndex = allocateStreamIndex();
+ if (streamIndex < 0) {
+ LOGE("ActivityContext::open() stream array full");
+ return (jint) oboe::Result::ErrorNoFreeHandles;
+ }
+
+ if (channelCount < 0 || channelCount > 256) {
+ LOGE("ActivityContext::open() channels out of range");
+ return (jint) oboe::Result::ErrorOutOfRange;
+ }
+
+ // Create an audio output stream.
+ LOGD("ActivityContext::open() try to create OboeStream #%d", streamIndex);
+ oboe::AudioStreamBuilder builder;
+ builder.setChannelCount(channelCount)
+ ->setDirection(isInput ? oboe::Direction::Input : oboe::Direction::Output)
+ ->setSharingMode((oboe::SharingMode) sharingMode)
+ ->setPerformanceMode((oboe::PerformanceMode) performanceMode)
+ ->setDeviceId(deviceId)
+ ->setSessionId((oboe::SessionId) sessionId)
+ ->setSampleRate(sampleRate)
+ ->setFormat((oboe::AudioFormat) format);
+
+ configureBuilder(isInput, builder);
+
+ if (audioApi == oboe::AudioApi::OpenSLES) {
+ builder.setFramesPerCallback(framesPerBurst);
+ }
+ builder.setAudioApi(audioApi);
+
+ // Open a stream based on the builder settings.
+ oboe::AudioStream *oboeStream = nullptr;
+ oboe::Result result = builder.openStream(&oboeStream);
+ LOGD("ActivityContext::open() builder.openStream() returned %d", result);
+ if (result != oboe::Result::OK) {
+ delete oboeStream;
+ oboeStream = nullptr;
+ freeStreamIndex(streamIndex);
+ streamIndex = -1;
+ } else {
+ mOboeStreams[streamIndex] = oboeStream;
+
+ mChannelCount = oboeStream->getChannelCount(); // FIXME store per stream
+ mFramesPerBurst = oboeStream->getFramesPerBurst();
+ mSampleRate = oboeStream->getSampleRate();
+
+ finishOpen(isInput, oboeStream);
+ }
+
+ if (!useCallback) {
+ int numSamples = getFramesPerBlock() * mChannelCount;
+ dataBuffer = std::make_unique<float[]>(numSamples);
+ }
+
+ return ((int)result < 0) ? (int)result : streamIndex;
+}
+
+oboe::Result ActivityContext::start() {
+ LOGD("ActivityContext: %s() called", __func__);
+ oboe::Result result = oboe::Result::OK;
+ oboe::AudioStream *inputStream = getInputStream();
+ oboe::AudioStream *outputStream = getOutputStream();
+ if (inputStream == nullptr && outputStream == nullptr) {
+ LOGD("%s() - no streams defined", __func__);
+ return oboe::Result::ErrorInvalidState; // not open
+ }
+
+ stop();
+
+ configureForStart();
+
+ result = startStreams();
+
+ if (!useCallback && result == oboe::Result::OK) {
+ LOGD("start thread for blocking I/O");
+ // Instead of using the callback, start a thread that writes the stream.
+ threadEnabled.store(true);
+ dataThread = new std::thread(threadCallback, this);
+ }
+
+ return result;
+}
+
+// =================================================================== ActivityTestOutput
+void ActivityTestOutput::close(int32_t streamIndex) {
+ ActivityContext::close(streamIndex);
+ manyToMulti.reset(nullptr);
+ monoToMulti.reset(nullptr);
+ mSinkFloat.reset();
+ mSinkI16.reset();
+}
+
+
+void ActivityTestOutput::setChannelEnabled(int channelIndex, bool enabled) {
if (manyToMulti == nullptr) {
return;
}
@@ -128,292 +283,59 @@
}
}
-int32_t NativeAudioContext::allocateStreamIndex() {
- int32_t streamIndex = -1;
- for (int32_t i = 0; i < kMaxStreams; i++) {
- if (mOboeStreams[i] == nullptr) {
- streamIndex = i;
- break;
- }
- }
- return streamIndex;
-}
-
-void NativeAudioContext::freeStreamIndex(int32_t streamIndex) {
- mOboeStreams[streamIndex] = nullptr;
-}
-
-int NativeAudioContext::open(
- jint nativeApi,
- jint sampleRate,
- jint channelCount,
- jint format,
- jint sharingMode,
- jint performanceMode,
- jint deviceId,
- jint sessionId,
- jint framesPerBurst, jboolean isInput) {
-
- oboe::AudioApi audioApi = oboe::AudioApi::Unspecified;
- switch (nativeApi) {
- case NATIVE_MODE_UNSPECIFIED:
- case NATIVE_MODE_AAUDIO:
- case NATIVE_MODE_OPENSLES:
- audioApi = convertNativeApiToAudioApi(nativeApi);
- break;
- default:
- return (jint) oboe::Result::ErrorOutOfRange;
- }
-
- int32_t streamIndex = allocateStreamIndex();
- if (streamIndex < 0) {
- LOGE("NativeAudioContext::open() stream array full");
- return (jint) oboe::Result::ErrorNoFreeHandles;
- }
-
- if (channelCount < 0 || channelCount > 256) {
- LOGE("NativeAudioContext::open() channels out of range");
- return (jint) oboe::Result::ErrorOutOfRange;
- }
-
- // Create an audio output stream.
- LOGD("NativeAudioContext::open() try to create OboeStream #%d", streamIndex);
- oboe::AudioStreamBuilder builder;
- builder.setChannelCount(channelCount)
- ->setDirection(isInput ? oboe::Direction::Input : oboe::Direction::Output)
- ->setSharingMode((oboe::SharingMode) sharingMode)
- ->setPerformanceMode((oboe::PerformanceMode) performanceMode)
- ->setDeviceId(deviceId)
- ->setSessionId((oboe::SessionId) sessionId)
- ->setSampleRate(sampleRate)
- ->setFormat((oboe::AudioFormat) format);
-
- if (mActivityType == ActivityType::Echo) {
- if (mFullDuplexEcho.get() == nullptr) {
- mFullDuplexEcho = std::make_unique<FullDuplexEcho>();
- }
- // only output uses a callback, input is polled
- if (!isInput) {
- builder.setCallback(mFullDuplexEcho.get());
- }
- } else {
- // We needed the proxy because we did not know the channelCount when we setup the Builder.
- if (useCallback) {
- LOGD("NativeAudioContext::open() set callback to use oboeCallbackProxy, size = %d",
- callbackSize);
- builder.setCallback(&oboeCallbackProxy);
- builder.setFramesPerCallback(callbackSize);
- }
- }
-
- if (audioApi == oboe::AudioApi::OpenSLES) {
- builder.setFramesPerCallback(framesPerBurst);
- }
- builder.setAudioApi(audioApi);
-
- // Open a stream based on the builder settings.
- oboe::AudioStream *oboeStream = nullptr;
- oboe::Result result = builder.openStream(&oboeStream);
- LOGD("NativeAudioContext::open() open(b) returned %d", result);
- if (result != oboe::Result::OK) {
- delete oboeStream;
- oboeStream = nullptr;
- freeStreamIndex(streamIndex);
- streamIndex = -1;
- } else {
- mOboeStreams[streamIndex] = oboeStream;
-
- mChannelCount = oboeStream->getChannelCount(); // FIXME store per stream
- mFramesPerBurst = oboeStream->getFramesPerBurst();
- mSampleRate = oboeStream->getSampleRate();
-
- if (mActivityType == ActivityType::Echo) {
- if (isInput) {
- mFullDuplexEcho->setInputStream(oboeStream);
- } else {
- mFullDuplexEcho->setOutputStream(oboeStream);
- }
- }
- }
-
- return ((int)result < 0) ? (int)result : streamIndex;
-}
-
-oboe::AudioStream * NativeAudioContext::getOutputStream() {
- for (int32_t i = 0; i < kMaxStreams; i++) {
- oboe::AudioStream *oboeStream = mOboeStreams[i];
- if (oboeStream != nullptr) {
- if (oboeStream->getDirection() == oboe::Direction::Output) {
- return oboeStream;
- }
- }
- }
- return nullptr;
-}
-
-oboe::AudioStream * NativeAudioContext::getInputStream() {
- for (int32_t i = 0; i < kMaxStreams; i++) {
- oboe::AudioStream *oboeStream = mOboeStreams[i];
- if (oboeStream != nullptr) {
- if (oboeStream->getDirection() == oboe::Direction::Input) {
- return oboeStream;
- }
- }
- }
- return nullptr;
-}
-
-void NativeAudioContext::configureForActivityType() {
- oboe::AudioStream *outputStream = nullptr;
-
+void ActivityTestOutput::configureForStart() {
manyToMulti = std::make_unique<ManyToMultiConverter>(mChannelCount);
- monoToMulti = std::make_unique<MonoToMultiConverter>(mChannelCount);
mSinkFloat = std::make_unique<SinkFloat>(mChannelCount);
mSinkI16 = std::make_unique<SinkI16>(mChannelCount);
- // TODO Use ActivityContext classes instead of switches.
- switch(mActivityType) {
- case ActivityType::Undefined:
- break;
- case ActivityType::TestInput:
- case ActivityType::RecordPlay:
- mInputAnalyzer.reset();
- if (useCallback) {
- oboeCallbackProxy.setCallback(&mInputAnalyzer);
- }
- mRecording = std::make_unique<MultiChannelRecording>(mChannelCount,
- SECONDS_TO_RECORD * mSampleRate);
- mInputAnalyzer.setRecording(mRecording.get());
- break;
-
- case ActivityType::TestOutput:
- outputStream = getOutputStream();
- {
- double frequency = 440.0;
- for (int i = 0; i < mChannelCount; i++) {
- sineOscillators[i].setSampleRate(outputStream->getSampleRate());
- sineOscillators[i].frequency.setValue(frequency);
- frequency *= 4.0 / 3.0; // each sine is at a higher frequency
- sineOscillators[i].amplitude.setValue(AMPLITUDE_SINE);
- sineOscillators[i].output.connect(manyToMulti->inputs[i].get());
- }
- }
-
- manyToMulti->output.connect(&(mSinkFloat.get()->input));
- manyToMulti->output.connect(&(mSinkI16.get()->input));
- break;
-
- case ActivityType::TapToTone:
- outputStream = getOutputStream();
- sawPingGenerator.setSampleRate(outputStream->getSampleRate());
- sawPingGenerator.frequency.setValue(FREQUENCY_SAW_PING);
- sawPingGenerator.amplitude.setValue(AMPLITUDE_SAW_PING);
-
- sawPingGenerator.output.connect(&(monoToMulti->input));
- monoToMulti->output.connect(&(mSinkFloat.get()->input));
- monoToMulti->output.connect(&(mSinkI16.get()->input));
-
- sawPingGenerator.setEnabled(false);
- break;
-
- case ActivityType::Echo:
- break;
- }
-
- if (outputStream != nullptr) {
-
- mSinkFloat->start();
- mSinkI16->start();
-
- // We needed the proxy because we did not know the channelCount
- // when we setup the Builder.
- if (outputStream->getFormat() == oboe::AudioFormat::I16) {
- audioStreamGateway.setAudioSink(mSinkI16);
- } else if (outputStream->getFormat() == oboe::AudioFormat::Float) {
- audioStreamGateway.setAudioSink(mSinkFloat);
- }
-
- if (useCallback) {
- oboeCallbackProxy.setCallback(&audioStreamGateway);
- }
-
- // Set starting size of buffer.
- constexpr int kDefaultNumBursts = 2; // "double buffer"
- int32_t numBursts = kDefaultNumBursts;
- // callbackSize is used for both callbacks and blocking write
- numBursts = (callbackSize <= mFramesPerBurst)
- ? kDefaultNumBursts
- : ((callbackSize * kDefaultNumBursts) + mFramesPerBurst - 1)
- / mFramesPerBurst;
- outputStream->setBufferSizeInFrames(numBursts * mFramesPerBurst);
- }
-
- if (!useCallback) {
- int numSamples = getFramesPerBlock() * mChannelCount;
- dataBuffer = std::make_unique<float[]>(numSamples);
- }
-}
-
-oboe::Result NativeAudioContext::start() {
- oboe::Result result = oboe::Result::OK;
- oboe::AudioStream *inputStream = getInputStream();
oboe::AudioStream *outputStream = getOutputStream();
- if (inputStream == nullptr && outputStream == nullptr) {
- return oboe::Result::ErrorInvalidState; // not open
+ {
+ double frequency = 440.0;
+ for (int i = 0; i < mChannelCount; i++) {
+ sineOscillators[i].setSampleRate(outputStream->getSampleRate());
+ sineOscillators[i].frequency.setValue(frequency);
+ frequency *= 4.0 / 3.0; // each sine is at a higher frequency
+ sineOscillators[i].amplitude.setValue(AMPLITUDE_SINE);
+ sineOscillators[i].output.connect(manyToMulti->inputs[i].get());
+ }
}
- stop();
+ manyToMulti->output.connect(&(mSinkFloat.get()->input));
+ manyToMulti->output.connect(&(mSinkI16.get()->input));
- LOGD("NativeAudioContext: %s() called", __func__);
- configureForActivityType();
-
- switch(mActivityType) {
- case ActivityType::Undefined:
- break;
- case ActivityType::TestInput:
- case ActivityType::RecordPlay:
- result = inputStream->requestStart();
- if (!useCallback && result == oboe::Result::OK) {
- LOGD("start thread for blocking I/O");
- // Instead of using the callback, start a thread that readsthe stream.
- threadEnabled.store(true);
- dataThread = new std::thread(threadCallback, this);
- }
- break;
-
- case ActivityType::TestOutput:
- case ActivityType::TapToTone:
- result = outputStream->requestStart();
- if (!useCallback && result == oboe::Result::OK) {
- LOGD("start thread for blocking I/O");
- // Instead of using the callback, start a thread that writes the stream.
- threadEnabled.store(true);
- dataThread = new std::thread(threadCallback, this);
- }
- break;
-
- case ActivityType::Echo:
- result = mFullDuplexEcho->start();
- break;
- }
-
- LOGD("OboeAudioStream_start: start returning %d", result);
- return result;
+ configureStreamGateway();
}
-void NativeAudioContext::runBlockingIO() {
+void ActivityTestOutput::configureStreamGateway() {
+ oboe::AudioStream *outputStream = getOutputStream();
+ if (outputStream->getFormat() == oboe::AudioFormat::I16) {
+ audioStreamGateway.setAudioSink(mSinkI16);
+ } else if (outputStream->getFormat() == oboe::AudioFormat::Float) {
+ audioStreamGateway.setAudioSink(mSinkFloat);
+ }
+
+ if (useCallback) {
+ oboeCallbackProxy.setCallback(&audioStreamGateway);
+ }
+
+ // Set starting size of buffer.
+ constexpr int kDefaultNumBursts = 2; // "double buffer"
+ int32_t numBursts = kDefaultNumBursts;
+ // callbackSize is used for both callbacks and blocking write
+ numBursts = (callbackSize <= mFramesPerBurst)
+ ? kDefaultNumBursts
+ : ((callbackSize * kDefaultNumBursts) + mFramesPerBurst - 1)
+ / mFramesPerBurst;
+ outputStream->setBufferSizeInFrames(numBursts * mFramesPerBurst);
+
+}
+
+void ActivityTestOutput::runBlockingIO() {
int32_t framesPerBlock = getFramesPerBlock();
oboe::DataCallbackResult callbackResult = oboe::DataCallbackResult::Continue;
- // TODO rethink which stream gets the callback for full duplex
- oboe::AudioStream *oboeStream = nullptr;
- for (int32_t i = 0; i < kMaxStreams; i++) {
- if (mOboeStreams[i] != nullptr) {
- oboeStream = mOboeStreams[i];
- break;
- }
- }
+ oboe::AudioStream *oboeStream = getOutputStream();
if (oboeStream == nullptr) {
LOGE("%s() : no stream found\n", __func__);
return;
@@ -421,45 +343,144 @@
while (threadEnabled.load()
&& callbackResult == oboe::DataCallbackResult::Continue) {
- if (oboeStream->getDirection() == oboe::Direction::Input) {
- // read from input
- auto result = oboeStream->read(dataBuffer.get(),
- framesPerBlock,
- NANOS_PER_SECOND);
- if (!result) {
- LOGE("%s() : read() returned %s\n", __func__, convertToText(result.error()));
- break;
- }
- int32_t framesRead = result.value();
- if (framesRead < framesPerBlock) { // timeout?
- LOGE("%s() : read() read %d of %d\n", __func__, framesRead, framesPerBlock);
- break;
- }
-
- // analyze input
- callbackResult = mInputAnalyzer.onAudioReady(oboeStream,
+ // generate output by calling the callback
+ callbackResult = audioStreamGateway.onAudioReady(oboeStream,
dataBuffer.get(),
- framesRead);
- } else { // OUTPUT?
- // generate output by calling the callback
- callbackResult = audioStreamGateway.onAudioReady(oboeStream,
- dataBuffer.get(),
- framesPerBlock);
+ framesPerBlock);
- auto result = oboeStream->write(dataBuffer.get(),
- framesPerBlock,
- NANOS_PER_SECOND);
+ auto result = oboeStream->write(dataBuffer.get(),
+ framesPerBlock,
+ NANOS_PER_SECOND);
- if (!result) {
- LOGE("%s() returned %s\n", __func__, convertToText(result.error()));
- break;
- }
- int32_t framesWritten = result.value();
- if (framesWritten < framesPerBlock) {
- LOGE("%s() : write() wrote %d of %d\n", __func__, framesWritten, framesPerBlock);
- break;
- }
+ if (!result) {
+ LOGE("%s() returned %s\n", __func__, convertToText(result.error()));
+ break;
+ }
+ int32_t framesWritten = result.value();
+ if (framesWritten < framesPerBlock) {
+ LOGE("%s() : write() wrote %d of %d\n", __func__, framesWritten, framesPerBlock);
+ break;
}
}
+}
+// ======================================================================= ActivityTestInput
+void ActivityTestInput::configureForStart() {
+ mInputAnalyzer.reset();
+ if (useCallback) {
+ oboeCallbackProxy.setCallback(&mInputAnalyzer);
+ }
+ mRecording = std::make_unique<MultiChannelRecording>(mChannelCount,
+ SECONDS_TO_RECORD * mSampleRate);
+ mInputAnalyzer.setRecording(mRecording.get());
+}
+
+void ActivityTestInput::runBlockingIO() {
+ int32_t framesPerBlock = getFramesPerBlock();
+ oboe::DataCallbackResult callbackResult = oboe::DataCallbackResult::Continue;
+
+ oboe::AudioStream *oboeStream = getInputStream();
+ if (oboeStream == nullptr) {
+ LOGE("%s() : no stream found\n", __func__);
+ return;
+ }
+
+ while (threadEnabled.load()
+ && callbackResult == oboe::DataCallbackResult::Continue) {
+ // read from input
+ auto result = oboeStream->read(dataBuffer.get(),
+ framesPerBlock,
+ NANOS_PER_SECOND);
+ if (!result) {
+ LOGE("%s() : read() returned %s\n", __func__, convertToText(result.error()));
+ break;
+ }
+ int32_t framesRead = result.value();
+ if (framesRead < framesPerBlock) { // timeout?
+ LOGE("%s() : read() read %d of %d\n", __func__, framesRead, framesPerBlock);
+ break;
+ }
+
+ // analyze input
+ callbackResult = mInputAnalyzer.onAudioReady(oboeStream,
+ dataBuffer.get(),
+ framesRead);
+ }
+}
+
+oboe::Result ActivityRecording::stopPlayback() {
+ LOGD("ActivityRecording::%s() called", __func__);
+ oboe::Result result = oboe::Result::OK;
+ if (playbackStream != nullptr) {
+ result = playbackStream->requestStop();
+ playbackStream->close();
+ mPlayRecordingCallback.setRecording(nullptr);
+ delete playbackStream;
+ playbackStream = nullptr;
+ }
+ return result;
+}
+
+oboe::Result ActivityRecording::startPlayback() {
+ stop();
+ LOGD("ActivityRecording::%s() called", __func__);
+ oboe::AudioStreamBuilder builder;
+ builder.setChannelCount(mChannelCount)
+ ->setSampleRate(mSampleRate)
+ ->setFormat(oboe::AudioFormat::Float)
+ ->setCallback(&mPlayRecordingCallback)
+ ->setAudioApi(oboe::AudioApi::OpenSLES);
+ oboe::Result result = builder.openStream(&playbackStream);
+ LOGD("ActivityRecording::%s() openStream() returned %d", __func__, result);
+ if (result != oboe::Result::OK) {
+ delete playbackStream;
+ playbackStream = nullptr;
+ } else if (playbackStream != nullptr) {
+ if (mRecording != nullptr) {
+ mRecording->rewind();
+ mPlayRecordingCallback.setRecording(mRecording.get());
+ result = playbackStream->requestStart();
+ }
+ }
+ return result;
+}
+
+
+// ======================================================================= ActivityTapToTone
+void ActivityTapToTone::configureForStart() {
+ monoToMulti = std::make_unique<MonoToMultiConverter>(mChannelCount);
+
+ mSinkFloat = std::make_unique<SinkFloat>(mChannelCount);
+ mSinkI16 = std::make_unique<SinkI16>(mChannelCount);
+
+ oboe::AudioStream *outputStream = getOutputStream();
+ sawPingGenerator.setSampleRate(outputStream->getSampleRate());
+ sawPingGenerator.frequency.setValue(FREQUENCY_SAW_PING);
+ sawPingGenerator.amplitude.setValue(AMPLITUDE_SAW_PING);
+
+ sawPingGenerator.output.connect(&(monoToMulti->input));
+ monoToMulti->output.connect(&(mSinkFloat.get()->input));
+ monoToMulti->output.connect(&(mSinkI16.get()->input));
+
+ sawPingGenerator.setEnabled(false);
+ configureStreamGateway();
+}
+
+// ======================================================================= ActivityEcho
+void ActivityEcho::configureBuilder(bool isInput, oboe::AudioStreamBuilder &builder) {
+ if (mFullDuplexEcho.get() == nullptr) {
+ mFullDuplexEcho = std::make_unique<FullDuplexEcho>();
+ }
+ // only output uses a callback, input is polled
+ if (!isInput) {
+ builder.setCallback(mFullDuplexEcho.get());
+ }
+}
+
+void ActivityEcho::finishOpen(bool isInput, oboe::AudioStream *oboeStream) {
+ if (isInput) {
+ mFullDuplexEcho->setInputStream(oboeStream);
+ } else {
+ mFullDuplexEcho->setOutputStream(oboeStream);
+ }
}
diff --git a/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h b/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h
index ec0d3e9..e0a273e 100644
--- a/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h
+++ b/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h
@@ -62,23 +62,20 @@
#define FUNCTION_IS_MMAP "AAudioStream_isMMapUsed"
/**
- * Implement the native API for the Oboe Tester.
- * Manage a stream.
- * Generate signals, etc.
+ * Abstract base class that corresponds to a test at the Java level.
*/
-class NativeAudioContext {
+class ActivityContext {
public:
- NativeAudioContext();
-
- void close(int32_t streamIndex);
-
- bool isMMapUsed(int32_t streamIndex);
+ ActivityContext() {}
+ virtual ~ActivityContext() = default;
oboe::AudioStream *getStream(int32_t streamIndex) {
return mOboeStreams[streamIndex]; // TODO range check
}
+ virtual void configureBuilder(bool isInput, oboe::AudioStreamBuilder &builder);
+
int open(jint nativeApi,
jint sampleRate,
jint channelCount,
@@ -87,163 +84,202 @@
jint performanceMode,
jint deviceId,
jint sessionId,
- jint framesPerBurst, jboolean isInput);
+ jint framesPerBurst,
+ jboolean isInput);
- void setToneType(int toneType) {
- LOGI("%s(%d)", __func__, toneType);
- mToneType = (ToneType) toneType;
- // connectTone();
- }
- int32_t getFramesPerBlock() {
- return (callbackSize == 0) ? mFramesPerBurst : callbackSize;
- }
+ virtual void close(int32_t streamIndex);
void printScheduler() {
int scheduler = audioStreamGateway.getScheduler();
LOGI("scheduler = 0x%08x, SCHED_FIFO = 0x%08X\n", scheduler, SCHED_FIFO);
}
- oboe::Result pause() {
- LOGD("NativeAudioContext::%s() called", __func__);
- oboe::Result result = oboe::Result::OK;
- stopBlockingIOThread();
- for (int32_t i = 0; i < kMaxStreams; i++) {
- oboe::AudioStream *oboeStream = mOboeStreams[i];
- if (oboeStream != nullptr) {
- result = oboeStream->requestPause();
- printScheduler();
- }
- }
- return result;
+ virtual void configureForStart() {}
+
+ oboe::Result start();
+
+ oboe::Result pause();
+
+ oboe::Result stopAllStreams();
+
+ virtual oboe::Result stop() {
+ return stopAllStreams();
}
- oboe::Result stopAudio() {
- LOGD("NativeAudioContext::%s() called", __func__);
- oboe::Result result = oboe::Result::OK;
- stopBlockingIOThread();
+ virtual void setAmplitude(double amplitude) {}
- for (int32_t i = 0; i < kMaxStreams; i++) {
- oboe::AudioStream *oboeStream = mOboeStreams[i];
- if (oboeStream != nullptr) {
- result = oboeStream->requestStop();
- printScheduler();
- }
- }
- LOGD("NativeAudioContext::%s() returns %d", __func__, result);
- return result;
+ virtual oboe::Result startPlayback() {
+ return oboe::Result::OK;
}
- oboe::Result stopPlayback() {
- LOGD("NativeAudioContext::%s() called", __func__);
- oboe::Result result = oboe::Result::OK;
- if (playbackStream != nullptr) {
- result = playbackStream->requestStop();
- playbackStream->close();
- mPlayRecordingCallback.setRecording(nullptr);
- delete playbackStream;
- playbackStream = nullptr;
- }
- return result;
+ virtual oboe::Result stopPlayback() {
+ return oboe::Result::OK;
}
- oboe::Result stop() {
- oboe::Result resultStopPlayback = stopPlayback();
- oboe::Result resultStopAudio = stopAudio();
+ virtual void runBlockingIO() {};
- LOGD("NativeAudioContext::%s() stop modules", __func__);
- for (int i = 0; i < mChannelCount; i++) {
- sineOscillators[i].stop();
- sawtoothOscillators[i].stop();
- }
- impulseGenerator.stop();
- sawPingGenerator.stop();
- if (mSinkFloat) {
- mSinkFloat->stop();
- }
- if (mSinkI16) {
- mSinkI16->stop();
- }
-
- oboe::Result result = (resultStopPlayback != oboe::Result::OK)
- ? resultStopPlayback
- : resultStopAudio;
-
- LOGD("NativeAudioContext::%s() returns %d", __func__, result);
- return result;
- }
-
- oboe::Result startPlayback() {
- stop();
- LOGD("NativeAudioContext::%s() called", __func__);
- oboe::AudioStreamBuilder builder;
- builder.setChannelCount(mChannelCount)
- ->setSampleRate(mSampleRate)
- ->setFormat(oboe::AudioFormat::Float)
- ->setCallback(&mPlayRecordingCallback)
- ->setAudioApi(oboe::AudioApi::OpenSLES);
- oboe::Result result = builder.openStream(&playbackStream);
- LOGD("NativeAudioContext::startPlayback() openStream() returned %d", result);
- if (result != oboe::Result::OK) {
- delete playbackStream;
- playbackStream = nullptr;
- } else if (playbackStream != nullptr) {
- if (mRecording != nullptr) {
- mRecording->rewind();
- mPlayRecordingCallback.setRecording(mRecording.get());
- result = playbackStream->requestStart();
- }
- }
- return result;
- }
-
- static void threadCallback(NativeAudioContext *context) {
+ static void threadCallback(ActivityContext *context) {
LOGD("%s: called", __func__);
context->runBlockingIO();
LOGD("%s: exiting", __func__);
}
- oboe::Result start();
-
- void setToneEnabled(bool enabled) {
- LOGD("%s(%d)", __func__, enabled ? 1 : 0);
- sawPingGenerator.setEnabled(enabled);
- }
-
- void setAmplitude(double amplitude) {
- LOGD("%s(%f)", __func__, amplitude);
- for (int i = 0; i < mChannelCount; i++) {
- sineOscillators[i].amplitude.setValue(amplitude);
- sawtoothOscillators[i].amplitude.setValue(amplitude);
+ void stopBlockingIOThread() {
+ if (dataThread != nullptr) {
+ // stop a thread that runs in place of the callback
+ threadEnabled.store(false); // ask thread to exit its loop
+ dataThread->join();
+ dataThread = nullptr;
}
- sawPingGenerator.amplitude.setValue(amplitude);
- impulseGenerator.amplitude.setValue(amplitude);
}
- void setCallbackReturnStop(bool b) {
- oboeCallbackProxy.setCallbackReturnStop(b);
+ virtual double getPeakLevel(int index) {
+ return 0.0;
+ }
+
+ virtual void setEnabled(bool enabled) {
+ }
+
+ bool isMMapUsed(int32_t streamIndex);
+
+ int32_t getFramesPerBlock() {
+ return (callbackSize == 0) ? mFramesPerBurst : callbackSize;
}
int64_t getCallbackCount() {
return oboeCallbackProxy.getCallbackCount();
}
- void setChannelEnabled(int channelIndex, bool enabled);
- void setActivityType(int activityType) {
- LOGD("%s(%d)", __func__, activityType);
- mActivityType = (ActivityType) activityType;
- }
+ virtual void setChannelEnabled(int channelIndex, bool enabled) {}
- double getPeakLevel(int index) {
+ static bool useCallback;
+ static bool callbackReturnStop;
+ static int callbackSize;
+
+
+protected:
+ oboe::AudioStream * getInputStream();
+ oboe::AudioStream * getOutputStream();
+ int32_t allocateStreamIndex();
+ void freeStreamIndex(int32_t streamIndex);
+
+ virtual void finishOpen(bool isInput, oboe::AudioStream *oboeStream) {}
+
+ virtual oboe::Result startStreams() = 0;
+
+ std::unique_ptr<float []> dataBuffer{};
+
+ AudioStreamGateway audioStreamGateway;
+ OboeStreamCallbackProxy oboeCallbackProxy;
+
+ static constexpr int kMaxStreams = 8;
+ oboe::AudioStream *mOboeStreams[kMaxStreams]{};
+ int32_t mFramesPerBurst = 0; // TODO per stream
+ int32_t mChannelCount = 0; // TODO per stream
+ int32_t mSampleRate = 0; // TODO per stream
+
+ std::atomic<bool> threadEnabled{false};
+ std::thread *dataThread = nullptr;
+
+ bool (*mAAudioStream_isMMap)(AAudioStream *stream) = nullptr;
+ void *mLibHandle = nullptr;
+
+private:
+};
+
+/**
+ * Test a single input stream.
+ */
+class ActivityTestInput : public ActivityContext {
+public:
+
+ ActivityTestInput() {}
+ virtual ~ActivityTestInput() = default;
+
+ void configureForStart() override;
+
+ double getPeakLevel(int index) override {
return mInputAnalyzer.getPeakLevel(index);
}
- bool useCallback = true;
- bool callbackReturnStop = false;
- int callbackSize = 0;
+ void runBlockingIO() override;
+
+ std::unique_ptr<MultiChannelRecording> mRecording{};
+
+ InputStreamCallbackAnalyzer mInputAnalyzer;
+
+protected:
+ oboe::Result startStreams() override {
+ return getInputStream()->requestStart();
+ }
private:
+};
+
+/**
+ * Record a configured input stream and play it back some simple way.
+ */
+class ActivityRecording : public ActivityTestInput {
+public:
+
+ ActivityRecording() {}
+ virtual ~ActivityRecording() = default;
+
+ oboe::Result stop() override {
+
+ oboe::Result resultStopPlayback = stopPlayback();
+ oboe::Result resultStopAudio = ActivityContext::stop();
+
+ oboe::Result result = (resultStopPlayback != oboe::Result::OK)
+ ? resultStopPlayback
+ : resultStopAudio;
+ return result;
+ }
+
+ oboe::Result startPlayback() override;
+
+ oboe::Result stopPlayback() override;
+
+ PlayRecordingCallback mPlayRecordingCallback;
+ oboe::AudioStream *playbackStream = nullptr;
+
+};
+
+/**
+ * Test a single output stream.
+ */
+class ActivityTestOutput : public ActivityContext {
+public:
+ ActivityTestOutput()
+ : sineOscillators(MAX_SINE_OSCILLATORS)
+ , sawtoothOscillators(MAX_SINE_OSCILLATORS) {}
+
+ virtual ~ActivityTestOutput() = default;
+
+ void close(int32_t streamIndex) override;
+
+ oboe::Result startStreams() override {
+ return getOutputStream()->requestStart();
+ }
+
+ void configureForStart() override;
+
+ virtual void configureStreamGateway();
+
+ void runBlockingIO() override;
+
+ void setAmplitude(double amplitude) override {
+ LOGD("%s(%f)", __func__, amplitude);
+ for (int i = 0; i < mChannelCount; i++) {
+ sineOscillators[i].amplitude.setValue(amplitude);
+ sawtoothOscillators[i].amplitude.setValue(amplitude);
+ }
+ impulseGenerator.amplitude.setValue(amplitude);
+ }
+
+ void setChannelEnabled(int channelIndex, bool enabled) override;
// WARNING - must match order in strings.xml and OboeAudioOutputStream.java
enum ToneType {
@@ -253,6 +289,98 @@
Sawtooth = 3
};
+protected:
+ ToneType mToneType = ToneType::Sine;
+ std::vector<SineOscillator> sineOscillators;
+ std::vector<SawtoothOscillator> sawtoothOscillators;
+
+ ImpulseOscillator impulseGenerator;
+
+ std::unique_ptr<ManyToMultiConverter> manyToMulti;
+ std::unique_ptr<MonoToMultiConverter> monoToMulti;
+ std::shared_ptr<flowgraph::SinkFloat> mSinkFloat;
+ std::shared_ptr<flowgraph::SinkI16> mSinkI16;
+};
+
+/**
+ * Generate a short beep with a very short attack.
+ * This is used by Java to measure output latency.
+ */
+class ActivityTapToTone : public ActivityTestOutput {
+public:
+ ActivityTapToTone() {}
+ virtual ~ActivityTapToTone() = default;
+
+ void configureForStart() override;
+
+ void setAmplitude(double amplitude) override {
+ LOGD("%s(%f)", __func__, amplitude);
+ ActivityTestOutput::setAmplitude(amplitude);
+ sawPingGenerator.amplitude.setValue(amplitude);
+ }
+
+ virtual void setEnabled(bool enabled) override {
+ sawPingGenerator.setEnabled(enabled);
+ }
+
+ SawPingGenerator sawPingGenerator;
+};
+
+/**
+ * Echo input to outp[ut through a delay line.
+ */
+class ActivityEcho : public ActivityContext {
+public:
+
+ oboe::Result startStreams() override {
+ return mFullDuplexEcho->start();
+ }
+
+ void configureBuilder(bool isInput, oboe::AudioStreamBuilder &builder) override;
+
+protected:
+ void finishOpen(bool isInput, oboe::AudioStream *oboeStream) override;
+
+private:
+ std::unique_ptr<FullDuplexEcho> mFullDuplexEcho{};
+};
+
+/**
+ * Switch between various
+ */
+class NativeAudioContext {
+public:
+
+ ActivityContext *getCurrentActivity() {
+ return currentActivity;
+ };
+
+ void setActivityType(int activityType) {
+ LOGD("%s(%d)", __func__, activityType);
+ mActivityType = (ActivityType) activityType;
+ switch(mActivityType) {
+ default:
+ case ActivityType::Undefined:
+ case ActivityType::TestOutput:
+ currentActivity = &mActivityTestOutput;
+ break;
+ case ActivityType::TestInput:
+ currentActivity = &mActivityTestInput;
+ break;
+ case ActivityType::TapToTone:
+ currentActivity = &mActivityTapToTone;
+ break;
+ case ActivityType::RecordPlay:
+ currentActivity = &mActivityRecording;
+ break;
+ case ActivityType::Echo:
+ currentActivity = &mActivityEcho;
+ break;
+ }
+ }
+
+private:
+
// WARNING - must match definitions in TestAudioActivity.java
enum ActivityType {
Undefined = -1,
@@ -263,65 +391,14 @@
Echo = 4
};
- oboe::AudioStream * getInputStream();
- oboe::AudioStream * getOutputStream();
-
- int32_t allocateStreamIndex();
-
- void configureForActivityType();
-
- void freeStreamIndex(int32_t streamIndex);
-
- void connectTone();
-
- void runBlockingIO();
-
- void stopBlockingIOThread() {
- if (!useCallback) {
- // stop a thread that runs in place of the callback
- threadEnabled.store(false); // ask thread to exit its loop
- if (dataThread != nullptr) {
- dataThread->join();
- dataThread = nullptr;
- }
- }
-
- }
-
- static constexpr int kMaxStreams = 8;
- oboe::AudioStream *mOboeStreams[kMaxStreams]{};
- int32_t mFramesPerBurst = 0; // TODO per stream
- int32_t mChannelCount = 0; // TODO per stream
- int32_t mSampleRate = 0; // TODO per stream
- ToneType mToneType = ToneType::Sine;
ActivityType mActivityType = ActivityType::Undefined;
+ ActivityTestOutput mActivityTestOutput;
+ ActivityTestInput mActivityTestInput;
+ ActivityTapToTone mActivityTapToTone;
+ ActivityRecording mActivityRecording;
+ ActivityEcho mActivityEcho;
- std::atomic<bool> threadEnabled{false};
- std::thread *dataThread = nullptr;
-
- OboeStreamCallbackProxy oboeCallbackProxy;
- AudioStreamGateway audioStreamGateway;
- InputStreamCallbackAnalyzer mInputAnalyzer;
-
- std::vector<SineOscillator> sineOscillators;
- std::vector<SawtoothOscillator> sawtoothOscillators;
-
- ImpulseOscillator impulseGenerator;
- SawPingGenerator sawPingGenerator;
- oboe::AudioStream *playbackStream = nullptr;
-
- std::unique_ptr<float []> dataBuffer{};
- std::unique_ptr<ManyToMultiConverter> manyToMulti;
- std::unique_ptr<MonoToMultiConverter> monoToMulti;
- std::shared_ptr<flowgraph::SinkFloat> mSinkFloat;
- std::shared_ptr<flowgraph::SinkI16> mSinkI16;
- std::unique_ptr<MultiChannelRecording> mRecording{};
- std::unique_ptr<FullDuplexEcho> mFullDuplexEcho{};
-
- PlayRecordingCallback mPlayRecordingCallback;
-
- bool (*mAAudioStream_isMMap)(AAudioStream *stream) = nullptr;
- void *mLibHandle = nullptr;
+ ActivityContext *currentActivity = &mActivityTestOutput;
};
diff --git a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp
index be75f63..2779c6b 100644
--- a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp
+++ b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp
@@ -27,7 +27,7 @@
#include "NativeAudioContext.h"
-static NativeAudioContext engine;
+NativeAudioContext engine;
/*********************************************************************************/
/********************** JNI Prototypes *****************************************/
@@ -48,14 +48,7 @@
jboolean isInput);
JNIEXPORT void JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_close(JNIEnv *env, jobject, jint);
-/*
-JNIEXPORT void JNICALL
-Java_com_google_sample_oboe_manualtest_TestAudioActivity_startNative(JNIEnv *env, jobject);
-JNIEXPORT void JNICALL
-Java_com_google_sample_oboe_manualtest_TestAudioActivity_pauseNative(JNIEnv *env, jobject);
-JNIEXPORT void JNICALL
-Java_com_google_sample_oboe_manualtest_TestAudioActivity_stopNative(JNIEnv *env, jobject);
-*/
+
JNIEXPORT jint JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_setThresholdInFrames(JNIEnv *env, jobject, jint, jint);
JNIEXPORT jint JNICALL
@@ -104,7 +97,7 @@
jboolean isInput) {
LOGD("OboeAudioStream_openNative: sampleRate = %d, framesPerBurst = %d", sampleRate, framesPerBurst);
- return (jint) engine.open(nativeApi,
+ return (jint) engine.getCurrentActivity()->open(nativeApi,
sampleRate,
channelCount,
format,
@@ -118,33 +111,33 @@
JNIEXPORT jint JNICALL
Java_com_google_sample_oboe_manualtest_TestAudioActivity_startNative(JNIEnv *env, jobject) {
- return (jint) engine.start();
+ return (jint) engine.getCurrentActivity()->start();
}
JNIEXPORT jint JNICALL
Java_com_google_sample_oboe_manualtest_TestAudioActivity_pauseNative(JNIEnv *env, jobject) {
- return (jint) engine.pause();
+ return (jint) engine.getCurrentActivity()->pause();
}
JNIEXPORT jint JNICALL
Java_com_google_sample_oboe_manualtest_TestAudioActivity_stopNative(JNIEnv *env, jobject) {
- return (jint) engine.stop();
+ return (jint) engine.getCurrentActivity()->stop();
}
JNIEXPORT jint JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_startPlaybackNative(JNIEnv *env, jobject) {
- return (jint) engine.startPlayback();
+ return (jint) engine.getCurrentActivity()->startPlayback();
}
JNIEXPORT void JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_close(JNIEnv *env, jobject, jint streamIndex) {
- engine.close(streamIndex);
+ engine.getCurrentActivity()->close(streamIndex);
}
JNIEXPORT jint JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_setBufferSizeInFrames(
JNIEnv *env, jobject, jint streamIndex, jint threshold) {
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
auto result = oboeStream->setBufferSizeInFrames(threshold);
return (!result)
@@ -158,7 +151,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getBufferSizeInFrames(
JNIEnv *env, jobject, jint streamIndex) {
jint result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = oboeStream->getBufferSizeInFrames();
}
@@ -169,7 +162,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getBufferCapacityInFrames(
JNIEnv *env, jobject, jint streamIndex) {
jint result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = oboeStream->getBufferCapacityInFrames();
}
@@ -193,7 +186,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getNativeApi(
JNIEnv *env, jobject, jint streamIndex) {
jint result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
oboe::AudioApi audioApi = oboeStream->getAudioApi();
result = convertAudioApiToNativeApi(audioApi);
@@ -206,7 +199,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getSampleRate(
JNIEnv *env, jobject, jint streamIndex) {
jint result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = oboeStream->getSampleRate();
}
@@ -217,7 +210,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getSharingMode(
JNIEnv *env, jobject, jint streamIndex) {
jint result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = (jint) oboeStream->getSharingMode();
}
@@ -228,7 +221,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getPerformanceMode(
JNIEnv *env, jobject, jint streamIndex) {
jint result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = (jint) oboeStream->getPerformanceMode();
}
@@ -239,7 +232,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getFramesPerBurst(
JNIEnv *env, jobject, jint streamIndex) {
jint result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = oboeStream->getFramesPerBurst();
}
@@ -250,7 +243,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getChannelCount(
JNIEnv *env, jobject, jint streamIndex) {
jint result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = oboeStream->getChannelCount();
}
@@ -260,7 +253,7 @@
JNIEXPORT jint JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getFormat(JNIEnv *env, jobject instance, jint streamIndex) {
jint result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = (jint) oboeStream->getFormat();
}
@@ -271,7 +264,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getDeviceId(
JNIEnv *env, jobject, jint streamIndex) {
jint result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = oboeStream->getDeviceId();
}
@@ -282,7 +275,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getSessionId(
JNIEnv *env, jobject, jint streamIndex) {
jint result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = oboeStream->getSessionId();
}
@@ -293,7 +286,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getFramesWritten(
JNIEnv *env, jobject, jint streamIndex) {
jlong result = (jint) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = oboeStream->getFramesWritten();
}
@@ -304,7 +297,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getFramesRead(
JNIEnv *env, jobject, jint streamIndex) {
jlong result = (jlong) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
result = oboeStream->getFramesRead();
}
@@ -315,7 +308,7 @@
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getXRunCount(
JNIEnv *env, jobject, jint streamIndex) {
jint result = (jlong) oboe::Result::ErrorNull;
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
auto oboeResult = oboeStream->getXRunCount();
if (!oboeResult) {
@@ -330,12 +323,12 @@
JNIEXPORT jlong JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getCallbackCount(
JNIEnv *env, jobject) {
- return engine.getCallbackCount();
+ return engine.getCurrentActivity()->getCallbackCount();
}
JNIEXPORT jdouble JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getLatency(JNIEnv *env, jobject instance, jint streamIndex) {
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
auto result = oboeStream->calculateLatencyMillis();
return (!result) ? -1.0 : result.value();
@@ -345,7 +338,7 @@
JNIEXPORT jint JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_getState(JNIEnv *env, jobject instance, jint streamIndex) {
- oboe::AudioStream *oboeStream = engine.getStream(streamIndex);
+ oboe::AudioStream *oboeStream = engine.getCurrentActivity()->getStream(streamIndex);
if (oboeStream != nullptr) {
auto state = oboeStream->getState();
if (state != oboe::StreamState::Starting && state != oboe::StreamState::Started) {
@@ -363,30 +356,30 @@
Java_com_google_sample_oboe_manualtest_AudioInputTester_getPeakLevel(JNIEnv *env,
jobject instance,
jint index) {
- return engine.getPeakLevel(index);
+ return engine.getCurrentActivity()->getPeakLevel(index);
}
JNIEXPORT void JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_setUseCallback(JNIEnv *env, jclass type,
jboolean useCallback) {
- engine.useCallback = useCallback;
+ ActivityContext::useCallback = useCallback;
}
JNIEXPORT void JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_setCallbackReturnStop(JNIEnv *env, jclass type,
jboolean b) {
- engine.setCallbackReturnStop(b);
+ ActivityContext::callbackReturnStop = b;
}
JNIEXPORT void JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_setCallbackSize(JNIEnv *env, jclass type,
jint callbackSize) {
- engine.callbackSize = callbackSize;
+ ActivityContext::callbackSize = callbackSize;
}
JNIEXPORT jboolean JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioStream_isMMap(JNIEnv *env, jobject instance, jint streamIndex) {
- return engine.isMMapUsed(streamIndex);
+ return engine.getCurrentActivity()->isMMapUsed(streamIndex);
}
// ================= OboeAudioOutputStream ================================
@@ -394,26 +387,26 @@
JNIEXPORT void JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioOutputStream_setToneEnabled(
JNIEnv *env, jobject, jboolean enabled) {
- engine.setToneEnabled(enabled);
+ engine.getCurrentActivity()->setEnabled(enabled);
}
JNIEXPORT void JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioOutputStream_setToneType(
JNIEnv *env, jobject, jint toneType) {
- engine.setToneType(toneType);
+// FIXME engine.getCurrentActivity()->setToneType(toneType);
}
JNIEXPORT void JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioOutputStream_setAmplitude(
JNIEnv *env, jobject, jdouble amplitude) {
- engine.setAmplitude(amplitude);
+ engine.getCurrentActivity()->setAmplitude(amplitude);
}
JNIEXPORT void JNICALL
Java_com_google_sample_oboe_manualtest_OboeAudioOutputStream_setChannelEnabled(
JNIEnv *env, jobject, jint channelIndex, jboolean enabled) {
- engine.setChannelEnabled(channelIndex, enabled);
+ engine.getCurrentActivity()->setChannelEnabled(channelIndex, enabled);
}