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