AudioStream.h revision e2fbb59e729f6c3cade3b531f6f6411417ccbf40
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    virtual bool isMMap() {
138        return false;
139    }
140
141    aaudio_result_t getSampleRate() const {
142        return mSampleRate;
143    }
144
145    aaudio_audio_format_t getFormat()  const {
146        return mFormat;
147    }
148
149    aaudio_result_t getSamplesPerFrame() const {
150        return mSamplesPerFrame;
151    }
152
153    virtual int32_t getPerformanceMode() const {
154        return mPerformanceMode;
155    }
156
157    void setPerformanceMode(aaudio_performance_mode_t performanceMode) {
158        mPerformanceMode = performanceMode;
159    }
160
161    int32_t getDeviceId() const {
162        return mDeviceId;
163    }
164
165    aaudio_sharing_mode_t getSharingMode() const {
166        return mSharingMode;
167    }
168
169    bool isSharingModeMatchRequired() const {
170        return mSharingModeMatchRequired;
171    }
172
173    aaudio_direction_t getDirection() const {
174        return mDirection;
175    }
176
177    /**
178     * This is only valid after setSamplesPerFrame() and setFormat() have been called.
179     */
180    int32_t getBytesPerFrame() const {
181        return mSamplesPerFrame * getBytesPerSample();
182    }
183
184    /**
185     * This is only valid after setFormat() has been called.
186     */
187    int32_t getBytesPerSample() const {
188        return AAudioConvert_formatToSizeInBytes(mFormat);
189    }
190
191    virtual int64_t getFramesWritten() {
192        return mFramesWritten.get();
193    }
194
195    virtual int64_t getFramesRead() {
196        return mFramesRead.get();
197    }
198
199    AAudioStream_dataCallback getDataCallbackProc() const {
200        return mDataCallbackProc;
201    }
202    AAudioStream_errorCallback getErrorCallbackProc() const {
203        return mErrorCallbackProc;
204    }
205
206    void *getDataCallbackUserData() const {
207        return mDataCallbackUserData;
208    }
209    void *getErrorCallbackUserData() const {
210        return mErrorCallbackUserData;
211    }
212
213    int32_t getFramesPerDataCallback() const {
214        return mFramesPerDataCallback;
215    }
216
217    bool isDataCallbackActive() {
218        return (mDataCallbackProc != nullptr) && isPlaying();
219    }
220
221    // ============== I/O ===========================
222    // A Stream will only implement read() or write() depending on its direction.
223    virtual aaudio_result_t write(const void *buffer,
224                             int32_t numFrames,
225                             int64_t timeoutNanoseconds) {
226        return AAUDIO_ERROR_UNIMPLEMENTED;
227    }
228
229    virtual aaudio_result_t read(void *buffer,
230                            int32_t numFrames,
231                            int64_t timeoutNanoseconds) {
232        return AAUDIO_ERROR_UNIMPLEMENTED;
233    }
234
235protected:
236
237    virtual int64_t incrementFramesWritten(int32_t frames) {
238        return mFramesWritten.increment(frames);
239    }
240
241    virtual int64_t incrementFramesRead(int32_t frames) {
242        return mFramesRead.increment(frames);
243    }
244
245    /**
246     * This should not be called after the open() call.
247     */
248    void setSampleRate(int32_t sampleRate) {
249        mSampleRate = sampleRate;
250    }
251
252    /**
253     * This should not be called after the open() call.
254     */
255    void setSamplesPerFrame(int32_t samplesPerFrame) {
256        mSamplesPerFrame = samplesPerFrame;
257    }
258
259    /**
260     * This should not be called after the open() call.
261     */
262    void setSharingMode(aaudio_sharing_mode_t sharingMode) {
263        mSharingMode = sharingMode;
264    }
265
266    /**
267     * This should not be called after the open() call.
268     */
269    void setFormat(aaudio_audio_format_t format) {
270        mFormat = format;
271    }
272
273    void setState(aaudio_stream_state_t state) {
274        mState = state;
275    }
276
277    void setDeviceId(int32_t deviceId) {
278        mDeviceId = deviceId;
279    }
280
281    std::mutex           mStreamMutex;
282
283    std::atomic<bool>    mCallbackEnabled;
284
285protected:
286    MonotonicCounter     mFramesWritten;
287    MonotonicCounter     mFramesRead;
288
289    void setPeriodNanoseconds(int64_t periodNanoseconds) {
290        mPeriodNanoseconds.store(periodNanoseconds, std::memory_order_release);
291    }
292
293    int64_t getPeriodNanoseconds() {
294        return mPeriodNanoseconds.load(std::memory_order_acquire);
295    }
296
297private:
298    // These do not change after open().
299    int32_t                mSamplesPerFrame = AAUDIO_UNSPECIFIED;
300    int32_t                mSampleRate = AAUDIO_UNSPECIFIED;
301    int32_t                mDeviceId = AAUDIO_UNSPECIFIED;
302    aaudio_sharing_mode_t  mSharingMode = AAUDIO_SHARING_MODE_SHARED;
303    bool                   mSharingModeMatchRequired = false; // must match sharing mode requested
304    aaudio_audio_format_t  mFormat = AAUDIO_FORMAT_UNSPECIFIED;
305    aaudio_direction_t     mDirection = AAUDIO_DIRECTION_OUTPUT;
306    aaudio_stream_state_t  mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
307
308    aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
309
310    // callback ----------------------------------
311
312    AAudioStream_dataCallback   mDataCallbackProc = nullptr;  // external callback functions
313    void                       *mDataCallbackUserData = nullptr;
314    int32_t                     mFramesPerDataCallback = AAUDIO_UNSPECIFIED; // frames
315
316    AAudioStream_errorCallback  mErrorCallbackProc = nullptr;
317    void                       *mErrorCallbackUserData = nullptr;
318
319    // background thread ----------------------------------
320    bool                   mHasThread = false;
321    pthread_t              mThread; // initialized in constructor
322
323    // These are set by the application thread and then read by the audio pthread.
324    std::atomic<int64_t>   mPeriodNanoseconds; // for tuning SCHED_FIFO threads
325    // TODO make atomic?
326    aaudio_audio_thread_proc_t mThreadProc = nullptr;
327    void*                  mThreadArg = nullptr;
328    aaudio_result_t        mThreadRegistrationResult = AAUDIO_OK;
329
330
331};
332
333} /* namespace aaudio */
334
335#endif /* AAUDIO_AUDIOSTREAM_H */
336