|
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 |
|
@@ -672,6 +680,61 @@ static void LogDeviceInfo() {
|
672 | 680 | last_output_volume_change_time_ = rtc::TimeMillis();
|
673 | 681 | }
|
674 | 682 |
|
| 683 | +void AudioDeviceIOS::HandleAudioWillRecord() { |
| 684 | + RTC_DCHECK_RUN_ON(&thread_checker_); |
| 685 | + |
| 686 | + LOGI() << "HandleAudioWillRecord"; |
| 687 | + |
| 688 | + // If we don't have an audio unit yet, or the audio unit is uninitialized, |
| 689 | + // there is no work to do. |
| 690 | + if (!audio_unit_ || audio_unit_->GetState() < VoiceProcessingAudioUnit::kInitialized) { |
| 691 | + return; |
| 692 | + } |
| 693 | + |
| 694 | + // The audio unit is already initialized or started. |
| 695 | + // Check to see if the sample rate or buffer size has changed. |
| 696 | + RTC_OBJC_TYPE(RTCAudioSession)* session = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance]; |
| 697 | + const double session_sample_rate = session.sampleRate; |
| 698 | + |
| 699 | + // Extra sanity check to ensure that the new sample rate is valid. |
| 700 | + if (session_sample_rate <= 0.0) { |
| 701 | + RTCLogError(@"Sample rate is invalid: %f", session_sample_rate); |
| 702 | + LOGI() << "Sample rate is invalid " << session_sample_rate; |
| 703 | + return; |
| 704 | + } |
| 705 | + // We need to adjust our format and buffer sizes. |
| 706 | + // The stream format is about to be changed and it requires that we first |
| 707 | + // stop and uninitialize the audio unit to deallocate its resources. |
| 708 | + RTCLog(@"Stopping and uninitializing audio unit to adjust buffers."); |
| 709 | + bool restart_audio_unit = false; |
| 710 | + if (audio_unit_->GetState() == VoiceProcessingAudioUnit::kStarted) { |
| 711 | + audio_unit_->Stop(); |
| 712 | + restart_audio_unit = true; |
| 713 | + PrepareForNewStart(); |
| 714 | + } |
| 715 | + if (audio_unit_->GetState() == VoiceProcessingAudioUnit::kInitialized) { |
| 716 | + audio_unit_->Uninitialize(); |
| 717 | + } |
| 718 | + |
| 719 | + // Allocate new buffers given the new stream format. |
| 720 | + SetupAudioBuffersForActiveAudioSession(); |
| 721 | + |
| 722 | + // Initialize the audio unit again with the new sample rate. |
| 723 | + RTC_DCHECK_EQ(playout_parameters_.sample_rate(), session_sample_rate); |
| 724 | + if (!audio_unit_->Initialize(session_sample_rate)) { |
| 725 | + RTCLogError(@"Failed to initialize the audio unit with sample rate: %f", session_sample_rate); |
| 726 | + return; |
| 727 | + } |
| 728 | + |
| 729 | + // Restart the audio unit if it was already running. |
| 730 | + if (restart_audio_unit && !audio_unit_->Start()) { |
| 731 | + RTCLogError(@"Failed to start audio unit with sample rate: %f", session_sample_rate); |
| 732 | + return; |
| 733 | + } |
| 734 | + |
| 735 | + LOGI() << "Successfully enabled audio unit for recording."; |
| 736 | +} |
| 737 | + |
675 | 738 | void AudioDeviceIOS::UpdateAudioDeviceBuffer() {
|
676 | 739 | LOGI() << "UpdateAudioDevicebuffer";
|
677 | 740 | // AttachAudioBuffer() is called at construction by the main class but check
|
|
0 commit comments