|
68 | 68 | kMessageTypeCanPlayOrRecordChange, |
69 | 69 | kMessageTypePlayoutGlitchDetected, |
70 | 70 | kMessageOutputVolumeChange, |
| 71 | + kMessageTypeAudioWillRecord, |
71 | 72 | }; |
72 | 73 |
|
73 | 74 | using ios::CheckAndLogError; |
@@ -373,6 +374,11 @@ static void LogDeviceInfo() { |
373 | 374 | thread_->Post(RTC_FROM_HERE, this, kMessageOutputVolumeChange); |
374 | 375 | } |
375 | 376 |
|
| 377 | +void AudioDeviceIOS::OnAudioWillRecord() { |
| 378 | + RTC_DCHECK(thread_); |
| 379 | + thread_->Post(RTC_FROM_HERE, this, kMessageTypeAudioWillRecord); |
| 380 | +} |
| 381 | + |
376 | 382 | OSStatus AudioDeviceIOS::OnDeliverRecordedData(AudioUnitRenderActionFlags* flags, |
377 | 383 | const AudioTimeStamp* time_stamp, |
378 | 384 | UInt32 bus_number, |
@@ -458,7 +464,7 @@ static void LogDeviceInfo() { |
458 | 464 | // Exclude extreme delta values since they do most likely not correspond |
459 | 465 | // to a real glitch. Instead, the most probable cause is that a headset |
460 | 466 | // has been plugged in or out. There are more direct ways to detect |
461 | | - // audio device changes (see HandleValidRouteChange()) but experiments |
| 467 | + // audio device changes (see ValidRouteChange()) but experiments |
462 | 468 | // show that using it leads to more complex implementations. |
463 | 469 | // TODO(henrika): more tests might be needed to come up with an even |
464 | 470 | // better upper limit. |
@@ -503,6 +509,8 @@ static void LogDeviceInfo() { |
503 | 509 | case kMessageOutputVolumeChange: |
504 | 510 | HandleOutputVolumeChange(); |
505 | 511 | break; |
| 512 | + case kMessageTypeAudioWillRecord: |
| 513 | + HandleAudioWillRecord(); |
506 | 514 | } |
507 | 515 | } |
508 | 516 |
|
@@ -673,6 +681,61 @@ static void LogDeviceInfo() { |
673 | 681 | last_output_volume_change_time_ = rtc::TimeMillis(); |
674 | 682 | } |
675 | 683 |
|
| 684 | +void AudioDeviceIOS::HandleAudioWillRecord() { |
| 685 | + RTC_DCHECK_RUN_ON(&thread_checker_); |
| 686 | + |
| 687 | + LOGI() << "HandleAudioWillRecord"; |
| 688 | + |
| 689 | + // If we don't have an audio unit yet, or the audio unit is uninitialized, |
| 690 | + // there is no work to do. |
| 691 | + if (!audio_unit_ || audio_unit_->GetState() < VoiceProcessingAudioUnit::kInitialized) { |
| 692 | + return; |
| 693 | + } |
| 694 | + |
| 695 | + // The audio unit is already initialized or started. |
| 696 | + // Check to see if the sample rate or buffer size has changed. |
| 697 | + RTC_OBJC_TYPE(RTCAudioSession)* session = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance]; |
| 698 | + const double session_sample_rate = session.sampleRate; |
| 699 | + |
| 700 | + // Extra sanity check to ensure that the new sample rate is valid. |
| 701 | + if (session_sample_rate <= 0.0) { |
| 702 | + RTCLogError(@"Sample rate is invalid: %f", session_sample_rate); |
| 703 | + LOGI() << "Sample rate is invalid " << session_sample_rate; |
| 704 | + return; |
| 705 | + } |
| 706 | + // We need to adjust our format and buffer sizes. |
| 707 | + // The stream format is about to be changed and it requires that we first |
| 708 | + // stop and uninitialize the audio unit to deallocate its resources. |
| 709 | + RTCLog(@"Stopping and uninitializing audio unit to adjust buffers."); |
| 710 | + bool restart_audio_unit = false; |
| 711 | + if (audio_unit_->GetState() == VoiceProcessingAudioUnit::kStarted) { |
| 712 | + audio_unit_->Stop(); |
| 713 | + restart_audio_unit = true; |
| 714 | + PrepareForNewStart(); |
| 715 | + } |
| 716 | + if (audio_unit_->GetState() == VoiceProcessingAudioUnit::kInitialized) { |
| 717 | + audio_unit_->Uninitialize(); |
| 718 | + } |
| 719 | + |
| 720 | + // Allocate new buffers given the new stream format. |
| 721 | + SetupAudioBuffersForActiveAudioSession(); |
| 722 | + |
| 723 | + // Initialize the audio unit again with the new sample rate. |
| 724 | + RTC_DCHECK_EQ(playout_parameters_.sample_rate(), session_sample_rate); |
| 725 | + if (!audio_unit_->Initialize(session_sample_rate)) { |
| 726 | + RTCLogError(@"Failed to initialize the audio unit with sample rate: %f", session_sample_rate); |
| 727 | + return; |
| 728 | + } |
| 729 | + |
| 730 | + // Restart the audio unit if it was already running. |
| 731 | + if (restart_audio_unit && !audio_unit_->Start()) { |
| 732 | + RTCLogError(@"Failed to start audio unit with sample rate: %f", session_sample_rate); |
| 733 | + return; |
| 734 | + } |
| 735 | + |
| 736 | + LOGI() << "Successfully enabled audio unit for recording."; |
| 737 | +} |
| 738 | + |
676 | 739 | void AudioDeviceIOS::UpdateAudioDeviceBuffer() { |
677 | 740 | LOGI() << "UpdateAudioDevicebuffer"; |
678 | 741 | // AttachAudioBuffer() is called at construction by the main class but check |
|
0 commit comments