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