@@ -322,42 +322,51 @@ pub fn set_device_sample_rate(device_id: AudioDeviceID, new_rate: f64) -> Result
322
322
}
323
323
}
324
324
325
- /// Find the closest match of the physical formats to the provided StreamFormat.
326
- /// Note that only the sample format and rate will be matched, the flags will be ignored.
325
+ /// Find the closest match of the physical formats to the provided `StreamFormat`.
326
+ /// It will pick the first format it finds that supports the provided sample format, rate and number of channels.
327
+ /// The provided format flags in the `StreamFormat` are ignored.
327
328
pub fn find_matching_physical_format (
328
329
device_id : AudioDeviceID ,
329
330
stream_format : StreamFormat ,
330
331
) -> Option < AudioStreamBasicDescription > {
331
332
if let Ok ( all_formats) = get_supported_physical_stream_formats ( device_id) {
332
- let wanted_samplerate = stream_format. sample_rate as usize ;
333
- let wanted_bits = stream_format. sample_format . size_in_bits ( ) ;
334
- let wanted_float = stream_format. sample_format == SampleFormat :: F32 ;
335
- let wanted_channels = stream_format. channels ;
333
+ let requested_samplerate = stream_format. sample_rate as usize ;
334
+ let requested_bits = stream_format. sample_format . size_in_bits ( ) ;
335
+ let requested_float = stream_format. sample_format == SampleFormat :: F32 ;
336
+ let requested_channels = stream_format. channels ;
336
337
for fmt in all_formats {
337
- let minrate = fmt. mSampleRateRange . mMinimum as usize ;
338
- let maxrate = fmt. mSampleRateRange . mMaximum as usize ;
338
+ let min_rate = fmt. mSampleRateRange . mMinimum as usize ;
339
+ let max_rate = fmt. mSampleRateRange . mMaximum as usize ;
339
340
let rate = fmt. mFormat . mSampleRate as usize ;
340
341
let channels = fmt. mFormat . mChannelsPerFrame ;
341
342
if let Some ( AudioFormat :: LinearPCM ( flags) ) = AudioFormat :: from_format_and_flag (
342
343
fmt. mFormat . mFormatID ,
343
344
Some ( fmt. mFormat . mFormatFlags ) ,
344
345
) {
345
- let floats = flags. contains ( LinearPcmFlags :: IS_FLOAT ) ;
346
- let ints = flags. contains ( LinearPcmFlags :: IS_SIGNED_INTEGER ) ;
347
- if wanted_float != floats || wanted_float == ints {
346
+ let is_float = flags. contains ( LinearPcmFlags :: IS_FLOAT ) ;
347
+ let is_int = flags. contains ( LinearPcmFlags :: IS_SIGNED_INTEGER ) ;
348
+ if is_int && is_float {
349
+ // Probably never occurs, check just in case
350
+ continue ;
351
+ }
352
+ if requested_float && !is_float {
353
+ // Wrong number type
354
+ continue ;
355
+ }
356
+ if !requested_float && !is_int {
348
357
// Wrong number type
349
358
continue ;
350
359
}
351
- if wanted_bits != fmt. mFormat . mBitsPerChannel {
360
+ if requested_bits != fmt. mFormat . mBitsPerChannel {
352
361
// Wrong number of bits
353
362
continue ;
354
363
}
355
- if wanted_channels > channels {
364
+ if requested_channels > channels {
356
365
// Too few channels
357
366
continue ;
358
367
}
359
- if rate == wanted_samplerate
360
- || ( wanted_samplerate >= minrate && wanted_samplerate <= maxrate )
368
+ if rate == requested_samplerate
369
+ || ( requested_samplerate >= min_rate && requested_samplerate <= max_rate )
361
370
{
362
371
return Some ( fmt. mFormat ) ;
363
372
}
@@ -373,9 +382,8 @@ pub fn set_device_physical_stream_format(
373
382
device_id : AudioDeviceID ,
374
383
new_asbd : AudioStreamBasicDescription ,
375
384
) -> Result < ( ) , Error > {
376
- // Check whether or not we need to change the device sample format and rate.
377
385
unsafe {
378
- // Get the current sample rate .
386
+ // Get the current format .
379
387
let property_address = AudioObjectPropertyAddress {
380
388
mSelector : kAudioStreamPropertyPhysicalFormat,
381
389
mScope : kAudioObjectPropertyScopeGlobal,
@@ -393,10 +401,7 @@ pub fn set_device_physical_stream_format(
393
401
) ;
394
402
Error :: from_os_status ( status) ?;
395
403
let asbd = maybe_asbd. assume_init ( ) ;
396
- //println!("Current: {:?}", asbd);
397
- //println!("New: {:?}", new_asbd);
398
404
399
- // If the requested sample rate and/or format is different to the device sample rate, update the device.
400
405
if !asbds_are_equal ( & asbd, & new_asbd) {
401
406
let property_address = AudioObjectPropertyAddress {
402
407
mSelector : kAudioStreamPropertyPhysicalFormat,
@@ -419,8 +424,7 @@ pub fn set_device_physical_stream_format(
419
424
Error :: from_os_status ( status) ?;
420
425
421
426
// Wait for the reported format to change.
422
- //
423
- // This should not take longer than a few ms, but we timeout after 1 sec just in case.
427
+ // This can take up to half a second, but we timeout after 2 sec just in case.
424
428
let timer = :: std:: time:: Instant :: now ( ) ;
425
429
loop {
426
430
let status = AudioObjectGetPropertyData (
@@ -460,20 +464,15 @@ fn asbds_are_equal(
460
464
&& left. mBitsPerChannel == right. mBitsPerChannel
461
465
}
462
466
463
- /// Get a vector with all supported physical formats as AudioBasicStreamDescriptions .
467
+ /// Get a vector with all supported physical formats as AudioBasicRangedDescriptions .
464
468
/// Only implemented for macOS, not iOS.
465
- /// TODO: figure out why this sometimes crashes with:
466
- /// malloc: Incorrect checksum for freed object 0x7fca6bc3c538: probably modified after being freed.
467
469
pub fn get_supported_physical_stream_formats (
468
470
device_id : AudioDeviceID ,
469
471
) -> Result < Vec < AudioStreamRangedDescription > , Error > {
470
472
// Get available formats.
471
473
let mut property_address = AudioObjectPropertyAddress {
472
474
mSelector : kAudioStreamPropertyPhysicalFormat,
473
475
mScope : kAudioObjectPropertyScopeGlobal,
474
- //mScope: kAudioDevicePropertyScopeInput,
475
- //mScope: kAudioObjectPropertyScopeOutput,
476
- //mScope: kAudioDevicePropertyScopeOutput,
477
476
mElement : kAudioObjectPropertyElementMaster,
478
477
} ;
479
478
let allformats = unsafe {
@@ -503,15 +502,6 @@ pub fn get_supported_physical_stream_formats(
503
502
Error :: from_os_status ( status) ?;
504
503
formats
505
504
} ;
506
- /*
507
- println!("---- All supported formats ----");
508
- for asbd in formats.iter() {
509
- if let Ok(sf) = StreamFormat::from_asbd(*asbd) {
510
- println!("{:#?}", asbd);
511
- println!("{:#?}", sf);
512
- }
513
- }
514
- */
515
505
Ok ( allformats)
516
506
}
517
507
0 commit comments