Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include <assert.h> |
| 18 | #include <stdint.h> |
Mikhail Naganov | d35c572 | 2018-02-05 17:26:45 -0800 | [diff] [blame] | 19 | #include <stdlib.h> |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 20 | |
| 21 | #include "aaudio/AAudioLoader.h" |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 22 | #include "aaudio/AudioStreamAAudio.h" |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 23 | #include "common/OboeDebug.h" |
| 24 | #include "oboe/Utilities.h" |
| 25 | |
Mikhail Naganov | d35c572 | 2018-02-05 17:26:45 -0800 | [diff] [blame] | 26 | #ifdef __ANDROID__ |
| 27 | #include <sys/system_properties.h> |
| 28 | #endif |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 29 | |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 30 | using namespace oboe; |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 31 | AAudioLoader *AudioStreamAAudio::mLibLoader = nullptr; |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 32 | |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 33 | // 'C' wrapper for the data callback method |
| 34 | static aaudio_data_callback_result_t oboe_aaudio_data_callback_proc( |
| 35 | AAudioStream *stream, |
| 36 | void *userData, |
| 37 | void *audioData, |
| 38 | int32_t numFrames) { |
| 39 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 40 | AudioStreamAAudio *oboeStream = (AudioStreamAAudio *)userData; |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 41 | if (oboeStream != NULL) { |
| 42 | return static_cast<aaudio_data_callback_result_t>( |
| 43 | oboeStream->callOnAudioReady(stream, audioData, numFrames)); |
| 44 | } else { |
| 45 | return static_cast<aaudio_data_callback_result_t>(DataCallbackResult::Stop); |
| 46 | } |
| 47 | } |
| 48 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 49 | static void oboe_aaudio_error_thread_proc(AudioStreamAAudio *oboeStream, |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 50 | AAudioStream *stream, |
| 51 | Result error) { |
| 52 | if (oboeStream != NULL) { |
| 53 | oboeStream->onErrorInThread(stream, error); |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | // 'C' wrapper for the error callback method |
| 58 | static void oboe_aaudio_error_callback_proc( |
| 59 | AAudioStream *stream, |
| 60 | void *userData, |
| 61 | aaudio_result_t error) { |
| 62 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 63 | AudioStreamAAudio *oboeStream = (AudioStreamAAudio *)userData; |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 64 | if (oboeStream != NULL) { |
| 65 | // Handle error on a separate thread |
| 66 | std::thread t(oboe_aaudio_error_thread_proc, oboeStream, stream, static_cast<Result>(error)); |
| 67 | t.detach(); |
| 68 | } |
| 69 | } |
| 70 | |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 71 | namespace oboe { |
| 72 | |
| 73 | /* |
| 74 | * Create a stream that uses Oboe Audio API. |
| 75 | */ |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 76 | AudioStreamAAudio::AudioStreamAAudio(const AudioStreamBuilder &builder) |
| 77 | : AudioStream(builder) |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 78 | , mFloatCallbackBuffer(nullptr) |
| 79 | , mShortCallbackBuffer(nullptr) |
Phil Burk | f9fc01d | 2018-02-09 14:53:22 -0800 | [diff] [blame] | 80 | , mAAudioStream(nullptr) { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 81 | mCallbackThreadEnabled.store(false); |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 82 | LOGD("AudioStreamAAudio() call isSupported()"); |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 83 | isSupported(); |
| 84 | } |
| 85 | |
Phil Burk | f3c46fb | 2018-02-14 17:40:17 -0800 | [diff] [blame] | 86 | AudioStreamAAudio::~AudioStreamAAudio() { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 87 | delete[] mFloatCallbackBuffer; |
| 88 | delete[] mShortCallbackBuffer; |
| 89 | } |
| 90 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 91 | bool AudioStreamAAudio::isSupported() { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 92 | mLibLoader = AAudioLoader::getInstance(); |
| 93 | int openResult = mLibLoader->open(); |
| 94 | return openResult == 0; |
| 95 | } |
| 96 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 97 | Result AudioStreamAAudio::open() { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 98 | Result result = Result::OK; |
| 99 | |
| 100 | if (mAAudioStream != nullptr) { |
| 101 | return Result::ErrorInvalidState; |
| 102 | } |
| 103 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 104 | result = AudioStream::open(); |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 105 | if (result != Result::OK) { |
| 106 | return result; |
| 107 | } |
| 108 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 109 | LOGD("AudioStreamAAudio(): AAudio_createStreamBuilder()"); |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 110 | AAudioStreamBuilder *aaudioBuilder; |
| 111 | result = static_cast<Result>(mLibLoader->createStreamBuilder(&aaudioBuilder)); |
| 112 | if (result != Result::OK) { |
| 113 | return result; |
| 114 | } |
| 115 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 116 | LOGD("AudioStreamAAudio.open() try with deviceId = %d", (int) mDeviceId); |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 117 | mLibLoader->builder_setBufferCapacityInFrames(aaudioBuilder, mBufferCapacityInFrames); |
| 118 | mLibLoader->builder_setChannelCount(aaudioBuilder, mChannelCount); |
| 119 | mLibLoader->builder_setDeviceId(aaudioBuilder, mDeviceId); |
| 120 | mLibLoader->builder_setDirection(aaudioBuilder, static_cast<aaudio_direction_t>(mDirection)); |
| 121 | mLibLoader->builder_setFormat(aaudioBuilder, static_cast<aaudio_format_t>(mFormat)); |
| 122 | mLibLoader->builder_setSampleRate(aaudioBuilder, mSampleRate); |
| 123 | mLibLoader->builder_setSharingMode(aaudioBuilder, |
| 124 | static_cast<aaudio_sharing_mode_t>(mSharingMode)); |
| 125 | mLibLoader->builder_setPerformanceMode(aaudioBuilder, |
| 126 | static_cast<aaudio_performance_mode_t>(mPerformanceMode)); |
| 127 | |
| 128 | // TODO get more parameters from the builder? |
| 129 | |
| 130 | if (mStreamCallback != nullptr) { |
| 131 | mLibLoader->builder_setDataCallback(aaudioBuilder, oboe_aaudio_data_callback_proc, this); |
| 132 | mLibLoader->builder_setFramesPerDataCallback(aaudioBuilder, getFramesPerCallback()); |
| 133 | } |
| 134 | mLibLoader->builder_setErrorCallback(aaudioBuilder, oboe_aaudio_error_callback_proc, this); |
| 135 | |
| 136 | { |
| 137 | AAudioStream *stream = nullptr; |
| 138 | result = static_cast<Result>(mLibLoader->builder_openStream(aaudioBuilder, &stream)); |
| 139 | mAAudioStream.store(stream); |
| 140 | } |
| 141 | if (result != Result::OK) { |
| 142 | goto error2; |
| 143 | } |
| 144 | |
| 145 | // Query and cache the values that will not change. |
| 146 | mDeviceId = mLibLoader->stream_getDeviceId(mAAudioStream); |
| 147 | mChannelCount = mLibLoader->stream_getChannelCount(mAAudioStream); |
| 148 | mSampleRate = mLibLoader->stream_getSampleRate(mAAudioStream); |
| 149 | mNativeFormat = static_cast<AudioFormat>(mLibLoader->stream_getFormat(mAAudioStream)); |
| 150 | if (mFormat == AudioFormat::Unspecified) { |
| 151 | mFormat = mNativeFormat; |
| 152 | } |
| 153 | mSharingMode = static_cast<SharingMode>(mLibLoader->stream_getSharingMode(mAAudioStream)); |
| 154 | mPerformanceMode = static_cast<PerformanceMode>( |
| 155 | mLibLoader->stream_getPerformanceMode(mAAudioStream)); |
| 156 | mBufferCapacityInFrames = mLibLoader->stream_getBufferCapacity(mAAudioStream); |
| 157 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 158 | LOGD("AudioStreamAAudio.open() app format = %d", (int) mFormat); |
| 159 | LOGD("AudioStreamAAudio.open() native format = %d", (int) mNativeFormat); |
| 160 | LOGD("AudioStreamAAudio.open() sample rate = %d", (int) mSampleRate); |
| 161 | LOGD("AudioStreamAAudio.open() capacity = %d", (int) mBufferCapacityInFrames); |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 162 | |
| 163 | error2: |
| 164 | mLibLoader->builder_delete(aaudioBuilder); |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 165 | LOGD("AudioStreamAAudio.open: AAudioStream_Open() returned %s, mAAudioStream = %p", |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 166 | mLibLoader->convertResultToText(static_cast<aaudio_result_t>(result)), |
| 167 | mAAudioStream.load()); |
| 168 | return result; |
| 169 | } |
| 170 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 171 | Result AudioStreamAAudio::close() |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 172 | { |
| 173 | // The main reason we have this mutex if to prevent a collision between a call |
| 174 | // by the application to stop a stream at the same time that an onError callback |
| 175 | // is being executed because of a disconnect. The close will delete the stream, |
| 176 | // which could otherwise cause the requestStop() to crash. |
| 177 | std::lock_guard<std::mutex> lock(mLock); |
| 178 | Result result = Result::OK; |
| 179 | // This will delete the AAudio stream object so we need to null out the pointer. |
| 180 | AAudioStream *stream = mAAudioStream.exchange(nullptr); |
| 181 | if (stream != nullptr) { |
| 182 | result = static_cast<Result>(mLibLoader->stream_close(stream)); |
| 183 | } |
| 184 | return result; |
| 185 | } |
| 186 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 187 | DataCallbackResult AudioStreamAAudio::callOnAudioReady(AAudioStream *stream, |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 188 | void *audioData, |
| 189 | int32_t numFrames) { |
| 190 | return mStreamCallback->onAudioReady( |
| 191 | this, |
| 192 | audioData, |
| 193 | numFrames); |
| 194 | } |
| 195 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 196 | void AudioStreamAAudio::onErrorInThread(AAudioStream *stream, Result error) { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 197 | LOGD("onErrorInThread() - entering ==================================="); |
| 198 | assert(stream == mAAudioStream.load()); |
| 199 | requestStop(); |
| 200 | if (mStreamCallback != nullptr) { |
| 201 | mStreamCallback->onErrorBeforeClose(this, error); |
| 202 | } |
| 203 | close(); |
| 204 | if (mStreamCallback != nullptr) { |
| 205 | mStreamCallback->onErrorAfterClose(this, error); |
| 206 | } |
| 207 | LOGD("onErrorInThread() - exiting ==================================="); |
| 208 | } |
| 209 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 210 | Result AudioStreamAAudio::convertApplicationDataToNative(int32_t numFrames) { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 211 | Result result = Result::ErrorUnimplemented; |
| 212 | int32_t numSamples = numFrames * getChannelCount(); |
| 213 | if (mFormat == AudioFormat::Float) { |
| 214 | if (mNativeFormat == AudioFormat::I16) { |
| 215 | convertFloatToPcm16(mFloatCallbackBuffer, mShortCallbackBuffer, numSamples); |
| 216 | result = Result::OK; |
| 217 | } |
| 218 | } else if (mFormat == AudioFormat::I16) { |
| 219 | if (mNativeFormat == AudioFormat::Float) { |
| 220 | convertPcm16ToFloat(mShortCallbackBuffer, mFloatCallbackBuffer, numSamples); |
| 221 | result = Result::OK; |
| 222 | } |
| 223 | } |
| 224 | return result; |
| 225 | } |
| 226 | |
Phil Burk | f9fc01d | 2018-02-09 14:53:22 -0800 | [diff] [blame] | 227 | Result AudioStreamAAudio::requestStart() { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 228 | std::lock_guard<std::mutex> lock(mLock); |
| 229 | AAudioStream *stream = mAAudioStream.load(); |
| 230 | if (stream != nullptr) { |
| 231 | return static_cast<Result>(mLibLoader->stream_requestStart(stream)); |
| 232 | } else { |
| 233 | return Result::ErrorNull; |
| 234 | } |
| 235 | } |
| 236 | |
Phil Burk | f9fc01d | 2018-02-09 14:53:22 -0800 | [diff] [blame] | 237 | Result AudioStreamAAudio::requestPause() { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 238 | std::lock_guard<std::mutex> lock(mLock); |
| 239 | AAudioStream *stream = mAAudioStream.load(); |
| 240 | if (stream != nullptr) { |
| 241 | return static_cast<Result>(mLibLoader->stream_requestPause(stream)); |
| 242 | } else { |
| 243 | return Result::ErrorNull; |
| 244 | } |
| 245 | } |
| 246 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 247 | Result AudioStreamAAudio::requestFlush() { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 248 | std::lock_guard<std::mutex> lock(mLock); |
| 249 | AAudioStream *stream = mAAudioStream.load(); |
| 250 | if (stream != nullptr) { |
| 251 | return static_cast<Result>(mLibLoader->stream_requestFlush(stream)); |
| 252 | } else { |
| 253 | return Result::ErrorNull; |
| 254 | } |
| 255 | } |
| 256 | |
Phil Burk | f9fc01d | 2018-02-09 14:53:22 -0800 | [diff] [blame] | 257 | Result AudioStreamAAudio::requestStop() { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 258 | std::lock_guard<std::mutex> lock(mLock); |
| 259 | AAudioStream *stream = mAAudioStream.load(); |
| 260 | if (stream != nullptr) { |
| 261 | return static_cast<Result>(mLibLoader->stream_requestStop(stream)); |
| 262 | } else { |
| 263 | return Result::ErrorNull; |
| 264 | } |
| 265 | } |
| 266 | |
Phil Burk | 4cf25f1 | 2018-02-14 08:05:01 -0800 | [diff] [blame] | 267 | ErrorOrValue<int32_t> AudioStreamAAudio::write(const void *buffer, |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 268 | int32_t numFrames, |
Phil Burk | f9fc01d | 2018-02-09 14:53:22 -0800 | [diff] [blame] | 269 | int64_t timeoutNanoseconds) { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 270 | AAudioStream *stream = mAAudioStream.load(); |
| 271 | if (stream != nullptr) { |
Phil Burk | 4cf25f1 | 2018-02-14 08:05:01 -0800 | [diff] [blame] | 272 | int32_t result = mLibLoader->stream_write(mAAudioStream, buffer, |
| 273 | numFrames, timeoutNanoseconds); |
Phil Burk | 7c19352 | 2018-02-15 08:07:52 -0800 | [diff] [blame^] | 274 | if (result < 0) { |
| 275 | return ErrorOrValue<int32_t>(static_cast<Result>(result)); |
| 276 | } else { |
| 277 | return ErrorOrValue<int32_t>(result); |
| 278 | } |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 279 | } else { |
Phil Burk | 4cf25f1 | 2018-02-14 08:05:01 -0800 | [diff] [blame] | 280 | return ErrorOrValue<int32_t>(Result::ErrorNull); |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 281 | } |
| 282 | } |
| 283 | |
Phil Burk | 4cf25f1 | 2018-02-14 08:05:01 -0800 | [diff] [blame] | 284 | ErrorOrValue<int32_t> AudioStreamAAudio::read(void *buffer, |
Phil Burk | 34217a7 | 2018-02-07 20:37:17 -0800 | [diff] [blame] | 285 | int32_t numFrames, |
Phil Burk | f9fc01d | 2018-02-09 14:53:22 -0800 | [diff] [blame] | 286 | int64_t timeoutNanoseconds) { |
Phil Burk | 34217a7 | 2018-02-07 20:37:17 -0800 | [diff] [blame] | 287 | AAudioStream *stream = mAAudioStream.load(); |
| 288 | if (stream != nullptr) { |
Phil Burk | 4cf25f1 | 2018-02-14 08:05:01 -0800 | [diff] [blame] | 289 | int32_t result = mLibLoader->stream_read(mAAudioStream, buffer, |
| 290 | numFrames, timeoutNanoseconds); |
Phil Burk | 7c19352 | 2018-02-15 08:07:52 -0800 | [diff] [blame^] | 291 | if (result < 0) { |
| 292 | return ErrorOrValue<int32_t>(static_cast<Result>(result)); |
| 293 | } else { |
| 294 | return ErrorOrValue<int32_t>(result); |
| 295 | } |
Phil Burk | 34217a7 | 2018-02-07 20:37:17 -0800 | [diff] [blame] | 296 | } else { |
Phil Burk | 4cf25f1 | 2018-02-14 08:05:01 -0800 | [diff] [blame] | 297 | return ErrorOrValue<int32_t>(Result::ErrorNull); |
Phil Burk | 34217a7 | 2018-02-07 20:37:17 -0800 | [diff] [blame] | 298 | } |
| 299 | } |
| 300 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 301 | Result AudioStreamAAudio::waitForStateChange(StreamState currentState, |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 302 | StreamState *nextState, |
Phil Burk | f9fc01d | 2018-02-09 14:53:22 -0800 | [diff] [blame] | 303 | int64_t timeoutNanoseconds) { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 304 | AAudioStream *stream = mAAudioStream.load(); |
| 305 | if (stream != nullptr) { |
| 306 | |
| 307 | aaudio_stream_state_t aaudioNextState; |
| 308 | aaudio_result_t result = mLibLoader->stream_waitForStateChange( |
| 309 | mAAudioStream, |
| 310 | static_cast<aaudio_stream_state_t>(currentState), |
| 311 | &aaudioNextState, |
| 312 | timeoutNanoseconds); |
| 313 | *nextState = static_cast<StreamState>(aaudioNextState); |
| 314 | return static_cast<Result>(result); |
| 315 | } else { |
| 316 | return Result::ErrorNull; |
| 317 | } |
| 318 | } |
| 319 | |
Phil Burk | f9fc01d | 2018-02-09 14:53:22 -0800 | [diff] [blame] | 320 | Result AudioStreamAAudio::setBufferSizeInFrames(int32_t requestedFrames) { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 321 | if (requestedFrames > mBufferCapacityInFrames) { |
| 322 | requestedFrames = mBufferCapacityInFrames; |
| 323 | } |
| 324 | return static_cast<Result>(mLibLoader->stream_setBufferSize(mAAudioStream, requestedFrames)); |
| 325 | } |
| 326 | |
Phil Burk | f9fc01d | 2018-02-09 14:53:22 -0800 | [diff] [blame] | 327 | StreamState AudioStreamAAudio::getState() { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 328 | AAudioStream *stream = mAAudioStream.load(); |
| 329 | if (stream != nullptr) { |
| 330 | return static_cast<StreamState>(mLibLoader->stream_getState(stream)); |
| 331 | } else { |
| 332 | return StreamState::Closed; |
| 333 | } |
| 334 | } |
| 335 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 336 | int32_t AudioStreamAAudio::getBufferSizeInFrames() const { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 337 | AAudioStream *stream = mAAudioStream.load(); |
| 338 | if (stream != nullptr) { |
| 339 | return mLibLoader->stream_getBufferSize(stream); |
| 340 | } else { |
| 341 | return static_cast<int32_t>(Result::ErrorNull); |
| 342 | } |
| 343 | } |
| 344 | |
Phil Burk | f9fc01d | 2018-02-09 14:53:22 -0800 | [diff] [blame] | 345 | int32_t AudioStreamAAudio::getFramesPerBurst() { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 346 | AAudioStream *stream = mAAudioStream.load(); |
| 347 | if (stream != nullptr) { |
| 348 | return mLibLoader->stream_getFramesPerBurst(stream); |
| 349 | } else { |
| 350 | return static_cast<int32_t>(Result::ErrorNull); |
| 351 | } |
| 352 | } |
| 353 | |
Phil Burk | 34217a7 | 2018-02-07 20:37:17 -0800 | [diff] [blame] | 354 | int64_t AudioStreamAAudio::getFramesRead() const { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 355 | AAudioStream *stream = mAAudioStream.load(); |
| 356 | if (stream != nullptr) { |
| 357 | return mLibLoader->stream_getFramesRead(stream); |
| 358 | } else { |
| 359 | return static_cast<int32_t>(Result::ErrorNull); |
| 360 | } |
| 361 | } |
Phil Burk | 34217a7 | 2018-02-07 20:37:17 -0800 | [diff] [blame] | 362 | |
| 363 | int64_t AudioStreamAAudio::getFramesWritten() const { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 364 | AAudioStream *stream = mAAudioStream.load(); |
| 365 | if (stream != nullptr) { |
| 366 | return mLibLoader->stream_getFramesWritten(stream); |
| 367 | } else { |
| 368 | return static_cast<int64_t>(Result::ErrorNull); |
| 369 | } |
| 370 | } |
| 371 | |
Phil Burk | a5d6637 | 2018-02-09 14:38:23 -0800 | [diff] [blame] | 372 | int32_t AudioStreamAAudio::getXRunCount() const { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 373 | AAudioStream *stream = mAAudioStream.load(); |
| 374 | if (stream != nullptr) { |
| 375 | return mLibLoader->stream_getXRunCount(stream); |
| 376 | } else { |
| 377 | return static_cast<int32_t>(Result::ErrorNull); |
| 378 | } |
| 379 | } |
| 380 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 381 | Result AudioStreamAAudio::getTimestamp(clockid_t clockId, |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 382 | int64_t *framePosition, |
| 383 | int64_t *timeNanoseconds) { |
| 384 | AAudioStream *stream = mAAudioStream.load(); |
| 385 | if (stream != nullptr) { |
| 386 | return static_cast<Result>(mLibLoader->stream_getTimestamp(stream, clockId, |
| 387 | framePosition, timeNanoseconds)); |
| 388 | } else { |
| 389 | return Result::ErrorNull; |
| 390 | } |
| 391 | } |
| 392 | |
Mikhail Naganov | d35c572 | 2018-02-05 17:26:45 -0800 | [diff] [blame] | 393 | } // namespace oboe |