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