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