aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Burk <philburk@google.com>2019-08-23 17:33:28 -0700
committerPhil Burk <philburk@google.com>2019-08-23 17:33:28 -0700
commitb69847cf6416d711f3f1f4ec2871364125bff925 (patch)
treee760aa198cc375e82d811cb6cc21ed51d255dd0a
parent99c00483810f46db61d9a729f90f551d0f7c03f8 (diff)
downloadoboe-b69847cf6416d711f3f1f4ec2871364125bff925.tar.gz
resampler: add Fastest quality
It will use a bi-linear interpolation. Also cleanup FullDuplexEcho
-rw-r--r--apps/OboeTester/app/src/main/cpp/FullDuplexEcho.cpp25
-rw-r--r--apps/OboeTester/app/src/main/cpp/flowunits/LinearShape.h2
-rw-r--r--apps/OboeTester/app/src/main/java/com/google/sample/oboe/manualtest/StreamConfiguration.java11
-rw-r--r--apps/OboeTester/app/src/main/res/values/strings.xml1
-rw-r--r--include/oboe/AudioStreamBuilder.h11
-rw-r--r--include/oboe/Definitions.h12
-rw-r--r--src/flowgraph/resampler/MultiChannelResampler.cpp6
-rw-r--r--src/flowgraph/resampler/MultiChannelResampler.h1
8 files changed, 38 insertions, 31 deletions
diff --git a/apps/OboeTester/app/src/main/cpp/FullDuplexEcho.cpp b/apps/OboeTester/app/src/main/cpp/FullDuplexEcho.cpp
index 30511a4b..0da2d002 100644
--- a/apps/OboeTester/app/src/main/cpp/FullDuplexEcho.cpp
+++ b/apps/OboeTester/app/src/main/cpp/FullDuplexEcho.cpp
@@ -29,32 +29,21 @@ oboe::DataCallbackResult FullDuplexEcho::onBothStreamsReady(
void *outputData,
int numOutputFrames) {
// FIXME only handles matching stream formats.
- // TODO use array of delays
// TODO Add delay node
// TODO use flowgraph to handle format conversion
int32_t framesToEcho = std::min(numInputFrames, numOutputFrames);
float *inputFloat = (float *)inputData;
float *outputFloat = (float *)outputData;
+ // zero out entire output array
+ memset(outputFloat, 0, numOutputFrames * getOutputStream()->getBytesPerFrame());
+
int32_t inputStride = getInputStream()->getChannelCount();
int32_t outputStride = getOutputStream()->getChannelCount();
float delayFrames = mDelayTimeSeconds * getOutputStream()->getSampleRate();
- if (outputStride == 1) {
- while (framesToEcho-- > 0) {
- *outputFloat++ = mDelayLine->process(delayFrames, *inputFloat); // mono delay
- inputFloat += inputStride;
- }
- } else if (outputStride == 2) {
- while (framesToEcho-- > 0) {
- *outputFloat++ = mDelayLine->process(delayFrames, *inputFloat); // mono delay
- *outputFloat++ = 0.0f;
- inputFloat += inputStride;
- }
- } // else TODO
-
- // zero out remainder of output array
- int32_t framesLeft = numOutputFrames - numInputFrames;
- if (framesLeft > 0) {
- memset(outputFloat, 0, framesLeft * getOutputStream()->getBytesPerFrame());
+ while (framesToEcho-- > 0) {
+ *outputFloat = mDelayLine->process(delayFrames, *inputFloat); // mono delay
+ inputFloat += inputStride;
+ outputFloat += outputStride;
}
return oboe::DataCallbackResult::Continue;
};
diff --git a/apps/OboeTester/app/src/main/cpp/flowunits/LinearShape.h b/apps/OboeTester/app/src/main/cpp/flowunits/LinearShape.h
index 694f9a74..2ea97e15 100644
--- a/apps/OboeTester/app/src/main/cpp/flowunits/LinearShape.h
+++ b/apps/OboeTester/app/src/main/cpp/flowunits/LinearShape.h
@@ -29,7 +29,7 @@ public:
int32_t onProcess(int numFrames) override;
- float getMinimum() const { // TODO create sweep base class
+ float getMinimum() const {
return mMinimum;
}
diff --git a/apps/OboeTester/app/src/main/java/com/google/sample/oboe/manualtest/StreamConfiguration.java b/apps/OboeTester/app/src/main/java/com/google/sample/oboe/manualtest/StreamConfiguration.java
index 733e9560..915dcdbd 100644
--- a/apps/OboeTester/app/src/main/java/com/google/sample/oboe/manualtest/StreamConfiguration.java
+++ b/apps/OboeTester/app/src/main/java/com/google/sample/oboe/manualtest/StreamConfiguration.java
@@ -48,10 +48,11 @@ public class StreamConfiguration {
public static final int PERFORMANCE_MODE_LOW_LATENCY = 12; // must match AAUDIO
public static final int RATE_CONVERSION_QUALITY_NONE = 0; // must match Oboe
- public static final int RATE_CONVERSION_QUALITY_LOW = 1; // must match Oboe
- public static final int RATE_CONVERSION_QUALITY_MEDIUM = 2; // must match Oboe
- public static final int RATE_CONVERSION_QUALITY_HIGH = 3; // must match Oboe
- public static final int RATE_CONVERSION_QUALITY_BEST = 4; // must match Oboe
+ public static final int RATE_CONVERSION_QUALITY_FASTEST = 1; // must match Oboe
+ public static final int RATE_CONVERSION_QUALITY_LOW = 2; // must match Oboe
+ public static final int RATE_CONVERSION_QUALITY_MEDIUM = 3; // must match Oboe
+ public static final int RATE_CONVERSION_QUALITY_HIGH = 4; // must match Oboe
+ public static final int RATE_CONVERSION_QUALITY_BEST = 5; // must match Oboe
private int mNativeApi;
private int mBufferCapacityInFrames;
@@ -67,7 +68,7 @@ public class StreamConfiguration {
private boolean mChannelConversionAllowed = true;
private int mRateConversionQuality = RATE_CONVERSION_QUALITY_HIGH;
- private int mFramesPerBurst = 29; // TODO review
+ private int mFramesPerBurst = 0;
private boolean mMMap = false;
public StreamConfiguration() {
diff --git a/apps/OboeTester/app/src/main/res/values/strings.xml b/apps/OboeTester/app/src/main/res/values/strings.xml
index 53c3bea0..72d3cba1 100644
--- a/apps/OboeTester/app/src/main/res/values/strings.xml
+++ b/apps/OboeTester/app/src/main/res/values/strings.xml
@@ -120,6 +120,7 @@
<string name="src_prompt">SRC:</string>
<string-array name="conversion_qualities">
<item>None</item>
+ <item>Fastest</item>
<item>Low</item>
<item>Medium</item>
<item>High</item>
diff --git a/include/oboe/AudioStreamBuilder.h b/include/oboe/AudioStreamBuilder.h
index 092d1773..4e1dad74 100644
--- a/include/oboe/AudioStreamBuilder.h
+++ b/include/oboe/AudioStreamBuilder.h
@@ -341,12 +341,13 @@ public:
}
/**
- * If set to None then Oboe will not do sample rate conversion. But the underlying APIs
- * might do sample rate conversion. Unfortunately sample rate conversion in Android typically
- * prevents one from getting a low latency stream. So we can do the conversion in Android
- * and still get a low latency stream.
+ * Specify the quality of the sample rate converter in Oboe.
*
- * Default is SampleRateConversionType::Sinc. TODO currently Linear
+ * If set to None then Oboe will not do sample rate conversion. But then the underlying APIs
+ * might do sample rate conversion, which can prevent one from getting a low latency stream.
+ * If we do the conversion in Oboe then we can still get a low latency stream.
+ *
+ * Default is SampleRateConversionQuality::None
*/
AudioStreamBuilder *setSampleRateConversionQuality(SampleRateConversionQuality quality) {
mSampleRateConversionQuality = quality;
diff --git a/include/oboe/Definitions.h b/include/oboe/Definitions.h
index 29fd55d1..b1ea7f13 100644
--- a/include/oboe/Definitions.h
+++ b/include/oboe/Definitions.h
@@ -228,18 +228,26 @@ namespace oboe {
};
/**
- * The algorithm used to perform sample rate conversion.
+ * Specifies the quality of the sample rate conversion performed by Oboe.
* Higher quality will require more CPU load.
+ * Higher quality conversion will probably be implemented using a sinc based resampler.
*/
enum class SampleRateConversionQuality : int32_t {
/**
* No conversion by Oboe. Underlying APIs may still do conversion.
*/
None,
-
+ /**
+ * Fastest conversion but may not sound great.
+ * This may be implemented using bilinear interpolation.
+ */
+ Fastest,
Low,
Medium,
High,
+ /**
+ * Highest quality conversion, which may be expensive in terms of CPU.
+ */
Best,
};
diff --git a/src/flowgraph/resampler/MultiChannelResampler.cpp b/src/flowgraph/resampler/MultiChannelResampler.cpp
index c35cf04f..c54ca758 100644
--- a/src/flowgraph/resampler/MultiChannelResampler.cpp
+++ b/src/flowgraph/resampler/MultiChannelResampler.cpp
@@ -54,6 +54,9 @@ MultiChannelResampler *MultiChannelResampler::make(int32_t channelCount,
// TODO benchmark and review these numTaps
switch (quality) {
+ case Quality::Fastest:
+ builder.setNumTaps(2);
+ break;
case Quality::Low:
builder.setNumTaps(4);
break;
@@ -77,6 +80,9 @@ MultiChannelResampler *MultiChannelResampler::make(int32_t channelCount,
}
MultiChannelResampler *MultiChannelResampler::Builder::build() {
+ if (getNumTaps() == 2) {
+ return new LinearResampler(*this);
+ }
IntegerRatio ratio(getInputRate(), getOutputRate());
ratio.reduce();
bool usePolyphase = (getNumTaps() * ratio.getDenominator()) <= kMaxCoefficients;
diff --git a/src/flowgraph/resampler/MultiChannelResampler.h b/src/flowgraph/resampler/MultiChannelResampler.h
index 31ff2c0b..3e6bb438 100644
--- a/src/flowgraph/resampler/MultiChannelResampler.h
+++ b/src/flowgraph/resampler/MultiChannelResampler.h
@@ -39,6 +39,7 @@ class MultiChannelResampler {
public:
enum class Quality : int32_t {
+ Fastest,
Low,
Medium,
High,