AudioStream.h revision 5fbc2ddb4e340d7af02d146ff2e7c3c4da28d535
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#ifndef AAUDIO_AUDIOSTREAM_H 18#define AAUDIO_AUDIOSTREAM_H 19 20#include <atomic> 21#include <mutex> 22#include <stdint.h> 23#include <aaudio/AAudio.h> 24 25#include "utility/AAudioUtilities.h" 26#include "utility/MonotonicCounter.h" 27 28namespace aaudio { 29 30typedef void *(*aaudio_audio_thread_proc_t)(void *); 31 32class AudioStreamBuilder; 33 34/** 35 * AAudio audio stream. 36 */ 37class AudioStream { 38public: 39 40 AudioStream(); 41 42 virtual ~AudioStream(); 43 44 45 // =========== Begin ABSTRACT methods =========================== 46 47 /* Asynchronous requests. 48 * Use waitForStateChange() to wait for completion. 49 */ 50 virtual aaudio_result_t requestStart() = 0; 51 virtual aaudio_result_t requestPause() = 0; 52 virtual aaudio_result_t requestFlush() = 0; 53 virtual aaudio_result_t requestStop() = 0; 54 55 virtual aaudio_result_t getTimestamp(clockid_t clockId, 56 int64_t *framePosition, 57 int64_t *timeNanoseconds) = 0; 58 59 60 /** 61 * Update state while in the middle of waitForStateChange() 62 * @return 63 */ 64 virtual aaudio_result_t updateStateWhileWaiting() = 0; 65 66 67 // =========== End ABSTRACT methods =========================== 68 69 virtual aaudio_result_t waitForStateChange(aaudio_stream_state_t currentState, 70 aaudio_stream_state_t *nextState, 71 int64_t timeoutNanoseconds); 72 73 /** 74 * Open the stream using the parameters in the builder. 75 * Allocate the necessary resources. 76 */ 77 virtual aaudio_result_t open(const AudioStreamBuilder& builder); 78 79 /** 80 * Close the stream and deallocate any resources from the open() call. 81 * It is safe to call close() multiple times. 82 */ 83 virtual aaudio_result_t close() { 84 return AAUDIO_OK; 85 } 86 87 virtual aaudio_result_t setBufferSize(int32_t requestedFrames) { 88 return AAUDIO_ERROR_UNIMPLEMENTED; 89 } 90 91 virtual aaudio_result_t createThread(int64_t periodNanoseconds, 92 aaudio_audio_thread_proc_t threadProc, 93 void *threadArg); 94 95 virtual aaudio_result_t joinThread(void **returnArg, int64_t timeoutNanoseconds); 96 97 virtual aaudio_result_t registerThread() { 98 return AAUDIO_OK; 99 } 100 101 virtual aaudio_result_t unregisterThread() { 102 return AAUDIO_OK; 103 } 104 105 /** 106 * Internal function used to call the audio thread passed by the user. 107 * It is unfortunately public because it needs to be called by a static 'C' function. 108 */ 109 void* wrapUserThread(); 110 111 // ============== Queries =========================== 112 113 aaudio_stream_state_t getState() const { 114 return mState; 115 } 116 117 virtual int32_t getBufferSize() const { 118 return AAUDIO_ERROR_UNIMPLEMENTED; 119 } 120 121 virtual int32_t getBufferCapacity() const { 122 return AAUDIO_ERROR_UNIMPLEMENTED; 123 } 124 125 virtual int32_t getFramesPerBurst() const { 126 return AAUDIO_ERROR_UNIMPLEMENTED; 127 } 128 129 virtual int32_t getXRunCount() const { 130 return AAUDIO_ERROR_UNIMPLEMENTED; 131 } 132 133 bool isPlaying() const { 134 return mState == AAUDIO_STREAM_STATE_STARTING || mState == AAUDIO_STREAM_STATE_STARTED; 135 } 136 137 aaudio_result_t getSampleRate() const { 138 return mSampleRate; 139 } 140 141 aaudio_audio_format_t getFormat() const { 142 return mFormat; 143 } 144 145 aaudio_result_t getSamplesPerFrame() const { 146 return mSamplesPerFrame; 147 } 148 149 int32_t getDeviceId() const { 150 return mDeviceId; 151 } 152 153 aaudio_sharing_mode_t getSharingMode() const { 154 return mSharingMode; 155 } 156 157 aaudio_direction_t getDirection() const { 158 return mDirection; 159 } 160 161 /** 162 * This is only valid after setSamplesPerFrame() and setFormat() have been called. 163 */ 164 int32_t getBytesPerFrame() const { 165 return mSamplesPerFrame * getBytesPerSample(); 166 } 167 168 /** 169 * This is only valid after setFormat() has been called. 170 */ 171 int32_t getBytesPerSample() const { 172 return AAudioConvert_formatToSizeInBytes(mFormat); 173 } 174 175 virtual int64_t getFramesWritten() { 176 return mFramesWritten.get(); 177 } 178 179 virtual int64_t getFramesRead() { 180 return mFramesRead.get(); 181 } 182 183 AAudioStream_dataCallback getDataCallbackProc() const { 184 return mDataCallbackProc; 185 } 186 AAudioStream_errorCallback getErrorCallbackProc() const { 187 return mErrorCallbackProc; 188 } 189 190 void *getDataCallbackUserData() const { 191 return mDataCallbackUserData; 192 } 193 void *getErrorCallbackUserData() const { 194 return mErrorCallbackUserData; 195 } 196 197 int32_t getFramesPerDataCallback() const { 198 return mFramesPerDataCallback; 199 } 200 201 bool isDataCallbackActive() { 202 return (mDataCallbackProc != nullptr) && isPlaying(); 203 } 204 205 // ============== I/O =========================== 206 // A Stream will only implement read() or write() depending on its direction. 207 virtual aaudio_result_t write(const void *buffer, 208 int32_t numFrames, 209 int64_t timeoutNanoseconds) { 210 return AAUDIO_ERROR_UNIMPLEMENTED; 211 } 212 213 virtual aaudio_result_t read(void *buffer, 214 int32_t numFrames, 215 int64_t timeoutNanoseconds) { 216 return AAUDIO_ERROR_UNIMPLEMENTED; 217 } 218 219protected: 220 221 virtual int64_t incrementFramesWritten(int32_t frames) { 222 return static_cast<int64_t>(mFramesWritten.increment(frames)); 223 } 224 225 virtual int64_t incrementFramesRead(int32_t frames) { 226 return static_cast<int64_t>(mFramesRead.increment(frames)); 227 } 228 229 /** 230 * Wait for a transition from one state to another. 231 * @return AAUDIO_OK if the endingState was observed, or AAUDIO_ERROR_UNEXPECTED_STATE 232 * if any state that was not the startingState or endingState was observed 233 * or AAUDIO_ERROR_TIMEOUT 234 */ 235 virtual aaudio_result_t waitForStateTransition(aaudio_stream_state_t startingState, 236 aaudio_stream_state_t endingState, 237 int64_t timeoutNanoseconds); 238 239 /** 240 * This should not be called after the open() call. 241 */ 242 void setSampleRate(int32_t sampleRate) { 243 mSampleRate = sampleRate; 244 } 245 246 /** 247 * This should not be called after the open() call. 248 */ 249 void setSamplesPerFrame(int32_t samplesPerFrame) { 250 mSamplesPerFrame = samplesPerFrame; 251 } 252 253 /** 254 * This should not be called after the open() call. 255 */ 256 void setSharingMode(aaudio_sharing_mode_t sharingMode) { 257 mSharingMode = sharingMode; 258 } 259 260 /** 261 * This should not be called after the open() call. 262 */ 263 void setFormat(aaudio_audio_format_t format) { 264 mFormat = format; 265 } 266 267 void setState(aaudio_stream_state_t state) { 268 mState = state; 269 } 270 271 void setDeviceId(int32_t deviceId) { 272 mDeviceId = deviceId; 273 } 274 275 std::mutex mStreamMutex; 276 277 std::atomic<bool> mCallbackEnabled; 278 279protected: 280 MonotonicCounter mFramesWritten; 281 MonotonicCounter mFramesRead; 282 283 void setPeriodNanoseconds(int64_t periodNanoseconds) { 284 mPeriodNanoseconds.store(periodNanoseconds, std::memory_order_release); 285 } 286 287 int64_t getPeriodNanoseconds() { 288 return mPeriodNanoseconds.load(std::memory_order_acquire); 289 } 290 291private: 292 // These do not change after open(). 293 int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED; 294 int32_t mSampleRate = AAUDIO_UNSPECIFIED; 295 int32_t mDeviceId = AAUDIO_UNSPECIFIED; 296 aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED; 297 aaudio_audio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED; 298 aaudio_direction_t mDirection = AAUDIO_DIRECTION_OUTPUT; 299 aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED; 300 301 // callback ---------------------------------- 302 303 AAudioStream_dataCallback mDataCallbackProc = nullptr; // external callback functions 304 void *mDataCallbackUserData = nullptr; 305 int32_t mFramesPerDataCallback = AAUDIO_UNSPECIFIED; // frames 306 307 AAudioStream_errorCallback mErrorCallbackProc = nullptr; 308 void *mErrorCallbackUserData = nullptr; 309 310 // background thread ---------------------------------- 311 bool mHasThread = false; 312 pthread_t mThread; // initialized in constructor 313 314 // These are set by the application thread and then read by the audio pthread. 315 std::atomic<int64_t> mPeriodNanoseconds; // for tuning SCHED_FIFO threads 316 // TODO make atomic? 317 aaudio_audio_thread_proc_t mThreadProc = nullptr; 318 void* mThreadArg = nullptr; 319 aaudio_result_t mThreadRegistrationResult = AAUDIO_OK; 320 321 322}; 323 324} /* namespace aaudio */ 325 326#endif /* AAUDIO_AUDIOSTREAM_H */ 327