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 * Specifies an object to handle data related callbacks from the underlying API. 353 * 354 * <strong>Important: See AudioStreamCallback for restrictions on what may be called 355 * from the callback methods.</strong> 356 * 357 * We pass a shared_ptr so that the sharedDataCallback object cannot be deleted 358 * before the stream is deleted. 359 * 360 * @param sharedDataCallback 361 * @return pointer to the builder so calls can be chained 362 */ setDataCallback(std::shared_ptr<AudioStreamDataCallback> sharedDataCallback)363 AudioStreamBuilder *setDataCallback(std::shared_ptr<AudioStreamDataCallback> sharedDataCallback) { 364 // Use this raw pointer in the rest of the code to retain backwards compatibility. 365 mDataCallback = sharedDataCallback.get(); 366 // Hold a shared_ptr to protect the raw pointer for the lifetime of the stream. 367 mSharedDataCallback = sharedDataCallback; 368 return this; 369 } 370 371 /** 372 * Pass a raw pointer to a data callback. This is not recommended because the dataCallback 373 * object might get deleted by the app while it is being used. 374 * 375 * @deprecated Call setDataCallback(std::shared_ptr<AudioStreamDataCallback>) instead. 376 * @param dataCallback 377 * @return pointer to the builder so calls can be chained 378 */ setDataCallback(AudioStreamDataCallback * dataCallback)379 AudioStreamBuilder *setDataCallback(AudioStreamDataCallback *dataCallback) { 380 mDataCallback = dataCallback; 381 mSharedDataCallback = nullptr; 382 return this; 383 } 384 385 /** 386 * Specifies an object to handle error related callbacks from the underlying API. 387 * This can occur when a stream is disconnected because a headset is plugged in or unplugged. 388 * It can also occur if the audio service fails or if an exclusive stream is stolen by 389 * another stream. 390 * 391 * <strong>Important: See AudioStreamCallback for restrictions on what may be called 392 * from the callback methods.</strong> 393 * 394 * <strong>When an error callback occurs, the associated stream must be stopped and closed 395 * in a separate thread.</strong> 396 * 397 * We pass a shared_ptr so that the errorCallback object cannot be deleted before the stream is deleted. 398 * If the stream was created using a shared_ptr then the stream cannot be deleted before the 399 * error callback has finished running. 400 * 401 * @param sharedErrorCallback 402 * @return pointer to the builder so calls can be chained 403 */ setErrorCallback(std::shared_ptr<AudioStreamErrorCallback> sharedErrorCallback)404 AudioStreamBuilder *setErrorCallback(std::shared_ptr<AudioStreamErrorCallback> sharedErrorCallback) { 405 // Use this raw pointer in the rest of the code to retain backwards compatibility. 406 mErrorCallback = sharedErrorCallback.get(); 407 // Hold a shared_ptr to protect the raw pointer for the lifetime of the stream. 408 mSharedErrorCallback = sharedErrorCallback; 409 return this; 410 } 411 412 /** 413 * Pass a raw pointer to an error callback. This is not recommended because the errorCallback 414 * object might get deleted by the app while it is being used. 415 * 416 * @deprecated Call setErrorCallback(std::shared_ptr<AudioStreamErrorCallback>) instead. 417 * @param errorCallback 418 * @return pointer to the builder so calls can be chained 419 */ setErrorCallback(AudioStreamErrorCallback * errorCallback)420 AudioStreamBuilder *setErrorCallback(AudioStreamErrorCallback *errorCallback) { 421 mErrorCallback = errorCallback; 422 mSharedErrorCallback = nullptr; 423 return this; 424 } 425 426 /** 427 * Specifies an object to handle data or error related callbacks from the underlying API. 428 * 429 * This is the equivalent of calling both setDataCallback() and setErrorCallback(). 430 * 431 * <strong>Important: See AudioStreamCallback for restrictions on what may be called 432 * from the callback methods.</strong> 433 * 434 * @deprecated Call setDataCallback(std::shared_ptr<AudioStreamDataCallback>) and 435 * setErrorCallback(std::shared_ptr<AudioStreamErrorCallback>) instead. 436 * @param streamCallback 437 * @return pointer to the builder so calls can be chained 438 */ setCallback(AudioStreamCallback * streamCallback)439 AudioStreamBuilder *setCallback(AudioStreamCallback *streamCallback) { 440 // Use the same callback object for both, dual inheritance. 441 mDataCallback = streamCallback; 442 mErrorCallback = streamCallback; 443 return this; 444 } 445 446 /** 447 * If true then Oboe might convert channel counts to achieve optimal results. 448 * On some versions of Android for example, stereo streams could not use a FAST track. 449 * So a mono stream might be used instead and duplicated to two channels. 450 * On some devices, mono streams might be broken, so a stereo stream might be opened 451 * and converted to mono. 452 * 453 * Default is false. 454 */ setChannelConversionAllowed(bool allowed)455 AudioStreamBuilder *setChannelConversionAllowed(bool allowed) { 456 mChannelConversionAllowed = allowed; 457 return this; 458 } 459 460 /** 461 * If true then Oboe might convert data formats to achieve optimal results. 462 * On some versions of Android, for example, a float stream could not get a 463 * low latency data path. So an I16 stream might be opened and converted to float. 464 * 465 * Default is false. 466 */ setFormatConversionAllowed(bool allowed)467 AudioStreamBuilder *setFormatConversionAllowed(bool allowed) { 468 mFormatConversionAllowed = allowed; 469 return this; 470 } 471 472 /** 473 * Specify the quality of the sample rate converter in Oboe. 474 * 475 * If set to None then Oboe will not do sample rate conversion. But the underlying APIs might 476 * still do sample rate conversion if you specify a sample rate. 477 * That can prevent you from getting a low latency stream. 478 * 479 * If you do the conversion in Oboe then you might still get a low latency stream. 480 * 481 * Default is SampleRateConversionQuality::None 482 */ setSampleRateConversionQuality(SampleRateConversionQuality quality)483 AudioStreamBuilder *setSampleRateConversionQuality(SampleRateConversionQuality quality) { 484 mSampleRateConversionQuality = quality; 485 return this; 486 } 487 488 /** 489 * Declare the name of the package creating the stream. 490 * 491 * This is usually {@code Context#getPackageName()}. 492 * 493 * The default, if you do not call this function, is a random package in the calling uid. 494 * The vast majority of apps have only one package per calling UID. 495 * If an invalid package name is set, input streams may not be given permission to 496 * record when started. 497 * 498 * The package name is usually the applicationId in your app's build.gradle file. 499 * 500 * Available since API level 31. 501 * 502 * @param packageName packageName of the calling app. 503 */ setPackageName(std::string packageName)504 AudioStreamBuilder *setPackageName(std::string packageName) { 505 mPackageName = packageName; 506 return this; 507 } 508 509 /** 510 * Declare the attribution tag of the context creating the stream. 511 * 512 * This is usually {@code Context#getAttributionTag()}. 513 * 514 * The default, if you do not call this function, is null. 515 * 516 * Available since API level 31. 517 * 518 * @param attributionTag attributionTag of the calling context. 519 */ setAttributionTag(std::string attributionTag)520 AudioStreamBuilder *setAttributionTag(std::string attributionTag) { 521 mAttributionTag = attributionTag; 522 return this; 523 } 524 525 /** 526 * @return true if AAudio will be used based on the current settings. 527 */ willUseAAudio()528 bool willUseAAudio() const { 529 return (mAudioApi == AudioApi::AAudio && isAAudioSupported()) 530 || (mAudioApi == AudioApi::Unspecified && isAAudioRecommended()); 531 } 532 533 /** 534 * Create and open a stream object based on the current settings. 535 * 536 * The caller owns the pointer to the AudioStream object 537 * and must delete it when finished. 538 * 539 * @deprecated Use openStream(std::shared_ptr<oboe::AudioStream> &stream) instead. 540 * @param stream pointer to a variable to receive the stream address 541 * @return OBOE_OK if successful or a negative error code 542 */ 543 Result openStream(AudioStream **stream); 544 545 /** 546 * Create and open a stream object based on the current settings. 547 * 548 * The caller shares the pointer to the AudioStream object. 549 * The shared_ptr is used internally by Oboe to prevent the stream from being 550 * deleted while it is being used by callbacks. 551 * 552 * @param stream reference to a shared_ptr to receive the stream address 553 * @return OBOE_OK if successful or a negative error code 554 */ 555 Result openStream(std::shared_ptr<oboe::AudioStream> &stream); 556 557 /** 558 * Create and open a ManagedStream object based on the current builder state. 559 * 560 * The caller must create a unique ptr, and pass by reference so it can be 561 * modified to point to an opened stream. The caller owns the unique ptr, 562 * and it will be automatically closed and deleted when going out of scope. 563 * 564 * @deprecated Use openStream(std::shared_ptr<oboe::AudioStream> &stream) instead. 565 * @param stream Reference to the ManagedStream (uniqueptr) used to keep track of stream 566 * @return OBOE_OK if successful or a negative error code. 567 */ 568 Result openManagedStream(ManagedStream &stream); 569 570 private: 571 572 /** 573 * @param other 574 * @return true if channels, format and sample rate match 575 */ 576 bool isCompatible(AudioStreamBase &other); 577 578 /** 579 * Create an AudioStream object. The AudioStream must be opened before use. 580 * 581 * The caller owns the pointer. 582 * 583 * @return pointer to an AudioStream object or nullptr. 584 */ 585 oboe::AudioStream *build(); 586 587 AudioApi mAudioApi = AudioApi::Unspecified; 588 }; 589 590 } // namespace oboe 591 592 #endif /* OBOE_STREAM_BUILDER_H_ */ 593