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