• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 OBOE_STREAM_BUILDER_H_
18 #define OBOE_STREAM_BUILDER_H_
19 
20 #include "oboe/Definitions.h"
21 #include "oboe/AudioStreamBase.h"
22 #include "ResultWithValue.h"
23 
24 namespace oboe {
25 
26     // This depends on AudioStream, so we use forward declaration, it will close and delete the stream
27     struct StreamDeleterFunctor;
28     using ManagedStream = std::unique_ptr<AudioStream, StreamDeleterFunctor>;
29 
30 /**
31  * Factory class for an audio Stream.
32  */
33 class AudioStreamBuilder : public AudioStreamBase {
34 public:
35 
AudioStreamBuilder()36     AudioStreamBuilder() : AudioStreamBase() {}
37 
AudioStreamBuilder(const AudioStreamBase & audioStreamBase)38     AudioStreamBuilder(const AudioStreamBase &audioStreamBase): AudioStreamBase(audioStreamBase) {}
39 
40     /**
41      * Request a specific number of channels.
42      *
43      * Default is kUnspecified. If the value is unspecified then
44      * the application should query for the actual value after the stream is opened.
45      */
setChannelCount(int channelCount)46     AudioStreamBuilder *setChannelCount(int channelCount) {
47         mChannelCount = channelCount;
48         return this;
49     }
50 
51     /**
52      * Request the direction for a stream. The default is Direction::Output.
53      *
54      * @param direction Direction::Output or Direction::Input
55      */
setDirection(Direction direction)56     AudioStreamBuilder *setDirection(Direction direction) {
57         mDirection = direction;
58         return this;
59     }
60 
61     /**
62      * Request a specific sample rate in Hz.
63      *
64      * Default is kUnspecified. If the value is unspecified then
65      * the application should query for the actual value after the stream is opened.
66      *
67      * Technically, this should be called the "frame rate" or "frames per second",
68      * because it refers to the number of complete frames transferred per second.
69      * But it is traditionally called "sample rate". Se we use that term.
70      *
71      */
setSampleRate(int32_t sampleRate)72     AudioStreamBuilder *setSampleRate(int32_t sampleRate) {
73         mSampleRate = sampleRate;
74         return this;
75     }
76 
77     /**
78      * Request a specific number of frames for the data callback.
79      *
80      * Default is kUnspecified. If the value is unspecified then
81      * the actual number may vary from callback to callback.
82      *
83      * If an application can handle a varying number of frames then we recommend
84      * leaving this unspecified. This allow the underlying API to optimize
85      * the callbacks. But if your application is, for example, doing FFTs or other block
86      * oriented operations, then call this function to get the sizes you need.
87      *
88      * @param framesPerCallback
89      * @return pointer to the builder so calls can be chained
90      */
setFramesPerCallback(int framesPerCallback)91     AudioStreamBuilder *setFramesPerCallback(int framesPerCallback) {
92         mFramesPerCallback = framesPerCallback;
93         return this;
94     }
95 
96     /**
97      * Request a sample data format, for example Format::Float.
98      *
99      * Default is Format::Unspecified. If the value is unspecified then
100      * the application should query for the actual value after the stream is opened.
101      */
setFormat(AudioFormat format)102     AudioStreamBuilder *setFormat(AudioFormat format) {
103         mFormat = format;
104         return this;
105     }
106 
107     /**
108      * Set the requested buffer capacity in frames.
109      * BufferCapacityInFrames is the maximum possible BufferSizeInFrames.
110      *
111      * The final stream capacity may differ. For AAudio it should be at least this big.
112      * For OpenSL ES, it could be smaller.
113      *
114      * Default is kUnspecified.
115      *
116      * @param bufferCapacityInFrames the desired buffer capacity in frames or kUnspecified
117      * @return pointer to the builder so calls can be chained
118      */
setBufferCapacityInFrames(int32_t bufferCapacityInFrames)119     AudioStreamBuilder *setBufferCapacityInFrames(int32_t bufferCapacityInFrames) {
120         mBufferCapacityInFrames = bufferCapacityInFrames;
121         return this;
122     }
123 
124     /**
125      * Get the audio API which will be requested when opening the stream. No guarantees that this is
126      * the API which will actually be used. Query the stream itself to find out the API which is
127      * being used.
128      *
129      * If you do not specify the API, then AAudio will be used if isAAudioRecommended()
130      * returns true. Otherwise OpenSL ES will be used.
131      *
132      * @return the requested audio API
133      */
getAudioApi()134     AudioApi getAudioApi() const { return mAudioApi; }
135 
136     /**
137      * If you leave this unspecified then Oboe will choose the best API
138      * for the device and SDK version at runtime.
139      *
140      * This should almost always be left unspecified, except for debugging purposes.
141      * Specifying AAudio will force Oboe to use AAudio on 8.0, which is extremely risky.
142      * Specifying OpenSLES should mainly be used to test legacy performance/functionality.
143      *
144      * If the caller requests AAudio and it is supported then AAudio will be used.
145      *
146      * @param audioApi Must be AudioApi::Unspecified, AudioApi::OpenSLES or AudioApi::AAudio.
147      * @return pointer to the builder so calls can be chained
148      */
setAudioApi(AudioApi audioApi)149     AudioStreamBuilder *setAudioApi(AudioApi audioApi) {
150         mAudioApi = audioApi;
151         return this;
152     }
153 
154     /**
155      * Is the AAudio API supported on this device?
156      *
157      * AAudio was introduced in the Oreo 8.0 release.
158      *
159      * @return true if supported
160      */
161     static bool isAAudioSupported();
162 
163     /**
164      * Is the AAudio API recommended this device?
165      *
166      * AAudio may be supported but not recommended because of version specific issues.
167      * AAudio is not recommended for Android 8.0 or earlier versions.
168      *
169      * @return true if recommended
170      */
171     static bool isAAudioRecommended();
172 
173     /**
174      * Request a mode for sharing the device.
175      * The requested sharing mode may not be available.
176      * So the application should query for the actual mode after the stream is opened.
177      *
178      * @param sharingMode SharingMode::Shared or SharingMode::Exclusive
179      * @return pointer to the builder so calls can be chained
180      */
setSharingMode(SharingMode sharingMode)181     AudioStreamBuilder *setSharingMode(SharingMode sharingMode) {
182         mSharingMode = sharingMode;
183         return this;
184     }
185 
186     /**
187      * Request a performance level for the stream.
188      * This will determine the latency, the power consumption, and the level of
189      * protection from glitches.
190      *
191      * @param performanceMode for example, PerformanceMode::LowLatency
192      * @return pointer to the builder so calls can be chained
193      */
setPerformanceMode(PerformanceMode performanceMode)194     AudioStreamBuilder *setPerformanceMode(PerformanceMode performanceMode) {
195         mPerformanceMode = performanceMode;
196         return this;
197     }
198 
199 
200     /**
201      * Set the intended use case for an output stream.
202      *
203      * The system will use this information to optimize the behavior of the stream.
204      * This could, for example, affect how volume and focus is handled for the stream.
205      * The usage is ignored for input streams.
206      *
207      * The default, if you do not call this function, is Usage::Media.
208      *
209      * Added in API level 28.
210      *
211      * @param usage the desired usage, eg. Usage::Game
212      */
setUsage(Usage usage)213     AudioStreamBuilder *setUsage(Usage usage) {
214         mUsage = usage;
215         return this;
216     }
217 
218     /**
219      * Set the type of audio data that an output stream will carry.
220      *
221      * The system will use this information to optimize the behavior of the stream.
222      * This could, for example, affect whether a stream is paused when a notification occurs.
223      * The contentType is ignored for input streams.
224      *
225      * The default, if you do not call this function, is ContentType::Music.
226      *
227      * Added in API level 28.
228      *
229      * @param contentType the type of audio data, eg. ContentType::Speech
230      */
setContentType(ContentType contentType)231     AudioStreamBuilder *setContentType(ContentType contentType) {
232         mContentType = contentType;
233         return this;
234     }
235 
236     /**
237      * Set the input (capture) preset for the stream.
238      *
239      * The system will use this information to optimize the behavior of the stream.
240      * This could, for example, affect which microphones are used and how the
241      * recorded data is processed.
242      *
243      * The default, if you do not call this function, is InputPreset::VoiceRecognition.
244      * That is because VoiceRecognition is the preset with the lowest latency
245      * on many platforms.
246      *
247      * Added in API level 28.
248      *
249      * @param inputPreset the desired configuration for recording
250      */
setInputPreset(InputPreset inputPreset)251     AudioStreamBuilder *setInputPreset(InputPreset inputPreset) {
252         mInputPreset = inputPreset;
253         return this;
254     }
255 
256     /** Set the requested session ID.
257      *
258      * The session ID can be used to associate a stream with effects processors.
259      * The effects are controlled using the Android AudioEffect Java API.
260      *
261      * The default, if you do not call this function, is SessionId::None.
262      *
263      * If set to SessionId::Allocate then a session ID will be allocated
264      * when the stream is opened.
265      *
266      * The allocated session ID can be obtained by calling AudioStream::getSessionId()
267      * and then used with this function when opening another stream.
268      * This allows effects to be shared between streams.
269      *
270      * Session IDs from Oboe can be used the Android Java APIs and vice versa.
271      * So a session ID from an Oboe stream can be passed to Java
272      * and effects applied using the Java AudioEffect API.
273      *
274      * Allocated session IDs will always be positive and nonzero.
275      *
276      * Added in API level 28.
277      *
278      * @param sessionId an allocated sessionID or SessionId::Allocate
279      */
setSessionId(SessionId sessionId)280     AudioStreamBuilder *setSessionId(SessionId sessionId) {
281         mSessionId = sessionId;
282         return this;
283     }
284 
285     /**
286      * Request a stream to a specific audio input/output device given an audio device ID.
287      *
288      * In most cases, the primary device will be the appropriate device to use, and the
289      * deviceId can be left kUnspecified.
290      *
291      * On Android, for example, the ID could be obtained from the Java AudioManager.
292      * AudioManager.getDevices() returns an array of AudioDeviceInfo[], which contains
293      * a getId() method (as well as other type information), that should be passed
294      * to this method.
295      *
296      *
297      * Note that when using OpenSL ES, this will be ignored and the created
298      * stream will have deviceId kUnspecified.
299      *
300      * @param deviceId device identifier or kUnspecified
301      * @return pointer to the builder so calls can be chained
302      */
setDeviceId(int32_t deviceId)303     AudioStreamBuilder *setDeviceId(int32_t deviceId) {
304         mDeviceId = deviceId;
305         return this;
306     }
307 
308     /**
309      * Specifies an object to handle data or error related callbacks from the underlying API.
310      *
311      * <strong>Important: See AudioStreamCallback for restrictions on what may be called
312      * from the callback methods.</strong>
313      *
314      * When an error callback occurs, the associated stream will be stopped and closed in a separate thread.
315      *
316      * A note on why the streamCallback parameter is a raw pointer rather than a smart pointer:
317      *
318      * The caller should retain ownership of the object streamCallback points to. At first glance weak_ptr may seem like
319      * a good candidate for streamCallback as this implies temporary ownership. However, a weak_ptr can only be created
320      * from a shared_ptr. A shared_ptr incurs some performance overhead. The callback object is likely to be accessed
321      * every few milliseconds when the stream requires new data so this overhead is something we want to avoid.
322      *
323      * This leaves a raw pointer as the logical type choice. The only caveat being that the caller must not destroy
324      * the callback before the stream has been closed.
325      *
326      * @param streamCallback
327      * @return pointer to the builder so calls can be chained
328      */
setCallback(AudioStreamCallback * streamCallback)329     AudioStreamBuilder *setCallback(AudioStreamCallback *streamCallback) {
330         mStreamCallback = streamCallback;
331         return this;
332     }
333 
334     /**
335      * If true then Oboe might convert channel counts to achieve optimal results.
336      * On some versions of Android for example, stereo streams could not use a FAST track.
337      * So a mono stream might be used instead and duplicated to two channels.
338      * On some devices, mono streams might be broken, so a stereo stream might be opened
339      * and converted to mono.
340      *
341      * Default is true.
342      */
setChannelConversionAllowed(bool allowed)343     AudioStreamBuilder *setChannelConversionAllowed(bool allowed) {
344         mChannelConversionAllowed = allowed;
345         return this;
346     }
347 
348     /**
349      * If true then  Oboe might convert data formats to achieve optimal results.
350      * On some versions of Android, for example, a float stream could not get a
351      * low latency data path. So an I16 stream might be opened and converted to float.
352      *
353      * Default is true.
354      */
setFormatConversionAllowed(bool allowed)355     AudioStreamBuilder *setFormatConversionAllowed(bool allowed) {
356         mFormatConversionAllowed = allowed;
357         return this;
358     }
359 
360     /**
361      * Specify the quality of the sample rate converter in Oboe.
362      *
363      * If set to None then Oboe will not do sample rate conversion. But the underlying APIs might
364      * still do sample rate conversion if you specify a sample rate.
365      * That can prevent you from getting a low latency stream.
366      *
367      * If you do the conversion in Oboe then you might still get a low latency stream.
368      *
369      * Default is SampleRateConversionQuality::None
370      */
setSampleRateConversionQuality(SampleRateConversionQuality quality)371     AudioStreamBuilder *setSampleRateConversionQuality(SampleRateConversionQuality quality) {
372         mSampleRateConversionQuality = quality;
373         return this;
374     }
375 
376     /**
377      * @return true if AAudio will be used based on the current settings.
378      */
willUseAAudio()379     bool willUseAAudio() const {
380         return (mAudioApi == AudioApi::AAudio && isAAudioSupported())
381                 || (mAudioApi == AudioApi::Unspecified && isAAudioRecommended());
382     }
383 
384     /**
385      * Create and open a stream object based on the current settings.
386      *
387      * The caller owns the pointer to the AudioStream object.
388      *
389      * @deprecated Use openStream(std::shared_ptr<oboe::AudioStream> &stream) instead.
390      * @param stream pointer to a variable to receive the stream address
391      * @return OBOE_OK if successful or a negative error code
392      */
393     Result openStream(AudioStream **stream);
394 
395     /**
396      * Create and open a stream object based on the current settings.
397      *
398      * The caller shares the pointer to the AudioStream object.
399      * The shared_ptr is used internally by Oboe to prevent the stream from being
400      * deleted while it is being used by callbacks.
401      *
402      * @param stream reference to a shared_ptr to receive the stream address
403      * @return OBOE_OK if successful or a negative error code
404      */
405     Result openStream(std::shared_ptr<oboe::AudioStream> &stream);
406 
407     /**
408      * Create and open a ManagedStream object based on the current builder state.
409      *
410      * The caller must create a unique ptr, and pass by reference so it can be
411      * modified to point to an opened stream. The caller owns the unique ptr,
412      * and it will be automatically closed and deleted when going out of scope.
413      * @param stream Reference to the ManagedStream (uniqueptr) used to keep track of stream
414      * @return OBOE_OK if successful or a negative error code.
415      */
416     Result openManagedStream(ManagedStream &stream);
417 
418 private:
419 
420     /**
421      * @param other
422      * @return true if channels, format and sample rate match
423      */
424     bool isCompatible(AudioStreamBase &other);
425 
426     /**
427      * Create an AudioStream object. The AudioStream must be opened before use.
428      *
429      * The caller owns the pointer.
430      *
431      * @return pointer to an AudioStream object or nullptr.
432      */
433     oboe::AudioStream *build();
434 
435     AudioApi       mAudioApi = AudioApi::Unspecified;
436 };
437 
438 } // namespace oboe
439 
440 #endif /* OBOE_STREAM_BUILDER_H_ */
441