diff options
author | Paul Adenot <[email protected]> | 2020-10-30 18:19:22 +0100 |
---|---|---|
committer | Paul Adenot <[email protected]> | 2020-11-02 16:08:27 +0000 |
commit | 48e349ef99980da483db56b78d06b196e05435b9 (patch) | |
tree | 9e835309fa3eada2005aaf97b0d4214a84a043a0 /src/cubeb_aaudio.cpp | |
parent | c81283271fa45fb7606e753719d9725d457189f2 (diff) | |
download | cubeb-48e349ef99980da483db56b78d06b196e05435b9.tar.gz cubeb-48e349ef99980da483db56b78d06b196e05435b9.zip |
Format src/cubeb_aaudio.cpp with clang-format
Diffstat (limited to 'src/cubeb_aaudio.cpp')
-rw-r--r-- | src/cubeb_aaudio.cpp | 874 |
1 files changed, 457 insertions, 417 deletions
diff --git a/src/cubeb_aaudio.cpp b/src/cubeb_aaudio.cpp index 3e249fc..b32e247 100644 --- a/src/cubeb_aaudio.cpp +++ b/src/cubeb_aaudio.cpp @@ -4,67 +4,65 @@ * This program is made available under an ISC-style license. See the * accompanying file LICENSE for details. */ +#include "cubeb-internal.h" +#include "cubeb/cubeb.h" +#include "cubeb_android.h" +#include "cubeb_log.h" +#include "cubeb_resampler.h" +#include <aaudio/AAudio.h> +#include <atomic> #include <cassert> -#include <mutex> +#include <chrono> #include <condition_variable> -#include <thread> -#include <cstring> -#include <atomic> #include <cstring> -#include <chrono> -#include <memory> #include <dlfcn.h> +#include <memory> +#include <mutex> +#include <thread> #include <time.h> -#include <aaudio/AAudio.h> -#include "cubeb/cubeb.h" -#include "cubeb-internal.h" -#include "cubeb_resampler.h" -#include "cubeb_log.h" -#include "cubeb_android.h" #ifdef DISABLE_LIBAAUDIO_DLOPEN #define WRAP(x) x #else #define WRAP(x) cubeb_##x -#define LIBAAUDIO_API_VISIT(X) \ - X(AAudio_convertResultToText) \ - X(AAudio_convertStreamStateToText) \ - X(AAudio_createStreamBuilder) \ - X(AAudioStreamBuilder_openStream) \ - X(AAudioStreamBuilder_setChannelCount) \ - X(AAudioStreamBuilder_setBufferCapacityInFrames)\ - X(AAudioStreamBuilder_setDirection) \ - X(AAudioStreamBuilder_setFormat) \ - X(AAudioStreamBuilder_setSharingMode) \ - X(AAudioStreamBuilder_setPerformanceMode) \ - X(AAudioStreamBuilder_setSampleRate) \ - X(AAudioStreamBuilder_delete) \ - X(AAudioStreamBuilder_setDataCallback) \ - X(AAudioStreamBuilder_setErrorCallback) \ - X(AAudioStream_close) \ - X(AAudioStream_read) \ - X(AAudioStream_requestStart) \ - X(AAudioStream_requestPause) \ - X(AAudioStream_setBufferSizeInFrames) \ - X(AAudioStream_getTimestamp) \ - X(AAudioStream_requestFlush) \ - X(AAudioStream_requestStop) \ - X(AAudioStream_getPerformanceMode) \ - X(AAudioStream_getSharingMode) \ - X(AAudioStream_getBufferSizeInFrames) \ - X(AAudioStream_getBufferCapacityInFrames) \ - X(AAudioStream_getSampleRate) \ - X(AAudioStream_waitForStateChange) \ - X(AAudioStream_getFramesRead) \ - X(AAudioStream_getState) \ - X(AAudioStream_getFramesWritten) \ - X(AAudioStream_getFramesPerBurst) \ - X(AAudioStreamBuilder_setInputPreset) \ - X(AAudioStreamBuilder_setUsage) \ - - - // not needed or added later on - // X(AAudioStreamBuilder_setFramesPerDataCallback) \ +#define LIBAAUDIO_API_VISIT(X) \ + X(AAudio_convertResultToText) \ + X(AAudio_convertStreamStateToText) \ + X(AAudio_createStreamBuilder) \ + X(AAudioStreamBuilder_openStream) \ + X(AAudioStreamBuilder_setChannelCount) \ + X(AAudioStreamBuilder_setBufferCapacityInFrames) \ + X(AAudioStreamBuilder_setDirection) \ + X(AAudioStreamBuilder_setFormat) \ + X(AAudioStreamBuilder_setSharingMode) \ + X(AAudioStreamBuilder_setPerformanceMode) \ + X(AAudioStreamBuilder_setSampleRate) \ + X(AAudioStreamBuilder_delete) \ + X(AAudioStreamBuilder_setDataCallback) \ + X(AAudioStreamBuilder_setErrorCallback) \ + X(AAudioStream_close) \ + X(AAudioStream_read) \ + X(AAudioStream_requestStart) \ + X(AAudioStream_requestPause) \ + X(AAudioStream_setBufferSizeInFrames) \ + X(AAudioStream_getTimestamp) \ + X(AAudioStream_requestFlush) \ + X(AAudioStream_requestStop) \ + X(AAudioStream_getPerformanceMode) \ + X(AAudioStream_getSharingMode) \ + X(AAudioStream_getBufferSizeInFrames) \ + X(AAudioStream_getBufferCapacityInFrames) \ + X(AAudioStream_getSampleRate) \ + X(AAudioStream_waitForStateChange) \ + X(AAudioStream_getFramesRead) \ + X(AAudioStream_getState) \ + X(AAudioStream_getFramesWritten) \ + X(AAudioStream_getFramesPerBurst) \ + X(AAudioStreamBuilder_setInputPreset) \ + X(AAudioStreamBuilder_setUsage) + +// not needed or added later on +// X(AAudioStreamBuilder_setFramesPerDataCallback) \ // X(AAudioStreamBuilder_setDeviceId) \ // X(AAudioStreamBuilder_setSamplesPerFrame) \ // X(AAudioStream_getSamplesPerFrame) \ @@ -104,17 +102,17 @@ enum class stream_state { struct cubeb_stream { /* Note: Must match cubeb_stream layout in cubeb.c. */ - cubeb * context {}; - void * user_ptr {}; + cubeb * context{}; + void * user_ptr{}; - std::atomic<bool> in_use {false}; - std::atomic<stream_state> state {stream_state::INIT}; + std::atomic<bool> in_use{false}; + std::atomic<stream_state> state{stream_state::INIT}; - AAudioStream * ostream {}; - AAudioStream * istream {}; - cubeb_data_callback data_callback {}; - cubeb_state_callback state_callback {}; - cubeb_resampler * resampler {}; + AAudioStream * ostream{}; + AAudioStream * istream{}; + cubeb_data_callback data_callback{}; + cubeb_state_callback state_callback{}; + cubeb_resampler * resampler{}; // mutex synchronizes access to the stream from the state thread // and user-called functions. Everything that is accessed in the @@ -122,12 +120,12 @@ struct cubeb_stream { std::mutex mutex; std::unique_ptr<char[]> in_buf; - unsigned in_frame_size {}; // size of one input frame + unsigned in_frame_size{}; // size of one input frame - cubeb_sample_format out_format {}; - std::atomic<float> volume {1.f}; - unsigned out_channels {}; - unsigned out_frame_size {}; + cubeb_sample_format out_format{}; + std::atomic<float> volume{1.f}; + unsigned out_channels{}; + unsigned out_frame_size{}; int64_t latest_output_latency = 0; int64_t latest_input_latency = 0; bool voice_input; @@ -135,8 +133,8 @@ struct cubeb_stream { }; struct cubeb { - struct cubeb_ops const * ops {}; - void * libaaudio {}; + struct cubeb_ops const * ops{}; + void * libaaudio{}; struct { // The state thread: it waits for state changes and stops @@ -145,8 +143,8 @@ struct cubeb { std::thread notifier; std::mutex mutex; std::condition_variable cond; - std::atomic<bool> join {false}; - std::atomic<bool> waiting {false}; + std::atomic<bool> join{false}; + std::atomic<bool> waiting{false}; } state; // streams[i].in_use signals whether a stream is used @@ -154,7 +152,8 @@ struct cubeb { }; // Only allowed from state thread, while mutex on stm is locked -static void shutdown(cubeb_stream * stm) +static void +shutdown(cubeb_stream * stm) { if (stm->istream) { WRAP(AAudioStream_requestStop)(stm->istream); @@ -169,24 +168,25 @@ static void shutdown(cubeb_stream * stm) // Returns whether the given state is one in which we wait for // an asynchronous change -static bool waiting_state(stream_state state) +static bool +waiting_state(stream_state state) { switch (state) { - case stream_state::DRAINING: - case stream_state::STARTING: - case stream_state::STOPPING: - return true; - default: - return false; + case stream_state::DRAINING: + case stream_state::STARTING: + case stream_state::STOPPING: + return true; + default: + return false; } } -static void update_state(cubeb_stream * stm) +static void +update_state(cubeb_stream * stm) { // Fast path for streams that don't wait for state change or are invalid enum stream_state old_state = stm->state.load(); - if (old_state == stream_state::INIT || - old_state == stream_state::STARTED || + if (old_state == stream_state::INIT || old_state == stream_state::STARTED || old_state == stream_state::STOPPED || old_state == stream_state::SHUTDOWN) { return; @@ -202,8 +202,7 @@ static void update_state(cubeb_stream * stm) // check again: if this is true now, the stream was destroyed or // changed between our fast path check and locking the mutex old_state = stm->state.load(); - if (old_state == stream_state::INIT || - old_state == stream_state::STARTED || + if (old_state == stream_state::INIT || old_state == stream_state::STARTED || old_state == stream_state::STOPPED || old_state == stream_state::SHUTDOWN) { return; @@ -235,20 +234,22 @@ static void update_state(cubeb_stream * stm) // why we are passing STATE_UNKNOWN. aaudio_result_t res; if (stm->istream) { - res = WRAP(AAudioStream_waitForStateChange)(stm->istream, - AAUDIO_STREAM_STATE_UNKNOWN, &istate, 0); + res = WRAP(AAudioStream_waitForStateChange)( + stm->istream, AAUDIO_STREAM_STATE_UNKNOWN, &istate, 0); if (res != AAUDIO_OK) { - LOG("AAudioStream_waitForStateChanged: %s", WRAP(AAudio_convertResultToText)(res)); + LOG("AAudioStream_waitForStateChanged: %s", + WRAP(AAudio_convertResultToText)(res)); return; } assert(istate); } if (stm->ostream) { - res = WRAP(AAudioStream_waitForStateChange)(stm->ostream, - AAUDIO_STREAM_STATE_UNKNOWN, &ostate, 0); + res = WRAP(AAudioStream_waitForStateChange)( + stm->ostream, AAUDIO_STREAM_STATE_UNKNOWN, &ostate, 0); if (res != AAUDIO_OK) { - LOG("AAudioStream_waitForStateChanged: %s", WRAP(AAudio_convertResultToText)(res)); + LOG("AAudioStream_waitForStateChanged: %s", + WRAP(AAudio_convertResultToText)(res)); return; } assert(ostate); @@ -256,11 +257,11 @@ static void update_state(cubeb_stream * stm) // handle invalid stream states if (istate == AAUDIO_STREAM_STATE_PAUSING || - istate == AAUDIO_STREAM_STATE_PAUSED || - istate == AAUDIO_STREAM_STATE_FLUSHING || - istate == AAUDIO_STREAM_STATE_FLUSHED || - istate == AAUDIO_STREAM_STATE_UNKNOWN || - istate == AAUDIO_STREAM_STATE_DISCONNECTED) { + istate == AAUDIO_STREAM_STATE_PAUSED || + istate == AAUDIO_STREAM_STATE_FLUSHING || + istate == AAUDIO_STREAM_STATE_FLUSHED || + istate == AAUDIO_STREAM_STATE_UNKNOWN || + istate == AAUDIO_STREAM_STATE_DISCONNECTED) { const char * name = WRAP(AAudio_convertStreamStateToText)(istate); LOG("Unexpected android input stream state %s", name); shutdown(stm); @@ -268,11 +269,11 @@ static void update_state(cubeb_stream * stm) } if (ostate == AAUDIO_STREAM_STATE_PAUSING || - ostate == AAUDIO_STREAM_STATE_PAUSED || - ostate == AAUDIO_STREAM_STATE_FLUSHING || - ostate == AAUDIO_STREAM_STATE_FLUSHED || - ostate == AAUDIO_STREAM_STATE_UNKNOWN || - ostate == AAUDIO_STREAM_STATE_DISCONNECTED) { + ostate == AAUDIO_STREAM_STATE_PAUSED || + ostate == AAUDIO_STREAM_STATE_FLUSHING || + ostate == AAUDIO_STREAM_STATE_FLUSHED || + ostate == AAUDIO_STREAM_STATE_UNKNOWN || + ostate == AAUDIO_STREAM_STATE_DISCONNECTED) { const char * name = WRAP(AAudio_convertStreamStateToText)(istate); LOG("Unexpected android output stream state %s", name); shutdown(stm); @@ -280,70 +281,69 @@ static void update_state(cubeb_stream * stm) } switch (old_state) { - case stream_state::STARTING: - if ((!istate || istate == AAUDIO_STREAM_STATE_STARTED) && - (!ostate || ostate == AAUDIO_STREAM_STATE_STARTED)) { - stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED); - new_state = stream_state::STARTED; - } - break; - case stream_state::DRAINING: - // The DRAINING state means that we want to stop the streams but - // may not have done so yet. - // The aaudio docs state that returning STOP from the callback isn't - // enough, the stream has to be stopped from another thread - // afterwards. - // No callbacks are triggered anymore when requestStop returns. - // That is important as we otherwise might read from a closed istream - // for a duplex stream. - // Therefor it is important to close ostream first. - if (ostate && - ostate != AAUDIO_STREAM_STATE_STOPPING && - ostate != AAUDIO_STREAM_STATE_STOPPED) { - res = WRAP(AAudioStream_requestStop)(stm->ostream); - if (res != AAUDIO_OK) { - LOG("AAudioStream_requestStop: %s", WRAP(AAudio_convertResultToText)(res)); - return; - } + case stream_state::STARTING: + if ((!istate || istate == AAUDIO_STREAM_STATE_STARTED) && + (!ostate || ostate == AAUDIO_STREAM_STATE_STARTED)) { + stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED); + new_state = stream_state::STARTED; + } + break; + case stream_state::DRAINING: + // The DRAINING state means that we want to stop the streams but + // may not have done so yet. + // The aaudio docs state that returning STOP from the callback isn't + // enough, the stream has to be stopped from another thread + // afterwards. + // No callbacks are triggered anymore when requestStop returns. + // That is important as we otherwise might read from a closed istream + // for a duplex stream. + // Therefor it is important to close ostream first. + if (ostate && ostate != AAUDIO_STREAM_STATE_STOPPING && + ostate != AAUDIO_STREAM_STATE_STOPPED) { + res = WRAP(AAudioStream_requestStop)(stm->ostream); + if (res != AAUDIO_OK) { + LOG("AAudioStream_requestStop: %s", + WRAP(AAudio_convertResultToText)(res)); + return; } - if (istate && - istate != AAUDIO_STREAM_STATE_STOPPING && - istate != AAUDIO_STREAM_STATE_STOPPED) { - res = WRAP(AAudioStream_requestStop)(stm->istream); - if (res != AAUDIO_OK) { - LOG("AAudioStream_requestStop: %s", WRAP(AAudio_convertResultToText)(res)); - return; - } + } + if (istate && istate != AAUDIO_STREAM_STATE_STOPPING && + istate != AAUDIO_STREAM_STATE_STOPPED) { + res = WRAP(AAudioStream_requestStop)(stm->istream); + if (res != AAUDIO_OK) { + LOG("AAudioStream_requestStop: %s", + WRAP(AAudio_convertResultToText)(res)); + return; } + } - // we always wait until both streams are stopped until we - // send CUBEB_STATE_DRAINED. Then we can directly transition - // our logical state to STOPPED, not triggering - // an additional CUBEB_STATE_STOPPED callback (which might - // be unexpected for the user). - if ((!ostate || ostate == AAUDIO_STREAM_STATE_STOPPED) && - (!istate || istate == AAUDIO_STREAM_STATE_STOPPED)) { - new_state = stream_state::STOPPED; - stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED); - } - break; - case stream_state::STOPPING: - assert(!istate || - istate == AAUDIO_STREAM_STATE_STOPPING || - istate == AAUDIO_STREAM_STATE_STOPPED); - assert(!ostate || - ostate == AAUDIO_STREAM_STATE_STOPPING || - ostate == AAUDIO_STREAM_STATE_STOPPED); - if ((!istate || istate == AAUDIO_STREAM_STATE_STOPPED) && - (!ostate || ostate == AAUDIO_STREAM_STATE_STOPPED)) { - stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED); - new_state = stream_state::STOPPED; - } - break; - default: - assert(false && "Unreachable: invalid state"); + // we always wait until both streams are stopped until we + // send CUBEB_STATE_DRAINED. Then we can directly transition + // our logical state to STOPPED, not triggering + // an additional CUBEB_STATE_STOPPED callback (which might + // be unexpected for the user). + if ((!ostate || ostate == AAUDIO_STREAM_STATE_STOPPED) && + (!istate || istate == AAUDIO_STREAM_STATE_STOPPED)) { + new_state = stream_state::STOPPED; + stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED); + } + break; + case stream_state::STOPPING: + assert(!istate || istate == AAUDIO_STREAM_STATE_STOPPING || + istate == AAUDIO_STREAM_STATE_STOPPED); + assert(!ostate || ostate == AAUDIO_STREAM_STATE_STOPPING || + ostate == AAUDIO_STREAM_STATE_STOPPED); + if ((!istate || istate == AAUDIO_STREAM_STATE_STOPPED) && + (!ostate || ostate == AAUDIO_STREAM_STATE_STOPPED)) { + stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED); + new_state = stream_state::STOPPED; + } + break; + default: + assert(false && "Unreachable: invalid state"); } - } while (old_state != new_state && !stm->state.compare_exchange_strong(old_state, new_state)); + } while (old_state != new_state && + !stm->state.compare_exchange_strong(old_state, new_state)); } // See https://nyorain.github.io/lock-free-wakeup.html for a note @@ -354,7 +354,8 @@ static void update_state(cubeb_stream * stm) // that only serves as notifier backup (in case the notification happens // right between the state thread checking and going to sleep in which case // this thread will kick in and signal it right again). -static void notifier_thread(cubeb* ctx) +static void +notifier_thread(cubeb * ctx) { unique_lock lock(ctx->state.mutex); @@ -374,7 +375,8 @@ static void notifier_thread(cubeb* ctx) LOG("Exiting notifier thread"); } -static void state_thread(cubeb* ctx) +static void +state_thread(cubeb * ctx) { unique_lock lock(ctx->state.mutex); @@ -453,10 +455,10 @@ aaudio_destroy(cubeb * ctx) ctx->state.join.store(true); ctx->state.cond.notify_all(); - if(ctx->state.thread.joinable()) { + if (ctx->state.thread.joinable()) { ctx->state.thread.join(); } - if(ctx->state.notifier.joinable()) { + if (ctx->state.notifier.joinable()) { ctx->state.notifier.join(); } @@ -467,7 +469,8 @@ aaudio_destroy(cubeb * ctx) } static void -apply_volume(cubeb_stream * stm, void * audio_data, uint32_t num_frames) { +apply_volume(cubeb_stream * stm, void * audio_data, uint32_t num_frames) +{ float volume = stm->volume.load(); // optimization: we don't have to change anything in this case if (volume == 1.f) { @@ -475,18 +478,18 @@ apply_volume(cubeb_stream * stm, void * audio_data, uint32_t num_frames) { } switch (stm->out_format) { - case CUBEB_SAMPLE_S16NE: - for (uint32_t i = 0u; i < num_frames * stm->out_channels; ++i) { - (static_cast<int16_t*>(audio_data))[i] *= volume; - } - break; - case CUBEB_SAMPLE_FLOAT32NE: - for (uint32_t i = 0u; i < num_frames * stm->out_channels; ++i) { - (static_cast<float*>(audio_data))[i] *= volume; - } - break; - default: - assert(false && "Unreachable: invalid stream out_format"); + case CUBEB_SAMPLE_S16NE: + for (uint32_t i = 0u; i < num_frames * stm->out_channels; ++i) { + (static_cast<int16_t *>(audio_data))[i] *= volume; + } + break; + case CUBEB_SAMPLE_FLOAT32NE: + for (uint32_t i = 0u; i < num_frames * stm->out_channels; ++i) { + (static_cast<float *>(audio_data))[i] *= volume; + } + break; + default: + assert(false && "Unreachable: invalid stream out_format"); } } @@ -496,9 +499,9 @@ apply_volume(cubeb_stream * stm, void * audio_data, uint32_t num_frames) { static aaudio_data_callback_result_t aaudio_duplex_data_cb(AAudioStream * astream, void * user_data, - void * audio_data, int32_t num_frames) + void * audio_data, int32_t num_frames) { - cubeb_stream * stm = (cubeb_stream*) user_data; + cubeb_stream * stm = (cubeb_stream *)user_data; assert(stm->ostream == astream); assert(stm->istream); assert(num_frames >= 0); @@ -506,7 +509,8 @@ aaudio_duplex_data_cb(AAudioStream * astream, void * user_data, stream_state state = atomic_load(&stm->state); // int istate = WRAP(AAudioStream_getState)(stm->istream); // int ostate = WRAP(AAudioStream_getState)(stm->ostream); - // ALOGV("aaudio duplex data cb on stream %p: state %ld (in: %d, out: %d), num_frames: %ld", + // ALOGV("aaudio duplex data cb on stream %p: state %ld (in: %d, out: %d), + // num_frames: %ld", // (void*) stm, state, istate, ostate, num_frames); // all other states may happen since the callback might be called @@ -525,11 +529,12 @@ aaudio_duplex_data_cb(AAudioStream * astream, void * user_data, // while this callback is for the output stream so this is ok. // We also pass timeout 0, giving us strong non-blocking guarantees. // This is exactly how it's done in the aaudio duplex example code snippet. - long in_num_frames = WRAP(AAudioStream_read)(stm->istream, - stm->in_buf.get(), num_frames, 0); + long in_num_frames = + WRAP(AAudioStream_read)(stm->istream, stm->in_buf.get(), num_frames, 0); if (in_num_frames < 0) { // error stm->state.store(stream_state::ERROR); - LOG("AAudioStream_read: %s", WRAP(AAudio_convertResultToText)(in_num_frames)); + LOG("AAudioStream_read: %s", + WRAP(AAudio_convertResultToText)(in_num_frames)); return AAUDIO_CALLBACK_RESULT_STOP; } @@ -537,8 +542,8 @@ aaudio_duplex_data_cb(AAudioStream * astream, void * user_data, // begin to buffer output but not have any input ready yet. We could // block AAudioStream_read (passing a timeout > 0) but that leads to issues // since blocking in this callback is a bad idea in general and it might break - // the stream when it is stopped by another thread shortly after being started. - // We therefore simply send silent input to the application, as shown + // the stream when it is stopped by another thread shortly after being + // started. We therefore simply send silent input to the application, as shown // in the AAudio duplex stream code example. if (in_num_frames < num_frames) { // LOG("AAudioStream_read returned not enough frames: %ld instead of %d", @@ -549,8 +554,9 @@ aaudio_duplex_data_cb(AAudioStream * astream, void * user_data, in_num_frames = num_frames; } - long done_frames = cubeb_resampler_fill(stm->resampler, stm->in_buf.get(), - &in_num_frames, audio_data, num_frames); + long done_frames = + cubeb_resampler_fill(stm->resampler, stm->in_buf.get(), &in_num_frames, + audio_data, num_frames); if (done_frames < 0 || done_frames > num_frames) { LOG("Error in data callback or resampler: %ld", done_frames); @@ -561,7 +567,8 @@ aaudio_duplex_data_cb(AAudioStream * astream, void * user_data, stm->context->state.waiting.store(true); stm->context->state.cond.notify_one(); - char * begin = static_cast<char*>(audio_data) + done_frames * stm->out_frame_size; + char * begin = + static_cast<char *>(audio_data) + done_frames * stm->out_frame_size; std::memset(begin, 0x0, (num_frames - done_frames) * stm->out_frame_size); } @@ -571,16 +578,17 @@ aaudio_duplex_data_cb(AAudioStream * astream, void * user_data, static aaudio_data_callback_result_t aaudio_output_data_cb(AAudioStream * astream, void * user_data, - void * audio_data, int32_t num_frames) + void * audio_data, int32_t num_frames) { - cubeb_stream * stm = (cubeb_stream*) user_data; + cubeb_stream * stm = (cubeb_stream *)user_data; assert(stm->ostream == astream); assert(!stm->istream); assert(num_frames >= 0); stream_state state = stm->state.load(); // int ostate = WRAP(AAudioStream_getState)(stm->ostream); - // ALOGV("aaudio output data cb on stream %p: state %ld (%d), num_frames: %ld", + // ALOGV("aaudio output data cb on stream %p: state %ld (%d), num_frames: + // %ld", // (void*) stm, state, ostate, num_frames); // all other states may happen since the callback might be called @@ -594,8 +602,8 @@ aaudio_output_data_cb(AAudioStream * astream, void * user_data, return AAUDIO_CALLBACK_RESULT_CONTINUE; } - long done_frames = cubeb_resampler_fill(stm->resampler, NULL, NULL, - audio_data, num_frames); + long done_frames = + cubeb_resampler_fill(stm->resampler, NULL, NULL, audio_data, num_frames); if (done_frames < 0 || done_frames > num_frames) { LOG("Error in data callback or resampler: %ld", done_frames); stm->state.store(stream_state::ERROR); @@ -605,7 +613,8 @@ aaudio_output_data_cb(AAudioStream * astream, void * user_data, stm->context->state.waiting.store(true); stm->context->state.cond.notify_one(); - char * begin = static_cast<char*>(audio_data) + done_frames * stm->out_frame_size; + char * begin = + static_cast<char *>(audio_data) + done_frames * stm->out_frame_size; std::memset(begin, 0x0, (num_frames - done_frames) * stm->out_frame_size); } @@ -615,9 +624,9 @@ aaudio_output_data_cb(AAudioStream * astream, void * user_data, static aaudio_data_callback_result_t aaudio_input_data_cb(AAudioStream * astream, void * user_data, - void * audio_data, int32_t num_frames) + void * audio_data, int32_t num_frames) { - cubeb_stream * stm = (cubeb_stream*) user_data; + cubeb_stream * stm = (cubeb_stream *)user_data; assert(stm->istream == astream); assert(!stm->ostream); assert(num_frames >= 0); @@ -638,8 +647,8 @@ aaudio_input_data_cb(AAudioStream * astream, void * user_data, } long input_frame_count = num_frames; - long done_frames = cubeb_resampler_fill(stm->resampler, - audio_data, &input_frame_count, NULL, 0); + long done_frames = cubeb_resampler_fill(stm->resampler, audio_data, + &input_frame_count, NULL, 0); if (done_frames < 0 || done_frames > num_frames) { LOG("Error in data callback or resampler: %ld", done_frames); stm->state.store(stream_state::ERROR); @@ -659,7 +668,7 @@ aaudio_input_data_cb(AAudioStream * astream, void * user_data, static void aaudio_error_cb(AAudioStream * astream, void * user_data, aaudio_result_t error) { - cubeb_stream * stm = static_cast<cubeb_stream*>(user_data); + cubeb_stream * stm = static_cast<cubeb_stream *>(user_data); assert(stm->ostream == astream || stm->istream == astream); LOG("AAudio error callback: %s", WRAP(AAudio_convertResultToText)(error)); stm->state.store(stream_state::ERROR); @@ -667,7 +676,7 @@ aaudio_error_cb(AAudioStream * astream, void * user_data, aaudio_result_t error) static int realize_stream(AAudioStreamBuilder * sb, const cubeb_stream_params * params, - AAudioStream ** stream, unsigned * frame_size) + AAudioStream ** stream, unsigned * frame_size) { aaudio_result_t res; assert(params->rate); @@ -678,16 +687,16 @@ realize_stream(AAudioStreamBuilder * sb, const cubeb_stream_params * params, aaudio_format_t fmt; switch (params->format) { - case CUBEB_SAMPLE_S16NE: - fmt = AAUDIO_FORMAT_PCM_I16; - *frame_size = sizeof(int16_t) * params->channels; - break; - case CUBEB_SAMPLE_FLOAT32NE: - fmt = AAUDIO_FORMAT_PCM_FLOAT; - *frame_size = sizeof(float) * params->channels; - break; - default: - return CUBEB_ERROR_INVALID_FORMAT; + case CUBEB_SAMPLE_S16NE: + fmt = AAUDIO_FORMAT_PCM_I16; + *frame_size = sizeof(int16_t) * params->channels; + break; + case CUBEB_SAMPLE_FLOAT32NE: + fmt = AAUDIO_FORMAT_PCM_FLOAT; + *frame_size = sizeof(float) * params->channels; + break; + default: + return CUBEB_ERROR_INVALID_FORMAT; } WRAP(AAudioStreamBuilder_setFormat)(sb, fmt); @@ -700,13 +709,16 @@ realize_stream(AAudioStreamBuilder * sb, const cubeb_stream_params * params, // Just try again with default rate, we create a resampler anyways WRAP(AAudioStreamBuilder_setSampleRate)(sb, AAUDIO_UNSPECIFIED); res = WRAP(AAudioStreamBuilder_openStream)(sb, stream); - LOG("Requested rate of %u is not supported, inserting resampler", params->rate); + LOG("Requested rate of %u is not supported, inserting resampler", + params->rate); } - // When the app has no permission to record audio (android.permission.RECORD_AUDIO) - // but requested and input stream, this will return INVALID_ARGUMENT. + // When the app has no permission to record audio + // (android.permission.RECORD_AUDIO) but requested and input stream, this will + // return INVALID_ARGUMENT. if (res != AAUDIO_OK) { - LOG("AAudioStreamBuilder_openStream: %s", WRAP(AAudio_convertResultToText)(res)); + LOG("AAudioStreamBuilder_openStream: %s", + WRAP(AAudio_convertResultToText)(res)); return CUBEB_ERROR; } @@ -718,11 +730,11 @@ aaudio_stream_destroy(cubeb_stream * stm) { lock_guard lock(stm->mutex); assert(stm->state == stream_state::STOPPED || - stm->state == stream_state::STOPPING || - stm->state == stream_state::INIT || - stm->state == stream_state::DRAINING || - stm->state == stream_state::ERROR || - stm->state == stream_state::SHUTDOWN); + stm->state == stream_state::STOPPING || + stm->state == stream_state::INIT || + stm->state == stream_state::DRAINING || + stm->state == stream_state::ERROR || + stm->state == stream_state::SHUTDOWN); aaudio_result_t res; @@ -735,7 +747,8 @@ aaudio_stream_destroy(cubeb_stream * stm) stm->state != stream_state::SHUTDOWN) { res = WRAP(AAudioStream_requestStop)(stm->ostream); if (res != AAUDIO_OK) { - LOG("AAudioStreamBuilder_requestStop: %s", WRAP(AAudio_convertResultToText)(res)); + LOG("AAudioStreamBuilder_requestStop: %s", + WRAP(AAudio_convertResultToText)(res)); } } @@ -749,7 +762,8 @@ aaudio_stream_destroy(cubeb_stream * stm) stm->state != stream_state::SHUTDOWN) { res = WRAP(AAudioStream_requestStop)(stm->istream); if (res != AAUDIO_OK) { - LOG("AAudioStreamBuilder_requestStop: %s", WRAP(AAudio_convertResultToText)(res)); + LOG("AAudioStreamBuilder_requestStop: %s", + WRAP(AAudio_convertResultToText)(res)); } } @@ -773,29 +787,29 @@ aaudio_stream_destroy(cubeb_stream * stm) } static int -aaudio_stream_init_impl( - cubeb_stream * stm, - cubeb_devid input_device, - cubeb_stream_params * input_stream_params, - cubeb_devid output_device, - cubeb_stream_params * output_stream_params, - unsigned int latency_frames) +aaudio_stream_init_impl(cubeb_stream * stm, cubeb_devid input_device, + cubeb_stream_params * input_stream_params, + cubeb_devid output_device, + cubeb_stream_params * output_stream_params, + unsigned int latency_frames) { assert(stm->state.load() == stream_state::INIT); stm->in_use.store(true); aaudio_result_t res; - AAudioStreamBuilder* sb; + AAudioStreamBuilder * sb; res = WRAP(AAudio_createStreamBuilder)(&sb); if (res != AAUDIO_OK) { - LOG("AAudio_createStreamBuilder: %s", WRAP(AAudio_convertResultToText)(res)); + LOG("AAudio_createStreamBuilder: %s", + WRAP(AAudio_convertResultToText)(res)); return CUBEB_ERROR; } // make sure the builder is always destroyed struct StreamBuilderDestructor { - void operator()(AAudioStreamBuilder* sb) { - WRAP(AAudioStreamBuilder_delete)(sb); + void operator()(AAudioStreamBuilder * sb) + { + WRAP(AAudioStreamBuilder_delete)(sb); } }; @@ -804,8 +818,8 @@ aaudio_stream_init_impl( WRAP(AAudioStreamBuilder_setErrorCallback)(sb, aaudio_error_cb, stm); WRAP(AAudioStreamBuilder_setBufferCapacityInFrames)(sb, latency_frames); - AAudioStream_dataCallback in_data_callback {}; - AAudioStream_dataCallback out_data_callback {}; + AAudioStream_dataCallback in_data_callback{}; + AAudioStream_dataCallback out_data_callback{}; if (output_stream_params && input_stream_params) { out_data_callback = aaudio_duplex_data_cb; in_data_callback = NULL; @@ -825,10 +839,12 @@ aaudio_stream_init_impl( if (latency_frames <= POWERSAVE_LATENCY_FRAMES_THRESHOLD) { LOG("AAudio setting low latency mode for stream"); - WRAP(AAudioStreamBuilder_setPerformanceMode)(sb, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); + WRAP(AAudioStreamBuilder_setPerformanceMode) + (sb, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); } else { LOG("AAudio setting power saving mode for stream"); - WRAP(AAudioStreamBuilder_setPerformanceMode)(sb, AAUDIO_PERFORMANCE_MODE_POWER_SAVING); + WRAP(AAudioStreamBuilder_setPerformanceMode) + (sb, AAUDIO_PERFORMANCE_MODE_POWER_SAVING); } unsigned frame_size; @@ -843,14 +859,16 @@ aaudio_stream_init_impl( WRAP(AAudioStreamBuilder_setUsage)(sb, output_preset); WRAP(AAudioStreamBuilder_setDirection)(sb, AAUDIO_DIRECTION_OUTPUT); WRAP(AAudioStreamBuilder_setDataCallback)(sb, out_data_callback, stm); - int res_err = realize_stream(sb, output_stream_params, &stm->ostream, &frame_size); + int res_err = + realize_stream(sb, output_stream_params, &stm->ostream, &frame_size); if (res_err) { return res_err; } // output debug information aaudio_sharing_mode_t sm = WRAP(AAudioStream_getSharingMode)(stm->ostream); - aaudio_performance_mode_t pm = WRAP(AAudioStream_getPerformanceMode)(stm->ostream); + aaudio_performance_mode_t pm = + WRAP(AAudioStream_getPerformanceMode)(stm->ostream); int bcap = WRAP(AAudioStream_getBufferCapacityInFrames)(stm->ostream); int bsize = WRAP(AAudioStream_getBufferSizeInFrames)(stm->ostream); int rate = WRAP(AAudioStream_getSampleRate)(stm->ostream); @@ -882,14 +900,16 @@ aaudio_stream_init_impl( WRAP(AAudioStreamBuilder_setInputPreset)(sb, input_preset); WRAP(AAudioStreamBuilder_setDirection)(sb, AAUDIO_DIRECTION_INPUT); WRAP(AAudioStreamBuilder_setDataCallback)(sb, in_data_callback, stm); - int res_err = realize_stream(sb, input_stream_params, &stm->istream, &frame_size); + int res_err = + realize_stream(sb, input_stream_params, &stm->istream, &frame_size); if (res_err) { return res_err; } // output debug information aaudio_sharing_mode_t sm = WRAP(AAudioStream_getSharingMode)(stm->istream); - aaudio_performance_mode_t pm = WRAP(AAudioStream_getPerformanceMode)(stm->istream); + aaudio_performance_mode_t pm = + WRAP(AAudioStream_getPerformanceMode)(stm->istream); int bcap = WRAP(AAudioStream_getBufferCapacityInFrames)(stm->istream); int bsize = WRAP(AAudioStream_getBufferSizeInFrames)(stm->istream); int rate = WRAP(AAudioStream_getSampleRate)(stm->istream); @@ -900,7 +920,8 @@ aaudio_stream_init_impl( LOG("AAudio input stream buffer rate: %d", rate); stm->in_buf.reset(new char[bcap * frame_size]()); - assert(!target_sample_rate || target_sample_rate == input_stream_params->rate); + assert(!target_sample_rate || + target_sample_rate == input_stream_params->rate); target_sample_rate = input_stream_params->rate; in_params = *input_stream_params; @@ -908,16 +929,11 @@ aaudio_stream_init_impl( stm->in_frame_size = frame_size; } - - // initialize resampler - stm->resampler = cubeb_resampler_create(stm, - input_stream_params ? &in_params : NULL, - output_stream_params ? &out_params : NULL, - target_sample_rate, - stm->data_callback, - stm->user_ptr, - CUBEB_RESAMPLER_QUALITY_DEFAULT); + stm->resampler = cubeb_resampler_create( + stm, input_stream_params ? &in_params : NULL, + output_stream_params ? &out_params : NULL, target_sample_rate, + stm->data_callback, stm->user_ptr, CUBEB_RESAMPLER_QUALITY_DEFAULT); if (!stm->resampler) { LOG("Failed to create resampler"); @@ -928,22 +944,19 @@ aaudio_stream_init_impl( // between a stream that was just initialized and one that played // already but was stopped. stm->state.store(stream_state::STOPPED); - LOG("Cubeb stream (%p) INIT success", (void*) stm); + LOG("Cubeb stream (%p) INIT success", (void *)stm); return CUBEB_OK; } static int -aaudio_stream_init(cubeb * ctx, - cubeb_stream ** stream, - char const * /* stream_name */, - cubeb_devid input_device, - cubeb_stream_params * input_stream_params, - cubeb_devid output_device, - cubeb_stream_params * output_stream_params, - unsigned int latency_frames, - cubeb_data_callback data_callback, - cubeb_state_callback state_callback, - void * user_ptr) +aaudio_stream_init(cubeb * ctx, cubeb_stream ** stream, + char const * /* stream_name */, cubeb_devid input_device, + cubeb_stream_params * input_stream_params, + cubeb_devid output_device, + cubeb_stream_params * output_stream_params, + unsigned int latency_frames, + cubeb_data_callback data_callback, + cubeb_state_callback state_callback, void * user_ptr) { assert(!input_device); assert(!output_device); @@ -961,11 +974,11 @@ aaudio_stream_init(cubeb * ctx, // if this fails, another thread initialized this stream // between our check of in_use and this. lock = unique_lock(ctx->streams[i].mutex, std::try_to_lock); - if(!lock.owns_lock()) { + if (!lock.owns_lock()) { continue; } - if(ctx->streams[i].in_use.load()) { + if (ctx->streams[i].in_use.load()) { lock = {}; continue; } @@ -986,11 +999,14 @@ aaudio_stream_init(cubeb * ctx, stm->voice_input = !!(input_stream_params->prefs & CUBEB_STREAM_PREF_VOICE); stm->voice_output = !!(output_stream_params->prefs & CUBEB_STREAM_PREF_VOICE); - LOG("cubeb stream prefs: voice_input: %s voice_output: %s", stm->voice_input ? "true" : "false", - stm->voice_output ? "true" : "false"); + LOG("cubeb stream prefs: voice_input: %s voice_output: %s", + stm->voice_input ? "true" : "false", + stm->voice_output ? "true" : "false"); - int err = aaudio_stream_init_impl(stm, input_device, input_stream_params, output_device, output_stream_params, latency_frames); - if(err != CUBEB_OK) { + int err = aaudio_stream_init_impl(stm, input_device, input_stream_params, + output_device, output_stream_params, + latency_frames); + if (err != CUBEB_OK) { // This is needed since aaudio_stream_destroy will lock the mutex again. // It's no problem that there is a gap in between as the stream isn't // actually in u se. @@ -1012,23 +1028,23 @@ aaudio_stream_start(cubeb_stream * stm) stream_state state = stm->state.load(); int istate = stm->istream ? WRAP(AAudioStream_getState)(stm->istream) : 0; int ostate = stm->ostream ? WRAP(AAudioStream_getState)(stm->ostream) : 0; - LOGV("STARTING stream %p: %d (%d %d)", (void*) stm, state, istate, ostate); + LOGV("STARTING stream %p: %d (%d %d)", (void *)stm, state, istate, ostate); switch (state) { - case stream_state::STARTED: - case stream_state::STARTING: - LOG("cubeb stream %p already STARTING/STARTED", (void*) stm); - return CUBEB_OK; - case stream_state::ERROR: - case stream_state::SHUTDOWN: - return CUBEB_ERROR; - case stream_state::INIT: - assert(false && "Invalid stream"); - return CUBEB_ERROR; - case stream_state::STOPPED: - case stream_state::STOPPING: - case stream_state::DRAINING: - break; + case stream_state::STARTED: + case stream_state::STARTING: + LOG("cubeb stream %p already STARTING/STARTED", (void *)stm); + return CUBEB_OK; + case stream_state::ERROR: + case stream_state::SHUTDOWN: + return CUBEB_ERROR; + case stream_state::INIT: + assert(false && "Invalid stream"); + return CUBEB_ERROR; + case stream_state::STOPPED: + case stream_state::STOPPING: + case stream_state::DRAINING: + break; } aaudio_result_t res; @@ -1040,7 +1056,8 @@ aaudio_stream_start(cubeb_stream * stm) if (stm->istream) { res = WRAP(AAudioStream_requestStart)(stm->istream); if (res != AAUDIO_OK) { - LOG("AAudioStream_requestStart (istream): %s", WRAP(AAudio_convertResultToText)(res)); + LOG("AAudioStream_requestStart (istream): %s", + WRAP(AAudio_convertResultToText)(res)); stm->state.store(stream_state::ERROR); return CUBEB_ERROR; } @@ -1049,7 +1066,8 @@ aaudio_stream_start(cubeb_stream * stm) if (stm->ostream) { res = WRAP(AAudioStream_requestStart)(stm->ostream); if (res != AAUDIO_OK) { - LOG("AAudioStream_requestStart (ostream): %s", WRAP(AAudio_convertResultToText)(res)); + LOG("AAudioStream_requestStart (ostream): %s", + WRAP(AAudio_convertResultToText)(res)); stm->state.store(stream_state::ERROR); return CUBEB_ERROR; } @@ -1058,34 +1076,36 @@ aaudio_stream_start(cubeb_stream * stm) int ret = CUBEB_OK; bool success; - while (!(success = stm->state.compare_exchange_strong(state, stream_state::STARTING))) { + while (!(success = stm->state.compare_exchange_strong( + state, stream_state::STARTING))) { // we land here only if the state has changed in the meantime switch (state) { - // If an error ocurred in the meantime, we can't change that. - // The stream will be stopped when shut down. - case stream_state::ERROR: - ret = CUBEB_ERROR; - break; - // The only situation in which the state could have switched to draining - // is if the callback was already fired and requested draining. Don't - // overwrite that. It's not an error either though. - case stream_state::DRAINING: - break; - - // If the state switched [DRAINING -> STOPPING] or [DRAINING/STOPPING -> STOPPED] - // in the meantime, we can simply overwrite that since we restarted the stream. - case stream_state::STOPPING: - case stream_state::STOPPED: - continue; + // If an error ocurred in the meantime, we can't change that. + // The stream will be stopped when shut down. + case stream_state::ERROR: + ret = CUBEB_ERROR; + break; + // The only situation in which the state could have switched to draining + // is if the callback was already fired and requested draining. Don't + // overwrite that. It's not an error either though. + case stream_state::DRAINING: + break; + + // If the state switched [DRAINING -> STOPPING] or [DRAINING/STOPPING -> + // STOPPED] in the meantime, we can simply overwrite that since we restarted + // the stream. + case stream_state::STOPPING: + case stream_state::STOPPED: + continue; - // There is no situation in which the state could have been valid before - // but now in shutdown mode, since we hold the streams mutex. - // There is also no way that it switched *into* STARTING or - // STARTED mode. - default: - assert(false && "Invalid state change"); - ret = CUBEB_ERROR; - break; + // There is no situation in which the state could have been valid before + // but now in shutdown mode, since we hold the streams mutex. + // There is also no way that it switched *into* STARTING or + // STARTED mode. + default: + assert(false && "Invalid state change"); + ret = CUBEB_ERROR; + break; } break; @@ -1108,23 +1128,23 @@ aaudio_stream_stop(cubeb_stream * stm) stream_state state = stm->state.load(); int istate = stm->istream ? WRAP(AAudioStream_getState)(stm->istream) : 0; int ostate = stm->ostream ? WRAP(AAudioStream_getState)(stm->ostream) : 0; - LOGV("STOPPING stream %p: %d (%d %d)", (void*) stm, state, istate, ostate); + LOGV("STOPPING stream %p: %d (%d %d)", (void *)stm, state, istate, ostate); switch (state) { - case stream_state::STOPPED: - case stream_state::STOPPING: - case stream_state::DRAINING: - LOG("cubeb stream %p already STOPPING/STOPPED", (void*) stm); - return CUBEB_OK; - case stream_state::ERROR: - case stream_state::SHUTDOWN: - return CUBEB_ERROR; - case stream_state::INIT: - assert(false && "Invalid stream"); - return CUBEB_ERROR; - case stream_state::STARTED: - case stream_state::STARTING: - break; + case stream_state::STOPPED: + case stream_state::STOPPING: + case stream_state::DRAINING: + LOG("cubeb stream %p already STOPPING/STOPPED", (void *)stm); + return CUBEB_OK; + case stream_state::ERROR: + case stream_state::SHUTDOWN: + return CUBEB_ERROR; + case stream_state::INIT: + assert(false && "Invalid stream"); + return CUBEB_ERROR; + case stream_state::STARTED: + case stream_state::STARTING: + break; } aaudio_result_t res; @@ -1138,7 +1158,8 @@ aaudio_stream_stop(cubeb_stream * stm) // doesn't state behavior. res = WRAP(AAudioStream_requestStop)(stm->ostream); if (res != AAUDIO_OK) { - LOG("AAudioStream_requestStop (ostream): %s", WRAP(AAudio_convertResultToText)(res)); + LOG("AAudioStream_requestStop (ostream): %s", + WRAP(AAudio_convertResultToText)(res)); stm->state.store(stream_state::ERROR); return CUBEB_ERROR; } @@ -1147,7 +1168,8 @@ aaudio_stream_stop(cubeb_stream * stm) if (stm->istream) { res = WRAP(AAudioStream_requestStop)(stm->istream); if (res != AAUDIO_OK) { - LOG("AAudioStream_requestStop (istream): %s", WRAP(AAudio_convertResultToText)(res)); + LOG("AAudioStream_requestStop (istream): %s", + WRAP(AAudio_convertResultToText)(res)); stm->state.store(stream_state::ERROR); return CUBEB_ERROR; } @@ -1155,35 +1177,36 @@ aaudio_stream_stop(cubeb_stream * stm) int ret = CUBEB_OK; bool success; - while (!(success = atomic_compare_exchange_strong(&stm->state, &state, stream_state::STOPPING))) { + while (!(success = atomic_compare_exchange_strong(&stm->state, &state, + stream_state::STOPPING))) { // we land here only if the state has changed in the meantime switch (state) { - // If an error ocurred in the meantime, we can't change that. - // The stream will be STOPPED when shut down. - case stream_state::ERROR: - ret = CUBEB_ERROR; - break; - // If it was switched to DRAINING in the meantime, it was or - // will be STOPPED soon anyways. We don't interfere with - // the DRAINING process, no matter in which state. - // Not an error - case stream_state::DRAINING: - case stream_state::STOPPING: - case stream_state::STOPPED: - break; - - // If the state switched from STARTING to STARTED in the meantime - // we can simply overwrite that since we just STOPPED it. - case stream_state::STARTED: - continue; + // If an error ocurred in the meantime, we can't change that. + // The stream will be STOPPED when shut down. + case stream_state::ERROR: + ret = CUBEB_ERROR; + break; + // If it was switched to DRAINING in the meantime, it was or + // will be STOPPED soon anyways. We don't interfere with + // the DRAINING process, no matter in which state. + // Not an error + case stream_state::DRAINING: + case stream_state::STOPPING: + case stream_state::STOPPED: + break; - // There is no situation in which the state could have been valid before - // but now in shutdown mode, since we hold the streams mutex. - // There is also no way that it switched *into* STARTING mode. - default: - assert(false && "Invalid state change"); - ret = CUBEB_ERROR; - break; + // If the state switched from STARTING to STARTED in the meantime + // we can simply overwrite that since we just STOPPED it. + case stream_state::STARTED: + continue; + + // There is no situation in which the state could have been valid before + // but now in shutdown mode, since we hold the streams mutex. + // There is also no way that it switched *into* STARTING mode. + default: + assert(false && "Invalid state change"); + ret = CUBEB_ERROR; + break; } break; @@ -1206,22 +1229,22 @@ aaudio_stream_get_position(cubeb_stream * stm, uint64_t * position) stream_state state = stm->state.load(); AAudioStream * stream = stm->ostream ? stm->ostream : stm->istream; switch (state) { - case stream_state::ERROR: - case stream_state::SHUTDOWN: - return CUBEB_ERROR; - case stream_state::DRAINING: - case stream_state::STOPPED: - case stream_state::STOPPING: - // getTimestamp is only valid when the stream is playing. - // Simply return the number of frames passed to aaudio - *position = WRAP(AAudioStream_getFramesRead)(stream); - return CUBEB_OK; - case stream_state::INIT: - assert(false && "Invalid stream"); - return CUBEB_ERROR; - case stream_state::STARTED: - case stream_state::STARTING: - break; + case stream_state::ERROR: + case stream_state::SHUTDOWN: + return CUBEB_ERROR; + case stream_state::DRAINING: + case stream_state::STOPPED: + case stream_state::STOPPING: + // getTimestamp is only valid when the stream is playing. + // Simply return the number of frames passed to aaudio + *position = WRAP(AAudioStream_getFramesRead)(stream); + return CUBEB_OK; + case stream_state::INIT: + assert(false && "Invalid stream"); + return CUBEB_ERROR; + case stream_state::STARTED: + case stream_state::STARTING: + break; } int64_t pos; @@ -1258,9 +1281,12 @@ aaudio_stream_get_latency(cubeb_stream * stm, uint32_t * latency) return CUBEB_ERROR; } - res = WRAP(AAudioStream_getTimestamp)(stm->ostream, CLOCK_MONOTONIC, &pos, &ns); + res = + WRAP(AAudioStream_getTimestamp)(stm->ostream, CLOCK_MONOTONIC, &pos, &ns); if (res != AAUDIO_OK) { - LOG("aaudio_stream_get_latency, AAudioStream_getTimestamp: %s, returning memoized value", WRAP(AAudio_convertResultToText)(res)); + LOG("aaudio_stream_get_latency, AAudioStream_getTimestamp: %s, returning " + "memoized value", + WRAP(AAudio_convertResultToText)(res)); // Expected when the stream is paused. *latency = stm->latest_output_latency; return CUBEB_OK; @@ -1286,10 +1312,13 @@ aaudio_stream_get_input_latency(cubeb_stream * stm, uint32_t * latency) return CUBEB_ERROR; } - res = WRAP(AAudioStream_getTimestamp)(stm->istream, CLOCK_MONOTONIC, &pos, &ns); + res = + WRAP(AAudioStream_getTimestamp)(stm->istream, CLOCK_MONOTONIC, &pos, &ns); if (res != AAUDIO_OK) { // Expected when the stream is paused. - LOG("aaudio_stream_get_input_latency, AAudioStream_getTimestamp: %s, returning memoized value", WRAP(AAudio_convertResultToText)(res)); + LOG("aaudio_stream_get_input_latency, AAudioStream_getTimestamp: %s, " + "returning memoized value", + WRAP(AAudio_convertResultToText)(res)); *latency = stm->latest_input_latency; return CUBEB_OK; } @@ -1310,27 +1339,35 @@ aaudio_stream_set_volume(cubeb_stream * stm, float volume) return CUBEB_OK; } -aaudio_data_callback_result_t dummy_callback(AAudioStream *stream, void *userData, void *audioData, int32_t numFrames) { +aaudio_data_callback_result_t +dummy_callback(AAudioStream * stream, void * userData, void * audioData, + int32_t numFrames) +{ return AAUDIO_CALLBACK_RESULT_STOP; } // Returns a dummy stream with all default settings -static AAudioStream* -init_dummy_stream() { - AAudioStreamBuilder *streamBuilder; +static AAudioStream * +init_dummy_stream() +{ + AAudioStreamBuilder * streamBuilder; aaudio_result_t res; res = WRAP(AAudio_createStreamBuilder)(&streamBuilder); if (res != AAUDIO_OK) { - LOG("init_dummy_stream: AAudio_createStreamBuilder: %s", WRAP(AAudio_convertResultToText)(res)); + LOG("init_dummy_stream: AAudio_createStreamBuilder: %s", + WRAP(AAudio_convertResultToText)(res)); return nullptr; } - WRAP(AAudioStreamBuilder_setDataCallback)(streamBuilder, dummy_callback, nullptr); - WRAP(AAudioStreamBuilder_setPerformanceMode)(streamBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); + WRAP(AAudioStreamBuilder_setDataCallback) + (streamBuilder, dummy_callback, nullptr); + WRAP(AAudioStreamBuilder_setPerformanceMode) + (streamBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); - AAudioStream *stream; + AAudioStream * stream; res = WRAP(AAudioStreamBuilder_openStream)(streamBuilder, &stream); if (res != AAUDIO_OK) { - LOG("init_dummy_stream: AAudioStreamBuilder_openStream %s", WRAP(AAudio_convertResultToText)(res)); + LOG("init_dummy_stream: AAudioStreamBuilder_openStream %s", + WRAP(AAudio_convertResultToText)(res)); return nullptr; } WRAP(AAudioStreamBuilder_delete)(streamBuilder); @@ -1339,14 +1376,16 @@ init_dummy_stream() { } static void -destroy_dummy_stream(AAudioStream* stream) { +destroy_dummy_stream(AAudioStream * stream) +{ WRAP(AAudioStream_close)(stream); } static int -aaudio_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_frames) +aaudio_get_min_latency(cubeb * ctx, cubeb_stream_params params, + uint32_t * latency_frames) { - AAudioStream* stream = init_dummy_stream(); + AAudioStream * stream = init_dummy_stream(); if (!stream) { return CUBEB_ERROR; @@ -1365,7 +1404,7 @@ aaudio_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten int aaudio_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) { - AAudioStream* stream = init_dummy_stream(); + AAudioStream * stream = init_dummy_stream(); if (!stream) { return CUBEB_ERROR; @@ -1380,36 +1419,36 @@ aaudio_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) return CUBEB_OK; } -extern "C" int aaudio_init(cubeb ** context, char const * context_name); +extern "C" int +aaudio_init(cubeb ** context, char const * context_name); const static struct cubeb_ops aaudio_ops = { - /*.init =*/ aaudio_init, - /*.get_backend_id =*/ aaudio_get_backend_id, - /*.get_max_channel_count =*/ aaudio_get_max_channel_count, - /* .get_min_latency =*/ aaudio_get_min_latency, - /*.get_preferred_sample_rate =*/ aaudio_get_preferred_sample_rate, - /*.enumerate_devices =*/ NULL, - /*.device_collection_destroy =*/ NULL, - /*.destroy =*/ aaudio_destroy, - /*.stream_init =*/ aaudio_stream_init, - /*.stream_destroy =*/ aaudio_stream_destroy, - /*.stream_start =*/ aaudio_stream_start, - /*.stream_stop =*/ aaudio_stream_stop, - /*.stream_reset_default_device =*/ NULL, - /*.stream_get_position =*/ aaudio_stream_get_position, - /*.stream_get_latency =*/ aaudio_stream_get_latency, - /*.stream_get_input_latency =*/ aaudio_stream_get_input_latency, - /*.stream_set_volume =*/ aaudio_stream_set_volume, - /*.stream_set_name =*/ NULL, - /*.stream_get_current_device =*/ NULL, - /*.stream_device_destroy =*/ NULL, - /*.stream_register_device_changed_callback =*/ NULL, - /*.register_device_collection_changed =*/ NULL -}; - + /*.init =*/aaudio_init, + /*.get_backend_id =*/aaudio_get_backend_id, + /*.get_max_channel_count =*/aaudio_get_max_channel_count, + /* .get_min_latency =*/aaudio_get_min_latency, + /*.get_preferred_sample_rate =*/aaudio_get_preferred_sample_rate, + /*.enumerate_devices =*/NULL, + /*.device_collection_destroy =*/NULL, + /*.destroy =*/aaudio_destroy, + /*.stream_init =*/aaudio_stream_init, + /*.stream_destroy =*/aaudio_stream_destroy, + /*.stream_start =*/aaudio_stream_start, + /*.stream_stop =*/aaudio_stream_stop, + /*.stream_reset_default_device =*/NULL, + /*.stream_get_position =*/aaudio_stream_get_position, + /*.stream_get_latency =*/aaudio_stream_get_latency, + /*.stream_get_input_latency =*/aaudio_stream_get_input_latency, + /*.stream_set_volume =*/aaudio_stream_set_volume, + /*.stream_set_name =*/NULL, + /*.stream_get_current_device =*/NULL, + /*.stream_device_destroy =*/NULL, + /*.stream_register_device_changed_callback =*/NULL, + /*.register_device_collection_changed =*/NULL}; extern "C" /*static*/ int -aaudio_init(cubeb ** context, char const * /* context_name */) { +aaudio_init(cubeb ** context, char const * /* context_name */) +{ // load api void * libaaudio = NULL; #ifndef DISABLE_LIBAAUDIO_DLOPEN @@ -1418,13 +1457,14 @@ aaudio_init(cubeb ** context, char const * /* context_name */) { return CUBEB_ERROR; } -#define LOAD(x) { \ - WRAP(x) = (decltype(WRAP(x))) (dlsym(libaaudio, #x)); \ - if (!WRAP(x)) { \ - LOG("AAudio: Failed to load %s", #x); \ - dlclose(libaaudio); \ - return CUBEB_ERROR; \ - } \ +#define LOAD(x) \ + { \ + WRAP(x) = (decltype(WRAP(x)))(dlsym(libaaudio, #x)); \ + if (!WRAP(x)) { \ + LOG("AAudio: Failed to load %s", #x); \ + dlclose(libaaudio); \ + return CUBEB_ERROR; \ + } \ } LIBAAUDIO_API_VISIT(LOAD); |