aaudio: add support for 24 and 32 bit PCM
Add new formats: AAUDIO_FORMAT_PCM_I24_PACKED
and AAUDIO_FORMAT_PCM_I32.
Pass formats to Legacy AudioTrack and AuddioRecord.
Request 24_PACKED in AAudio Service for MMAP streams.
Also add a flowgraph module for converting the I32 data
to/from FLOAT.
Bug: 65067568
Bug: 157671580
Test: To determine which format the MMAP path is using for the DSP,
Test: adb shell dumpsys media.aaudio
Test: then look for the "Exclusive MMAP Endpoints" and "Format:".
Test: The formats listed are the internal AudioFlinger formats:
Test: 1=16_BIT, 3=32_BIT, 4=8_24_BIT, 5=FLOAT, 6=24_BIT_PACKED
Test: atest AAudioTestCases
Test: adb shell write_sine_callback -? # to list new formats
Test: adb shell write_sine_callback -pl -f3 # MMAP LOWLAT I24_PACKED
Test: adb shell write_sine_callback -pl -f4 # MMAP LOWLAT I32
Test: # Legacy LOWLAT I24_PACKED
Test: adb shell write_sine_callback -pl -f3 -m1
Test: adb shell write_sine_callback -pl -f4 -m1 # Legacy LOWLAT I32
Test: adb shell write_sine_callback -pn -f3 # Legacy I24_PACKED
Test: adb shell write_sine_callback -pn -f4 # Legacy I32
Change-Id: Ibe13bfd54425d110f50f89eb10c63872a2f99839
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 6666788..eeba10c 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -65,7 +65,7 @@
/**
* This format uses the int16_t data type.
- * The maximum range of the data is -32768 to 32767.
+ * The maximum range of the data is -32768 (0x8000) to 32767 (0x7FFF).
*/
AAUDIO_FORMAT_PCM_I16,
@@ -77,7 +77,31 @@
* See also 'floatData' at
* https://developer.android.com/reference/android/media/AudioTrack#write(float[],%20int,%20int,%20int)
*/
- AAUDIO_FORMAT_PCM_FLOAT
+ AAUDIO_FORMAT_PCM_FLOAT,
+
+ /**
+ * This format uses 24-bit samples packed into 3 bytes.
+ * The bytes are in the native endian order.
+ * The maximum range of the data is -8388608 (0x800000)
+ * to 8388607 (0x7FFFFF).
+ *
+ * Note that the lower precision bits may be ignored by the device.
+ *
+ * Available since API level 31.
+ */
+ AAUDIO_FORMAT_PCM_I24_PACKED,
+
+ /**
+ * This format uses 32-bit samples stored in an int32_t data type.
+ * The maximum range of the data is -2147483648 (0x80000000)
+ * to 2147483647 (0x7FFFFFFF).
+ *
+ * Note that the lower precision bits may be ignored by the device.
+ *
+ * Available since API level 31.
+ */
+ AAUDIO_FORMAT_PCM_I32
+
};
typedef int32_t aaudio_format_t;
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
index aafcccc..d02d1b6 100644
--- a/media/libaaudio/src/Android.bp
+++ b/media/libaaudio/src/Android.bp
@@ -130,9 +130,11 @@
"flowgraph/SinkFloat.cpp",
"flowgraph/SinkI16.cpp",
"flowgraph/SinkI24.cpp",
+ "flowgraph/SinkI32.cpp",
"flowgraph/SourceFloat.cpp",
"flowgraph/SourceI16.cpp",
"flowgraph/SourceI24.cpp",
+ "flowgraph/SourceI32.cpp",
],
sanitize: {
integer_overflow: true,
diff --git a/media/libaaudio/src/client/AAudioFlowGraph.cpp b/media/libaaudio/src/client/AAudioFlowGraph.cpp
index 8f2c488..61b50f3 100644
--- a/media/libaaudio/src/client/AAudioFlowGraph.cpp
+++ b/media/libaaudio/src/client/AAudioFlowGraph.cpp
@@ -26,9 +26,11 @@
#include <flowgraph/SinkFloat.h>
#include <flowgraph/SinkI16.h>
#include <flowgraph/SinkI24.h>
+#include <flowgraph/SinkI32.h>
#include <flowgraph/SourceFloat.h>
#include <flowgraph/SourceI16.h>
#include <flowgraph/SourceI24.h>
+#include <flowgraph/SourceI32.h>
using namespace flowgraph;
@@ -38,7 +40,8 @@
int32_t sinkChannelCount) {
AudioFloatOutputPort *lastOutput = nullptr;
- ALOGV("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d",
+ // TODO change back to ALOGD
+ ALOGI("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d",
__func__, sourceFormat, sourceChannelCount, sinkFormat, sinkChannelCount);
switch (sourceFormat) {
@@ -51,7 +54,10 @@
case AUDIO_FORMAT_PCM_24_BIT_PACKED:
mSource = std::make_unique<SourceI24>(sourceChannelCount);
break;
- default: // TODO add I32
+ case AUDIO_FORMAT_PCM_32_BIT:
+ mSource = std::make_unique<SourceI32>(sourceChannelCount);
+ break;
+ default:
ALOGE("%s() Unsupported source format = %d", __func__, sourceFormat);
return AAUDIO_ERROR_UNIMPLEMENTED;
}
@@ -90,7 +96,10 @@
case AUDIO_FORMAT_PCM_24_BIT_PACKED:
mSink = std::make_unique<SinkI24>(sinkChannelCount);
break;
- default: // TODO add I32
+ case AUDIO_FORMAT_PCM_32_BIT:
+ mSink = std::make_unique<SinkI32>(sinkChannelCount);
+ break;
+ default:
ALOGE("%s() Unsupported sink format = %d", __func__, sinkFormat);
return AAUDIO_ERROR_UNIMPLEMENTED;
}
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 809c76e..2815c6a 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -104,7 +104,7 @@
if (getFormat() == AUDIO_FORMAT_DEFAULT) {
setFormat(AUDIO_FORMAT_PCM_FLOAT);
}
- // Request FLOAT for the shared mixer.
+ // Request FLOAT for the shared mixer or the device.
request.getConfiguration().setFormat(AUDIO_FORMAT_PCM_FLOAT);
// Build the request to send to the server.
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index 5f45261..2c81c91 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -54,7 +54,9 @@
switch (format) {
case AUDIO_FORMAT_DEFAULT:
case AUDIO_FORMAT_PCM_16_BIT:
+ case AUDIO_FORMAT_PCM_32_BIT:
case AUDIO_FORMAT_PCM_FLOAT:
+ case AUDIO_FORMAT_PCM_24_BIT_PACKED:
break; // valid
default:
ALOGD("audioFormat not valid, audio_format_t = 0x%08x", format);
diff --git a/media/libaaudio/src/core/AudioGlobal.cpp b/media/libaaudio/src/core/AudioGlobal.cpp
index 7f5d8d5..0e5b8be 100644
--- a/media/libaaudio/src/core/AudioGlobal.cpp
+++ b/media/libaaudio/src/core/AudioGlobal.cpp
@@ -80,6 +80,8 @@
AAUDIO_CASE_ENUM(AAUDIO_FORMAT_INVALID);
AAUDIO_CASE_ENUM(AAUDIO_FORMAT_PCM_I16);
AAUDIO_CASE_ENUM(AAUDIO_FORMAT_PCM_FLOAT);
+ AAUDIO_CASE_ENUM(AAUDIO_FORMAT_PCM_I24_PACKED);
+ AAUDIO_CASE_ENUM(AAUDIO_FORMAT_PCM_I32);
}
return "Unrecognized";
}
diff --git a/media/libaaudio/src/flowgraph/FlowgraphUtilities.h b/media/libaaudio/src/flowgraph/FlowgraphUtilities.h
new file mode 100644
index 0000000..b750410
--- /dev/null
+++ b/media/libaaudio/src/flowgraph/FlowgraphUtilities.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2020 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLOWGRAPH_UTILITIES_H
+#define FLOWGRAPH_UTILITIES_H
+
+#include <unistd.h>
+
+using namespace flowgraph;
+
+class FlowgraphUtilities {
+public:
+// This was copied from audio_utils/primitives.h
+/**
+ * Convert a single-precision floating point value to a Q0.31 integer value.
+ * Rounds to nearest, ties away from 0.
+ *
+ * Values outside the range [-1.0, 1.0) are properly clamped to -2147483648 and 2147483647,
+ * including -Inf and +Inf. NaN values are considered undefined, and behavior may change
+ * depending on hardware and future implementation of this function.
+ */
+static int32_t clamp32FromFloat(float f)
+{
+ static const float scale = (float)(1UL << 31);
+ static const float limpos = 1.;
+ static const float limneg = -1.;
+
+ if (f <= limneg) {
+ return -0x80000000; /* or 0x80000000 */
+ } else if (f >= limpos) {
+ return 0x7fffffff;
+ }
+ f *= scale;
+ /* integer conversion is through truncation (though int to float is not).
+ * ensure that we round to nearest, ties away from 0.
+ */
+ return f > 0 ? f + 0.5 : f - 0.5;
+}
+
+};
+
+#endif // FLOWGRAPH_UTILITIES_H
diff --git a/media/libaaudio/src/flowgraph/SinkI24.cpp b/media/libaaudio/src/flowgraph/SinkI24.cpp
index 6592828..0cb077d 100644
--- a/media/libaaudio/src/flowgraph/SinkI24.cpp
+++ b/media/libaaudio/src/flowgraph/SinkI24.cpp
@@ -15,7 +15,7 @@
*/
#include <algorithm>
-#include <unistd.h>
+#include <stdint.h>
#ifdef __ANDROID__
#include <audio_utils/primitives.h>
@@ -26,7 +26,6 @@
using namespace flowgraph;
-
SinkI24::SinkI24(int32_t channelCount)
: AudioSink(channelCount) {}
diff --git a/media/libaaudio/src/flowgraph/SinkI32.cpp b/media/libaaudio/src/flowgraph/SinkI32.cpp
new file mode 100644
index 0000000..eab863d
--- /dev/null
+++ b/media/libaaudio/src/flowgraph/SinkI32.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2020 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __ANDROID__
+#include <audio_utils/primitives.h>
+#endif
+
+#include "AudioProcessorBase.h"
+#include "FlowgraphUtilities.h"
+#include "SinkI32.h"
+
+using namespace flowgraph;
+
+SinkI32::SinkI32(int32_t channelCount)
+ : AudioSink(channelCount) {}
+
+int32_t SinkI32::read(void *data, int32_t numFrames) {
+ int32_t *intData = (int32_t *) data;
+ const int32_t channelCount = input.getSamplesPerFrame();
+
+ int32_t framesLeft = numFrames;
+ while (framesLeft > 0) {
+ // Run the graph and pull data through the input port.
+ int32_t framesRead = pull(framesLeft);
+ if (framesRead <= 0) {
+ break;
+ }
+ const float *signal = input.getBlock();
+ int32_t numSamples = framesRead * channelCount;
+#ifdef __ANDROID__
+ memcpy_to_i32_from_float(intData, signal, numSamples);
+ intData += numSamples;
+ signal += numSamples;
+#else
+ for (int i = 0; i < numSamples; i++) {
+ *intData++ = FlowgraphUtilities::clamp32FromFloat(*signal++);
+ }
+#endif
+ framesLeft -= framesRead;
+ }
+ return numFrames - framesLeft;
+}
diff --git a/media/libaaudio/src/flowgraph/SinkI32.h b/media/libaaudio/src/flowgraph/SinkI32.h
new file mode 100644
index 0000000..09d23b7
--- /dev/null
+++ b/media/libaaudio/src/flowgraph/SinkI32.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLOWGRAPH_SINK_I32_H
+#define FLOWGRAPH_SINK_I32_H
+
+#include <stdint.h>
+
+#include "AudioProcessorBase.h"
+
+namespace flowgraph {
+
+class SinkI32 : public AudioSink {
+public:
+ explicit SinkI32(int32_t channelCount);
+ ~SinkI32() override = default;
+
+ int32_t read(void *data, int32_t numFrames) override;
+};
+
+} /* namespace flowgraph */
+
+#endif //FLOWGRAPH_SINK_I32_H
diff --git a/media/libaaudio/src/flowgraph/SourceI24.cpp b/media/libaaudio/src/flowgraph/SourceI24.cpp
index f319880..097954e 100644
--- a/media/libaaudio/src/flowgraph/SourceI24.cpp
+++ b/media/libaaudio/src/flowgraph/SourceI24.cpp
@@ -15,7 +15,7 @@
*/
#include <algorithm>
-#include <unistd.h>
+#include <stdint.h>
#ifdef __ANDROID__
#include <audio_utils/primitives.h>
diff --git a/media/libaaudio/src/flowgraph/SourceI24.h b/media/libaaudio/src/flowgraph/SourceI24.h
index 39f14da..2ed6f18 100644
--- a/media/libaaudio/src/flowgraph/SourceI24.h
+++ b/media/libaaudio/src/flowgraph/SourceI24.h
@@ -17,8 +17,7 @@
#ifndef FLOWGRAPH_SOURCE_I24_H
#define FLOWGRAPH_SOURCE_I24_H
-#include <unistd.h>
-#include <sys/types.h>
+#include <stdint.h>
#include "AudioProcessorBase.h"
diff --git a/media/libaaudio/src/flowgraph/SourceI32.cpp b/media/libaaudio/src/flowgraph/SourceI32.cpp
new file mode 100644
index 0000000..e8177ad
--- /dev/null
+++ b/media/libaaudio/src/flowgraph/SourceI32.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2020 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <unistd.h>
+
+#ifdef __ANDROID__
+#include <audio_utils/primitives.h>
+#endif
+
+#include "AudioProcessorBase.h"
+#include "SourceI32.h"
+
+using namespace flowgraph;
+
+SourceI32::SourceI32(int32_t channelCount)
+ : AudioSource(channelCount) {
+}
+
+int32_t SourceI32::onProcess(int64_t framePosition, int32_t numFrames) {
+ float *floatData = output.getBlock();
+ int32_t channelCount = output.getSamplesPerFrame();
+
+ int32_t framesLeft = mSizeInFrames - mFrameIndex;
+ int32_t framesToProcess = std::min(numFrames, framesLeft);
+ int32_t numSamples = framesToProcess * channelCount;
+
+ const int32_t *intBase = static_cast<const int32_t *>(mData);
+ const int32_t *intData = &intBase[mFrameIndex * channelCount];
+
+#ifdef __ANDROID__
+ memcpy_to_float_from_i32(floatData, intData, numSamples);
+#else
+ for (int i = 0; i < numSamples; i++) {
+ *floatData++ = *intData++ * kScale;
+ }
+#endif
+
+ mFrameIndex += framesToProcess;
+ return framesToProcess;
+}
diff --git a/media/libaaudio/src/flowgraph/SourceI32.h b/media/libaaudio/src/flowgraph/SourceI32.h
new file mode 100644
index 0000000..e50f9be
--- /dev/null
+++ b/media/libaaudio/src/flowgraph/SourceI32.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLOWGRAPH_SOURCE_I32_H
+#define FLOWGRAPH_SOURCE_I32_H
+
+#include <stdint.h>
+
+#include "AudioProcessorBase.h"
+
+namespace flowgraph {
+
+class SourceI32 : public AudioSource {
+public:
+ explicit SourceI32(int32_t channelCount);
+ ~SourceI32() override = default;
+
+ int32_t onProcess(int64_t framePosition, int32_t numFrames) override;
+
+private:
+ static constexpr float kScale = 1.0 / (1UL << 31);
+};
+
+} /* namespace flowgraph */
+
+#endif //FLOWGRAPH_SOURCE_I32_H
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 3dfb801..d795725 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -134,6 +134,12 @@
case AAUDIO_FORMAT_PCM_FLOAT:
androidFormat = AUDIO_FORMAT_PCM_FLOAT;
break;
+ case AAUDIO_FORMAT_PCM_I24_PACKED:
+ androidFormat = AUDIO_FORMAT_PCM_24_BIT_PACKED;
+ break;
+ case AAUDIO_FORMAT_PCM_I32:
+ androidFormat = AUDIO_FORMAT_PCM_32_BIT;
+ break;
default:
androidFormat = AUDIO_FORMAT_INVALID;
ALOGE("%s() 0x%08X unrecognized", __func__, aaudioFormat);
@@ -154,6 +160,12 @@
case AUDIO_FORMAT_PCM_FLOAT:
aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
break;
+ case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+ aaudioFormat = AAUDIO_FORMAT_PCM_I24_PACKED;
+ break;
+ case AUDIO_FORMAT_PCM_32_BIT:
+ aaudioFormat = AAUDIO_FORMAT_PCM_I32;
+ break;
default:
aaudioFormat = AAUDIO_FORMAT_INVALID;
ALOGE("%s() 0x%08X unrecognized", __func__, androidFormat);
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 5bccfd5..85b2057 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -72,24 +72,46 @@
aaudio_result_t AAudioServiceEndpointMMAP::open(const aaudio::AAudioStreamRequest &request) {
aaudio_result_t result = AAUDIO_OK;
- audio_config_base_t config;
- audio_port_handle_t deviceId;
-
copyFrom(request.getConstantConfiguration());
-
- const audio_attributes_t attributes = getAudioAttributesFrom(this);
-
mMmapClient.clientUid = request.getUserId();
mMmapClient.clientPid = request.getProcessId();
mMmapClient.packageName.setTo(String16(""));
+ audio_format_t audioFormat = getFormat();
+
+ // FLOAT is not directly supported by the HAL so ask for a 24-bit.
+ bool isHighResRequested = audioFormat == AUDIO_FORMAT_PCM_FLOAT
+ || audioFormat == AUDIO_FORMAT_PCM_32_BIT;
+ if (isHighResRequested) {
+ // TODO remove these logs when finished debugging.
+ ALOGD("%s() change format from %d to 24_BIT_PACKED", __func__, audioFormat);
+ audioFormat = AUDIO_FORMAT_PCM_24_BIT_PACKED;
+ }
+
+ result = openWithFormat(audioFormat);
+ if (result == AAUDIO_OK) return result;
+
+ // TODO The HAL and AudioFlinger should be recommending a format if the open fails.
+ // But that recommendation is not propagating back from the HAL.
+ // So for now just try something very likely to work.
+ if (result == AAUDIO_ERROR_UNAVAILABLE && audioFormat == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
+ ALOGD("%s() 24_BIT failed, perhaps due to format. Try again with 16_BIT", __func__);
+ audioFormat = AUDIO_FORMAT_PCM_16_BIT;
+ result = openWithFormat(audioFormat);
+ }
+ return result;
+}
+
+aaudio_result_t AAudioServiceEndpointMMAP::openWithFormat(audio_format_t audioFormat) {
+ aaudio_result_t result = AAUDIO_OK;
+ audio_config_base_t config;
+ audio_port_handle_t deviceId;
+
+ const audio_attributes_t attributes = getAudioAttributesFrom(this);
+
mRequestedDeviceId = deviceId = getDeviceId();
// Fill in config
- audio_format_t audioFormat = getFormat();
- if (audioFormat == AUDIO_FORMAT_DEFAULT || audioFormat == AUDIO_FORMAT_PCM_FLOAT) {
- audioFormat = AUDIO_FORMAT_PCM_16_BIT;
- }
config.format = audioFormat;
int32_t aaudioSampleRate = getSampleRate();
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
index a2a0922..24b161d 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.h
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -88,6 +88,9 @@
aaudio_result_t getExternalPosition(uint64_t *positionFrames, int64_t *timeNanos);
private:
+
+ aaudio_result_t openWithFormat(audio_format_t audioFormat);
+
MonotonicCounter mFramesTransferred;
// Interface to the AudioFlinger MMAP support.