1 /* 2 * libjingle 3 * Copyright 2012, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/app/webrtc/test/fakeaudiocapturemodule.h" 29 30 #include "webrtc/base/common.h" 31 #include "webrtc/base/refcount.h" 32 #include "webrtc/base/thread.h" 33 #include "webrtc/base/timeutils.h" 34 35 // Audio sample value that is high enough that it doesn't occur naturally when 36 // frames are being faked. E.g. NetEq will not generate this large sample value 37 // unless it has received an audio frame containing a sample of this value. 38 // Even simpler buffers would likely just contain audio sample values of 0. 39 static const int kHighSampleValue = 10000; 40 41 // Same value as src/modules/audio_device/main/source/audio_device_config.h in 42 // https://code.google.com/p/webrtc/ 43 static const uint32 kAdmMaxIdleTimeProcess = 1000; 44 45 // Constants here are derived by running VoE using a real ADM. 46 // The constants correspond to 10ms of mono audio at 44kHz. 47 static const int kTimePerFrameMs = 10; 48 static const int kNumberOfChannels = 1; 49 static const int kSamplesPerSecond = 44000; 50 static const int kTotalDelayMs = 0; 51 static const int kClockDriftMs = 0; 52 static const uint32_t kMaxVolume = 14392; 53 54 enum { 55 MSG_START_PROCESS, 56 MSG_RUN_PROCESS, 57 MSG_STOP_PROCESS, 58 }; 59 60 FakeAudioCaptureModule::FakeAudioCaptureModule( 61 rtc::Thread* process_thread) 62 : last_process_time_ms_(0), 63 audio_callback_(NULL), 64 recording_(false), 65 playing_(false), 66 play_is_initialized_(false), 67 rec_is_initialized_(false), 68 current_mic_level_(kMaxVolume), 69 started_(false), 70 next_frame_time_(0), 71 process_thread_(process_thread), 72 frames_received_(0) { 73 } 74 75 FakeAudioCaptureModule::~FakeAudioCaptureModule() { 76 // Ensure that thread stops calling ProcessFrame(). 77 process_thread_->Send(this, MSG_STOP_PROCESS); 78 } 79 80 rtc::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create( 81 rtc::Thread* process_thread) { 82 if (process_thread == NULL) return NULL; 83 84 rtc::scoped_refptr<FakeAudioCaptureModule> capture_module( 85 new rtc::RefCountedObject<FakeAudioCaptureModule>(process_thread)); 86 if (!capture_module->Initialize()) { 87 return NULL; 88 } 89 return capture_module; 90 } 91 92 int FakeAudioCaptureModule::frames_received() const { 93 rtc::CritScope cs(&crit_); 94 return frames_received_; 95 } 96 97 int32_t FakeAudioCaptureModule::TimeUntilNextProcess() { 98 const uint32 current_time = rtc::Time(); 99 if (current_time < last_process_time_ms_) { 100 // TODO: wraparound could be handled more gracefully. 101 return 0; 102 } 103 const uint32 elapsed_time = current_time - last_process_time_ms_; 104 if (kAdmMaxIdleTimeProcess < elapsed_time) { 105 return 0; 106 } 107 return kAdmMaxIdleTimeProcess - elapsed_time; 108 } 109 110 int32_t FakeAudioCaptureModule::Process() { 111 last_process_time_ms_ = rtc::Time(); 112 return 0; 113 } 114 115 int32_t FakeAudioCaptureModule::ChangeUniqueId(const int32_t /*id*/) { 116 ASSERT(false); 117 return 0; 118 } 119 120 int32_t FakeAudioCaptureModule::ActiveAudioLayer( 121 AudioLayer* /*audio_layer*/) const { 122 ASSERT(false); 123 return 0; 124 } 125 126 webrtc::AudioDeviceModule::ErrorCode FakeAudioCaptureModule::LastError() const { 127 ASSERT(false); 128 return webrtc::AudioDeviceModule::kAdmErrNone; 129 } 130 131 int32_t FakeAudioCaptureModule::RegisterEventObserver( 132 webrtc::AudioDeviceObserver* /*event_callback*/) { 133 // Only used to report warnings and errors. This fake implementation won't 134 // generate any so discard this callback. 135 return 0; 136 } 137 138 int32_t FakeAudioCaptureModule::RegisterAudioCallback( 139 webrtc::AudioTransport* audio_callback) { 140 rtc::CritScope cs(&crit_callback_); 141 audio_callback_ = audio_callback; 142 return 0; 143 } 144 145 int32_t FakeAudioCaptureModule::Init() { 146 // Initialize is called by the factory method. Safe to ignore this Init call. 147 return 0; 148 } 149 150 int32_t FakeAudioCaptureModule::Terminate() { 151 // Clean up in the destructor. No action here, just success. 152 return 0; 153 } 154 155 bool FakeAudioCaptureModule::Initialized() const { 156 ASSERT(false); 157 return 0; 158 } 159 160 int16_t FakeAudioCaptureModule::PlayoutDevices() { 161 ASSERT(false); 162 return 0; 163 } 164 165 int16_t FakeAudioCaptureModule::RecordingDevices() { 166 ASSERT(false); 167 return 0; 168 } 169 170 int32_t FakeAudioCaptureModule::PlayoutDeviceName( 171 uint16_t /*index*/, 172 char /*name*/[webrtc::kAdmMaxDeviceNameSize], 173 char /*guid*/[webrtc::kAdmMaxGuidSize]) { 174 ASSERT(false); 175 return 0; 176 } 177 178 int32_t FakeAudioCaptureModule::RecordingDeviceName( 179 uint16_t /*index*/, 180 char /*name*/[webrtc::kAdmMaxDeviceNameSize], 181 char /*guid*/[webrtc::kAdmMaxGuidSize]) { 182 ASSERT(false); 183 return 0; 184 } 185 186 int32_t FakeAudioCaptureModule::SetPlayoutDevice(uint16_t /*index*/) { 187 // No playout device, just playing from file. Return success. 188 return 0; 189 } 190 191 int32_t FakeAudioCaptureModule::SetPlayoutDevice(WindowsDeviceType /*device*/) { 192 if (play_is_initialized_) { 193 return -1; 194 } 195 return 0; 196 } 197 198 int32_t FakeAudioCaptureModule::SetRecordingDevice(uint16_t /*index*/) { 199 // No recording device, just dropping audio. Return success. 200 return 0; 201 } 202 203 int32_t FakeAudioCaptureModule::SetRecordingDevice( 204 WindowsDeviceType /*device*/) { 205 if (rec_is_initialized_) { 206 return -1; 207 } 208 return 0; 209 } 210 211 int32_t FakeAudioCaptureModule::PlayoutIsAvailable(bool* /*available*/) { 212 ASSERT(false); 213 return 0; 214 } 215 216 int32_t FakeAudioCaptureModule::InitPlayout() { 217 play_is_initialized_ = true; 218 return 0; 219 } 220 221 bool FakeAudioCaptureModule::PlayoutIsInitialized() const { 222 return play_is_initialized_; 223 } 224 225 int32_t FakeAudioCaptureModule::RecordingIsAvailable(bool* /*available*/) { 226 ASSERT(false); 227 return 0; 228 } 229 230 int32_t FakeAudioCaptureModule::InitRecording() { 231 rec_is_initialized_ = true; 232 return 0; 233 } 234 235 bool FakeAudioCaptureModule::RecordingIsInitialized() const { 236 ASSERT(false); 237 return 0; 238 } 239 240 int32_t FakeAudioCaptureModule::StartPlayout() { 241 if (!play_is_initialized_) { 242 return -1; 243 } 244 { 245 rtc::CritScope cs(&crit_); 246 playing_ = true; 247 } 248 bool start = true; 249 UpdateProcessing(start); 250 return 0; 251 } 252 253 int32_t FakeAudioCaptureModule::StopPlayout() { 254 bool start = false; 255 { 256 rtc::CritScope cs(&crit_); 257 playing_ = false; 258 start = ShouldStartProcessing(); 259 } 260 UpdateProcessing(start); 261 return 0; 262 } 263 264 bool FakeAudioCaptureModule::Playing() const { 265 rtc::CritScope cs(&crit_); 266 return playing_; 267 } 268 269 int32_t FakeAudioCaptureModule::StartRecording() { 270 if (!rec_is_initialized_) { 271 return -1; 272 } 273 { 274 rtc::CritScope cs(&crit_); 275 recording_ = true; 276 } 277 bool start = true; 278 UpdateProcessing(start); 279 return 0; 280 } 281 282 int32_t FakeAudioCaptureModule::StopRecording() { 283 bool start = false; 284 { 285 rtc::CritScope cs(&crit_); 286 recording_ = false; 287 start = ShouldStartProcessing(); 288 } 289 UpdateProcessing(start); 290 return 0; 291 } 292 293 bool FakeAudioCaptureModule::Recording() const { 294 rtc::CritScope cs(&crit_); 295 return recording_; 296 } 297 298 int32_t FakeAudioCaptureModule::SetAGC(bool /*enable*/) { 299 // No AGC but not needed since audio is pregenerated. Return success. 300 return 0; 301 } 302 303 bool FakeAudioCaptureModule::AGC() const { 304 ASSERT(false); 305 return 0; 306 } 307 308 int32_t FakeAudioCaptureModule::SetWaveOutVolume(uint16_t /*volume_left*/, 309 uint16_t /*volume_right*/) { 310 ASSERT(false); 311 return 0; 312 } 313 314 int32_t FakeAudioCaptureModule::WaveOutVolume( 315 uint16_t* /*volume_left*/, 316 uint16_t* /*volume_right*/) const { 317 ASSERT(false); 318 return 0; 319 } 320 321 int32_t FakeAudioCaptureModule::InitSpeaker() { 322 // No speaker, just playing from file. Return success. 323 return 0; 324 } 325 326 bool FakeAudioCaptureModule::SpeakerIsInitialized() const { 327 ASSERT(false); 328 return 0; 329 } 330 331 int32_t FakeAudioCaptureModule::InitMicrophone() { 332 // No microphone, just playing from file. Return success. 333 return 0; 334 } 335 336 bool FakeAudioCaptureModule::MicrophoneIsInitialized() const { 337 ASSERT(false); 338 return 0; 339 } 340 341 int32_t FakeAudioCaptureModule::SpeakerVolumeIsAvailable(bool* /*available*/) { 342 ASSERT(false); 343 return 0; 344 } 345 346 int32_t FakeAudioCaptureModule::SetSpeakerVolume(uint32_t /*volume*/) { 347 ASSERT(false); 348 return 0; 349 } 350 351 int32_t FakeAudioCaptureModule::SpeakerVolume(uint32_t* /*volume*/) const { 352 ASSERT(false); 353 return 0; 354 } 355 356 int32_t FakeAudioCaptureModule::MaxSpeakerVolume( 357 uint32_t* /*max_volume*/) const { 358 ASSERT(false); 359 return 0; 360 } 361 362 int32_t FakeAudioCaptureModule::MinSpeakerVolume( 363 uint32_t* /*min_volume*/) const { 364 ASSERT(false); 365 return 0; 366 } 367 368 int32_t FakeAudioCaptureModule::SpeakerVolumeStepSize( 369 uint16_t* /*step_size*/) const { 370 ASSERT(false); 371 return 0; 372 } 373 374 int32_t FakeAudioCaptureModule::MicrophoneVolumeIsAvailable( 375 bool* /*available*/) { 376 ASSERT(false); 377 return 0; 378 } 379 380 int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) { 381 rtc::CritScope cs(&crit_); 382 current_mic_level_ = volume; 383 return 0; 384 } 385 386 int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const { 387 rtc::CritScope cs(&crit_); 388 *volume = current_mic_level_; 389 return 0; 390 } 391 392 int32_t FakeAudioCaptureModule::MaxMicrophoneVolume( 393 uint32_t* max_volume) const { 394 *max_volume = kMaxVolume; 395 return 0; 396 } 397 398 int32_t FakeAudioCaptureModule::MinMicrophoneVolume( 399 uint32_t* /*min_volume*/) const { 400 ASSERT(false); 401 return 0; 402 } 403 404 int32_t FakeAudioCaptureModule::MicrophoneVolumeStepSize( 405 uint16_t* /*step_size*/) const { 406 ASSERT(false); 407 return 0; 408 } 409 410 int32_t FakeAudioCaptureModule::SpeakerMuteIsAvailable(bool* /*available*/) { 411 ASSERT(false); 412 return 0; 413 } 414 415 int32_t FakeAudioCaptureModule::SetSpeakerMute(bool /*enable*/) { 416 ASSERT(false); 417 return 0; 418 } 419 420 int32_t FakeAudioCaptureModule::SpeakerMute(bool* /*enabled*/) const { 421 ASSERT(false); 422 return 0; 423 } 424 425 int32_t FakeAudioCaptureModule::MicrophoneMuteIsAvailable(bool* /*available*/) { 426 ASSERT(false); 427 return 0; 428 } 429 430 int32_t FakeAudioCaptureModule::SetMicrophoneMute(bool /*enable*/) { 431 ASSERT(false); 432 return 0; 433 } 434 435 int32_t FakeAudioCaptureModule::MicrophoneMute(bool* /*enabled*/) const { 436 ASSERT(false); 437 return 0; 438 } 439 440 int32_t FakeAudioCaptureModule::MicrophoneBoostIsAvailable( 441 bool* /*available*/) { 442 ASSERT(false); 443 return 0; 444 } 445 446 int32_t FakeAudioCaptureModule::SetMicrophoneBoost(bool /*enable*/) { 447 ASSERT(false); 448 return 0; 449 } 450 451 int32_t FakeAudioCaptureModule::MicrophoneBoost(bool* /*enabled*/) const { 452 ASSERT(false); 453 return 0; 454 } 455 456 int32_t FakeAudioCaptureModule::StereoPlayoutIsAvailable( 457 bool* available) const { 458 // No recording device, just dropping audio. Stereo can be dropped just 459 // as easily as mono. 460 *available = true; 461 return 0; 462 } 463 464 int32_t FakeAudioCaptureModule::SetStereoPlayout(bool /*enable*/) { 465 // No recording device, just dropping audio. Stereo can be dropped just 466 // as easily as mono. 467 return 0; 468 } 469 470 int32_t FakeAudioCaptureModule::StereoPlayout(bool* /*enabled*/) const { 471 ASSERT(false); 472 return 0; 473 } 474 475 int32_t FakeAudioCaptureModule::StereoRecordingIsAvailable( 476 bool* available) const { 477 // Keep thing simple. No stereo recording. 478 *available = false; 479 return 0; 480 } 481 482 int32_t FakeAudioCaptureModule::SetStereoRecording(bool enable) { 483 if (!enable) { 484 return 0; 485 } 486 return -1; 487 } 488 489 int32_t FakeAudioCaptureModule::StereoRecording(bool* /*enabled*/) const { 490 ASSERT(false); 491 return 0; 492 } 493 494 int32_t FakeAudioCaptureModule::SetRecordingChannel( 495 const ChannelType channel) { 496 if (channel != AudioDeviceModule::kChannelBoth) { 497 // There is no right or left in mono. I.e. kChannelBoth should be used for 498 // mono. 499 ASSERT(false); 500 return -1; 501 } 502 return 0; 503 } 504 505 int32_t FakeAudioCaptureModule::RecordingChannel(ChannelType* channel) const { 506 // Stereo recording not supported. However, WebRTC ADM returns kChannelBoth 507 // in that case. Do the same here. 508 *channel = AudioDeviceModule::kChannelBoth; 509 return 0; 510 } 511 512 int32_t FakeAudioCaptureModule::SetPlayoutBuffer(const BufferType /*type*/, 513 uint16_t /*size_ms*/) { 514 ASSERT(false); 515 return 0; 516 } 517 518 int32_t FakeAudioCaptureModule::PlayoutBuffer(BufferType* /*type*/, 519 uint16_t* /*size_ms*/) const { 520 ASSERT(false); 521 return 0; 522 } 523 524 int32_t FakeAudioCaptureModule::PlayoutDelay(uint16_t* delay_ms) const { 525 // No delay since audio frames are dropped. 526 *delay_ms = 0; 527 return 0; 528 } 529 530 int32_t FakeAudioCaptureModule::RecordingDelay(uint16_t* /*delay_ms*/) const { 531 ASSERT(false); 532 return 0; 533 } 534 535 int32_t FakeAudioCaptureModule::CPULoad(uint16_t* /*load*/) const { 536 ASSERT(false); 537 return 0; 538 } 539 540 int32_t FakeAudioCaptureModule::StartRawOutputFileRecording( 541 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) { 542 ASSERT(false); 543 return 0; 544 } 545 546 int32_t FakeAudioCaptureModule::StopRawOutputFileRecording() { 547 ASSERT(false); 548 return 0; 549 } 550 551 int32_t FakeAudioCaptureModule::StartRawInputFileRecording( 552 const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) { 553 ASSERT(false); 554 return 0; 555 } 556 557 int32_t FakeAudioCaptureModule::StopRawInputFileRecording() { 558 ASSERT(false); 559 return 0; 560 } 561 562 int32_t FakeAudioCaptureModule::SetRecordingSampleRate( 563 const uint32_t /*samples_per_sec*/) { 564 ASSERT(false); 565 return 0; 566 } 567 568 int32_t FakeAudioCaptureModule::RecordingSampleRate( 569 uint32_t* /*samples_per_sec*/) const { 570 ASSERT(false); 571 return 0; 572 } 573 574 int32_t FakeAudioCaptureModule::SetPlayoutSampleRate( 575 const uint32_t /*samples_per_sec*/) { 576 ASSERT(false); 577 return 0; 578 } 579 580 int32_t FakeAudioCaptureModule::PlayoutSampleRate( 581 uint32_t* /*samples_per_sec*/) const { 582 ASSERT(false); 583 return 0; 584 } 585 586 int32_t FakeAudioCaptureModule::ResetAudioDevice() { 587 ASSERT(false); 588 return 0; 589 } 590 591 int32_t FakeAudioCaptureModule::SetLoudspeakerStatus(bool /*enable*/) { 592 ASSERT(false); 593 return 0; 594 } 595 596 int32_t FakeAudioCaptureModule::GetLoudspeakerStatus(bool* /*enabled*/) const { 597 ASSERT(false); 598 return 0; 599 } 600 601 void FakeAudioCaptureModule::OnMessage(rtc::Message* msg) { 602 switch (msg->message_id) { 603 case MSG_START_PROCESS: 604 StartProcessP(); 605 break; 606 case MSG_RUN_PROCESS: 607 ProcessFrameP(); 608 break; 609 case MSG_STOP_PROCESS: 610 StopProcessP(); 611 break; 612 default: 613 // All existing messages should be caught. Getting here should never 614 // happen. 615 ASSERT(false); 616 } 617 } 618 619 bool FakeAudioCaptureModule::Initialize() { 620 // Set the send buffer samples high enough that it would not occur on the 621 // remote side unless a packet containing a sample of that magnitude has been 622 // sent to it. Note that the audio processing pipeline will likely distort the 623 // original signal. 624 SetSendBuffer(kHighSampleValue); 625 last_process_time_ms_ = rtc::Time(); 626 return true; 627 } 628 629 void FakeAudioCaptureModule::SetSendBuffer(int value) { 630 Sample* buffer_ptr = reinterpret_cast<Sample*>(send_buffer_); 631 const int buffer_size_in_samples = sizeof(send_buffer_) / 632 kNumberBytesPerSample; 633 for (int i = 0; i < buffer_size_in_samples; ++i) { 634 buffer_ptr[i] = value; 635 } 636 } 637 638 void FakeAudioCaptureModule::ResetRecBuffer() { 639 memset(rec_buffer_, 0, sizeof(rec_buffer_)); 640 } 641 642 bool FakeAudioCaptureModule::CheckRecBuffer(int value) { 643 const Sample* buffer_ptr = reinterpret_cast<const Sample*>(rec_buffer_); 644 const int buffer_size_in_samples = sizeof(rec_buffer_) / 645 kNumberBytesPerSample; 646 for (int i = 0; i < buffer_size_in_samples; ++i) { 647 if (buffer_ptr[i] >= value) return true; 648 } 649 return false; 650 } 651 652 bool FakeAudioCaptureModule::ShouldStartProcessing() { 653 return recording_ || playing_; 654 } 655 656 void FakeAudioCaptureModule::UpdateProcessing(bool start) { 657 if (start) { 658 process_thread_->Post(this, MSG_START_PROCESS); 659 } else { 660 process_thread_->Send(this, MSG_STOP_PROCESS); 661 } 662 } 663 664 void FakeAudioCaptureModule::StartProcessP() { 665 ASSERT(rtc::Thread::Current() == process_thread_); 666 if (started_) { 667 // Already started. 668 return; 669 } 670 ProcessFrameP(); 671 } 672 673 void FakeAudioCaptureModule::ProcessFrameP() { 674 ASSERT(rtc::Thread::Current() == process_thread_); 675 if (!started_) { 676 next_frame_time_ = rtc::Time(); 677 started_ = true; 678 } 679 680 bool playing; 681 bool recording; 682 { 683 rtc::CritScope cs(&crit_); 684 playing = playing_; 685 recording = recording_; 686 } 687 688 // Receive and send frames every kTimePerFrameMs. 689 if (playing) { 690 ReceiveFrameP(); 691 } 692 if (recording) { 693 SendFrameP(); 694 } 695 696 next_frame_time_ += kTimePerFrameMs; 697 const uint32 current_time = rtc::Time(); 698 const uint32 wait_time = (next_frame_time_ > current_time) ? 699 next_frame_time_ - current_time : 0; 700 process_thread_->PostDelayed(wait_time, this, MSG_RUN_PROCESS); 701 } 702 703 void FakeAudioCaptureModule::ReceiveFrameP() { 704 ASSERT(rtc::Thread::Current() == process_thread_); 705 { 706 rtc::CritScope cs(&crit_callback_); 707 if (!audio_callback_) { 708 return; 709 } 710 ResetRecBuffer(); 711 uint32_t nSamplesOut = 0; 712 #ifdef USE_WEBRTC_DEV_BRANCH 713 int64_t elapsed_time_ms = 0; 714 #else 715 uint32_t rtp_timestamp = 0; 716 #endif 717 int64_t ntp_time_ms = 0; 718 if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample, 719 kNumberOfChannels, kSamplesPerSecond, 720 rec_buffer_, nSamplesOut, 721 #ifdef USE_WEBRTC_DEV_BRANCH 722 &elapsed_time_ms, &ntp_time_ms) != 0) { 723 #else 724 &rtp_timestamp, &ntp_time_ms) != 0) { 725 #endif 726 ASSERT(false); 727 } 728 ASSERT(nSamplesOut == kNumberSamples); 729 } 730 // The SetBuffer() function ensures that after decoding, the audio buffer 731 // should contain samples of similar magnitude (there is likely to be some 732 // distortion due to the audio pipeline). If one sample is detected to 733 // have the same or greater magnitude somewhere in the frame, an actual frame 734 // has been received from the remote side (i.e. faked frames are not being 735 // pulled). 736 if (CheckRecBuffer(kHighSampleValue)) { 737 rtc::CritScope cs(&crit_); 738 ++frames_received_; 739 } 740 } 741 742 void FakeAudioCaptureModule::SendFrameP() { 743 ASSERT(rtc::Thread::Current() == process_thread_); 744 rtc::CritScope cs(&crit_callback_); 745 if (!audio_callback_) { 746 return; 747 } 748 bool key_pressed = false; 749 uint32_t current_mic_level = 0; 750 MicrophoneVolume(¤t_mic_level); 751 if (audio_callback_->RecordedDataIsAvailable(send_buffer_, kNumberSamples, 752 kNumberBytesPerSample, 753 kNumberOfChannels, 754 kSamplesPerSecond, kTotalDelayMs, 755 kClockDriftMs, current_mic_level, 756 key_pressed, 757 current_mic_level) != 0) { 758 ASSERT(false); 759 } 760 SetMicrophoneVolume(current_mic_level); 761 } 762 763 void FakeAudioCaptureModule::StopProcessP() { 764 ASSERT(rtc::Thread::Current() == process_thread_); 765 started_ = false; 766 process_thread_->Clear(this); 767 } 768