AudioStream.h revision 3316d5e6d375a4f09c681205e9094d30a0bfc4a2
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 <stdint.h> 22#include <aaudio/AAudioDefinitions.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 // TODO use aaudio_clockid_t all the way down to AudioClock 54 virtual aaudio_result_t getTimestamp(clockid_t clockId, 55 int64_t *framePosition, 56 int64_t *timeNanoseconds) = 0; 57 58 59 virtual aaudio_result_t updateState() = 0; 60 61 62 // =========== End ABSTRACT methods =========================== 63 64 virtual aaudio_result_t waitForStateChange(aaudio_stream_state_t currentState, 65 aaudio_stream_state_t *nextState, 66 int64_t timeoutNanoseconds); 67 68 /** 69 * Open the stream using the parameters in the builder. 70 * Allocate the necessary resources. 71 */ 72 virtual aaudio_result_t open(const AudioStreamBuilder& builder); 73 74 /** 75 * Close the stream and deallocate any resources from the open() call. 76 * It is safe to call close() multiple times. 77 */ 78 virtual aaudio_result_t close() { 79 return AAUDIO_OK; 80 } 81 82 virtual aaudio_result_t setBufferSize(int32_t requestedFrames) { 83 return AAUDIO_ERROR_UNIMPLEMENTED; 84 } 85 86 virtual aaudio_result_t createThread(int64_t periodNanoseconds, 87 aaudio_audio_thread_proc_t *threadProc, 88 void *threadArg); 89 90 virtual aaudio_result_t joinThread(void **returnArg, int64_t timeoutNanoseconds); 91 92 virtual aaudio_result_t registerThread() { 93 return AAUDIO_OK; 94 } 95 96 virtual aaudio_result_t unregisterThread() { 97 return AAUDIO_OK; 98 } 99 100 /** 101 * Internal function used to call the audio thread passed by the user. 102 * It is unfortunately public because it needs to be called by a static 'C' function. 103 */ 104 void* wrapUserThread(); 105 106 // ============== Queries =========================== 107 108 aaudio_stream_state_t getState() const { 109 return mState; 110 } 111 112 virtual int32_t getBufferSize() const { 113 return AAUDIO_ERROR_UNIMPLEMENTED; 114 } 115 116 virtual int32_t getBufferCapacity() const { 117 return AAUDIO_ERROR_UNIMPLEMENTED; 118 } 119 120 virtual int32_t getFramesPerBurst() const { 121 return AAUDIO_ERROR_UNIMPLEMENTED; 122 } 123 124 virtual int32_t getXRunCount() const { 125 return AAUDIO_ERROR_UNIMPLEMENTED; 126 } 127 128 bool isPlaying() const { 129 return mState == AAUDIO_STREAM_STATE_STARTING || mState == AAUDIO_STREAM_STATE_STARTED; 130 } 131 132 aaudio_result_t getSampleRate() const { 133 return mSampleRate; 134 } 135 136 aaudio_audio_format_t getFormat() const { 137 return mFormat; 138 } 139 140 aaudio_result_t getSamplesPerFrame() const { 141 return mSamplesPerFrame; 142 } 143 144 int32_t getDeviceId() const { 145 return mDeviceId; 146 } 147 148 aaudio_sharing_mode_t getSharingMode() const { 149 return mSharingMode; 150 } 151 152 aaudio_direction_t getDirection() const { 153 return mDirection; 154 } 155 156 int32_t getBytesPerFrame() const { 157 return mSamplesPerFrame * getBytesPerSample(); 158 } 159 160 int32_t getBytesPerSample() const { 161 return AAudioConvert_formatToSizeInBytes(mFormat); 162 } 163 164 virtual int64_t getFramesWritten() { 165 return mFramesWritten.get(); 166 } 167 168 virtual int64_t getFramesRead() { 169 return mFramesRead.get(); 170 } 171 172 173 // ============== I/O =========================== 174 // A Stream will only implement read() or write() depending on its direction. 175 virtual aaudio_result_t write(const void *buffer, 176 int32_t numFrames, 177 int64_t timeoutNanoseconds) { 178 return AAUDIO_ERROR_UNIMPLEMENTED; 179 } 180 181 virtual aaudio_result_t read(void *buffer, 182 int32_t numFrames, 183 int64_t timeoutNanoseconds) { 184 return AAUDIO_ERROR_UNIMPLEMENTED; 185 } 186 187protected: 188 189 virtual int64_t incrementFramesWritten(int32_t frames) { 190 return static_cast<int64_t>(mFramesWritten.increment(frames)); 191 } 192 193 virtual int64_t incrementFramesRead(int32_t frames) { 194 return static_cast<int64_t>(mFramesRead.increment(frames)); 195 } 196 197 /** 198 * Wait for a transition from one state to another. 199 * @return AAUDIO_OK if the endingState was observed, or AAUDIO_ERROR_UNEXPECTED_STATE 200 * if any state that was not the startingState or endingState was observed 201 * or AAUDIO_ERROR_TIMEOUT 202 */ 203 virtual aaudio_result_t waitForStateTransition(aaudio_stream_state_t startingState, 204 aaudio_stream_state_t endingState, 205 int64_t timeoutNanoseconds); 206 207 /** 208 * This should not be called after the open() call. 209 */ 210 void setSampleRate(int32_t sampleRate) { 211 mSampleRate = sampleRate; 212 } 213 214 /** 215 * This should not be called after the open() call. 216 */ 217 void setSamplesPerFrame(int32_t samplesPerFrame) { 218 mSamplesPerFrame = samplesPerFrame; 219 } 220 221 /** 222 * This should not be called after the open() call. 223 */ 224 void setSharingMode(aaudio_sharing_mode_t sharingMode) { 225 mSharingMode = sharingMode; 226 } 227 228 /** 229 * This should not be called after the open() call. 230 */ 231 void setFormat(aaudio_audio_format_t format) { 232 mFormat = format; 233 } 234 235 void setState(aaudio_stream_state_t state) { 236 mState = state; 237 } 238 239 240 241protected: 242 MonotonicCounter mFramesWritten; 243 MonotonicCounter mFramesRead; 244 245 void setPeriodNanoseconds(int64_t periodNanoseconds) { 246 mPeriodNanoseconds.store(periodNanoseconds, std::memory_order_release); 247 } 248 249 int64_t getPeriodNanoseconds() { 250 return mPeriodNanoseconds.load(std::memory_order_acquire); 251 } 252 253private: 254 // These do not change after open(). 255 int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED; 256 int32_t mSampleRate = AAUDIO_UNSPECIFIED; 257 int32_t mDeviceId = AAUDIO_UNSPECIFIED; 258 aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED; 259 aaudio_audio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED; 260 aaudio_direction_t mDirection = AAUDIO_DIRECTION_OUTPUT; 261 aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED; 262 263 // background thread ---------------------------------- 264 bool mHasThread = false; 265 pthread_t mThread; // initialized in constructor 266 267 // These are set by the application thread and then read by the audio pthread. 268 std::atomic<int64_t> mPeriodNanoseconds; // for tuning SCHED_FIFO threads 269 // TODO make atomic? 270 aaudio_audio_thread_proc_t* mThreadProc = nullptr; 271 void* mThreadArg = nullptr; 272 aaudio_result_t mThreadRegistrationResult = AAUDIO_OK; 273 274 275}; 276 277} /* namespace aaudio */ 278 279#endif /* AAUDIO_AUDIOSTREAM_H */ 280