Loading media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp +63 −24 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ #include <time.h> #include <aaudio/AAudio.h> #define NUM_SECONDS 10 #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) Loading @@ -33,13 +33,13 @@ #define SHARING_MODE AAUDIO_SHARING_MODE_SHARED /** * Simple wrapper for AAudio that opens a default stream and then calls * a callback function to fill the output buffers. * Simple wrapper for AAudio that opens an input stream and then calls * a callback function to process the input data. */ class SimpleAAudioPlayer { class SimpleAAudioRecorder { public: SimpleAAudioPlayer() {} ~SimpleAAudioPlayer() { SimpleAAudioRecorder() {} ~SimpleAAudioRecorder() { close(); }; Loading Loading @@ -71,6 +71,15 @@ public: } 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 Loading @@ -85,7 +94,7 @@ public: AAudioStreamBuilder_setDirection(mBuilder, AAUDIO_DIRECTION_INPUT); AAudioStreamBuilder_setSharingMode(mBuilder, mRequestedSharingMode); AAudioStreamBuilder_setDataCallback(mBuilder, proc, userContext); AAudioStreamBuilder_setFormat(mBuilder, AAUDIO_FORMAT_PCM_I16); AAudioStreamBuilder_setFormat(mBuilder, AAUDIO_FORMAT_PCM_FLOAT); // Open an AAudioStream using the Builder. result = AAudioStreamBuilder_openStream(mBuilder, &mStream); Loading Loading @@ -121,11 +130,10 @@ public: } // Write zero data to fill up the buffer and prevent underruns. // Assume format is PCM_I16. TODO use floats. aaudio_result_t prime() { int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(mStream); const int numFrames = 32; // arbitrary int16_t zeros[numFrames * samplesPerFrame]; float zeros[numFrames * samplesPerFrame]; memset(zeros, 0, sizeof(zeros)); aaudio_result_t result = numFrames; while (result == numFrames) { Loading @@ -151,8 +159,16 @@ public: fprintf(stderr, "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; } // 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; } Loading Loading @@ -227,7 +243,7 @@ void displayPeakLevel(float peakLevel) { int main(int argc, char **argv) { (void)argc; // unused SimpleAAudioPlayer player; SimpleAAudioRecorder recorder; PeakTrackerData_t myData = {0.0}; aaudio_result_t result; const int displayRateHz = 20; // arbitrary Loading @@ -238,37 +254,60 @@ int main(int argc, char **argv) setvbuf(stdout, nullptr, _IONBF, (size_t) 0); printf("%s - Display audio input using an AAudio callback\n", argv[0]); player.setSharingMode(SHARING_MODE); recorder.setSharingMode(SHARING_MODE); result = recorder.open(MyDataCallbackProc, &myData); if (result != AAUDIO_OK) { fprintf(stderr, "ERROR - recorder.open() returned %d\n", result); goto error; } printf("recorder.getFramesPerSecond() = %d\n", recorder.getFramesPerSecond()); printf("recorder.getSamplesPerFrame() = %d\n", recorder.getSamplesPerFrame()); result = player.open(MyDataCallbackProc, &myData); result = recorder.start(); if (result != AAUDIO_OK) { fprintf(stderr, "ERROR - player.open() returned %d\n", result); fprintf(stderr, "ERROR - recorder.start() returned %d\n", result); goto error; } printf("player.getFramesPerSecond() = %d\n", player.getFramesPerSecond()); printf("player.getSamplesPerFrame() = %d\n", player.getSamplesPerFrame()); result = player.start(); printf("Sleep for %d seconds while audio record in a callback thread.\n", NUM_SECONDS); for (int i = 0; i < loopsNeeded; i++) { const struct timespec request = { .tv_sec = 0, .tv_nsec = NANOS_PER_SECOND / displayRateHz }; (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/); printf("%08d: ", (int)recorder.getFramesRead()); displayPeakLevel(myData.peakLevel); } printf("Woke up. Stop for a moment.\n"); result = recorder.stop(); if (result != AAUDIO_OK) { goto error; } sleep(1); result = recorder.start(); if (result != AAUDIO_OK) { fprintf(stderr, "ERROR - player.start() returned %d\n", result); fprintf(stderr, "ERROR - recorder.start() returned %d\n", result); goto error; } printf("Sleep for %d seconds while audio plays in a callback thread.\n", NUM_SECONDS); printf("Sleep for %d seconds while audio records in a callback thread.\n", NUM_SECONDS); for (int i = 0; i < loopsNeeded; i++) { const struct timespec request = { .tv_sec = 0, .tv_nsec = NANOS_PER_SECOND / displayRateHz }; (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/); printf("%08d: ", (int)recorder.getFramesRead()); displayPeakLevel(myData.peakLevel); } printf("Woke up now.\n"); result = player.stop(); result = recorder.stop(); if (result != AAUDIO_OK) { goto error; } result = player.close(); result = recorder.close(); if (result != AAUDIO_OK) { goto error; } Loading @@ -276,7 +315,7 @@ int main(int argc, char **argv) printf("SUCCESS\n"); return EXIT_SUCCESS; error: player.close(); recorder.close(); printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result)); return EXIT_FAILURE; } Loading media/libaaudio/include/aaudio/AAudio.h +8 −0 Original line number Diff line number Diff line Loading @@ -507,6 +507,9 @@ AAUDIO_API aaudio_result_t AAudioStream_requestStart(AAudioStream* stream); * Use AAudioStream_Start() to resume playback after a pause. * After this call the state will be in AAUDIO_STREAM_STATE_PAUSING or AAUDIO_STREAM_STATE_PAUSED. * * This will return AAUDIO_ERROR_UNIMPLEMENTED for input streams. * For input streams use AAudioStream_requestStop(). * * @param stream reference provided by AAudioStreamBuilder_openStream() * @return AAUDIO_OK or a negative error. */ Loading @@ -519,6 +522,8 @@ AAUDIO_API aaudio_result_t AAudioStream_requestPause(AAudioStream* stream); * Frame counters are not reset by a flush. They may be advanced. * After this call the state will be in AAUDIO_STREAM_STATE_FLUSHING or AAUDIO_STREAM_STATE_FLUSHED. * * This will return AAUDIO_ERROR_UNIMPLEMENTED for input streams. * * @param stream reference provided by AAudioStreamBuilder_openStream() * @return AAUDIO_OK or a negative error. */ Loading Loading @@ -704,6 +709,9 @@ AAUDIO_API int32_t AAudioStream_getFramesPerDataCallback(AAudioStream* stream); * * An underrun or overrun can cause an audible "pop" or "glitch". * * Note that some INPUT devices may not support this function. * In that case a 0 will always be returned. * * @param stream reference provided by AAudioStreamBuilder_openStream() * @return the underrun or overrun count */ Loading media/libaaudio/src/legacy/AudioStreamRecord.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -177,10 +177,13 @@ aaudio_result_t AudioStreamRecord::requestStart() aaudio_result_t AudioStreamRecord::requestPause() { // This does not make sense for an input stream. // There is no real difference between pause() and stop(). return AAUDIO_ERROR_UNIMPLEMENTED; } aaudio_result_t AudioStreamRecord::requestFlush() { // This does not make sense for an input stream. return AAUDIO_ERROR_UNIMPLEMENTED; } Loading Loading @@ -259,7 +262,7 @@ int32_t AudioStreamRecord::getBufferCapacity() const int32_t AudioStreamRecord::getXRunCount() const { return AAUDIO_ERROR_UNIMPLEMENTED; // TODO implement when AudioRecord supports it return 0; // TODO implement when AudioRecord supports it } int32_t AudioStreamRecord::getFramesPerBurst() const Loading Loading
media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp +63 −24 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ #include <time.h> #include <aaudio/AAudio.h> #define NUM_SECONDS 10 #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) Loading @@ -33,13 +33,13 @@ #define SHARING_MODE AAUDIO_SHARING_MODE_SHARED /** * Simple wrapper for AAudio that opens a default stream and then calls * a callback function to fill the output buffers. * Simple wrapper for AAudio that opens an input stream and then calls * a callback function to process the input data. */ class SimpleAAudioPlayer { class SimpleAAudioRecorder { public: SimpleAAudioPlayer() {} ~SimpleAAudioPlayer() { SimpleAAudioRecorder() {} ~SimpleAAudioRecorder() { close(); }; Loading Loading @@ -71,6 +71,15 @@ public: } 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 Loading @@ -85,7 +94,7 @@ public: AAudioStreamBuilder_setDirection(mBuilder, AAUDIO_DIRECTION_INPUT); AAudioStreamBuilder_setSharingMode(mBuilder, mRequestedSharingMode); AAudioStreamBuilder_setDataCallback(mBuilder, proc, userContext); AAudioStreamBuilder_setFormat(mBuilder, AAUDIO_FORMAT_PCM_I16); AAudioStreamBuilder_setFormat(mBuilder, AAUDIO_FORMAT_PCM_FLOAT); // Open an AAudioStream using the Builder. result = AAudioStreamBuilder_openStream(mBuilder, &mStream); Loading Loading @@ -121,11 +130,10 @@ public: } // Write zero data to fill up the buffer and prevent underruns. // Assume format is PCM_I16. TODO use floats. aaudio_result_t prime() { int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(mStream); const int numFrames = 32; // arbitrary int16_t zeros[numFrames * samplesPerFrame]; float zeros[numFrames * samplesPerFrame]; memset(zeros, 0, sizeof(zeros)); aaudio_result_t result = numFrames; while (result == numFrames) { Loading @@ -151,8 +159,16 @@ public: fprintf(stderr, "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; } // 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; } Loading Loading @@ -227,7 +243,7 @@ void displayPeakLevel(float peakLevel) { int main(int argc, char **argv) { (void)argc; // unused SimpleAAudioPlayer player; SimpleAAudioRecorder recorder; PeakTrackerData_t myData = {0.0}; aaudio_result_t result; const int displayRateHz = 20; // arbitrary Loading @@ -238,37 +254,60 @@ int main(int argc, char **argv) setvbuf(stdout, nullptr, _IONBF, (size_t) 0); printf("%s - Display audio input using an AAudio callback\n", argv[0]); player.setSharingMode(SHARING_MODE); recorder.setSharingMode(SHARING_MODE); result = recorder.open(MyDataCallbackProc, &myData); if (result != AAUDIO_OK) { fprintf(stderr, "ERROR - recorder.open() returned %d\n", result); goto error; } printf("recorder.getFramesPerSecond() = %d\n", recorder.getFramesPerSecond()); printf("recorder.getSamplesPerFrame() = %d\n", recorder.getSamplesPerFrame()); result = player.open(MyDataCallbackProc, &myData); result = recorder.start(); if (result != AAUDIO_OK) { fprintf(stderr, "ERROR - player.open() returned %d\n", result); fprintf(stderr, "ERROR - recorder.start() returned %d\n", result); goto error; } printf("player.getFramesPerSecond() = %d\n", player.getFramesPerSecond()); printf("player.getSamplesPerFrame() = %d\n", player.getSamplesPerFrame()); result = player.start(); printf("Sleep for %d seconds while audio record in a callback thread.\n", NUM_SECONDS); for (int i = 0; i < loopsNeeded; i++) { const struct timespec request = { .tv_sec = 0, .tv_nsec = NANOS_PER_SECOND / displayRateHz }; (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/); printf("%08d: ", (int)recorder.getFramesRead()); displayPeakLevel(myData.peakLevel); } printf("Woke up. Stop for a moment.\n"); result = recorder.stop(); if (result != AAUDIO_OK) { goto error; } sleep(1); result = recorder.start(); if (result != AAUDIO_OK) { fprintf(stderr, "ERROR - player.start() returned %d\n", result); fprintf(stderr, "ERROR - recorder.start() returned %d\n", result); goto error; } printf("Sleep for %d seconds while audio plays in a callback thread.\n", NUM_SECONDS); printf("Sleep for %d seconds while audio records in a callback thread.\n", NUM_SECONDS); for (int i = 0; i < loopsNeeded; i++) { const struct timespec request = { .tv_sec = 0, .tv_nsec = NANOS_PER_SECOND / displayRateHz }; (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/); printf("%08d: ", (int)recorder.getFramesRead()); displayPeakLevel(myData.peakLevel); } printf("Woke up now.\n"); result = player.stop(); result = recorder.stop(); if (result != AAUDIO_OK) { goto error; } result = player.close(); result = recorder.close(); if (result != AAUDIO_OK) { goto error; } Loading @@ -276,7 +315,7 @@ int main(int argc, char **argv) printf("SUCCESS\n"); return EXIT_SUCCESS; error: player.close(); recorder.close(); printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result)); return EXIT_FAILURE; } Loading
media/libaaudio/include/aaudio/AAudio.h +8 −0 Original line number Diff line number Diff line Loading @@ -507,6 +507,9 @@ AAUDIO_API aaudio_result_t AAudioStream_requestStart(AAudioStream* stream); * Use AAudioStream_Start() to resume playback after a pause. * After this call the state will be in AAUDIO_STREAM_STATE_PAUSING or AAUDIO_STREAM_STATE_PAUSED. * * This will return AAUDIO_ERROR_UNIMPLEMENTED for input streams. * For input streams use AAudioStream_requestStop(). * * @param stream reference provided by AAudioStreamBuilder_openStream() * @return AAUDIO_OK or a negative error. */ Loading @@ -519,6 +522,8 @@ AAUDIO_API aaudio_result_t AAudioStream_requestPause(AAudioStream* stream); * Frame counters are not reset by a flush. They may be advanced. * After this call the state will be in AAUDIO_STREAM_STATE_FLUSHING or AAUDIO_STREAM_STATE_FLUSHED. * * This will return AAUDIO_ERROR_UNIMPLEMENTED for input streams. * * @param stream reference provided by AAudioStreamBuilder_openStream() * @return AAUDIO_OK or a negative error. */ Loading Loading @@ -704,6 +709,9 @@ AAUDIO_API int32_t AAudioStream_getFramesPerDataCallback(AAudioStream* stream); * * An underrun or overrun can cause an audible "pop" or "glitch". * * Note that some INPUT devices may not support this function. * In that case a 0 will always be returned. * * @param stream reference provided by AAudioStreamBuilder_openStream() * @return the underrun or overrun count */ Loading
media/libaaudio/src/legacy/AudioStreamRecord.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -177,10 +177,13 @@ aaudio_result_t AudioStreamRecord::requestStart() aaudio_result_t AudioStreamRecord::requestPause() { // This does not make sense for an input stream. // There is no real difference between pause() and stop(). return AAUDIO_ERROR_UNIMPLEMENTED; } aaudio_result_t AudioStreamRecord::requestFlush() { // This does not make sense for an input stream. return AAUDIO_ERROR_UNIMPLEMENTED; } Loading Loading @@ -259,7 +262,7 @@ int32_t AudioStreamRecord::getBufferCapacity() const int32_t AudioStreamRecord::getXRunCount() const { return AAUDIO_ERROR_UNIMPLEMENTED; // TODO implement when AudioRecord supports it return 0; // TODO implement when AudioRecord supports it } int32_t AudioStreamRecord::getFramesPerBurst() const Loading