Addressing code reviews for echo sample
diff --git a/samples/common/audio_common.cpp b/samples/common/audio_common.cpp
index 82dc8a4..3d296af 100644
--- a/samples/common/audio_common.cpp
+++ b/samples/common/audio_common.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,99 +14,52 @@
* limitations under the License.
*/
-#include <string>
#include "audio_common.h"
#include <logging_macros.h>
+#include <string>
+#include <cinttypes>
-static const oboe::AudioFormat audioFormatEnum[] = {
- oboe::AudioFormat::Invalid,
- oboe::AudioFormat::Unspecified,
- oboe::AudioFormat::I16,
- oboe::AudioFormat::Float,
-};
-static const int32_t audioFormatCount = sizeof(audioFormatEnum)/
- sizeof(audioFormatEnum[0]);
-
-static const uint32_t sampleFormatBPP[] = {
- 0xffff,
- 0xffff,
- 16, //I16
- 32, //FLOAT
-};
uint16_t SampleFormatToBpp(oboe::AudioFormat format) {
- for (int32_t i = 0; i < audioFormatCount; ++i) {
- if (audioFormatEnum[i] == format)
- return sampleFormatBPP[i];
+ switch (format) {
+ case oboe::AudioFormat::I16:
+ return 16;
+ case oboe::AudioFormat::Float:
+ return 32;
+ default:
+ return 0;
}
- return 0xffff;
-}
-static const char * audioFormatStr[] = {
- "AAUDIO_FORMAT_INVALID", // = -1,
- "AAUDIO_FORMAT_UNSPECIFIED", // = 0,
- "AAUDIO_FORMAT_PCM_I16",
- "AAUDIO_FORMAT_PCM_FLOAT",
-};
-const char* FormatToString(oboe::AudioFormat format) {
- for (int32_t i = 0; i < audioFormatCount; ++i) {
- if (audioFormatEnum[i] == format)
- return audioFormatStr[i];
- }
- return "UNKNOW_AUDIO_FORMAT";
}
void PrintAudioStreamInfo(const oboe::AudioStream *stream) {
-#define STREAM_CALL(func) (stream)->func()
- LOGI("StreamID: %p", stream);
+ LOGI("StreamID: %p", stream);
+ oboe::Direction dir = stream->getDirection();
+ LOGI("Direction: %s", oboe::convertToText(dir));
+ LOGI("API type: %s", oboe::convertToText(stream->getAudioApi()));
+ LOGI("BufferCapacity: %d", stream->getBufferCapacityInFrames());
+ LOGI("BufferSize: %d", stream->getBufferSizeInFrames());
+ LOGI("FramesPerBurst: %d", stream->getFramesPerBurst());
+ LOGI("XRunCount: %d", stream->getXRunCount().value());
+ LOGI("SampleRate: %d", stream->getSampleRate());
+ LOGI("SamplesPerFrame: %d", stream->getChannelCount());
+ LOGI("DeviceId: %d", stream->getDeviceId());
+ LOGI("Format: %s", oboe::convertToText(stream->getFormat()));
+ LOGI("SharingMode: %s", oboe::convertToText(stream->getSharingMode()));
+ LOGI("PerformanceMode: %s", oboe::convertToText(stream->getPerformanceMode()));
- LOGI("API type: %s", oboe::convertToText(stream->getAudioApi()));
- LOGI("BufferCapacity: %d", STREAM_CALL(getBufferCapacityInFrames));
- LOGI("BufferSize: %d", STREAM_CALL(getBufferSizeInFrames));
-// Question: does this one have to non-constant function?
-// LOGI("FramesPerBurst: %d", STREAM_CALL(getFramesPerBurst));
- LOGI("FramesPerBurst: %d", const_cast<oboe::AudioStream* >(stream)->getFramesPerBurst());
- LOGI("XRunCount: %d", STREAM_CALL(getXRunCount));
- LOGI("SampleRate: %d", STREAM_CALL(getSampleRate));
- LOGI("SamplesPerFrame: %d", STREAM_CALL(getChannelCount));
- LOGI("DeviceId: %d", STREAM_CALL(getDeviceId));
- LOGI("Format: %s", FormatToString(STREAM_CALL(getFormat)));
- LOGI("SharingMode: %s", (STREAM_CALL(getSharingMode)) == oboe::SharingMode::Exclusive?
- "EXCLUSIVE" : "SHARED");
-
- oboe::PerformanceMode perfMode = STREAM_CALL(getPerformanceMode);
- std::string perfModeDescription;
- switch (perfMode){
- case oboe::PerformanceMode ::None:
- perfModeDescription = "NONE";
- break;
- case oboe::PerformanceMode::LowLatency:
- perfModeDescription = "LOW_LATENCY";
- break;
- case oboe::PerformanceMode::PowerSaving:
- perfModeDescription = "POWER_SAVING";
- break;
- default:
- perfModeDescription = "UNKNOWN";
- break;
- }
- LOGI("PerformanceMode: %s", perfModeDescription.c_str());
-
- oboe::Direction dir = STREAM_CALL(getDirection);
- LOGI("Direction: %s", (dir == oboe::Direction ::Output ? "OUTPUT" : "INPUT"));
- if (dir == oboe::Direction ::Output) {
- LOGI("FramesReadByDevice: %d", (int32_t)STREAM_CALL(getFramesRead));
- LOGI("FramesWriteByApp: %d", (int32_t)STREAM_CALL(getFramesWritten));
- } else {
- LOGI("FramesReadByApp: %d", (int32_t)STREAM_CALL(getFramesRead));
- LOGI("FramesWriteByDevice: %d", (int32_t)STREAM_CALL(getFramesWritten));
- }
-#undef STREAM_CALL
+ if (dir == oboe::Direction ::Output) {
+ LOGI("FramesReadByDevice: %" PRIx64, stream->getFramesRead());
+ LOGI("FramesWriteByApp: %d", (int32_t)stream->getFramesWritten());
+ } else {
+ LOGI("FramesReadByApp: %d", (int32_t)stream->getFramesRead());
+ LOGI("FramesWriteByDevice: %d", (int32_t)stream->getFramesWritten());
+ }
}
-int64_t timestamp_to_nanoseconds(timespec ts){
- return (ts.tv_sec * (int64_t) NANOS_PER_SECOND) + ts.tv_nsec;
+int64_t timestamp_to_nanoseconds(timespec ts) {
+ return (ts.tv_sec * oboe::kNanosPerSecond) + ts.tv_nsec;
}
-int64_t get_time_nanoseconds(clockid_t clockid){
+int64_t get_time_nanoseconds(clockid_t clockid) {
timespec ts;
clock_gettime(clockid, &ts);
return timestamp_to_nanoseconds(ts);
diff --git a/samples/common/audio_common.h b/samples/common/audio_common.h
index 36a4b5e..83d3fda 100644
--- a/samples/common/audio_common.h
+++ b/samples/common/audio_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,9 +21,6 @@
#include <chrono>
#include <oboe/Oboe.h>
-// Time constants
-#define NANOS_PER_SECOND 1000000000L
-#define NANOS_PER_MILLISECOND 1000000L
constexpr int kMonoChannelCount = 1;
constexpr int kStereoChannelCount = 2;
@@ -36,7 +33,7 @@
struct timeval Time;
gettimeofday( &Time, NULL );
- return (static_cast<uint64_t>(1000000) * Time.tv_sec + Time.tv_usec);
+ return (static_cast<uint64_t>(oboe::kNanosPerMillisecond) * Time.tv_sec + Time.tv_usec);
}
/*
diff --git a/samples/echo/src/main/cpp/AudioEffect.cpp b/samples/echo/src/main/cpp/AudioEffect.cpp
index 3f7c842..3080237 100644
--- a/samples/echo/src/main/cpp/AudioEffect.cpp
+++ b/samples/echo/src/main/cpp/AudioEffect.cpp
@@ -19,6 +19,9 @@
#include <cstring>
#include <audio_common.h>
+#define CLAMP_FOR_I16(x) ((x)>SHRT_MAX ? SHRT_MAX : \
+ ((x)<SHRT_MIN ? SHRT_MIN : (x)))
+
/*
* Mixing Audio in integer domain to avoid FP calculation
* (FG * ( MixFactor * 16 ) + BG * ( (1.0f-MixFactor) * 16 )) / 16
@@ -28,7 +31,6 @@
AudioMixer::AudioMixer() :
AudioFormat(48000, 2, oboe::AudioFormat::I16) {
- busy_ = false;
bgMixFactorInt_ = (int32_t)
(bgMixFactor_ * kFloatToIntMapFactor + 0.5f);
fgMixFactorInt_ = kFloatToIntMapFactor - bgMixFactorInt_;
@@ -49,8 +51,13 @@
void AudioMixer::setBackgroundMixer(float mixer) {
if (mixer >= 0.0f && mixer <= 1.0f) {
bgMixFactor_ = mixer;
- bgMixFactorInt_ = (int32_t)
- (bgMixFactor_ * kFloatToIntMapFactor + 0.5f);
+ if (bgMixFactor_ < 0.05f) {
+ bgMixFactor_ = 0.0f;
+ bgMixFactorInt_ = 0;
+ } else {
+ bgMixFactorInt_ = (int32_t)
+ (bgMixFactor_ * kFloatToIntMapFactor + 0.5f);
+ }
fgMixFactorInt_ = kFloatToIntMapFactor - bgMixFactorInt_;
}
}
@@ -63,12 +70,10 @@
* @param channelCount channels for PCM audio pointed by samples
* @param freq is PCM audio frequency (48000hz for this sample)
*/
-void AudioMixer::addStream(std::unique_ptr<int16_t[]>samples, size_t sampleCount,
- int32_t sampleRate, int32_t channelCount, oboe::AudioFormat format){
- if (busy_) {
- LOGW("filtering in progress, filter configuration is IGNORED");
- return;
- }
+bool AudioMixer::addStream(std::unique_ptr<int16_t[]>samples, size_t sampleCount,
+ int32_t sampleRate, int32_t channelCount, oboe::AudioFormat format) {
+ // Wait for lock, from user context.
+ std::lock_guard<std::mutex> lock(lock_);
bgAudio_ = std::move(samples);
bgAudioSampleCount_ = sampleCount;
sampleRate_ = sampleRate;
@@ -76,6 +81,8 @@
channelCount_ = channelCount;
curPosition_ = 0;
+
+ return true;
}
/**
@@ -87,35 +94,67 @@
*/
void AudioMixer::process(int16_t *liveAudio, int32_t channelCount,
int32_t numFrames) {
- assert(bgAudio_ && liveAudio);
- if (numFrames > bgAudioSampleCount_ || channelCount != channelCount_ ||
+ if(!bgAudio_ || !liveAudio) {
+ return;
+ }
+
+ if ((numFrames * channelCount) > bgAudioSampleCount_ ||
+ channelCount != channelCount_ ||
bgMixFactorInt_ == 0) {
return;
}
- busy_ = true;
+ if (!lock_.try_lock()) {
+ // UI thread still updating the stream, skip blending
+ return;
+ }
+
+ size_t sampleCount = numFrames * channelCount;
int32_t curSample;
- for (int i = 0; i < (numFrames * channelCount); i++) {
+ for (int i = 0; i < sampleCount ; i++) {
curSample = liveAudio[i];
curSample = curSample * fgMixFactorInt_ +
bgAudio_[curPosition_] * bgMixFactorInt_;
curSample /= kFloatToIntMapFactor;
- curSample = (curSample > SHRT_MAX ? SHRT_MAX : curSample);
- liveAudio[i] = (int16_t)(curSample < SHRT_MIN ? SHRT_MIN : curSample);
+ curSample = CLAMP_FOR_I16(curSample);
+ liveAudio[i] = (int16_t)curSample;
curPosition_ = (curPosition_ + 1 ) % bgAudioSampleCount_;
}
- busy_ = false;
+
+ lock_.unlock();
}
/**
* query for audio format supportability
*/
-bool AudioMixer::AudioFormatSupported(int32_t frequency,
- int32_t channels, oboe::AudioFormat format) const {
- return (frequency == sampleRate_ &&
- channels == channelCount_ &&
- format == format_);
+bool AudioMixer::AudioFormatSupported(int32_t sampleRate,
+ int32_t channels, oboe::AudioFormat format) {
+ if (sampleRate != sampleRate_ || format != format_) {
+ return false;
+ }
+
+ if (channels == channelCount_ ) {
+ return true;
+ }
+
+ if(channelCount_ == channels * 2) {
+ size_t dst = 0, src = 0;
+ size_t totalFrames = bgAudioSampleCount_ / channelCount_;
+ for(size_t frame = 0; frame < totalFrames; frame++) {
+ for (int32_t c = 0; c < channelCount_; c += 2) {
+ int32_t sample = bgAudio_[src] + bgAudio_[src + 1];
+ src += 2;
+ sample /= 2;
+ bgAudio_[dst++] = static_cast<int16_t>(CLAMP_FOR_I16(sample));
+ }
+ }
+ channelCount_ >>= 1;
+ bgAudioSampleCount_ >>= 1;
+ return true;
+ }
+
+ return false;
}
/**
@@ -143,11 +182,11 @@
* Destructor
*/
AudioDelay::~AudioDelay() {
- if(buffer_) delete static_cast<uint8_t*>(buffer_);
+ delete buffer_;
}
/**
- * Configure for delay time ( in miliseconds ). It is possible to dynamically
+ * Configure for delay time ( in second ). It is possible to dynamically
* adjust the value
* @param delay in seconds
* @return true if delay time is set successfully
@@ -160,10 +199,7 @@
std::lock_guard<std::mutex> lock(lock_);
- if(buffer_) {
- delete static_cast<uint8_t*>(buffer_);
- buffer_ = nullptr;
- }
+ delete (buffer_);
delay_ = delay;
allocateBuffer();
@@ -194,7 +230,9 @@
buffer_ = new uint8_t[bufCapacity_];
assert(buffer_);
- memset(buffer_, 0, bufCapacity_);
+ if (buffer_) {
+ memset(buffer_, 0, bufCapacity_);
+ }
curPos_ = 0;
// bufSize_ is in Frames ( not samples, not bytes )
@@ -237,7 +275,9 @@
void AudioDelay::process(int16_t *liveAudio,
int32_t channelCount,
int32_t numFrames) {
- if (feedbackFactor_ == 0 ||
+
+ if (!buffer_ || !liveAudio ||
+ feedbackFactor_ == 0 ||
channelCount != channelCount_ ||
bufSize_ < numFrames) {
return;
@@ -253,22 +293,13 @@
// process every sample
int32_t sampleCount = channelCount * numFrames;
- int16_t* samples = & static_cast<int16_t*>(buffer_)[curPos_];
- int32_t curSample;
+ int16_t* samples = & reinterpret_cast<int16_t*>(buffer_)[curPos_ * channelCount_];
for (size_t idx = 0; idx < sampleCount; idx++) {
-#if 1
- curSample = (samples[idx] * feedbackFactor_ +
+ int32_t curSample = (samples[idx] * feedbackFactor_ +
liveAudio[idx] * liveAudioFactor_) / kFloatToIntMapFactor;
-#else
- curSample = (samples[idx] * feedbackFactor_) / kFloatToIntMapFactor +
- liveAudio[idx];
-#endif
- if(curSample > SHRT_MAX)
- curSample = SHRT_MAX;
- else if (curSample < SHRT_MIN)
- curSample = SHRT_MAX;
- samples[idx] = static_cast<int16_t>(curSample);
+ CLAMP_FOR_I16(curSample);
liveAudio[idx] = samples[idx];
+ samples[idx] = static_cast<int16_t>(curSample);
}
curPos_ += numFrames;
diff --git a/samples/echo/src/main/cpp/AudioEffect.h b/samples/echo/src/main/cpp/AudioEffect.h
index 9119507..8ca5769 100644
--- a/samples/echo/src/main/cpp/AudioEffect.h
+++ b/samples/echo/src/main/cpp/AudioEffect.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,20 +48,20 @@
~AudioMixer();
void process(int16_t *liveAudio, int32_t channelCount,
int32_t numFrames);
- void addStream(std::unique_ptr<int16_t[]>samples, size_t sampleCount,
+ bool addStream(std::unique_ptr<int16_t[]>samples, size_t sampleCount,
int32_t sampleRate, int32_t channelCount,
oboe::AudioFormat format);
void setBackgroundMixer(float bgMix);
bool AudioFormatSupported(int32_t sampleRate, int32_t channels,
- oboe::AudioFormat format) const;
+ oboe::AudioFormat format);
private:
- std::unique_ptr<int16_t[]> bgAudio_ = nullptr;
+ std::unique_ptr<int16_t[]> bgAudio_;
size_t bgAudioSampleCount_ = 0;
size_t curPosition_ = 0;
- std::atomic_bool busy_;
float bgMixFactor_ = 0.5f;
int32_t fgMixFactorInt_;
int32_t bgMixFactorInt_;
+ std::mutex lock_;
};
/**
@@ -93,7 +93,7 @@
private:
float delay_ = 0.0f;
float decay_ = 0.1f;
- void *buffer_ = nullptr;
+ uint8_t *buffer_ = nullptr;
size_t bufCapacity_ = 0;
size_t bufSize_ = 0;
size_t curPos_ = 0;
diff --git a/samples/echo/src/main/cpp/CMakeLists.txt b/samples/echo/src/main/cpp/CMakeLists.txt
index ed2764b..fe6db7c 100644
--- a/samples/echo/src/main/cpp/CMakeLists.txt
+++ b/samples/echo/src/main/cpp/CMakeLists.txt
@@ -44,4 +44,4 @@
target_compile_options(echo
PRIVATE
- -Wall)
+ -Wall -Werror)
diff --git a/samples/echo/src/main/cpp/EchoAudioEngine.cpp b/samples/echo/src/main/cpp/EchoAudioEngine.cpp
index 10267f8..d2775b2 100644
--- a/samples/echo/src/main/cpp/EchoAudioEngine.cpp
+++ b/samples/echo/src/main/cpp/EchoAudioEngine.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,14 @@
#include <climits>
#include <assert.h>
+/**
+ * Duplex is not very stable right after starting up:
+ * the callbacks may not be happening at the right times
+ * The time to get it stable varies on different systems. Half second
+ * is used for this sample, during the time this sample plays silence.
+ */
+const float kSystemWarmupTime = 0.5f;
+
EchoAudioEngine::EchoAudioEngine() {
assert(outputChannelCount_ == inputChannelCount_);
mixerEffect_ = std::unique_ptr<AudioMixer>(new AudioMixer);
@@ -30,7 +38,6 @@
stopStream(recordingStream_);
closeStream(playStream_);
- frameCallbackCount_ = 0;
closeStream(recordingStream_);
}
@@ -158,20 +165,16 @@
assert(playStream_->getFormat() == oboe::AudioFormat::I16);
assert(outputChannelCount_ == playStream_->getChannelCount());
+ systemStartupFrames_ = static_cast<uint64_t>
+ (sampleRate_ * kSystemWarmupTime);
+ processedFrameCount_ = 0;
+
framesPerBurst_ = playStream_->getFramesPerBurst();
- // Read blocking timeout value: half of the burst size
- audioBlockingReadTimeout_ = static_cast<uint64_t>(.5f * framesPerBurst_
- / sampleRate_ * NANOS_PER_SECOND);
-
- latencyTuner_ = std::unique_ptr<oboe::LatencyTuner>
- (new oboe::LatencyTuner(*playStream_));
-
delayEffect_ = std::unique_ptr<AudioDelay>(new AudioDelay(
sampleRate_,outputChannelCount_, format_, echoDelay_, echoDecay_));
assert(delayEffect_ && mixerEffect_);
- frameCallbackCount_ = 0;
warnIfNotLowLatency(playStream_);
PrintAudioStreamInfo(playStream_);
@@ -211,7 +214,8 @@
->setDeviceId(playbackDeviceId_)
->setDirection(oboe::Direction::Output)
->setChannelCount(outputChannelCount_)
- ->setSampleRate(sampleRate_);
+ ->setSampleRate(sampleRate_)
+ ->setFramesPerCallback(framesPerBurst_);
return setupCommonStreamParameters(builder);
}
@@ -318,23 +322,29 @@
assert(oboeStream == playStream_);
- if (frameCallbackCount_) {
- latencyTuner_->tune();
+ int32_t prevFrameRead = 0, framesRead = 0;
+ if (processedFrameCount_ < systemStartupFrames_) {
+ do {
+ // Drain the audio for the starting up period, half second for
+ // this sample.
+ prevFrameRead = framesRead;
+
+ oboe::ResultWithValue<int32_t> status =
+ recordingStream_->read(audioData, numFrames, 0);
+ framesRead = (!status) ? 0 : status.value();
+ if (framesRead == 0)
+ break;
+
+ } while (framesRead);
+
+ framesRead = prevFrameRead;
+ } else {
+ oboe::ResultWithValue<int32_t> status =
+ recordingStream_->read(audioData, numFrames, 0);
+
+ framesRead = (!status) ? 0 : status.value();
}
- frameCallbackCount_++;
- // blocking read with timeout:
- // recorder may not have data ready, specifically
- // at the very beginning; in this case, simply play
- // silent audio. The timeout is equivalent to
- // framesPerBurst()/2
- // Do not make it too long, otherwise player would underrun
- // and if tuning is in process, player will increase
- // FramesPerBurst.
- oboe::ErrorOrValue<int32_t> status =
- recordingStream_->read(audioData, numFrames, audioBlockingReadTimeout_);
-
- int32_t framesRead = (!status) ? 0 : status.value();
if (framesRead < numFrames) {
int32_t bytesPerFrame = recordingStream_->getChannelCount() *
SampleFormatToBpp(oboeStream->getFormat()) / 8;
@@ -343,12 +353,16 @@
memset(padPos, 0, (size_t)(numFrames - framesRead) * bytesPerFrame);
}
+ // Processing audio: padded silence audio treated as valid audio
+ // glitch would be felt by turning off mixer
delayEffect_->process(static_cast<int16_t *>(audioData),
outputChannelCount_, numFrames);
if (mixAudio_) {
mixerEffect_->process(static_cast<int16_t *>(audioData),
- outputChannelCount_, numFrames);
+ outputChannelCount_, numFrames);
}
+ processedFrameCount_ += numFrames;
+
return oboe::DataCallbackResult::Continue;
}
diff --git a/samples/echo/src/main/cpp/EchoAudioEngine.h b/samples/echo/src/main/cpp/EchoAudioEngine.h
index c937d6c..6a7a628 100644
--- a/samples/echo/src/main/cpp/EchoAudioEngine.h
+++ b/samples/echo/src/main/cpp/EchoAudioEngine.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,7 +53,8 @@
private:
bool isEchoOn_ = false;
- uint64_t frameCallbackCount_ = 0;
+ uint64_t processedFrameCount_ = 0;
+ uint64_t systemStartupFrames_ = 0;
int32_t recordingDeviceId_ = oboe::kUnspecified;
int32_t playbackDeviceId_ = oboe::kUnspecified;
oboe::AudioFormat format_ = oboe::AudioFormat::I16;
@@ -64,15 +65,13 @@
oboe::AudioStream *playStream_ = nullptr;
int32_t framesPerBurst_;
std::mutex restartingLock_;
- std::unique_ptr<AudioMixer> mixerEffect_ = nullptr;
- std::unique_ptr<AudioDelay> delayEffect_ = nullptr;
- uint64_t audioBlockingReadTimeout_ = NANOS_PER_MILLISECOND;
+ std::unique_ptr<AudioMixer> mixerEffect_;
+ std::unique_ptr<AudioDelay> delayEffect_;
oboe::AudioApi audioApi_ = oboe::AudioApi::AAudio;
float echoDelay_ = 0.5f;
float echoDecay_ = 0.1f;
bool mixAudio_ = false;
- std::unique_ptr<oboe::LatencyTuner> latencyTuner_;
void openRecordingStream();
void openPlaybackStream();
diff --git a/samples/echo/src/main/cpp/jni_bridge.cpp b/samples/echo/src/main/cpp/jni_bridge.cpp
index fe55fca..742b381 100644
--- a/samples/echo/src/main/cpp/jni_bridge.cpp
+++ b/samples/echo/src/main/cpp/jni_bridge.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,10 @@
#include <android/asset_manager_jni.h>
static EchoAudioEngine *engine = nullptr;
+
+static const int OBOE_API_AAUDIO = 0;
+static const int OBOE_API_OPENSL_ES = 1;
+
extern "C" {
JNIEXPORT bool JNICALL
@@ -132,9 +136,6 @@
}
-static const int OBOE_API_AAUDIO = 0;
-static const int OBOE_API_OPENSL_ES = 1;
-
JNIEXPORT jboolean JNICALL
Java_com_google_sample_oboe_echo_EchoEngine_setAPI(JNIEnv *env, jclass type, jint apiType) {
if (engine == nullptr) {
diff --git a/samples/echo/src/main/res/layout/activity_main.xml b/samples/echo/src/main/res/layout/activity_main.xml
index cbfc51f..de5b51b 100644
--- a/samples/echo/src/main/res/layout/activity_main.xml
+++ b/samples/echo/src/main/res/layout/activity_main.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2017 The Android Open Source Project
+ ~ Copyright (C) 2018 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.