186938671ea9cf95e3742659924189a1d016dfd59Phil Burk/* 286938671ea9cf95e3742659924189a1d016dfd59Phil Burk * Copyright (C) 2017 The Android Open Source Project 386938671ea9cf95e3742659924189a1d016dfd59Phil Burk * 486938671ea9cf95e3742659924189a1d016dfd59Phil Burk * Licensed under the Apache License, Version 2.0 (the "License"); 586938671ea9cf95e3742659924189a1d016dfd59Phil Burk * you may not use this file except in compliance with the License. 686938671ea9cf95e3742659924189a1d016dfd59Phil Burk * You may obtain a copy of the License at 786938671ea9cf95e3742659924189a1d016dfd59Phil Burk * 886938671ea9cf95e3742659924189a1d016dfd59Phil Burk * http://www.apache.org/licenses/LICENSE-2.0 986938671ea9cf95e3742659924189a1d016dfd59Phil Burk * 1086938671ea9cf95e3742659924189a1d016dfd59Phil Burk * Unless required by applicable law or agreed to in writing, software 1186938671ea9cf95e3742659924189a1d016dfd59Phil Burk * distributed under the License is distributed on an "AS IS" BASIS, 1286938671ea9cf95e3742659924189a1d016dfd59Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1386938671ea9cf95e3742659924189a1d016dfd59Phil Burk * See the License for the specific language governing permissions and 1486938671ea9cf95e3742659924189a1d016dfd59Phil Burk * limitations under the License. 1586938671ea9cf95e3742659924189a1d016dfd59Phil Burk */ 1686938671ea9cf95e3742659924189a1d016dfd59Phil Burk 1786938671ea9cf95e3742659924189a1d016dfd59Phil Burk// Try to trigger bugs by playing randomly on multiple streams. 1886938671ea9cf95e3742659924189a1d016dfd59Phil Burk 1986938671ea9cf95e3742659924189a1d016dfd59Phil Burk#include <stdio.h> 2086938671ea9cf95e3742659924189a1d016dfd59Phil Burk#include <stdlib.h> 2186938671ea9cf95e3742659924189a1d016dfd59Phil Burk#include <vector> 2286938671ea9cf95e3742659924189a1d016dfd59Phil Burk 2386938671ea9cf95e3742659924189a1d016dfd59Phil Burk#include <aaudio/AAudio.h> 2486938671ea9cf95e3742659924189a1d016dfd59Phil Burk#include "AAudioArgsParser.h" 2586938671ea9cf95e3742659924189a1d016dfd59Phil Burk#include "AAudioExampleUtils.h" 2686938671ea9cf95e3742659924189a1d016dfd59Phil Burk#include "AAudioSimplePlayer.h" 2786938671ea9cf95e3742659924189a1d016dfd59Phil Burk#include "SineGenerator.h" 2886938671ea9cf95e3742659924189a1d016dfd59Phil Burk 2986938671ea9cf95e3742659924189a1d016dfd59Phil Burk#define DEFAULT_TIMEOUT_NANOS (1 * NANOS_PER_SECOND) 3086938671ea9cf95e3742659924189a1d016dfd59Phil Burk 3186938671ea9cf95e3742659924189a1d016dfd59Phil Burk#define NUM_LOOPS 1000 3286938671ea9cf95e3742659924189a1d016dfd59Phil Burk#define MAX_MICROS_DELAY (2 * 1000 * 1000) 3386938671ea9cf95e3742659924189a1d016dfd59Phil Burk 3486938671ea9cf95e3742659924189a1d016dfd59Phil Burk// TODO Consider adding an input stream. 3586938671ea9cf95e3742659924189a1d016dfd59Phil Burk#define PROB_START (0.20) 3686938671ea9cf95e3742659924189a1d016dfd59Phil Burk#define PROB_PAUSE (PROB_START + 0.10) 3786938671ea9cf95e3742659924189a1d016dfd59Phil Burk#define PROB_FLUSH (PROB_PAUSE + 0.10) 3886938671ea9cf95e3742659924189a1d016dfd59Phil Burk#define PROB_STOP (PROB_FLUSH + 0.10) 3986938671ea9cf95e3742659924189a1d016dfd59Phil Burk#define PROB_CLOSE (PROB_STOP + 0.10) 4086938671ea9cf95e3742659924189a1d016dfd59Phil Burkstatic_assert(PROB_CLOSE < 0.9, "Probability sum too high."); 4186938671ea9cf95e3742659924189a1d016dfd59Phil Burk 4286938671ea9cf95e3742659924189a1d016dfd59Phil Burkaaudio_data_callback_result_t AAudioMonkeyDataCallback( 4386938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAudioStream *stream, 4486938671ea9cf95e3742659924189a1d016dfd59Phil Burk void *userData, 4586938671ea9cf95e3742659924189a1d016dfd59Phil Burk void *audioData, 4686938671ea9cf95e3742659924189a1d016dfd59Phil Burk int32_t numFrames); 4786938671ea9cf95e3742659924189a1d016dfd59Phil Burk 4886938671ea9cf95e3742659924189a1d016dfd59Phil Burkvoid AAudioMonkeyErrorCallbackProc( 4986938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAudioStream *stream __unused, 5086938671ea9cf95e3742659924189a1d016dfd59Phil Burk void *userData __unused, 5186938671ea9cf95e3742659924189a1d016dfd59Phil Burk aaudio_result_t error) { 5286938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("Error Callback, error: %d\n",(int)error); 5386938671ea9cf95e3742659924189a1d016dfd59Phil Burk} 5486938671ea9cf95e3742659924189a1d016dfd59Phil Burk 5586938671ea9cf95e3742659924189a1d016dfd59Phil Burk// This function is not thread safe. Only use this from a single thread. 5686938671ea9cf95e3742659924189a1d016dfd59Phil Burkdouble nextRandomDouble() { 5786938671ea9cf95e3742659924189a1d016dfd59Phil Burk return drand48(); 5886938671ea9cf95e3742659924189a1d016dfd59Phil Burk} 5986938671ea9cf95e3742659924189a1d016dfd59Phil Burk 6086938671ea9cf95e3742659924189a1d016dfd59Phil Burkclass AAudioMonkey : public AAudioSimplePlayer { 6186938671ea9cf95e3742659924189a1d016dfd59Phil Burkpublic: 6286938671ea9cf95e3742659924189a1d016dfd59Phil Burk 6386938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAudioMonkey(int index, AAudioArgsParser *argParser) 6486938671ea9cf95e3742659924189a1d016dfd59Phil Burk : mArgParser(argParser) 6586938671ea9cf95e3742659924189a1d016dfd59Phil Burk , mIndex(index) {} 6686938671ea9cf95e3742659924189a1d016dfd59Phil Burk 6786938671ea9cf95e3742659924189a1d016dfd59Phil Burk aaudio_result_t open() { 6886938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("Monkey # %d ---------------------------------------------- OPEN\n", mIndex); 6986938671ea9cf95e3742659924189a1d016dfd59Phil Burk double offset = mIndex * 50; 7086938671ea9cf95e3742659924189a1d016dfd59Phil Burk mSine1.setup(440.0, 48000); 7186938671ea9cf95e3742659924189a1d016dfd59Phil Burk mSine1.setSweep(300.0 + offset, 600.0 + offset, 5.0); 7286938671ea9cf95e3742659924189a1d016dfd59Phil Burk mSine2.setup(660.0, 48000); 7386938671ea9cf95e3742659924189a1d016dfd59Phil Burk mSine2.setSweep(350.0 + offset, 900.0 + offset, 7.0); 7486938671ea9cf95e3742659924189a1d016dfd59Phil Burk 7586938671ea9cf95e3742659924189a1d016dfd59Phil Burk aaudio_result_t result = AAudioSimplePlayer::open(*mArgParser, 7686938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAudioMonkeyDataCallback, 7786938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAudioMonkeyErrorCallbackProc, 7886938671ea9cf95e3742659924189a1d016dfd59Phil Burk this); 7986938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (result != AAUDIO_OK) { 8086938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("ERROR - player.open() returned %d\n", result); 8186938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 8286938671ea9cf95e3742659924189a1d016dfd59Phil Burk 8386938671ea9cf95e3742659924189a1d016dfd59Phil Burk mArgParser->compareWithStream(getStream()); 8486938671ea9cf95e3742659924189a1d016dfd59Phil Burk return result; 8586938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 8686938671ea9cf95e3742659924189a1d016dfd59Phil Burk 8786938671ea9cf95e3742659924189a1d016dfd59Phil Burk bool isOpen() { 8886938671ea9cf95e3742659924189a1d016dfd59Phil Burk return (getStream() != nullptr); 8986938671ea9cf95e3742659924189a1d016dfd59Phil Burk 9086938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 9186938671ea9cf95e3742659924189a1d016dfd59Phil Burk /** 9286938671ea9cf95e3742659924189a1d016dfd59Phil Burk * 9386938671ea9cf95e3742659924189a1d016dfd59Phil Burk * @return true if stream passes tests 9486938671ea9cf95e3742659924189a1d016dfd59Phil Burk */ 9586938671ea9cf95e3742659924189a1d016dfd59Phil Burk bool validate() { 9686938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (!isOpen()) return true; // closed is OK 9786938671ea9cf95e3742659924189a1d016dfd59Phil Burk 9886938671ea9cf95e3742659924189a1d016dfd59Phil Burk // update and query stream state 9986938671ea9cf95e3742659924189a1d016dfd59Phil Burk aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN; 10086938671ea9cf95e3742659924189a1d016dfd59Phil Burk aaudio_result_t result = AAudioStream_waitForStateChange(getStream(), 10186938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAUDIO_STREAM_STATE_UNKNOWN, &state, 0); 10286938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (result != AAUDIO_OK) { 10386938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("ERROR - AAudioStream_waitForStateChange returned %d\n", result); 10486938671ea9cf95e3742659924189a1d016dfd59Phil Burk return false; 10586938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 10686938671ea9cf95e3742659924189a1d016dfd59Phil Burk 10786938671ea9cf95e3742659924189a1d016dfd59Phil Burk int64_t framesRead = AAudioStream_getFramesRead(getStream()); 10886938671ea9cf95e3742659924189a1d016dfd59Phil Burk int64_t framesWritten = AAudioStream_getFramesWritten(getStream()); 10986938671ea9cf95e3742659924189a1d016dfd59Phil Burk int32_t xRuns = AAudioStream_getXRunCount(getStream()); 11086938671ea9cf95e3742659924189a1d016dfd59Phil Burk // Print status 11186938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("%30s, framesWritten = %8lld, framesRead = %8lld, xRuns = %d\n", 11286938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAudio_convertStreamStateToText(state), 11386938671ea9cf95e3742659924189a1d016dfd59Phil Burk (unsigned long long) framesWritten, 11486938671ea9cf95e3742659924189a1d016dfd59Phil Burk (unsigned long long) framesRead, 11586938671ea9cf95e3742659924189a1d016dfd59Phil Burk xRuns); 11686938671ea9cf95e3742659924189a1d016dfd59Phil Burk 11786938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (framesWritten < framesRead) { 11886938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("WARNING - UNDERFLOW - diff = %d !!!!!!!!!!!!\n", 11986938671ea9cf95e3742659924189a1d016dfd59Phil Burk (int) (framesWritten - framesRead)); 12086938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 12186938671ea9cf95e3742659924189a1d016dfd59Phil Burk return true; 12286938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 12386938671ea9cf95e3742659924189a1d016dfd59Phil Burk 12486938671ea9cf95e3742659924189a1d016dfd59Phil Burk aaudio_result_t invoke() { 12586938671ea9cf95e3742659924189a1d016dfd59Phil Burk aaudio_result_t result = AAUDIO_OK; 12686938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (!isOpen()) { 12786938671ea9cf95e3742659924189a1d016dfd59Phil Burk result = open(); 12886938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (result != AAUDIO_OK) return result; 12986938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 13086938671ea9cf95e3742659924189a1d016dfd59Phil Burk 13186938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (!validate()) { 13286938671ea9cf95e3742659924189a1d016dfd59Phil Burk return -1; 13386938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 13486938671ea9cf95e3742659924189a1d016dfd59Phil Burk 13586938671ea9cf95e3742659924189a1d016dfd59Phil Burk double dice = nextRandomDouble(); 13686938671ea9cf95e3742659924189a1d016dfd59Phil Burk // Select an action based on a weighted probability. 13786938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (dice < PROB_START) { 13886938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("start\n"); 13986938671ea9cf95e3742659924189a1d016dfd59Phil Burk result = AAudioStream_requestStart(getStream()); 14086938671ea9cf95e3742659924189a1d016dfd59Phil Burk } else if (dice < PROB_PAUSE) { 14186938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("pause\n"); 14286938671ea9cf95e3742659924189a1d016dfd59Phil Burk result = AAudioStream_requestPause(getStream()); 14386938671ea9cf95e3742659924189a1d016dfd59Phil Burk } else if (dice < PROB_FLUSH) { 14486938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("flush\n"); 14586938671ea9cf95e3742659924189a1d016dfd59Phil Burk result = AAudioStream_requestFlush(getStream()); 14686938671ea9cf95e3742659924189a1d016dfd59Phil Burk } else if (dice < PROB_STOP) { 14786938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("stop\n"); 14886938671ea9cf95e3742659924189a1d016dfd59Phil Burk result = AAudioStream_requestStop(getStream()); 14986938671ea9cf95e3742659924189a1d016dfd59Phil Burk } else if (dice < PROB_CLOSE) { 15086938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("close\n"); 15186938671ea9cf95e3742659924189a1d016dfd59Phil Burk result = close(); 15286938671ea9cf95e3742659924189a1d016dfd59Phil Burk } else { 15386938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("do nothing\n"); 15486938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 15586938671ea9cf95e3742659924189a1d016dfd59Phil Burk 15686938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (result == AAUDIO_ERROR_INVALID_STATE) { 15786938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf(" got AAUDIO_ERROR_INVALID_STATE - expected from a monkey\n"); 15886938671ea9cf95e3742659924189a1d016dfd59Phil Burk result = AAUDIO_OK; 15986938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 16086938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (result == AAUDIO_OK && isOpen()) { 16186938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (!validate()) { 16286938671ea9cf95e3742659924189a1d016dfd59Phil Burk result = -1; 16386938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 16486938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 16586938671ea9cf95e3742659924189a1d016dfd59Phil Burk return result; 16686938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 16786938671ea9cf95e3742659924189a1d016dfd59Phil Burk 16886938671ea9cf95e3742659924189a1d016dfd59Phil Burk aaudio_data_callback_result_t renderAudio( 16986938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAudioStream *stream, 17086938671ea9cf95e3742659924189a1d016dfd59Phil Burk void *audioData, 17186938671ea9cf95e3742659924189a1d016dfd59Phil Burk int32_t numFrames) { 17286938671ea9cf95e3742659924189a1d016dfd59Phil Burk 17386938671ea9cf95e3742659924189a1d016dfd59Phil Burk int32_t samplesPerFrame = AAudioStream_getChannelCount(stream); 17486938671ea9cf95e3742659924189a1d016dfd59Phil Burk // This code only plays on the first one or two channels. 17586938671ea9cf95e3742659924189a1d016dfd59Phil Burk // TODO Support arbitrary number of channels. 17686938671ea9cf95e3742659924189a1d016dfd59Phil Burk switch (AAudioStream_getFormat(stream)) { 17786938671ea9cf95e3742659924189a1d016dfd59Phil Burk case AAUDIO_FORMAT_PCM_I16: { 17886938671ea9cf95e3742659924189a1d016dfd59Phil Burk int16_t *audioBuffer = (int16_t *) audioData; 17986938671ea9cf95e3742659924189a1d016dfd59Phil Burk // Render sine waves as shorts to first channel. 18086938671ea9cf95e3742659924189a1d016dfd59Phil Burk mSine1.render(&audioBuffer[0], samplesPerFrame, numFrames); 18186938671ea9cf95e3742659924189a1d016dfd59Phil Burk // Render sine waves to second channel if there is one. 18286938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (samplesPerFrame > 1) { 18386938671ea9cf95e3742659924189a1d016dfd59Phil Burk mSine2.render(&audioBuffer[1], samplesPerFrame, numFrames); 18486938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 18586938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 18686938671ea9cf95e3742659924189a1d016dfd59Phil Burk break; 18786938671ea9cf95e3742659924189a1d016dfd59Phil Burk case AAUDIO_FORMAT_PCM_FLOAT: { 18886938671ea9cf95e3742659924189a1d016dfd59Phil Burk float *audioBuffer = (float *) audioData; 18986938671ea9cf95e3742659924189a1d016dfd59Phil Burk // Render sine waves as floats to first channel. 19086938671ea9cf95e3742659924189a1d016dfd59Phil Burk mSine1.render(&audioBuffer[0], samplesPerFrame, numFrames); 19186938671ea9cf95e3742659924189a1d016dfd59Phil Burk // Render sine waves to second channel if there is one. 19286938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (samplesPerFrame > 1) { 19386938671ea9cf95e3742659924189a1d016dfd59Phil Burk mSine2.render(&audioBuffer[1], samplesPerFrame, numFrames); 19486938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 19586938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 19686938671ea9cf95e3742659924189a1d016dfd59Phil Burk break; 19786938671ea9cf95e3742659924189a1d016dfd59Phil Burk default: 19886938671ea9cf95e3742659924189a1d016dfd59Phil Burk return AAUDIO_CALLBACK_RESULT_STOP; 19986938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 20086938671ea9cf95e3742659924189a1d016dfd59Phil Burk return AAUDIO_CALLBACK_RESULT_CONTINUE; 20186938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 20286938671ea9cf95e3742659924189a1d016dfd59Phil Burk 20386938671ea9cf95e3742659924189a1d016dfd59Phil Burkprivate: 20486938671ea9cf95e3742659924189a1d016dfd59Phil Burk const AAudioArgsParser *mArgParser; 20586938671ea9cf95e3742659924189a1d016dfd59Phil Burk const int mIndex; 20686938671ea9cf95e3742659924189a1d016dfd59Phil Burk SineGenerator mSine1; 20786938671ea9cf95e3742659924189a1d016dfd59Phil Burk SineGenerator mSine2; 20886938671ea9cf95e3742659924189a1d016dfd59Phil Burk}; 20986938671ea9cf95e3742659924189a1d016dfd59Phil Burk 21086938671ea9cf95e3742659924189a1d016dfd59Phil Burk// Callback function that fills the audio output buffer. 21186938671ea9cf95e3742659924189a1d016dfd59Phil Burkaaudio_data_callback_result_t AAudioMonkeyDataCallback( 21286938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAudioStream *stream, 21386938671ea9cf95e3742659924189a1d016dfd59Phil Burk void *userData, 21486938671ea9cf95e3742659924189a1d016dfd59Phil Burk void *audioData, 21586938671ea9cf95e3742659924189a1d016dfd59Phil Burk int32_t numFrames 21686938671ea9cf95e3742659924189a1d016dfd59Phil Burk) { 21786938671ea9cf95e3742659924189a1d016dfd59Phil Burk // should not happen but just in case... 21886938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (userData == nullptr) { 21986938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("ERROR - AAudioMonkeyDataCallback needs userData\n"); 22086938671ea9cf95e3742659924189a1d016dfd59Phil Burk return AAUDIO_CALLBACK_RESULT_STOP; 22186938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 22286938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAudioMonkey *monkey = (AAudioMonkey *) userData; 22386938671ea9cf95e3742659924189a1d016dfd59Phil Burk return monkey->renderAudio(stream, audioData, numFrames); 22486938671ea9cf95e3742659924189a1d016dfd59Phil Burk} 22586938671ea9cf95e3742659924189a1d016dfd59Phil Burk 22686938671ea9cf95e3742659924189a1d016dfd59Phil Burk 22786938671ea9cf95e3742659924189a1d016dfd59Phil Burkstatic void usage() { 22886938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAudioArgsParser::usage(); 22986938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf(" -i{seed} Initial random seed\n"); 23086938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf(" -t{count} number of monkeys in the Troop\n"); 23186938671ea9cf95e3742659924189a1d016dfd59Phil Burk} 23286938671ea9cf95e3742659924189a1d016dfd59Phil Burk 23386938671ea9cf95e3742659924189a1d016dfd59Phil Burkint main(int argc, const char **argv) { 23486938671ea9cf95e3742659924189a1d016dfd59Phil Burk AAudioArgsParser argParser; 23586938671ea9cf95e3742659924189a1d016dfd59Phil Burk std::vector<AAudioMonkey> monkeys; 23686938671ea9cf95e3742659924189a1d016dfd59Phil Burk aaudio_result_t result; 23786938671ea9cf95e3742659924189a1d016dfd59Phil Burk int numMonkeys = 1; 23886938671ea9cf95e3742659924189a1d016dfd59Phil Burk 23986938671ea9cf95e3742659924189a1d016dfd59Phil Burk // Make printf print immediately so that debug info is not stuck 24086938671ea9cf95e3742659924189a1d016dfd59Phil Burk // in a buffer if we hang or crash. 24186938671ea9cf95e3742659924189a1d016dfd59Phil Burk setvbuf(stdout, nullptr, _IONBF, (size_t) 0); 24286938671ea9cf95e3742659924189a1d016dfd59Phil Burk 24386938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("%s - Monkeys\n", argv[0]); 24486938671ea9cf95e3742659924189a1d016dfd59Phil Burk 24586938671ea9cf95e3742659924189a1d016dfd59Phil Burk long int seed = (long int)getNanoseconds(); // different every time by default 24686938671ea9cf95e3742659924189a1d016dfd59Phil Burk 24786938671ea9cf95e3742659924189a1d016dfd59Phil Burk for (int i = 1; i < argc; i++) { 24886938671ea9cf95e3742659924189a1d016dfd59Phil Burk const char *arg = argv[i]; 24986938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (argParser.parseArg(arg)) { 25086938671ea9cf95e3742659924189a1d016dfd59Phil Burk // Handle options that are not handled by the ArgParser 25186938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (arg[0] == '-') { 25286938671ea9cf95e3742659924189a1d016dfd59Phil Burk char option = arg[1]; 25386938671ea9cf95e3742659924189a1d016dfd59Phil Burk switch (option) { 25486938671ea9cf95e3742659924189a1d016dfd59Phil Burk case 'i': 25586938671ea9cf95e3742659924189a1d016dfd59Phil Burk seed = atol(&arg[2]); 25686938671ea9cf95e3742659924189a1d016dfd59Phil Burk break; 25786938671ea9cf95e3742659924189a1d016dfd59Phil Burk case 't': 25886938671ea9cf95e3742659924189a1d016dfd59Phil Burk numMonkeys = atoi(&arg[2]); 25986938671ea9cf95e3742659924189a1d016dfd59Phil Burk break; 26086938671ea9cf95e3742659924189a1d016dfd59Phil Burk default: 26186938671ea9cf95e3742659924189a1d016dfd59Phil Burk usage(); 26286938671ea9cf95e3742659924189a1d016dfd59Phil Burk exit(EXIT_FAILURE); 26386938671ea9cf95e3742659924189a1d016dfd59Phil Burk break; 26486938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 26586938671ea9cf95e3742659924189a1d016dfd59Phil Burk } else { 26686938671ea9cf95e3742659924189a1d016dfd59Phil Burk usage(); 26786938671ea9cf95e3742659924189a1d016dfd59Phil Burk exit(EXIT_FAILURE); 26886938671ea9cf95e3742659924189a1d016dfd59Phil Burk break; 26986938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 27086938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 27186938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 27286938671ea9cf95e3742659924189a1d016dfd59Phil Burk 27386938671ea9cf95e3742659924189a1d016dfd59Phil Burk srand48(seed); 27486938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("seed = %ld, nextRandomDouble() = %f\n", seed, nextRandomDouble()); 27586938671ea9cf95e3742659924189a1d016dfd59Phil Burk 27686938671ea9cf95e3742659924189a1d016dfd59Phil Burk for (int m = 0; m < numMonkeys; m++) { 27786938671ea9cf95e3742659924189a1d016dfd59Phil Burk monkeys.emplace_back(m, &argParser); 27886938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 27986938671ea9cf95e3742659924189a1d016dfd59Phil Burk 28086938671ea9cf95e3742659924189a1d016dfd59Phil Burk for (int i = 0; i < NUM_LOOPS; i++) { 28186938671ea9cf95e3742659924189a1d016dfd59Phil Burk // pick a random monkey and invoke it 28286938671ea9cf95e3742659924189a1d016dfd59Phil Burk double dice = nextRandomDouble(); 28386938671ea9cf95e3742659924189a1d016dfd59Phil Burk int monkeyIndex = floor(dice * numMonkeys); 28486938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("----------- Monkey #%d\n", monkeyIndex); 28586938671ea9cf95e3742659924189a1d016dfd59Phil Burk result = monkeys[monkeyIndex].invoke(); 28686938671ea9cf95e3742659924189a1d016dfd59Phil Burk if (result != AAUDIO_OK) { 28786938671ea9cf95e3742659924189a1d016dfd59Phil Burk goto error; 28886938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 28986938671ea9cf95e3742659924189a1d016dfd59Phil Burk 29086938671ea9cf95e3742659924189a1d016dfd59Phil Burk // sleep some random time 29186938671ea9cf95e3742659924189a1d016dfd59Phil Burk dice = nextRandomDouble(); 29286938671ea9cf95e3742659924189a1d016dfd59Phil Burk dice = dice * dice * dice; // skew towards smaller delays 29386938671ea9cf95e3742659924189a1d016dfd59Phil Burk int micros = (int) (dice * MAX_MICROS_DELAY); 29486938671ea9cf95e3742659924189a1d016dfd59Phil Burk usleep(micros); 29586938671ea9cf95e3742659924189a1d016dfd59Phil Burk 29686938671ea9cf95e3742659924189a1d016dfd59Phil Burk // TODO consider making this multi-threaded, one thread per monkey, to catch more bugs 29786938671ea9cf95e3742659924189a1d016dfd59Phil Burk } 29886938671ea9cf95e3742659924189a1d016dfd59Phil Burk 29986938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("PASS\n"); 30086938671ea9cf95e3742659924189a1d016dfd59Phil Burk return EXIT_SUCCESS; 30186938671ea9cf95e3742659924189a1d016dfd59Phil Burk 30286938671ea9cf95e3742659924189a1d016dfd59Phil Burkerror: 30386938671ea9cf95e3742659924189a1d016dfd59Phil Burk printf("FAIL - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result)); 30486938671ea9cf95e3742659924189a1d016dfd59Phil Burk usleep(1000 * 1000); // give me time to stop the logcat 30586938671ea9cf95e3742659924189a1d016dfd59Phil Burk return EXIT_FAILURE; 30686938671ea9cf95e3742659924189a1d016dfd59Phil Burk} 30786938671ea9cf95e3742659924189a1d016dfd59Phil Burk 308