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