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