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