• 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 "oboe/Utilities.h"
23 #include "ResultWithValue.h"
24 
25 namespace oboe {
26 
27     // This depends on AudioStream, so we use forward declaration, it will close and delete the stream
28     struct StreamDeleterFunctor;
29     using ManagedStream = std::unique_ptr<AudioStream, StreamDeleterFunctor>;
30 
31 /**
32  * Factory class for an audio Stream.
33  */
34 class AudioStreamBuilder : public AudioStreamBase {
35 public:
36 
AudioStreamBuilder()37     AudioStreamBuilder() : AudioStreamBase() {}
38 
AudioStreamBuilder(const AudioStreamBase & audioStreamBase)39     AudioStreamBuilder(const AudioStreamBase &audioStreamBase): AudioStreamBase(audioStreamBase) {}
40 
41     /**
42      * Request a specific number of channels.
43      *
44      * Default is kUnspecified. If the value is unspecified then
45      * the application should query for the actual value after the stream is opened.
46      *
47      * As the channel count here may be different from the corresponding channel count of
48      * provided channel mask used in setChannelMask(). The last called will be respected
49      * if this function and setChannelMask() are called.
50      */
setChannelCount(int channelCount)51     AudioStreamBuilder *setChannelCount(int channelCount) {
52         mChannelCount = channelCount;
53         mChannelMask = ChannelMask::Unspecified;
54         return this;
55     }
56 
57     /**
58      * Request a specific channel mask.
59      *
60      * Default is kUnspecified. If the value is unspecified then the application
61      * should query for the actual value after the stream is opened.
62      *
63      * As the corresponding channel count of provided channel mask here may be different
64      * from the channel count used in setChannelCount(). The last called will be respected
65      * if this function and setChannelCount() are called.
66      *
67      * As the setChannelMask API is available on Android 32+, this call will only take effects
68      * on Android 32+.
69      */
setChannelMask(ChannelMask channelMask)70      AudioStreamBuilder *setChannelMask(ChannelMask channelMask) {
71          mChannelMask = channelMask;
72          mChannelCount = getChannelCountFromChannelMask(channelMask);
73          return this;
74      }
75 
76     /**
77      * Request the direction for a stream. The default is Direction::Output.
78      *
79      * @param direction Direction::Output or Direction::Input
80      */
setDirection(Direction direction)81     AudioStreamBuilder *setDirection(Direction direction) {
82         mDirection = direction;
83         return this;
84     }
85 
86     /**
87      * Request a specific sample rate in Hz.
88      *
89      * Default is kUnspecified. If the value is unspecified then
90      * the application should query for the actual value after the stream is opened.
91      *
92      * Technically, this should be called the "frame rate" or "frames per second",
93      * because it refers to the number of complete frames transferred per second.
94      * But it is traditionally called "sample rate". Se we use that term.
95      *
96      */
setSampleRate(int32_t sampleRate)97     AudioStreamBuilder *setSampleRate(int32_t sampleRate) {
98         mSampleRate = sampleRate;
99         return this;
100     }
101 
102     /**
103      * @deprecated use `setFramesPerDataCallback` instead.
104      */
setFramesPerCallback(int framesPerCallback)105     AudioStreamBuilder *setFramesPerCallback(int framesPerCallback) {
106         return setFramesPerDataCallback(framesPerCallback);
107     }
108 
109     /**
110      * Request a specific number of frames for the data callback.
111      *
112      * Default is kUnspecified. If the value is unspecified then
113      * the actual number may vary from callback to callback.
114      *
115      * If an application can handle a varying number of frames then we recommend
116      * leaving this unspecified. This allow the underlying API to optimize
117      * the callbacks. But if your application is, for example, doing FFTs or other block
118      * oriented operations, then call this function to get the sizes you need.
119      *
120      * Calling setFramesPerDataCallback() does not guarantee anything about timing.
121      * This just collects the data into a the number of frames that your app requires.
122      * We encourage leaving this unspecified in most cases.
123      *
124      * If this number is larger than the burst size, some bursts will not receive a callback.
125      * If this number is smaller than the burst size, there may be multiple callbacks in a single
126      * burst.
127      *
128      * @param framesPerCallback
129      * @return pointer to the builder so calls can be chained
130      */
setFramesPerDataCallback(int framesPerCallback)131     AudioStreamBuilder *setFramesPerDataCallback(int framesPerCallback) {
132         mFramesPerCallback = framesPerCallback;
133         return this;
134     }
135 
136     /**
137      * Request a sample data format, for example Format::Float.
138      *
139      * Default is Format::Unspecified. If the value is unspecified then
140      * the application should query for the actual value after the stream is opened.
141      */
setFormat(AudioFormat format)142     AudioStreamBuilder *setFormat(AudioFormat format) {
143         mFormat = format;
144         return this;
145     }
146 
147     /**
148      * Set the requested buffer capacity in frames.
149      * BufferCapacityInFrames is the maximum possible BufferSizeInFrames.
150      *
151      * The final stream capacity may differ. For AAudio it should be at least this big.
152      * For OpenSL ES, it could be smaller.
153      *
154      * Default is kUnspecified.
155      *
156      * @param bufferCapacityInFrames the desired buffer capacity in frames or kUnspecified
157      * @return pointer to the builder so calls can be chained
158      */
setBufferCapacityInFrames(int32_t bufferCapacityInFrames)159     AudioStreamBuilder *setBufferCapacityInFrames(int32_t bufferCapacityInFrames) {
160         mBufferCapacityInFrames = bufferCapacityInFrames;
161         return this;
162     }
163 
164     /**
165      * Get the audio API which will be requested when opening the stream. No guarantees that this is
166      * the API which will actually be used. Query the stream itself to find out the API which is
167      * being used.
168      *
169      * If you do not specify the API, then AAudio will be used if isAAudioRecommended()
170      * returns true. Otherwise OpenSL ES will be used.
171      *
172      * @return the requested audio API
173      */
getAudioApi()174     AudioApi getAudioApi() const { return mAudioApi; }
175 
176     /**
177      * If you leave this unspecified then Oboe will choose the best API
178      * for the device and SDK version at runtime.
179      *
180      * This should almost always be left unspecified, except for debugging purposes.
181      * Specifying AAudio will force Oboe to use AAudio on 8.0, which is extremely risky.
182      * Specifying OpenSLES should mainly be used to test legacy performance/functionality.
183      *
184      * If the caller requests AAudio and it is supported then AAudio will be used.
185      *
186      * @param audioApi Must be AudioApi::Unspecified, AudioApi::OpenSLES or AudioApi::AAudio.
187      * @return pointer to the builder so calls can be chained
188      */
setAudioApi(AudioApi audioApi)189     AudioStreamBuilder *setAudioApi(AudioApi audioApi) {
190         mAudioApi = audioApi;
191         return this;
192     }
193 
194     /**
195      * Is the AAudio API supported on this device?
196      *
197      * AAudio was introduced in the Oreo 8.0 release.
198      *
199      * @return true if supported
200      */
201     static bool isAAudioSupported();
202 
203     /**
204      * Is the AAudio API recommended this device?
205      *
206      * AAudio may be supported but not recommended because of version specific issues.
207      * AAudio is not recommended for Android 8.0 or earlier versions.
208      *
209      * @return true if recommended
210      */
211     static bool isAAudioRecommended();
212 
213     /**
214      * Request a mode for sharing the device.
215      * The requested sharing mode may not be available.
216      * So the application should query for the actual mode after the stream is opened.
217      *
218      * @param sharingMode SharingMode::Shared or SharingMode::Exclusive
219      * @return pointer to the builder so calls can be chained
220      */
setSharingMode(SharingMode sharingMode)221     AudioStreamBuilder *setSharingMode(SharingMode sharingMode) {
222         mSharingMode = sharingMode;
223         return this;
224     }
225 
226     /**
227      * Request a performance level for the stream.
228      * This will determine the latency, the power consumption, and the level of
229      * protection from glitches.
230      *
231      * @param performanceMode for example, PerformanceMode::LowLatency
232      * @return pointer to the builder so calls can be chained
233      */
setPerformanceMode(PerformanceMode performanceMode)234     AudioStreamBuilder *setPerformanceMode(PerformanceMode performanceMode) {
235         mPerformanceMode = performanceMode;
236         return this;
237     }
238 
239 
240     /**
241      * Set the intended use case for an output stream.
242      *
243      * The system will use this information to optimize the behavior of the stream.
244      * This could, for example, affect how volume and focus is handled for the stream.
245      * The usage is ignored for input streams.
246      *
247      * The default, if you do not call this function, is Usage::Media.
248      *
249      * Added in API level 28.
250      *
251      * @param usage the desired usage, eg. Usage::Game
252      */
setUsage(Usage usage)253     AudioStreamBuilder *setUsage(Usage usage) {
254         mUsage = usage;
255         return this;
256     }
257 
258     /**
259      * Set the type of audio data that an output stream will carry.
260      *
261      * The system will use this information to optimize the behavior of the stream.
262      * This could, for example, affect whether a stream is paused when a notification occurs.
263      * The contentType is ignored for input streams.
264      *
265      * The default, if you do not call this function, is ContentType::Music.
266      *
267      * Added in API level 28.
268      *
269      * @param contentType the type of audio data, eg. ContentType::Speech
270      */
setContentType(ContentType contentType)271     AudioStreamBuilder *setContentType(ContentType contentType) {
272         mContentType = contentType;
273         return this;
274     }
275 
276     /**
277      * Set the input (capture) preset for the stream.
278      *
279      * The system will use this information to optimize the behavior of the stream.
280      * This could, for example, affect which microphones are used and how the
281      * recorded data is processed.
282      *
283      * The default, if you do not call this function, is InputPreset::VoiceRecognition.
284      * That is because VoiceRecognition is the preset with the lowest latency
285      * on many platforms.
286      *
287      * Added in API level 28.
288      *
289      * @param inputPreset the desired configuration for recording
290      */
setInputPreset(InputPreset inputPreset)291     AudioStreamBuilder *setInputPreset(InputPreset inputPreset) {
292         mInputPreset = inputPreset;
293         return this;
294     }
295 
296     /** Set the requested session ID.
297      *
298      * The session ID can be used to associate a stream with effects processors.
299      * The effects are controlled using the Android AudioEffect Java API.
300      *
301      * The default, if you do not call this function, is SessionId::None.
302      *
303      * If set to SessionId::Allocate then a session ID will be allocated
304      * when the stream is opened.
305      *
306      * The allocated session ID can be obtained by calling AudioStream::getSessionId()
307      * and then used with this function when opening another stream.
308      * This allows effects to be shared between streams.
309      *
310      * Session IDs from Oboe can be used the Android Java APIs and vice versa.
311      * So a session ID from an Oboe stream can be passed to Java
312      * and effects applied using the Java AudioEffect API.
313      *
314      * Allocated session IDs will always be positive and nonzero.
315      *
316      * Added in API level 28.
317      *
318      * @param sessionId an allocated sessionID or SessionId::Allocate
319      */
setSessionId(SessionId sessionId)320     AudioStreamBuilder *setSessionId(SessionId sessionId) {
321         mSessionId = sessionId;
322         return this;
323     }
324 
325     /**
326      * Request a stream to a specific audio input/output device given an audio device ID.
327      *
328      * In most cases, the primary device will be the appropriate device to use, and the
329      * deviceId can be left kUnspecified.
330      *
331      * The ID could be obtained from the Java AudioManager.
332      * AudioManager.getDevices() returns an array of AudioDeviceInfo,
333      * which contains a getId() method. That ID can be passed to this function.
334      *
335      * It is possible that you may not get the device that you requested.
336      * So if it is important to you, you should call
337      * stream->getDeviceId() after the stream is opened to
338      * verify the actual ID.
339      *
340      * Note that when using OpenSL ES, this will be ignored and the created
341      * stream will have deviceId kUnspecified.
342      *
343      * @param deviceId device identifier or kUnspecified
344      * @return pointer to the builder so calls can be chained
345      */
setDeviceId(int32_t deviceId)346     AudioStreamBuilder *setDeviceId(int32_t deviceId) {
347         mDeviceId = deviceId;
348         return this;
349     }
350 
351     /**
352      * Specify whether this stream audio may or may not be captured by other apps or the system.
353      *
354      * The default is AllowedCapturePolicy::Unspecified which maps to AAUDIO_ALLOW_CAPTURE_BY_ALL.
355      *
356      * Note that an application can also set its global policy, in which case the most restrictive
357      * policy is always applied. See android.media.AudioAttributes.setAllowedCapturePolicy.
358      *
359      * Added in API level 29 to AAudio.
360      *
361      * @param inputPreset the desired level of opt-out from being captured.
362      * @return pointer to the builder so calls can be chained
363      */
setAllowedCapturePolicy(AllowedCapturePolicy allowedCapturePolicy)364     AudioStreamBuilder *setAllowedCapturePolicy(AllowedCapturePolicy allowedCapturePolicy) {
365         mAllowedCapturePolicy = allowedCapturePolicy;
366         return this;
367     }
368 
369     /** Indicates whether this input stream must be marked as privacy sensitive or not.
370      *
371      * When PrivacySensitiveMode::Enabled, this input stream is privacy sensitive and any
372      * concurrent capture is not permitted.
373      *
374      * This is off (PrivacySensitiveMode::Disabled) by default except when the input preset is
375      * InputPreset::VoiceRecognition or InputPreset::Camcorder
376      *
377      * Always takes precedence over default from input preset when set explicitly.
378      *
379      * Only relevant if the stream direction is Direction::Input and AAudio is used.
380      *
381      * Added in API level 30 to AAudio.
382      *
383      * @param privacySensitive PrivacySensitiveMode::Enabled if capture from this stream must be
384      * marked as privacy sensitive, PrivacySensitiveMode::Disabled if stream should be marked as
385      * not sensitive.
386      * @return pointer to the builder so calls can be chained
387      */
setPrivacySensitiveMode(PrivacySensitiveMode privacySensitiveMode)388     AudioStreamBuilder *setPrivacySensitiveMode(PrivacySensitiveMode privacySensitiveMode) {
389         mPrivacySensitiveMode = privacySensitiveMode;
390         return this;
391     }
392 
393     /**
394      * Specifies whether the audio data of this output stream has already been processed for spatialization.
395      *
396      * If the stream has been processed for spatialization, setting this to true will prevent issues such as
397      * double-processing on platforms that will spatialize audio data.
398      *
399      * This is false by default.
400      *
401      * Available since API level 32.
402      *
403      * @param isContentSpatialized whether the content is already spatialized
404      * @return pointer to the builder so calls can be chained
405      */
setIsContentSpatialized(bool isContentSpatialized)406     AudioStreamBuilder *setIsContentSpatialized(bool isContentSpatialized) {
407         mIsContentSpatialized = isContentSpatialized;
408         return this;
409     }
410 
411     /**
412      * Sets the behavior affecting whether spatialization will be used.
413      *
414      * The AAudio system will use this information to select whether the stream will go through a
415      * spatializer effect or not when the effect is supported and enabled.
416      *
417      * This is SpatializationBehavior::Never by default.
418      *
419      * Available since API level 32.
420      *
421      * @param spatializationBehavior the desired spatialization behavior
422      * @return pointer to the builder so calls can be chained
423      */
setSpatializationBehavior(SpatializationBehavior spatializationBehavior)424     AudioStreamBuilder *setSpatializationBehavior(SpatializationBehavior spatializationBehavior) {
425         mSpatializationBehavior = spatializationBehavior;
426         return this;
427     }
428 
429     /**
430      * Specifies an object to handle data related callbacks from the underlying API.
431      *
432      * <strong>Important: See AudioStreamCallback for restrictions on what may be called
433      * from the callback methods.</strong>
434      *
435      * We pass a shared_ptr so that the sharedDataCallback object cannot be deleted
436      * before the stream is deleted.
437      *
438      * @param sharedDataCallback
439      * @return pointer to the builder so calls can be chained
440      */
setDataCallback(std::shared_ptr<AudioStreamDataCallback> sharedDataCallback)441     AudioStreamBuilder *setDataCallback(std::shared_ptr<AudioStreamDataCallback> sharedDataCallback) {
442         // Use this raw pointer in the rest of the code to retain backwards compatibility.
443         mDataCallback = sharedDataCallback.get();
444         // Hold a shared_ptr to protect the raw pointer for the lifetime of the stream.
445         mSharedDataCallback = sharedDataCallback;
446         return this;
447     }
448 
449     /**
450     * Pass a raw pointer to a data callback. This is not recommended because the dataCallback
451     * object might get deleted by the app while it is being used.
452     *
453     * @deprecated Call setDataCallback(std::shared_ptr<AudioStreamDataCallback>) instead.
454     * @param dataCallback
455     * @return pointer to the builder so calls can be chained
456     */
setDataCallback(AudioStreamDataCallback * dataCallback)457     AudioStreamBuilder *setDataCallback(AudioStreamDataCallback *dataCallback) {
458         mDataCallback = dataCallback;
459         mSharedDataCallback = nullptr;
460         return this;
461     }
462 
463     /**
464      * Specifies an object to handle error related callbacks from the underlying API.
465      * This can occur when a stream is disconnected because a headset is plugged in or unplugged.
466      * It can also occur if the audio service fails or if an exclusive stream is stolen by
467      * another stream.
468      *
469      * Note that error callbacks will only be called when a data callback has been specified
470      * and the stream is started. If you are not using a data callback then the read(), write()
471      * and requestStart() methods will return errors if the stream is disconnected.
472      *
473      * <strong>Important: See AudioStreamCallback for restrictions on what may be called
474      * from the callback methods.</strong>
475      *
476      * <strong>When an error callback occurs, the associated stream must be stopped and closed
477      * in a separate thread.</strong>
478      *
479      * We pass a shared_ptr so that the errorCallback object cannot be deleted before the stream is deleted.
480      * If the stream was created using a shared_ptr then the stream cannot be deleted before the
481      * error callback has finished running.
482      *
483      * @param sharedErrorCallback
484      * @return pointer to the builder so calls can be chained
485      */
setErrorCallback(std::shared_ptr<AudioStreamErrorCallback> sharedErrorCallback)486     AudioStreamBuilder *setErrorCallback(std::shared_ptr<AudioStreamErrorCallback> sharedErrorCallback) {
487         // Use this raw pointer in the rest of the code to retain backwards compatibility.
488         mErrorCallback = sharedErrorCallback.get();
489         // Hold a shared_ptr to protect the raw pointer for the lifetime of the stream.
490         mSharedErrorCallback = sharedErrorCallback;
491         return this;
492     }
493 
494     /**
495     * Pass a raw pointer to an error callback. This is not recommended because the errorCallback
496     * object might get deleted by the app while it is being used.
497     *
498     * @deprecated Call setErrorCallback(std::shared_ptr<AudioStreamErrorCallback>) instead.
499     * @param errorCallback
500     * @return pointer to the builder so calls can be chained
501     */
setErrorCallback(AudioStreamErrorCallback * errorCallback)502     AudioStreamBuilder *setErrorCallback(AudioStreamErrorCallback *errorCallback) {
503         mErrorCallback = errorCallback;
504         mSharedErrorCallback = nullptr;
505         return this;
506     }
507 
508     /**
509      * Specifies an object to handle data presentation related callbacks from the underlying API.
510      * This can occur when all data queued in the audio system for an offload stream has been
511      * played.
512      *
513      * Note that presentation callbacks will only be called when a data callback has been specified
514      * and the stream is started.
515      *
516      * <strong>Important: See AudioStreamCallback for restrictions on what may be called
517      * from the callback methods.</strong>
518      *
519      * We pass a shared_ptr so that the presentationCallback object cannot be deleted before the
520      * stream is deleted. If the stream was created using a shared_ptr then the stream cannot be
521      * deleted before the presentation callback has finished running.
522      *
523      * @param sharedPresentationCallback
524      * @return pointer to the builder so calls can be chained
525      */
setPresentationCallback(std::shared_ptr<AudioStreamPresentationCallback> sharedPresentationCallback)526     AudioStreamBuilder *setPresentationCallback(
527             std::shared_ptr<AudioStreamPresentationCallback> sharedPresentationCallback) {
528         mSharedPresentationCallback = sharedPresentationCallback;
529         return this;
530     }
531 
532     /**
533      * Specifies an object to handle data or error related callbacks from the underlying API.
534      *
535      * This is the equivalent of calling both setDataCallback() and setErrorCallback().
536      *
537      * <strong>Important: See AudioStreamCallback for restrictions on what may be called
538      * from the callback methods.</strong>
539      *
540      * @deprecated Call setDataCallback(std::shared_ptr<AudioStreamDataCallback>) and
541      *     setErrorCallback(std::shared_ptr<AudioStreamErrorCallback>) instead.
542      * @param streamCallback
543      * @return pointer to the builder so calls can be chained
544      */
setCallback(AudioStreamCallback * streamCallback)545     AudioStreamBuilder *setCallback(AudioStreamCallback *streamCallback) {
546         // Use the same callback object for both, dual inheritance.
547         mDataCallback = streamCallback;
548         mErrorCallback = streamCallback;
549         return this;
550     }
551 
552     /**
553      * If true then Oboe might convert channel counts to achieve optimal results.
554      * On some versions of Android for example, stereo streams could not use a FAST track.
555      * So a mono stream might be used instead and duplicated to two channels.
556      * On some devices, mono streams might be broken, so a stereo stream might be opened
557      * and converted to mono.
558      *
559      * Default is false.
560      */
setChannelConversionAllowed(bool allowed)561     AudioStreamBuilder *setChannelConversionAllowed(bool allowed) {
562         mChannelConversionAllowed = allowed;
563         return this;
564     }
565 
566     /**
567      * If true then Oboe might convert data formats to achieve optimal results.
568      * On some versions of Android, for example, a float stream could not get a
569      * low latency data path. So an I16 stream might be opened and converted to float.
570      *
571      * Default is false.
572      */
setFormatConversionAllowed(bool allowed)573     AudioStreamBuilder *setFormatConversionAllowed(bool allowed) {
574         mFormatConversionAllowed = allowed;
575         return this;
576     }
577 
578     /**
579      * Specify the quality of the sample rate converter in Oboe.
580      *
581      * If set to None then Oboe will not do sample rate conversion. But the underlying APIs might
582      * still do sample rate conversion if you specify a sample rate.
583      * That can prevent you from getting a low latency stream.
584      *
585      * If you do the conversion in Oboe then you might still get a low latency stream.
586      *
587      * Default is SampleRateConversionQuality::Medium
588      */
setSampleRateConversionQuality(SampleRateConversionQuality quality)589     AudioStreamBuilder *setSampleRateConversionQuality(SampleRateConversionQuality quality) {
590         mSampleRateConversionQuality = quality;
591         return this;
592     }
593 
594     /**
595     * Declare the name of the package creating the stream.
596     *
597     * This is usually {@code Context#getPackageName()}.
598     *
599     * The default, if you do not call this function, is a random package in the calling uid.
600     * The vast majority of apps have only one package per calling UID.
601     * If an invalid package name is set, input streams may not be given permission to
602     * record when started.
603     *
604     * The package name is usually the applicationId in your app's build.gradle file.
605     *
606     * Available since API level 31.
607     *
608     * @param packageName packageName of the calling app.
609     */
setPackageName(std::string packageName)610     AudioStreamBuilder *setPackageName(std::string packageName) {
611         mPackageName = packageName;
612         return this;
613     }
614 
615     /**
616     * Declare the attribution tag of the context creating the stream.
617     *
618     * This is usually {@code Context#getAttributionTag()}.
619     *
620     * The default, if you do not call this function, is null.
621     *
622     * Available since API level 31.
623     *
624     * @param attributionTag attributionTag of the calling context.
625     */
setAttributionTag(std::string attributionTag)626     AudioStreamBuilder *setAttributionTag(std::string attributionTag) {
627         mAttributionTag = attributionTag;
628         return this;
629     }
630 
631     /**
632      * @return true if AAudio will be used based on the current settings.
633      */
willUseAAudio()634     bool willUseAAudio() const {
635         return (mAudioApi == AudioApi::AAudio && isAAudioSupported())
636                 || (mAudioApi == AudioApi::Unspecified && isAAudioRecommended());
637     }
638 
639     /**
640      * Create and open a stream object based on the current settings.
641      *
642      * The caller owns the pointer to the AudioStream object
643      * and must delete it when finished.
644      *
645      * @deprecated Use openStream(std::shared_ptr<oboe::AudioStream> &stream) instead.
646      * @param stream pointer to a variable to receive the stream address
647      * @return OBOE_OK if successful or a negative error code
648      */
649     Result openStream(AudioStream **stream);
650 
651     /**
652      * Create and open a stream object based on the current settings.
653      *
654      * The caller shares the pointer to the AudioStream object.
655      * The shared_ptr is used internally by Oboe to prevent the stream from being
656      * deleted while it is being used by callbacks.
657      *
658      * @param stream reference to a shared_ptr to receive the stream address
659      * @return OBOE_OK if successful or a negative error code
660      */
661     Result openStream(std::shared_ptr<oboe::AudioStream> &stream);
662 
663     /**
664      * Create and open a ManagedStream object based on the current builder state.
665      *
666      * The caller must create a unique ptr, and pass by reference so it can be
667      * modified to point to an opened stream. The caller owns the unique ptr,
668      * and it will be automatically closed and deleted when going out of scope.
669      *
670      * @deprecated Use openStream(std::shared_ptr<oboe::AudioStream> &stream) instead.
671      * @param stream Reference to the ManagedStream (uniqueptr) used to keep track of stream
672      * @return OBOE_OK if successful or a negative error code.
673      */
674     Result openManagedStream(ManagedStream &stream);
675 
676 private:
677 
678     /**
679      * Use this internally to implement opening with a shared_ptr.
680      *
681      * @param stream pointer to a variable to receive the stream address
682      * @return OBOE_OK if successful or a negative error code.
683      */
684     Result openStreamInternal(AudioStream **streamPP);
685 
686     /**
687      * @param other
688      * @return true if channels, format and sample rate match
689      */
690     bool isCompatible(AudioStreamBase &other);
691 
692     /**
693      * Create an AudioStream object. The AudioStream must be opened before use.
694      *
695      * The caller owns the pointer.
696      *
697      * @return pointer to an AudioStream object or nullptr.
698      */
699     oboe::AudioStream *build();
700 
701     AudioApi       mAudioApi = AudioApi::Unspecified;
702 };
703 
704 } // namespace oboe
705 
706 #endif /* OBOE_STREAM_BUILDER_H_ */
707