|
|
|
@ -15,6 +15,7 @@
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// Play sine waves using an AAudio callback.
|
|
|
|
|
// If a disconnection occurs then reopen the stream on the new device.
|
|
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
@ -22,33 +23,32 @@
|
|
|
|
|
#include <sched.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <aaudio/AAudio.h>
|
|
|
|
|
#include "AAudioExampleUtils.h"
|
|
|
|
|
#include "AAudioSimplePlayer.h"
|
|
|
|
|
#include "../../utils/AAudioSimplePlayer.h"
|
|
|
|
|
|
|
|
|
|
int main(int argc, const char **argv)
|
|
|
|
|
/**
|
|
|
|
|
* Open stream, play some sine waves, then close the stream.
|
|
|
|
|
*
|
|
|
|
|
* @param argParser
|
|
|
|
|
* @return AAUDIO_OK or negative error code
|
|
|
|
|
*/
|
|
|
|
|
static aaudio_result_t testOpenPlayClose(AAudioArgsParser &argParser)
|
|
|
|
|
{
|
|
|
|
|
AAudioArgsParser argParser;
|
|
|
|
|
AAudioSimplePlayer player;
|
|
|
|
|
SineThreadedData_t myData;
|
|
|
|
|
aaudio_result_t result;
|
|
|
|
|
int32_t actualSampleRate;
|
|
|
|
|
|
|
|
|
|
// 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 sweep using an AAudio callback V0.1.3\n", argv[0]);
|
|
|
|
|
AAudioSimplePlayer &player = myData.simplePlayer;
|
|
|
|
|
aaudio_result_t result = AAUDIO_OK;
|
|
|
|
|
bool disconnected = false;
|
|
|
|
|
int64_t startedAtNanos;
|
|
|
|
|
|
|
|
|
|
printf("----------------------- run complete test --------------------------\n");
|
|
|
|
|
myData.schedulerChecked = false;
|
|
|
|
|
myData.callbackCount = 0;
|
|
|
|
|
myData.forceUnderruns = false; // set true to test AAudioStream_getXRunCount()
|
|
|
|
|
|
|
|
|
|
if (argParser.parseArgs(argc, argv)) {
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = player.open(argParser,
|
|
|
|
|
SimplePlayerDataCallbackProc, SimplePlayerErrorCallbackProc, &myData);
|
|
|
|
|
if (result != AAUDIO_OK) {
|
|
|
|
@ -58,13 +58,19 @@ int main(int argc, const char **argv)
|
|
|
|
|
|
|
|
|
|
argParser.compareWithStream(player.getStream());
|
|
|
|
|
|
|
|
|
|
actualSampleRate = player.getSampleRate();
|
|
|
|
|
myData.sineOsc1.setup(440.0, actualSampleRate);
|
|
|
|
|
myData.sineOsc1.setSweep(300.0, 600.0, 5.0);
|
|
|
|
|
myData.sineOsc2.setup(660.0, actualSampleRate);
|
|
|
|
|
myData.sineOsc2.setSweep(350.0, 900.0, 7.0);
|
|
|
|
|
// Setup sine wave generators.
|
|
|
|
|
{
|
|
|
|
|
int32_t actualSampleRate = player.getSampleRate();
|
|
|
|
|
myData.sineOsc1.setup(440.0, actualSampleRate);
|
|
|
|
|
myData.sineOsc1.setSweep(300.0, 600.0, 5.0);
|
|
|
|
|
myData.sineOsc1.setAmplitude(0.2);
|
|
|
|
|
myData.sineOsc2.setup(660.0, actualSampleRate);
|
|
|
|
|
myData.sineOsc2.setSweep(350.0, 900.0, 7.0);
|
|
|
|
|
myData.sineOsc2.setAmplitude(0.2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
// writes not allowed for callback streams
|
|
|
|
|
result = player.prime(); // FIXME crashes AudioTrack.cpp
|
|
|
|
|
if (result != AAUDIO_OK) {
|
|
|
|
|
fprintf(stderr, "ERROR - player.prime() returned %d\n", result);
|
|
|
|
@ -78,34 +84,32 @@ int main(int argc, const char **argv)
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Play a sine wave in the background.
|
|
|
|
|
printf("Sleep for %d seconds while audio plays in a callback thread.\n",
|
|
|
|
|
argParser.getDurationSeconds());
|
|
|
|
|
startedAtNanos = getNanoseconds(CLOCK_MONOTONIC);
|
|
|
|
|
for (int second = 0; second < argParser.getDurationSeconds(); second++)
|
|
|
|
|
{
|
|
|
|
|
const struct timespec request = { .tv_sec = 1, .tv_nsec = 0 };
|
|
|
|
|
(void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
|
|
|
|
|
|
|
|
|
|
aaudio_stream_state_t state;
|
|
|
|
|
result = AAudioStream_waitForStateChange(player.getStream(),
|
|
|
|
|
AAUDIO_STREAM_STATE_CLOSED,
|
|
|
|
|
&state,
|
|
|
|
|
0);
|
|
|
|
|
// Sleep a while. Wake up early if there is an error, for example a DISCONNECT.
|
|
|
|
|
long ret = myData.waker.wait(AAUDIO_OK, NANOS_PER_SECOND);
|
|
|
|
|
int64_t millis = (getNanoseconds(CLOCK_MONOTONIC) - startedAtNanos) / NANOS_PER_MILLISECOND;
|
|
|
|
|
result = myData.waker.get();
|
|
|
|
|
printf("wait() returns %ld, aaudio_result = %d, at %6d millis"
|
|
|
|
|
", second = %d, framesWritten = %8d, underruns = %d\n",
|
|
|
|
|
ret, result, (int) millis,
|
|
|
|
|
second,
|
|
|
|
|
(int) AAudioStream_getFramesWritten(player.getStream()),
|
|
|
|
|
(int) AAudioStream_getXRunCount(player.getStream()));
|
|
|
|
|
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));
|
|
|
|
|
if (result == AAUDIO_ERROR_DISCONNECTED) {
|
|
|
|
|
disconnected = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
printf("framesWritten = %d, underruns = %d\n",
|
|
|
|
|
(int) AAudioStream_getFramesWritten(player.getStream()),
|
|
|
|
|
(int) AAudioStream_getXRunCount(player.getStream())
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
printf("Woke up now.\n");
|
|
|
|
|
printf("AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
|
|
|
|
|
|
|
|
|
|
printf("call stop()\n");
|
|
|
|
|
printf("call stop() callback # = %d\n", myData.callbackCount);
|
|
|
|
|
result = player.stop();
|
|
|
|
|
if (result != AAUDIO_OK) {
|
|
|
|
|
goto error;
|
|
|
|
@ -126,10 +130,28 @@ int main(int argc, const char **argv)
|
|
|
|
|
printf("max numFrames = %8d\n", (int) myData.maxNumFrames);
|
|
|
|
|
|
|
|
|
|
printf("SUCCESS\n");
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
|
error:
|
|
|
|
|
player.close();
|
|
|
|
|
printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
return disconnected ? AAUDIO_ERROR_DISCONNECTED : result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, const char **argv)
|
|
|
|
|
{
|
|
|
|
|
AAudioArgsParser argParser;
|
|
|
|
|
aaudio_result_t result;
|
|
|
|
|
|
|
|
|
|
// 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 sweep using an AAudio callback V0.1.2\n", argv[0]);
|
|
|
|
|
|
|
|
|
|
if (argParser.parseArgs(argc, argv)) {
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Keep looping until we can complete the test without disconnecting.
|
|
|
|
|
while((result = testOpenPlayClose(argParser)) == AAUDIO_ERROR_DISCONNECTED);
|
|
|
|
|
|
|
|
|
|
return (result) ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|