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