aaudio: add tests for device switch detection and refactor
Add detection for device switch during capture and playback tests:
write_sine, write_sine_callback, input_monitor, input_monitor_callback
Refactor tests and move simple player, simple recorder and utility
methods in separate header files and folder.
Bug: 33355262
Test: run write_sine and input_monitor tests
Change-Id: Iced66fa4344aecd8a2952e22a98e6e8454f38a5e
diff --git a/media/libaaudio/examples/input_monitor/jni/Android.mk b/media/libaaudio/examples/input_monitor/jni/Android.mk
index 51a5a85..3e24f9f 100644
--- a/media/libaaudio/examples/input_monitor/jni/Android.mk
+++ b/media/libaaudio/examples/input_monitor/jni/Android.mk
@@ -4,32 +4,30 @@
LOCAL_MODULE_TAGS := tests
LOCAL_C_INCLUDES := \
$(call include-path-for, audio-utils) \
- frameworks/av/media/liboboe/include
+ frameworks/av/media/libaaudio/include \
+ frameworks/av/media/libaaudio/src \
+ frameworks/av/media/libaaudio/examples/utils
-LOCAL_SRC_FILES:= frameworks/av/media/liboboe/src/write_sine.cpp
-LOCAL_SHARED_LIBRARIES := libaudioutils libmedia libtinyalsa \
- libbinder libcutils libutils
-LOCAL_STATIC_LIBRARIES := libsndfile
-LOCAL_MODULE := write_sine_ndk
-LOCAL_SHARED_LIBRARIES += liboboe_prebuilt
+# NDK recommends using this kind of relative path instead of an absolute path.
+LOCAL_SRC_FILES:= ../src/input_monitor.cpp
+LOCAL_SHARED_LIBRARIES := libaaudio
+LOCAL_MODULE := input_monitor_ndk
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
LOCAL_C_INCLUDES := \
$(call include-path-for, audio-utils) \
- frameworks/av/media/liboboe/include
+ frameworks/av/media/libaaudio/include \
+ frameworks/av/media/libaaudio/examples/utils
-LOCAL_SRC_FILES:= frameworks/av/media/liboboe/src/write_sine_threaded.cpp
-LOCAL_SHARED_LIBRARIES := libaudioutils libmedia libtinyalsa \
- libbinder libcutils libutils
-LOCAL_STATIC_LIBRARIES := libsndfile
-LOCAL_MODULE := write_sine_threaded_ndk
-LOCAL_SHARED_LIBRARIES += liboboe_prebuilt
+LOCAL_SRC_FILES:= ../src/input_monitor_callback.cpp
+LOCAL_SHARED_LIBRARIES := libaaudio
+LOCAL_MODULE := input_monitor_callback_ndk
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
-LOCAL_MODULE := liboboe_prebuilt
-LOCAL_SRC_FILES := liboboe.so
+LOCAL_MODULE := libaaudio_prebuilt
+LOCAL_SRC_FILES := libaaudio.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
-include $(PREBUILT_SHARED_LIBRARY)
+include $(PREBUILT_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/media/libaaudio/examples/input_monitor/src/input_monitor.cpp b/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
index 7357c69..5d55eaa 100644
--- a/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
+++ b/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
@@ -22,36 +22,21 @@
#include <stdlib.h>
#include <math.h>
#include <aaudio/AAudio.h>
+#include "AAudioExampleUtils.h"
+#include "AAudioSimpleRecorder.h"
#define SAMPLE_RATE 48000
-#define NUM_SECONDS 5
-#define NANOS_PER_MICROSECOND ((int64_t)1000)
-#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
-#define NANOS_PER_SECOND (NANOS_PER_MILLISECOND * 1000)
-#define MIN_FRAMES_TO_READ 48 /* arbitrary, 1 msec at 48000 Hz */
+#define NUM_SECONDS 10
-static const char *getSharingModeText(aaudio_sharing_mode_t mode) {
- const char *modeText = "unknown";
- switch (mode) {
- case AAUDIO_SHARING_MODE_EXCLUSIVE:
- modeText = "EXCLUSIVE";
- break;
- case AAUDIO_SHARING_MODE_SHARED:
- modeText = "SHARED";
- break;
- default:
- break;
- }
- return modeText;
-}
+#define MIN_FRAMES_TO_READ 48 /* arbitrary, 1 msec at 48000 Hz */
int main(int argc, char **argv)
{
(void)argc; // unused
aaudio_result_t result;
-
+ AAudioSimpleRecorder recorder;
int actualSamplesPerFrame;
int actualSampleRate;
const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM_I16;
@@ -66,7 +51,6 @@
//const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
aaudio_sharing_mode_t actualSharingMode;
- AAudioStreamBuilder *aaudioBuilder = nullptr;
AAudioStream *aaudioStream = nullptr;
aaudio_stream_state_t state;
int32_t framesPerBurst = 0;
@@ -84,24 +68,16 @@
printf("%s - Monitor input level using AAudio\n", argv[0]);
- // Use an AAudioStreamBuilder to contain requested parameters.
- result = AAudio_createStreamBuilder(&aaudioBuilder);
+ recorder.setPerformanceMode(requestedPerformanceMode);
+ recorder.setSharingMode(requestedSharingMode);
+
+ result = recorder.open(requestedInputChannelCount, 48000, requestedDataFormat,
+ nullptr, nullptr, nullptr);
if (result != AAUDIO_OK) {
+ fprintf(stderr, "ERROR - recorder.open() returned %d\n", result);
goto finish;
}
-
- // Request stream properties.
- AAudioStreamBuilder_setDirection(aaudioBuilder, AAUDIO_DIRECTION_INPUT);
- AAudioStreamBuilder_setFormat(aaudioBuilder, requestedDataFormat);
- AAudioStreamBuilder_setSharingMode(aaudioBuilder, requestedSharingMode);
- AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, requestedPerformanceMode);
- AAudioStreamBuilder_setChannelCount(aaudioBuilder, requestedInputChannelCount);
-
- // Create an AAudioStream using the Builder.
- result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
- if (result != AAUDIO_OK) {
- goto finish;
- }
+ aaudioStream = recorder.getStream();
actualSamplesPerFrame = AAudioStream_getSamplesPerFrame(aaudioStream);
printf("SamplesPerFrame = %d\n", actualSamplesPerFrame);
@@ -143,10 +119,9 @@
}
// Start the stream.
- printf("call AAudioStream_requestStart()\n");
- result = AAudioStream_requestStart(aaudioStream);
+ result = recorder.start();
if (result != AAUDIO_OK) {
- fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d\n", result);
+ fprintf(stderr, "ERROR - recorder.start() returned %d\n", result);
goto finish;
}
@@ -181,12 +156,7 @@
// Display level as stars, eg. "******".
if ((loopCounter++ % 10) == 0) {
- printf("%5.3f ", peakLevel);
- int numStars = (int)(peakLevel * 50);
- for (int i = 0; i < numStars; i++) {
- printf("*");
- }
- printf("\n");
+ displayPeakLevel(peakLevel);
peakLevel = 0.0;
}
}
@@ -194,9 +164,13 @@
xRunCount = AAudioStream_getXRunCount(aaudioStream);
printf("AAudioStream_getXRunCount %d\n", xRunCount);
+ result = recorder.stop();
+ if (result != AAUDIO_OK) {
+ goto finish;
+ }
+
finish:
- AAudioStream_close(aaudioStream);
- AAudioStreamBuilder_delete(aaudioBuilder);
+ recorder.close();
delete[] data;
printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
return (result != AAUDIO_OK) ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp b/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp
index 4c2d870..9de2eb0 100644
--- a/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp
+++ b/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp
@@ -23,229 +23,18 @@
#include <math.h>
#include <time.h>
#include <aaudio/AAudio.h>
+#include "AAudioExampleUtils.h"
+#include "AAudioSimpleRecorder.h"
#define NUM_SECONDS 5
-#define NANOS_PER_MICROSECOND ((int64_t)1000)
-#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
-#define NANOS_PER_SECOND (NANOS_PER_MILLISECOND * 1000)
-
-//#define SHARING_MODE AAUDIO_SHARING_MODE_EXCLUSIVE
-#define SHARING_MODE AAUDIO_SHARING_MODE_SHARED
-
-/**
- * Simple wrapper for AAudio that opens an input stream and then calls
- * a callback function to process the input data.
- */
-class SimpleAAudioRecorder {
-public:
- SimpleAAudioRecorder() {}
- ~SimpleAAudioRecorder() {
- close();
- };
-
- /**
- * Call this before calling open().
- * @param requestedSharingMode
- */
- void setSharingMode(aaudio_sharing_mode_t requestedSharingMode) {
- mRequestedSharingMode = requestedSharingMode;
- }
-
- /**
- * Also known as "sample rate"
- * Only call this after open() has been called.
- */
- int32_t getFramesPerSecond() {
- if (mStream == nullptr) {
- return AAUDIO_ERROR_INVALID_STATE;
- }
- return AAudioStream_getSampleRate(mStream);;
- }
-
- /**
- * Only call this after open() has been called.
- */
- int32_t getSamplesPerFrame() {
- if (mStream == nullptr) {
- return AAUDIO_ERROR_INVALID_STATE;
- }
- return AAudioStream_getSamplesPerFrame(mStream);;
- }
- /**
- * Only call this after open() has been called.
- */
- int64_t getFramesRead() {
- if (mStream == nullptr) {
- return AAUDIO_ERROR_INVALID_STATE;
- }
- return AAudioStream_getFramesRead(mStream);;
- }
-
- /**
- * Open a stream
- */
- aaudio_result_t open(AAudioStream_dataCallback proc, void *userContext) {
- aaudio_result_t result = AAUDIO_OK;
-
- // Use an AAudioStreamBuilder to contain requested parameters.
- result = AAudio_createStreamBuilder(&mBuilder);
- if (result != AAUDIO_OK) return result;
-
- AAudioStreamBuilder_setDirection(mBuilder, AAUDIO_DIRECTION_INPUT);
- AAudioStreamBuilder_setSharingMode(mBuilder, mRequestedSharingMode);
- AAudioStreamBuilder_setDataCallback(mBuilder, proc, userContext);
- AAudioStreamBuilder_setFormat(mBuilder, AAUDIO_FORMAT_PCM_I16);
-
- // Open an AAudioStream using the Builder.
- result = AAudioStreamBuilder_openStream(mBuilder, &mStream);
- if (result != AAUDIO_OK) {
- fprintf(stderr, "ERROR - AAudioStreamBuilder_openStream() returned %d %s\n",
- result, AAudio_convertResultToText(result));
- goto finish1;
- }
-
- printf("AAudioStream_getFramesPerBurst() = %d\n",
- AAudioStream_getFramesPerBurst(mStream));
- printf("AAudioStream_getBufferSizeInFrames() = %d\n",
- AAudioStream_getBufferSizeInFrames(mStream));
- printf("AAudioStream_getBufferCapacityInFrames() = %d\n",
- AAudioStream_getBufferCapacityInFrames(mStream));
- return result;
-
- finish1:
- AAudioStreamBuilder_delete(mBuilder);
- mBuilder = nullptr;
- return result;
- }
-
- aaudio_result_t close() {
- if (mStream != nullptr) {
- printf("call AAudioStream_close(%p)\n", mStream); fflush(stdout);
- AAudioStream_close(mStream);
- mStream = nullptr;
- AAudioStreamBuilder_delete(mBuilder);
- mBuilder = nullptr;
- }
- return AAUDIO_OK;
- }
-
- // Write zero data to fill up the buffer and prevent underruns.
- aaudio_result_t prime() {
- int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(mStream);
- const int numFrames = 32; // arbitrary
- float zeros[numFrames * samplesPerFrame];
- memset(zeros, 0, sizeof(zeros));
- aaudio_result_t result = numFrames;
- while (result == numFrames) {
- result = AAudioStream_write(mStream, zeros, numFrames, 0);
- }
- return result;
- }
-
- // Start the stream. AAudio will start calling your callback function.
- aaudio_result_t start() {
- aaudio_result_t result = AAudioStream_requestStart(mStream);
- if (result != AAUDIO_OK) {
- fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d %s\n",
- result, AAudio_convertResultToText(result));
- }
- return result;
- }
-
- // Stop the stream. AAudio will stop calling your callback function.
- aaudio_result_t stop() {
- aaudio_result_t result = AAudioStream_requestStop(mStream);
- if (result != AAUDIO_OK) {
- fprintf(stderr, "ERROR - AAudioStream_requestStop() returned %d %s\n",
- result, AAudio_convertResultToText(result));
- }
- return result;
- }
-
- // Pause the stream. AAudio will stop calling your callback function.
- aaudio_result_t pause() {
- aaudio_result_t result = AAudioStream_requestPause(mStream);
- if (result != AAUDIO_OK) {
- fprintf(stderr, "ERROR - AAudioStream_requestPause() returned %d %s\n",
- result, AAudio_convertResultToText(result));
- }
- return result;
- }
-
-private:
- AAudioStreamBuilder *mBuilder = nullptr;
- AAudioStream *mStream = nullptr;
- aaudio_sharing_mode_t mRequestedSharingMode = SHARING_MODE;
-};
-
-// Application data that gets passed to the callback.
-typedef struct PeakTrackerData {
- float peakLevel;
-} PeakTrackerData_t;
-
-#define DECAY_FACTOR 0.999
-
-// Callback function that fills the audio output buffer.
-aaudio_data_callback_result_t MyDataCallbackProc(
- AAudioStream *stream,
- void *userData,
- void *audioData,
- int32_t numFrames
- ) {
-
- PeakTrackerData_t *data = (PeakTrackerData_t *) userData;
- // printf("MyCallbackProc(): frameCount = %d\n", numFrames);
- int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(stream);
- float sample;
- // This code assume mono or stereo.
- switch (AAudioStream_getFormat(stream)) {
- case AAUDIO_FORMAT_PCM_I16: {
- int16_t *audioBuffer = (int16_t *) audioData;
- // Peak follower
- for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
- sample = audioBuffer[frameIndex * samplesPerFrame] * (1.0/32768);
- data->peakLevel *= DECAY_FACTOR;
- if (sample > data->peakLevel) {
- data->peakLevel = sample;
- }
- }
- }
- break;
- case AAUDIO_FORMAT_PCM_FLOAT: {
- float *audioBuffer = (float *) audioData;
- // Peak follower
- for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
- sample = audioBuffer[frameIndex * samplesPerFrame];
- data->peakLevel *= DECAY_FACTOR;
- if (sample > data->peakLevel) {
- data->peakLevel = sample;
- }
- }
- }
- break;
- default:
- return AAUDIO_CALLBACK_RESULT_STOP;
- }
-
- return AAUDIO_CALLBACK_RESULT_CONTINUE;
-}
-
-void displayPeakLevel(float peakLevel) {
- printf("%5.3f ", peakLevel);
- const int maxStars = 50; // arbitrary, fits on one line
- int numStars = (int) (peakLevel * maxStars);
- for (int i = 0; i < numStars; i++) {
- printf("*");
- }
- printf("\n");
-}
int main(int argc, char **argv)
{
(void)argc; // unused
- SimpleAAudioRecorder recorder;
+ AAudioSimpleRecorder recorder;
PeakTrackerData_t myData = {0.0};
aaudio_result_t result;
+ aaudio_stream_state_t state;
const int displayRateHz = 20; // arbitrary
const int loopsNeeded = NUM_SECONDS * displayRateHz;
@@ -254,9 +43,8 @@
setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
printf("%s - Display audio input using an AAudio callback\n", argv[0]);
- recorder.setSharingMode(SHARING_MODE);
-
- result = recorder.open(MyDataCallbackProc, &myData);
+ result = recorder.open(2, 48000, AAUDIO_FORMAT_PCM_I16,
+ SimpleRecorderDataCallbackProc, SimpleRecorderErrorCallbackProc, &myData);
if (result != AAUDIO_OK) {
fprintf(stderr, "ERROR - recorder.open() returned %d\n", result);
goto error;
@@ -278,6 +66,19 @@
(void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
printf("%08d: ", (int)recorder.getFramesRead());
displayPeakLevel(myData.peakLevel);
+
+ result = AAudioStream_waitForStateChange(recorder.getStream(),
+ AAUDIO_STREAM_STATE_CLOSED,
+ &state,
+ 0);
+ if (result != AAUDIO_OK) {
+ fprintf(stderr, "ERROR - AAudioStream_waitForStateChange() returned %d\n", result);
+ goto error;
+ }
+ if (state != AAUDIO_STREAM_STATE_STARTING && state != AAUDIO_STREAM_STATE_STARTED) {
+ printf("Stream state is %d %s!\n", state, AAudio_convertStreamStateToText(state));
+ break;
+ }
}
printf("Woke up. Stop for a moment.\n");
@@ -300,6 +101,12 @@
(void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
printf("%08d: ", (int)recorder.getFramesRead());
displayPeakLevel(myData.peakLevel);
+
+ state = AAudioStream_getState(recorder.getStream());
+ if (state != AAUDIO_STREAM_STATE_STARTING && state != AAUDIO_STREAM_STATE_STARTED) {
+ printf("Stream state is %d %s!\n", state, AAudio_convertStreamStateToText(state));
+ break;
+ }
}
printf("Woke up now.\n");
diff --git a/media/libaaudio/examples/input_monitor/static/Android.mk b/media/libaaudio/examples/input_monitor/static/Android.mk
index e83f179..00a4cda 100644
--- a/media/libaaudio/examples/input_monitor/static/Android.mk
+++ b/media/libaaudio/examples/input_monitor/static/Android.mk
@@ -4,7 +4,8 @@
LOCAL_MODULE_TAGS := examples
LOCAL_C_INCLUDES := \
$(call include-path-for, audio-utils) \
- frameworks/av/media/libaaudio/include
+ frameworks/av/media/libaaudio/include \
+ frameworks/av/media/libaaudio/examples/utils
# TODO reorganize folders to avoid using ../
LOCAL_SRC_FILES:= ../src/input_monitor.cpp
@@ -22,7 +23,8 @@
LOCAL_MODULE_TAGS := tests
LOCAL_C_INCLUDES := \
$(call include-path-for, audio-utils) \
- frameworks/av/media/libaaudio/include
+ frameworks/av/media/libaaudio/include \
+ frameworks/av/media/libaaudio/examples/utils
LOCAL_SRC_FILES:= ../src/input_monitor_callback.cpp
diff --git a/media/libaaudio/examples/utils/AAudioExampleUtils.h b/media/libaaudio/examples/utils/AAudioExampleUtils.h
new file mode 100644
index 0000000..66de25f
--- /dev/null
+++ b/media/libaaudio/examples/utils/AAudioExampleUtils.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 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 AAUDIO_EXAMPLE_UTILS_H
+#define AAUDIO_EXAMPLE_UTILS_H
+
+#include <unistd.h>
+#include <sched.h>
+#include <aaudio/AAudio.h>
+
+#define NANOS_PER_MICROSECOND ((int64_t)1000)
+#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
+#define NANOS_PER_SECOND (NANOS_PER_MILLISECOND * 1000)
+
+static const char *getSharingModeText(aaudio_sharing_mode_t mode) {
+ const char *modeText = "unknown";
+ switch (mode) {
+ case AAUDIO_SHARING_MODE_EXCLUSIVE:
+ modeText = "EXCLUSIVE";
+ break;
+ case AAUDIO_SHARING_MODE_SHARED:
+ modeText = "SHARED";
+ break;
+ default:
+ break;
+ }
+ return modeText;
+}
+
+static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
+ struct timespec time;
+ int result = clock_gettime(clockId, &time);
+ if (result < 0) {
+ return -errno;
+ }
+ return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec;
+}
+
+void displayPeakLevel(float peakLevel) {
+ printf("%5.3f ", peakLevel);
+ const int maxStars = 50; // arbitrary, fits on one line
+ int numStars = (int) (peakLevel * maxStars);
+ for (int i = 0; i < numStars; i++) {
+ printf("*");
+ }
+ printf("\n");
+}
+
+#endif // AAUDIO_EXAMPLE_UTILS_H
diff --git a/media/libaaudio/examples/utils/AAudioSimplePlayer.h b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
new file mode 100644
index 0000000..aaeb25f
--- /dev/null
+++ b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+// Play sine waves using an AAudio callback.
+
+#ifndef AAUDIO_SIMPLE_PLAYER_H
+#define AAUDIO_SIMPLE_PLAYER_H
+
+#include <unistd.h>
+#include <sched.h>
+
+#include <aaudio/AAudio.h>
+#include "SineGenerator.h"
+
+//#define SHARING_MODE AAUDIO_SHARING_MODE_EXCLUSIVE
+#define SHARING_MODE AAUDIO_SHARING_MODE_SHARED
+#define PERFORMANCE_MODE AAUDIO_PERFORMANCE_MODE_NONE
+
+/**
+ * Simple wrapper for AAudio that opens an output stream either in callback or blocking write mode.
+ */
+class AAudioSimplePlayer {
+public:
+ AAudioSimplePlayer() {}
+ ~AAudioSimplePlayer() {
+ close();
+ };
+
+ /**
+ * Call this before calling open().
+ * @param requestedSharingMode
+ */
+ void setSharingMode(aaudio_sharing_mode_t requestedSharingMode) {
+ mRequestedSharingMode = requestedSharingMode;
+ }
+
+ /**
+ * Call this before calling open().
+ * @param requestedPerformanceMode
+ */
+ void setPerformanceMode(aaudio_performance_mode_t requestedPerformanceMode) {
+ mRequestedPerformanceMode = requestedPerformanceMode;
+ }
+
+ /**
+ * Also known as "sample rate"
+ * Only call this after open() has been called.
+ */
+ int32_t getFramesPerSecond() {
+ if (mStream == nullptr) {
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
+ return AAudioStream_getSampleRate(mStream);;
+ }
+
+ /**
+ * Only call this after open() has been called.
+ */
+ int32_t getChannelCount() {
+ if (mStream == nullptr) {
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
+ return AAudioStream_getChannelCount(mStream);;
+ }
+
+ /**
+ * Open a stream
+ */
+ aaudio_result_t open(int channelCount, int sampSampleRate, aaudio_format_t format,
+ AAudioStream_dataCallback dataProc, AAudioStream_errorCallback errorProc,
+ void *userContext) {
+ aaudio_result_t result = AAUDIO_OK;
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ result = AAudio_createStreamBuilder(&mBuilder);
+ if (result != AAUDIO_OK) return result;
+
+ //AAudioStreamBuilder_setSampleRate(mBuilder, 44100);
+ AAudioStreamBuilder_setPerformanceMode(mBuilder, mRequestedPerformanceMode);
+ AAudioStreamBuilder_setSharingMode(mBuilder, mRequestedSharingMode);
+ if (dataProc != nullptr) {
+ AAudioStreamBuilder_setDataCallback(mBuilder, dataProc, userContext);
+ }
+ if (errorProc != nullptr) {
+ AAudioStreamBuilder_setErrorCallback(mBuilder, errorProc, userContext);
+ }
+ AAudioStreamBuilder_setChannelCount(mBuilder, channelCount);
+ AAudioStreamBuilder_setSampleRate(mBuilder, sampSampleRate);
+ AAudioStreamBuilder_setFormat(mBuilder, format);
+ //AAudioStreamBuilder_setFramesPerDataCallback(mBuilder, CALLBACK_SIZE_FRAMES);
+ AAudioStreamBuilder_setBufferCapacityInFrames(mBuilder, 48 * 8);
+
+ //aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_NONE;
+ aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
+ //aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
+ AAudioStreamBuilder_setPerformanceMode(mBuilder, perfMode);
+
+ // Open an AAudioStream using the Builder.
+ result = AAudioStreamBuilder_openStream(mBuilder, &mStream);
+ if (result != AAUDIO_OK) goto finish1;
+
+ printf("AAudioStream_getFramesPerBurst() = %d\n",
+ AAudioStream_getFramesPerBurst(mStream));
+ printf("AAudioStream_getBufferSizeInFrames() = %d\n",
+ AAudioStream_getBufferSizeInFrames(mStream));
+ printf("AAudioStream_getBufferCapacityInFrames() = %d\n",
+ AAudioStream_getBufferCapacityInFrames(mStream));
+ printf("AAudioStream_getPerformanceMode() = %d, requested %d\n",
+ AAudioStream_getPerformanceMode(mStream), perfMode);
+
+ finish1:
+ AAudioStreamBuilder_delete(mBuilder);
+ mBuilder = nullptr;
+ return result;
+ }
+
+ aaudio_result_t close() {
+ if (mStream != nullptr) {
+ printf("call AAudioStream_close(%p)\n", mStream); fflush(stdout);
+ AAudioStream_close(mStream);
+ mStream = nullptr;
+ AAudioStreamBuilder_delete(mBuilder);
+ mBuilder = nullptr;
+ }
+ return AAUDIO_OK;
+ }
+
+ // Write zero data to fill up the buffer and prevent underruns.
+ aaudio_result_t prime() {
+ int32_t samplesPerFrame = AAudioStream_getChannelCount(mStream);
+ const int numFrames = 32;
+ float zeros[numFrames * samplesPerFrame];
+ memset(zeros, 0, sizeof(zeros));
+ aaudio_result_t result = numFrames;
+ while (result == numFrames) {
+ result = AAudioStream_write(mStream, zeros, numFrames, 0);
+ }
+ return result;
+ }
+
+ // Start the stream. AAudio will start calling your callback function.
+ aaudio_result_t start() {
+ aaudio_result_t result = AAudioStream_requestStart(mStream);
+ if (result != AAUDIO_OK) {
+ printf("ERROR - AAudioStream_requestStart() returned %d %s\n",
+ result, AAudio_convertResultToText(result));
+ }
+ return result;
+ }
+
+ // Stop the stream. AAudio will stop calling your callback function.
+ aaudio_result_t stop() {
+ aaudio_result_t result = AAudioStream_requestStop(mStream);
+ if (result != AAUDIO_OK) {
+ printf("ERROR - AAudioStream_requestStop() returned %d %s\n",
+ result, AAudio_convertResultToText(result));
+ }
+ int32_t xRunCount = AAudioStream_getXRunCount(mStream);
+ printf("AAudioStream_getXRunCount %d\n", xRunCount);
+ return result;
+ }
+
+ AAudioStream *getStream() const {
+ return mStream;
+ }
+
+private:
+ AAudioStreamBuilder *mBuilder = nullptr;
+ AAudioStream *mStream = nullptr;
+ aaudio_sharing_mode_t mRequestedSharingMode = SHARING_MODE;
+ aaudio_performance_mode_t mRequestedPerformanceMode = PERFORMANCE_MODE;
+};
+
+typedef struct SineThreadedData_s {
+ SineGenerator sineOsc1;
+ SineGenerator sineOsc2;
+ int scheduler;
+ bool schedulerChecked;
+} SineThreadedData_t;
+
+// Callback function that fills the audio output buffer.
+aaudio_data_callback_result_t SimplePlayerDataCallbackProc(
+ AAudioStream *stream,
+ void *userData,
+ void *audioData,
+ int32_t numFrames
+ ) {
+
+ // should not happen but just in case...
+ if (userData == nullptr) {
+ fprintf(stderr, "ERROR - SimplePlayerDataCallbackProc needs userData\n");
+ return AAUDIO_CALLBACK_RESULT_STOP;
+ }
+ SineThreadedData_t *sineData = (SineThreadedData_t *) userData;
+
+ if (!sineData->schedulerChecked) {
+ sineData->scheduler = sched_getscheduler(gettid());
+ sineData->schedulerChecked = true;
+ }
+
+ int32_t samplesPerFrame = AAudioStream_getChannelCount(stream);
+ // This code only plays on the first one or two channels.
+ // TODO Support arbitrary number of channels.
+ switch (AAudioStream_getFormat(stream)) {
+ case AAUDIO_FORMAT_PCM_I16: {
+ int16_t *audioBuffer = (int16_t *) audioData;
+ // Render sine waves as shorts to first channel.
+ sineData->sineOsc1.render(&audioBuffer[0], samplesPerFrame, numFrames);
+ // Render sine waves to second channel if there is one.
+ if (samplesPerFrame > 1) {
+ sineData->sineOsc2.render(&audioBuffer[1], samplesPerFrame, numFrames);
+ }
+ }
+ break;
+ case AAUDIO_FORMAT_PCM_FLOAT: {
+ float *audioBuffer = (float *) audioData;
+ // Render sine waves as floats to first channel.
+ sineData->sineOsc1.render(&audioBuffer[0], samplesPerFrame, numFrames);
+ // Render sine waves to second channel if there is one.
+ if (samplesPerFrame > 1) {
+ sineData->sineOsc2.render(&audioBuffer[1], samplesPerFrame, numFrames);
+ }
+ }
+ break;
+ default:
+ return AAUDIO_CALLBACK_RESULT_STOP;
+ }
+
+ return AAUDIO_CALLBACK_RESULT_CONTINUE;
+}
+
+void SimplePlayerErrorCallbackProc(
+ AAudioStream *stream __unused,
+ void *userData __unused,
+ aaudio_result_t error)
+{
+ printf("Error Callback, error: %d\n",(int)error);
+}
+
+#endif //AAUDIO_SIMPLE_PLAYER_H
diff --git a/media/libaaudio/examples/utils/AAudioSimpleRecorder.h b/media/libaaudio/examples/utils/AAudioSimpleRecorder.h
new file mode 100644
index 0000000..9e7c463
--- /dev/null
+++ b/media/libaaudio/examples/utils/AAudioSimpleRecorder.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+// Record input using AAudio and display the peak amplitudes.
+
+#ifndef AAUDIO_SIMPLE_RECORDER_H
+#define AAUDIO_SIMPLE_RECORDER_H
+
+#include <aaudio/AAudio.h>
+
+//#define SHARING_MODE AAUDIO_SHARING_MODE_EXCLUSIVE
+#define SHARING_MODE AAUDIO_SHARING_MODE_SHARED
+#define PERFORMANCE_MODE AAUDIO_PERFORMANCE_MODE_NONE
+/**
+ * Simple wrapper for AAudio that opens an input stream either in callback or blocking read mode.
+ */
+class AAudioSimpleRecorder {
+public:
+ AAudioSimpleRecorder() {}
+ ~AAudioSimpleRecorder() {
+ close();
+ };
+
+ /**
+ * Call this before calling open().
+ * @param requestedSharingMode
+ */
+ void setSharingMode(aaudio_sharing_mode_t requestedSharingMode) {
+ mRequestedSharingMode = requestedSharingMode;
+ }
+
+ /**
+ * Call this before calling open().
+ * @param requestedPerformanceMode
+ */
+ void setPerformanceMode(aaudio_performance_mode_t requestedPerformanceMode) {
+ mRequestedPerformanceMode = requestedPerformanceMode;
+ }
+
+ /**
+ * Also known as "sample rate"
+ * Only call this after open() has been called.
+ */
+ int32_t getFramesPerSecond() {
+ if (mStream == nullptr) {
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
+ return AAudioStream_getSampleRate(mStream);;
+ }
+
+ /**
+ * Only call this after open() has been called.
+ */
+ int32_t getSamplesPerFrame() {
+ if (mStream == nullptr) {
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
+ return AAudioStream_getSamplesPerFrame(mStream);;
+ }
+ /**
+ * Only call this after open() has been called.
+ */
+ int64_t getFramesRead() {
+ if (mStream == nullptr) {
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
+ return AAudioStream_getFramesRead(mStream);;
+ }
+
+ /**
+ * Open a stream
+ */
+ aaudio_result_t open(int channelCount, int sampSampleRate, aaudio_format_t format,
+ AAudioStream_dataCallback dataProc, AAudioStream_errorCallback errorProc,
+ void *userContext) {
+ aaudio_result_t result = AAUDIO_OK;
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ result = AAudio_createStreamBuilder(&mBuilder);
+ if (result != AAUDIO_OK) return result;
+
+ AAudioStreamBuilder_setDirection(mBuilder, AAUDIO_DIRECTION_INPUT);
+ AAudioStreamBuilder_setPerformanceMode(mBuilder, mRequestedPerformanceMode);
+ AAudioStreamBuilder_setSharingMode(mBuilder, mRequestedSharingMode);
+ if (dataProc != nullptr) {
+ AAudioStreamBuilder_setDataCallback(mBuilder, dataProc, userContext);
+ }
+ if (errorProc != nullptr) {
+ AAudioStreamBuilder_setErrorCallback(mBuilder, errorProc, userContext);
+ }
+ AAudioStreamBuilder_setChannelCount(mBuilder, channelCount);
+ AAudioStreamBuilder_setSampleRate(mBuilder, sampSampleRate);
+ AAudioStreamBuilder_setFormat(mBuilder, format);
+
+ // Open an AAudioStream using the Builder.
+ result = AAudioStreamBuilder_openStream(mBuilder, &mStream);
+ if (result != AAUDIO_OK) {
+ fprintf(stderr, "ERROR - AAudioStreamBuilder_openStream() returned %d %s\n",
+ result, AAudio_convertResultToText(result));
+ goto finish1;
+ }
+
+ printf("AAudioStream_getFramesPerBurst() = %d\n",
+ AAudioStream_getFramesPerBurst(mStream));
+ printf("AAudioStream_getBufferSizeInFrames() = %d\n",
+ AAudioStream_getBufferSizeInFrames(mStream));
+ printf("AAudioStream_getBufferCapacityInFrames() = %d\n",
+ AAudioStream_getBufferCapacityInFrames(mStream));
+ return result;
+
+ finish1:
+ AAudioStreamBuilder_delete(mBuilder);
+ mBuilder = nullptr;
+ return result;
+ }
+
+ aaudio_result_t close() {
+ if (mStream != nullptr) {
+ printf("call AAudioStream_close(%p)\n", mStream); fflush(stdout);
+ AAudioStream_close(mStream);
+ mStream = nullptr;
+ AAudioStreamBuilder_delete(mBuilder);
+ mBuilder = nullptr;
+ }
+ return AAUDIO_OK;
+ }
+
+ // Write zero data to fill up the buffer and prevent underruns.
+ aaudio_result_t prime() {
+ int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(mStream);
+ const int numFrames = 32; // arbitrary
+ float zeros[numFrames * samplesPerFrame];
+ memset(zeros, 0, sizeof(zeros));
+ aaudio_result_t result = numFrames;
+ while (result == numFrames) {
+ result = AAudioStream_write(mStream, zeros, numFrames, 0);
+ }
+ return result;
+ }
+
+ // Start the stream. AAudio will start calling your callback function.
+ aaudio_result_t start() {
+ aaudio_result_t result = AAudioStream_requestStart(mStream);
+ if (result != AAUDIO_OK) {
+ fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d %s\n",
+ result, AAudio_convertResultToText(result));
+ }
+ return result;
+ }
+
+ // Stop the stream. AAudio will stop calling your callback function.
+ aaudio_result_t stop() {
+ aaudio_result_t result = AAudioStream_requestStop(mStream);
+ if (result != AAUDIO_OK) {
+ fprintf(stderr, "ERROR - AAudioStream_requestStop() returned %d %s\n",
+ result, AAudio_convertResultToText(result));
+ }
+ return result;
+ }
+
+ // Pause the stream. AAudio will stop calling your callback function.
+ aaudio_result_t pause() {
+ aaudio_result_t result = AAudioStream_requestPause(mStream);
+ if (result != AAUDIO_OK) {
+ fprintf(stderr, "ERROR - AAudioStream_requestPause() returned %d %s\n",
+ result, AAudio_convertResultToText(result));
+ }
+ return result;
+ }
+
+ AAudioStream *getStream() const {
+ return mStream;
+ }
+
+private:
+ AAudioStreamBuilder *mBuilder = nullptr;
+ AAudioStream *mStream = nullptr;
+ aaudio_sharing_mode_t mRequestedSharingMode = SHARING_MODE;
+ aaudio_performance_mode_t mRequestedPerformanceMode = PERFORMANCE_MODE;
+};
+
+// Application data that gets passed to the callback.
+typedef struct PeakTrackerData {
+ float peakLevel;
+} PeakTrackerData_t;
+
+#define DECAY_FACTOR 0.999
+
+// Callback function that fills the audio output buffer.
+aaudio_data_callback_result_t SimpleRecorderDataCallbackProc(
+ AAudioStream *stream,
+ void *userData,
+ void *audioData,
+ int32_t numFrames
+ ) {
+
+ // should not happen but just in case...
+ if (userData == nullptr) {
+ fprintf(stderr, "ERROR - SimpleRecorderDataCallbackProc needs userData\n");
+ return AAUDIO_CALLBACK_RESULT_STOP;
+ }
+ PeakTrackerData_t *data = (PeakTrackerData_t *) userData;
+ // printf("MyCallbackProc(): frameCount = %d\n", numFrames);
+ int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(stream);
+ float sample;
+ // This code assume mono or stereo.
+ switch (AAudioStream_getFormat(stream)) {
+ case AAUDIO_FORMAT_PCM_I16: {
+ int16_t *audioBuffer = (int16_t *) audioData;
+ // Peak follower
+ for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
+ sample = audioBuffer[frameIndex * samplesPerFrame] * (1.0/32768);
+ data->peakLevel *= DECAY_FACTOR;
+ if (sample > data->peakLevel) {
+ data->peakLevel = sample;
+ }
+ }
+ }
+ break;
+ case AAUDIO_FORMAT_PCM_FLOAT: {
+ float *audioBuffer = (float *) audioData;
+ // Peak follower
+ for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
+ sample = audioBuffer[frameIndex * samplesPerFrame];
+ data->peakLevel *= DECAY_FACTOR;
+ if (sample > data->peakLevel) {
+ data->peakLevel = sample;
+ }
+ }
+ }
+ break;
+ default:
+ return AAUDIO_CALLBACK_RESULT_STOP;
+ }
+
+ return AAUDIO_CALLBACK_RESULT_CONTINUE;
+}
+
+void SimpleRecorderErrorCallbackProc(
+ AAudioStream *stream __unused,
+ void *userData __unused,
+ aaudio_result_t error)
+{
+ printf("Error Callback, error: %d\n",(int)error);
+}
+
+#endif //AAUDIO_SIMPLE_RECORDER_H
diff --git a/media/libaaudio/examples/write_sine/src/SineGenerator.h b/media/libaaudio/examples/utils/SineGenerator.h
similarity index 100%
rename from media/libaaudio/examples/write_sine/src/SineGenerator.h
rename to media/libaaudio/examples/utils/SineGenerator.h
diff --git a/media/libaaudio/examples/write_sine/jni/Android.mk b/media/libaaudio/examples/write_sine/jni/Android.mk
index 0bda008..c306ed3 100644
--- a/media/libaaudio/examples/write_sine/jni/Android.mk
+++ b/media/libaaudio/examples/write_sine/jni/Android.mk
@@ -5,7 +5,8 @@
LOCAL_C_INCLUDES := \
$(call include-path-for, audio-utils) \
frameworks/av/media/libaaudio/include \
- frameworks/av/media/libaaudio/src
+ frameworks/av/media/libaaudio/src \
+ frameworks/av/media/libaaudio/examples/utils
# NDK recommends using this kind of relative path instead of an absolute path.
LOCAL_SRC_FILES:= ../src/write_sine.cpp
@@ -17,7 +18,8 @@
LOCAL_MODULE_TAGS := tests
LOCAL_C_INCLUDES := \
$(call include-path-for, audio-utils) \
- frameworks/av/media/libaaudio/include
+ frameworks/av/media/libaaudio/include \
+ frameworks/av/media/libaaudio/examples/utils
LOCAL_SRC_FILES:= ../src/write_sine_callback.cpp
LOCAL_SHARED_LIBRARIES := libaaudio
diff --git a/media/libaaudio/examples/write_sine/src/write_sine.cpp b/media/libaaudio/examples/write_sine/src/write_sine.cpp
index 57a5273..27c6128 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine.cpp
@@ -20,58 +20,33 @@
#include <stdlib.h>
#include <math.h>
#include <aaudio/AAudio.h>
-#include "SineGenerator.h"
+#include "AAudioExampleUtils.h"
+#include "AAudioSimplePlayer.h"
#define SAMPLE_RATE 48000
-#define NUM_SECONDS 5
-#define NANOS_PER_MICROSECOND ((int64_t)1000)
-#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
-#define NANOS_PER_SECOND (NANOS_PER_MILLISECOND * 1000)
+#define NUM_SECONDS 20
#define REQUESTED_FORMAT AAUDIO_FORMAT_PCM_I16
#define REQUESTED_SHARING_MODE AAUDIO_SHARING_MODE_SHARED
//#define REQUESTED_SHARING_MODE AAUDIO_SHARING_MODE_EXCLUSIVE
-static const char *getSharingModeText(aaudio_sharing_mode_t mode) {
- const char *modeText = "unknown";
- switch (mode) {
- case AAUDIO_SHARING_MODE_EXCLUSIVE:
- modeText = "EXCLUSIVE";
- break;
- case AAUDIO_SHARING_MODE_SHARED:
- modeText = "SHARED";
- break;
- default:
- break;
- }
- return modeText;
-}
-
-// TODO move to a common utility library
-static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
- struct timespec time;
- int result = clock_gettime(clockId, &time);
- if (result < 0) {
- return -errno;
- }
- return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec;
-}
int main(int argc, char **argv)
{
(void)argc; // unused
+ AAudioSimplePlayer player;
+ SineThreadedData_t myData;
aaudio_result_t result = AAUDIO_OK;
const int requestedChannelCount = 2;
int actualChannelCount = 0;
const int requestedSampleRate = SAMPLE_RATE;
int actualSampleRate = 0;
+ aaudio_audio_format_t requestedDataFormat = REQUESTED_FORMAT;
aaudio_audio_format_t actualDataFormat = AAUDIO_FORMAT_UNSPECIFIED;
-
aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
- AAudioStreamBuilder *aaudioBuilder = nullptr;
AAudioStream *aaudioStream = nullptr;
aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED;
int32_t framesPerBurst = 0;
@@ -83,36 +58,23 @@
float *floatData = nullptr;
int16_t *shortData = nullptr;
- SineGenerator sineOsc1;
- SineGenerator sineOsc2;
-
// Make printf print immediately so that debug info is not stuck
// in a buffer if we hang or crash.
setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
printf("%s - Play a sine wave using AAudio\n", argv[0]);
- // Use an AAudioStreamBuilder to contain requested parameters.
- result = AAudio_createStreamBuilder(&aaudioBuilder);
+ player.setSharingMode(REQUESTED_SHARING_MODE);
+
+ result = player.open(requestedChannelCount, requestedSampleRate, requestedDataFormat,
+ nullptr, nullptr, &myData);
if (result != AAUDIO_OK) {
+ fprintf(stderr, "ERROR - player.open() returned %d\n", result);
goto finish;
}
+ aaudioStream = player.getStream();
// Request stream properties.
- AAudioStreamBuilder_setSampleRate(aaudioBuilder, requestedSampleRate);
- AAudioStreamBuilder_setChannelCount(aaudioBuilder, requestedChannelCount);
- AAudioStreamBuilder_setFormat(aaudioBuilder, REQUESTED_FORMAT);
- AAudioStreamBuilder_setSharingMode(aaudioBuilder, REQUESTED_SHARING_MODE);
-
- AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_NONE);
- //AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
- //AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_POWER_SAVING);
-
- // Create an AAudioStream using the Builder.
- result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
- if (result != AAUDIO_OK) {
- goto finish;
- }
state = AAudioStream_getState(aaudioStream);
printf("after open, state = %s\n", AAudio_convertStreamStateToText(state));
@@ -121,8 +83,8 @@
actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
printf("SampleRate: requested = %d, actual = %d\n", requestedSampleRate, actualSampleRate);
- sineOsc1.setup(440.0, actualSampleRate);
- sineOsc2.setup(660.0, actualSampleRate);
+ myData.sineOsc1.setup(440.0, actualSampleRate);
+ myData.sineOsc2.setup(660.0, actualSampleRate);
actualChannelCount = AAudioStream_getChannelCount(aaudioStream);
printf("ChannelCount: requested = %d, actual = %d\n",
@@ -167,8 +129,8 @@
}
// Start the stream.
- printf("call AAudioStream_requestStart()\n");
- result = AAudioStream_requestStart(aaudioStream);
+ printf("call player.start()\n");
+ result = player.start();
if (result != AAUDIO_OK) {
fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d\n", result);
goto finish;
@@ -184,15 +146,15 @@
if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) {
// Render sine waves to left and right channels.
- sineOsc1.render(&floatData[0], actualChannelCount, framesPerWrite);
+ myData.sineOsc1.render(&floatData[0], actualChannelCount, framesPerWrite);
if (actualChannelCount > 1) {
- sineOsc2.render(&floatData[1], actualChannelCount, framesPerWrite);
+ myData.sineOsc2.render(&floatData[1], actualChannelCount, framesPerWrite);
}
} else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) {
// Render sine waves to left and right channels.
- sineOsc1.render(&shortData[0], actualChannelCount, framesPerWrite);
+ myData.sineOsc1.render(&shortData[0], actualChannelCount, framesPerWrite);
if (actualChannelCount > 1) {
- sineOsc2.render(&shortData[1], actualChannelCount, framesPerWrite);
+ myData.sineOsc2.render(&shortData[1], actualChannelCount, framesPerWrite);
}
}
@@ -240,11 +202,16 @@
xRunCount = AAudioStream_getXRunCount(aaudioStream);
printf("AAudioStream_getXRunCount %d\n", xRunCount);
+ printf("call stop()\n");
+ result = player.stop();
+ if (result != AAUDIO_OK) {
+ goto finish;
+ }
+
finish:
+ player.close();
delete[] floatData;
delete[] shortData;
- AAudioStream_close(aaudioStream);
- AAudioStreamBuilder_delete(aaudioBuilder);
printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
return (result != AAUDIO_OK) ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
index 20a981b..69145aa 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
@@ -24,210 +24,18 @@
#include <math.h>
#include <time.h>
#include <aaudio/AAudio.h>
-#include "SineGenerator.h"
+#include "AAudioExampleUtils.h"
+#include "AAudioSimplePlayer.h"
#define NUM_SECONDS 5
-//#define SHARING_MODE AAUDIO_SHARING_MODE_EXCLUSIVE
-#define SHARING_MODE AAUDIO_SHARING_MODE_SHARED
-
-// TODO refactor common code into a single SimpleAAudio class
-/**
- * Simple wrapper for AAudio that opens a default stream and then calls
- * a callback function to fill the output buffers.
- */
-class SimpleAAudioPlayer {
-public:
- SimpleAAudioPlayer() {}
- ~SimpleAAudioPlayer() {
- close();
- };
-
- /**
- * Call this before calling open().
- * @param requestedSharingMode
- */
- void setSharingMode(aaudio_sharing_mode_t requestedSharingMode) {
- mRequestedSharingMode = requestedSharingMode;
- }
-
- /**
- * Also known as "sample rate"
- * Only call this after open() has been called.
- */
- int32_t getFramesPerSecond() {
- if (mStream == nullptr) {
- return AAUDIO_ERROR_INVALID_STATE;
- }
- return AAudioStream_getSampleRate(mStream);;
- }
-
- /**
- * Only call this after open() has been called.
- */
- int32_t getChannelCount() {
- if (mStream == nullptr) {
- return AAUDIO_ERROR_INVALID_STATE;
- }
- return AAudioStream_getChannelCount(mStream);;
- }
-
- /**
- * Open a stream
- */
- aaudio_result_t open(AAudioStream_dataCallback dataProc, void *userContext) {
- aaudio_result_t result = AAUDIO_OK;
-
- // Use an AAudioStreamBuilder to contain requested parameters.
- result = AAudio_createStreamBuilder(&mBuilder);
- if (result != AAUDIO_OK) return result;
-
- //AAudioStreamBuilder_setSampleRate(mBuilder, 44100);
- AAudioStreamBuilder_setSharingMode(mBuilder, mRequestedSharingMode);
- AAudioStreamBuilder_setDataCallback(mBuilder, dataProc, userContext);
- AAudioStreamBuilder_setFormat(mBuilder, AAUDIO_FORMAT_PCM_FLOAT);
- //AAudioStreamBuilder_setFramesPerDataCallback(mBuilder, CALLBACK_SIZE_FRAMES);
- AAudioStreamBuilder_setBufferCapacityInFrames(mBuilder, 48 * 8);
-
- //aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_NONE;
- aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
- //aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
- AAudioStreamBuilder_setPerformanceMode(mBuilder, perfMode);
-
- // Open an AAudioStream using the Builder.
- result = AAudioStreamBuilder_openStream(mBuilder, &mStream);
- if (result != AAUDIO_OK) goto finish1;
-
- printf("AAudioStream_getFramesPerBurst() = %d\n",
- AAudioStream_getFramesPerBurst(mStream));
- printf("AAudioStream_getBufferSizeInFrames() = %d\n",
- AAudioStream_getBufferSizeInFrames(mStream));
- printf("AAudioStream_getBufferCapacityInFrames() = %d\n",
- AAudioStream_getBufferCapacityInFrames(mStream));
- printf("AAudioStream_getPerformanceMode() = %d, requested %d\n",
- AAudioStream_getPerformanceMode(mStream), perfMode);
-
- finish1:
- AAudioStreamBuilder_delete(mBuilder);
- mBuilder = nullptr;
- return result;
- }
-
- aaudio_result_t close() {
- if (mStream != nullptr) {
- printf("call AAudioStream_close(%p)\n", mStream); fflush(stdout);
- AAudioStream_close(mStream);
- mStream = nullptr;
- AAudioStreamBuilder_delete(mBuilder);
- mBuilder = nullptr;
- }
- return AAUDIO_OK;
- }
-
- // Write zero data to fill up the buffer and prevent underruns.
- aaudio_result_t prime() {
- int32_t samplesPerFrame = AAudioStream_getChannelCount(mStream);
- const int numFrames = 32;
- float zeros[numFrames * samplesPerFrame];
- memset(zeros, 0, sizeof(zeros));
- aaudio_result_t result = numFrames;
- while (result == numFrames) {
- result = AAudioStream_write(mStream, zeros, numFrames, 0);
- }
- return result;
- }
-
- // Start the stream. AAudio will start calling your callback function.
- aaudio_result_t start() {
- aaudio_result_t result = AAudioStream_requestStart(mStream);
- if (result != AAUDIO_OK) {
- printf("ERROR - AAudioStream_requestStart() returned %d %s\n",
- result, AAudio_convertResultToText(result));
- }
- return result;
- }
-
- // Stop the stream. AAudio will stop calling your callback function.
- aaudio_result_t stop() {
- aaudio_result_t result = AAudioStream_requestStop(mStream);
- if (result != AAUDIO_OK) {
- printf("ERROR - AAudioStream_requestStop() returned %d %s\n",
- result, AAudio_convertResultToText(result));
- }
- int32_t xRunCount = AAudioStream_getXRunCount(mStream);
- printf("AAudioStream_getXRunCount %d\n", xRunCount);
- return result;
- }
-
- AAudioStream *getStream() const {
- return mStream;
- }
-
-private:
- AAudioStreamBuilder *mBuilder = nullptr;
- AAudioStream *mStream = nullptr;
- aaudio_sharing_mode_t mRequestedSharingMode = SHARING_MODE;
-};
-
// Application data that gets passed to the callback.
#define MAX_FRAME_COUNT_RECORDS 256
-typedef struct SineThreadedData_s {
- SineGenerator sineOsc1;
- SineGenerator sineOsc2;
- int scheduler;
- bool schedulerChecked;
-} SineThreadedData_t;
-
-// Callback function that fills the audio output buffer.
-aaudio_data_callback_result_t MyDataCallbackProc(
- AAudioStream *stream,
- void *userData,
- void *audioData,
- int32_t numFrames
- ) {
-
- SineThreadedData_t *sineData = (SineThreadedData_t *) userData;
-
- if (!sineData->schedulerChecked) {
- sineData->scheduler = sched_getscheduler(gettid());
- sineData->schedulerChecked = true;
- }
-
- int32_t samplesPerFrame = AAudioStream_getChannelCount(stream);
- // This code only plays on the first one or two channels.
- // TODO Support arbitrary number of channels.
- switch (AAudioStream_getFormat(stream)) {
- case AAUDIO_FORMAT_PCM_I16: {
- int16_t *audioBuffer = (int16_t *) audioData;
- // Render sine waves as shorts to first channel.
- sineData->sineOsc1.render(&audioBuffer[0], samplesPerFrame, numFrames);
- // Render sine waves to second channel if there is one.
- if (samplesPerFrame > 1) {
- sineData->sineOsc2.render(&audioBuffer[1], samplesPerFrame, numFrames);
- }
- }
- break;
- case AAUDIO_FORMAT_PCM_FLOAT: {
- float *audioBuffer = (float *) audioData;
- // Render sine waves as floats to first channel.
- sineData->sineOsc1.render(&audioBuffer[0], samplesPerFrame, numFrames);
- // Render sine waves to second channel if there is one.
- if (samplesPerFrame > 1) {
- sineData->sineOsc2.render(&audioBuffer[1], samplesPerFrame, numFrames);
- }
- }
- break;
- default:
- return AAUDIO_CALLBACK_RESULT_STOP;
- }
-
- return AAUDIO_CALLBACK_RESULT_CONTINUE;
-}
int main(int argc, char **argv)
{
(void)argc; // unused
- SimpleAAudioPlayer player;
+ AAudioSimplePlayer player;
SineThreadedData_t myData;
aaudio_result_t result;
@@ -236,11 +44,10 @@
setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
printf("%s - Play a sine sweep using an AAudio callback\n", argv[0]);
- player.setSharingMode(SHARING_MODE);
-
myData.schedulerChecked = false;
- result = player.open(MyDataCallbackProc, &myData);
+ result = player.open(2, 44100, AAUDIO_FORMAT_PCM_FLOAT,
+ SimplePlayerDataCallbackProc, SimplePlayerErrorCallbackProc, &myData);
if (result != AAUDIO_OK) {
fprintf(stderr, "ERROR - player.open() returned %d\n", result);
goto error;
diff --git a/media/libaaudio/examples/write_sine/static/Android.mk b/media/libaaudio/examples/write_sine/static/Android.mk
index 3fee08a..6911efb 100644
--- a/media/libaaudio/examples/write_sine/static/Android.mk
+++ b/media/libaaudio/examples/write_sine/static/Android.mk
@@ -5,7 +5,8 @@
LOCAL_C_INCLUDES := \
$(call include-path-for, audio-utils) \
frameworks/av/media/libaaudio/src \
- frameworks/av/media/libaaudio/include
+ frameworks/av/media/libaaudio/include \
+ frameworks/av/media/libaaudio/examples/utils
# NDK recommends using this kind of relative path instead of an absolute path.
LOCAL_SRC_FILES:= ../src/write_sine.cpp
@@ -23,7 +24,8 @@
LOCAL_MODULE_TAGS := tests
LOCAL_C_INCLUDES := \
$(call include-path-for, audio-utils) \
- frameworks/av/media/libaaudio/include
+ frameworks/av/media/libaaudio/include \
+ frameworks/av/media/libaaudio/examples/utils
LOCAL_SRC_FILES:= ../src/write_sine_callback.cpp