1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/audio_device/audio_device_buffer.h" 12 13 #include <assert.h> 14 #include <string.h> 15 16 #include "webrtc/modules/audio_device/audio_device_config.h" 17 #include "webrtc/modules/audio_device/audio_device_utility.h" 18 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 19 #include "webrtc/system_wrappers/interface/logging.h" 20 #include "webrtc/system_wrappers/interface/trace.h" 21 22 namespace webrtc { 23 24 static const int kHighDelayThresholdMs = 300; 25 static const int kLogHighDelayIntervalFrames = 500; // 5 seconds. 26 27 // ---------------------------------------------------------------------------- 28 // ctor 29 // ---------------------------------------------------------------------------- 30 31 AudioDeviceBuffer::AudioDeviceBuffer() : 32 _id(-1), 33 _critSect(*CriticalSectionWrapper::CreateCriticalSection()), 34 _critSectCb(*CriticalSectionWrapper::CreateCriticalSection()), 35 _ptrCbAudioTransport(NULL), 36 _recSampleRate(0), 37 _playSampleRate(0), 38 _recChannels(0), 39 _playChannels(0), 40 _recChannel(AudioDeviceModule::kChannelBoth), 41 _recBytesPerSample(0), 42 _playBytesPerSample(0), 43 _recSamples(0), 44 _recSize(0), 45 _playSamples(0), 46 _playSize(0), 47 _recFile(*FileWrapper::Create()), 48 _playFile(*FileWrapper::Create()), 49 _currentMicLevel(0), 50 _newMicLevel(0), 51 _typingStatus(false), 52 _playDelayMS(0), 53 _recDelayMS(0), 54 _clockDrift(0), 55 // Set to the interval in order to log on the first occurrence. 56 high_delay_counter_(kLogHighDelayIntervalFrames) { 57 // valid ID will be set later by SetId, use -1 for now 58 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s created", __FUNCTION__); 59 memset(_recBuffer, 0, kMaxBufferSizeBytes); 60 memset(_playBuffer, 0, kMaxBufferSizeBytes); 61 } 62 63 // ---------------------------------------------------------------------------- 64 // dtor 65 // ---------------------------------------------------------------------------- 66 67 AudioDeviceBuffer::~AudioDeviceBuffer() 68 { 69 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTION__); 70 { 71 CriticalSectionScoped lock(&_critSect); 72 73 _recFile.Flush(); 74 _recFile.CloseFile(); 75 delete &_recFile; 76 77 _playFile.Flush(); 78 _playFile.CloseFile(); 79 delete &_playFile; 80 } 81 82 delete &_critSect; 83 delete &_critSectCb; 84 } 85 86 // ---------------------------------------------------------------------------- 87 // SetId 88 // ---------------------------------------------------------------------------- 89 90 void AudioDeviceBuffer::SetId(uint32_t id) 91 { 92 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "AudioDeviceBuffer::SetId(id=%d)", id); 93 _id = id; 94 } 95 96 // ---------------------------------------------------------------------------- 97 // RegisterAudioCallback 98 // ---------------------------------------------------------------------------- 99 100 int32_t AudioDeviceBuffer::RegisterAudioCallback(AudioTransport* audioCallback) 101 { 102 CriticalSectionScoped lock(&_critSectCb); 103 _ptrCbAudioTransport = audioCallback; 104 105 return 0; 106 } 107 108 // ---------------------------------------------------------------------------- 109 // InitPlayout 110 // ---------------------------------------------------------------------------- 111 112 int32_t AudioDeviceBuffer::InitPlayout() 113 { 114 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__); 115 return 0; 116 } 117 118 // ---------------------------------------------------------------------------- 119 // InitRecording 120 // ---------------------------------------------------------------------------- 121 122 int32_t AudioDeviceBuffer::InitRecording() 123 { 124 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__); 125 return 0; 126 } 127 128 // ---------------------------------------------------------------------------- 129 // SetRecordingSampleRate 130 // ---------------------------------------------------------------------------- 131 132 int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz) 133 { 134 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingSampleRate(fsHz=%u)", fsHz); 135 136 CriticalSectionScoped lock(&_critSect); 137 _recSampleRate = fsHz; 138 return 0; 139 } 140 141 // ---------------------------------------------------------------------------- 142 // SetPlayoutSampleRate 143 // ---------------------------------------------------------------------------- 144 145 int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz) 146 { 147 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutSampleRate(fsHz=%u)", fsHz); 148 149 CriticalSectionScoped lock(&_critSect); 150 _playSampleRate = fsHz; 151 return 0; 152 } 153 154 // ---------------------------------------------------------------------------- 155 // RecordingSampleRate 156 // ---------------------------------------------------------------------------- 157 158 int32_t AudioDeviceBuffer::RecordingSampleRate() const 159 { 160 return _recSampleRate; 161 } 162 163 // ---------------------------------------------------------------------------- 164 // PlayoutSampleRate 165 // ---------------------------------------------------------------------------- 166 167 int32_t AudioDeviceBuffer::PlayoutSampleRate() const 168 { 169 return _playSampleRate; 170 } 171 172 // ---------------------------------------------------------------------------- 173 // SetRecordingChannels 174 // ---------------------------------------------------------------------------- 175 176 int32_t AudioDeviceBuffer::SetRecordingChannels(uint8_t channels) 177 { 178 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingChannels(channels=%u)", channels); 179 180 CriticalSectionScoped lock(&_critSect); 181 _recChannels = channels; 182 _recBytesPerSample = 2*channels; // 16 bits per sample in mono, 32 bits in stereo 183 return 0; 184 } 185 186 // ---------------------------------------------------------------------------- 187 // SetPlayoutChannels 188 // ---------------------------------------------------------------------------- 189 190 int32_t AudioDeviceBuffer::SetPlayoutChannels(uint8_t channels) 191 { 192 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutChannels(channels=%u)", channels); 193 194 CriticalSectionScoped lock(&_critSect); 195 _playChannels = channels; 196 // 16 bits per sample in mono, 32 bits in stereo 197 _playBytesPerSample = 2*channels; 198 return 0; 199 } 200 201 // ---------------------------------------------------------------------------- 202 // SetRecordingChannel 203 // 204 // Select which channel to use while recording. 205 // This API requires that stereo is enabled. 206 // 207 // Note that, the nChannel parameter in RecordedDataIsAvailable will be 208 // set to 2 even for kChannelLeft and kChannelRight. However, nBytesPerSample 209 // will be 2 instead of 4 four these cases. 210 // ---------------------------------------------------------------------------- 211 212 int32_t AudioDeviceBuffer::SetRecordingChannel(const AudioDeviceModule::ChannelType channel) 213 { 214 CriticalSectionScoped lock(&_critSect); 215 216 if (_recChannels == 1) 217 { 218 return -1; 219 } 220 221 if (channel == AudioDeviceModule::kChannelBoth) 222 { 223 // two bytes per channel 224 _recBytesPerSample = 4; 225 } 226 else 227 { 228 // only utilize one out of two possible channels (left or right) 229 _recBytesPerSample = 2; 230 } 231 _recChannel = channel; 232 233 return 0; 234 } 235 236 // ---------------------------------------------------------------------------- 237 // RecordingChannel 238 // ---------------------------------------------------------------------------- 239 240 int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const 241 { 242 channel = _recChannel; 243 return 0; 244 } 245 246 // ---------------------------------------------------------------------------- 247 // RecordingChannels 248 // ---------------------------------------------------------------------------- 249 250 uint8_t AudioDeviceBuffer::RecordingChannels() const 251 { 252 return _recChannels; 253 } 254 255 // ---------------------------------------------------------------------------- 256 // PlayoutChannels 257 // ---------------------------------------------------------------------------- 258 259 uint8_t AudioDeviceBuffer::PlayoutChannels() const 260 { 261 return _playChannels; 262 } 263 264 // ---------------------------------------------------------------------------- 265 // SetCurrentMicLevel 266 // ---------------------------------------------------------------------------- 267 268 int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level) 269 { 270 _currentMicLevel = level; 271 return 0; 272 } 273 274 int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus) 275 { 276 _typingStatus = typingStatus; 277 return 0; 278 } 279 280 // ---------------------------------------------------------------------------- 281 // NewMicLevel 282 // ---------------------------------------------------------------------------- 283 284 uint32_t AudioDeviceBuffer::NewMicLevel() const 285 { 286 return _newMicLevel; 287 } 288 289 // ---------------------------------------------------------------------------- 290 // SetVQEData 291 // ---------------------------------------------------------------------------- 292 293 void AudioDeviceBuffer::SetVQEData(int playDelayMs, int recDelayMs, 294 int clockDrift) { 295 if (high_delay_counter_ < kLogHighDelayIntervalFrames) { 296 ++high_delay_counter_; 297 } else { 298 if (playDelayMs + recDelayMs > kHighDelayThresholdMs) { 299 high_delay_counter_ = 0; 300 LOG(LS_WARNING) << "High audio device delay reported (render=" 301 << playDelayMs << " ms, capture=" << recDelayMs << " ms)"; 302 } 303 } 304 305 _playDelayMS = playDelayMs; 306 _recDelayMS = recDelayMs; 307 _clockDrift = clockDrift; 308 } 309 310 // ---------------------------------------------------------------------------- 311 // StartInputFileRecording 312 // ---------------------------------------------------------------------------- 313 314 int32_t AudioDeviceBuffer::StartInputFileRecording( 315 const char fileName[kAdmMaxFileNameSize]) 316 { 317 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__); 318 319 CriticalSectionScoped lock(&_critSect); 320 321 _recFile.Flush(); 322 _recFile.CloseFile(); 323 324 return (_recFile.OpenFile(fileName, false, false, false)); 325 } 326 327 // ---------------------------------------------------------------------------- 328 // StopInputFileRecording 329 // ---------------------------------------------------------------------------- 330 331 int32_t AudioDeviceBuffer::StopInputFileRecording() 332 { 333 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__); 334 335 CriticalSectionScoped lock(&_critSect); 336 337 _recFile.Flush(); 338 _recFile.CloseFile(); 339 340 return 0; 341 } 342 343 // ---------------------------------------------------------------------------- 344 // StartOutputFileRecording 345 // ---------------------------------------------------------------------------- 346 347 int32_t AudioDeviceBuffer::StartOutputFileRecording( 348 const char fileName[kAdmMaxFileNameSize]) 349 { 350 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__); 351 352 CriticalSectionScoped lock(&_critSect); 353 354 _playFile.Flush(); 355 _playFile.CloseFile(); 356 357 return (_playFile.OpenFile(fileName, false, false, false)); 358 } 359 360 // ---------------------------------------------------------------------------- 361 // StopOutputFileRecording 362 // ---------------------------------------------------------------------------- 363 364 int32_t AudioDeviceBuffer::StopOutputFileRecording() 365 { 366 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__); 367 368 CriticalSectionScoped lock(&_critSect); 369 370 _playFile.Flush(); 371 _playFile.CloseFile(); 372 373 return 0; 374 } 375 376 // ---------------------------------------------------------------------------- 377 // SetRecordedBuffer 378 // 379 // Store recorded audio buffer in local memory ready for the actual 380 // "delivery" using a callback. 381 // 382 // This method can also parse out left or right channel from a stereo 383 // input signal, i.e., emulate mono. 384 // 385 // Examples: 386 // 387 // 16-bit,48kHz mono, 10ms => nSamples=480 => _recSize=2*480=960 bytes 388 // 16-bit,48kHz stereo,10ms => nSamples=480 => _recSize=4*480=1920 bytes 389 // ---------------------------------------------------------------------------- 390 391 int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer, 392 uint32_t nSamples) 393 { 394 CriticalSectionScoped lock(&_critSect); 395 396 if (_recBytesPerSample == 0) 397 { 398 assert(false); 399 return -1; 400 } 401 402 _recSamples = nSamples; 403 _recSize = _recBytesPerSample*nSamples; // {2,4}*nSamples 404 if (_recSize > kMaxBufferSizeBytes) 405 { 406 assert(false); 407 return -1; 408 } 409 410 if (nSamples != _recSamples) 411 { 412 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "invalid number of recorded samples (%d)", nSamples); 413 return -1; 414 } 415 416 if (_recChannel == AudioDeviceModule::kChannelBoth) 417 { 418 // (default) copy the complete input buffer to the local buffer 419 memcpy(&_recBuffer[0], audioBuffer, _recSize); 420 } 421 else 422 { 423 int16_t* ptr16In = (int16_t*)audioBuffer; 424 int16_t* ptr16Out = (int16_t*)&_recBuffer[0]; 425 426 if (AudioDeviceModule::kChannelRight == _recChannel) 427 { 428 ptr16In++; 429 } 430 431 // exctract left or right channel from input buffer to the local buffer 432 for (uint32_t i = 0; i < _recSamples; i++) 433 { 434 *ptr16Out = *ptr16In; 435 ptr16Out++; 436 ptr16In++; 437 ptr16In++; 438 } 439 } 440 441 if (_recFile.Open()) 442 { 443 // write to binary file in mono or stereo (interleaved) 444 _recFile.Write(&_recBuffer[0], _recSize); 445 } 446 447 return 0; 448 } 449 450 // ---------------------------------------------------------------------------- 451 // DeliverRecordedData 452 // ---------------------------------------------------------------------------- 453 454 int32_t AudioDeviceBuffer::DeliverRecordedData() 455 { 456 CriticalSectionScoped lock(&_critSectCb); 457 458 // Ensure that user has initialized all essential members 459 if ((_recSampleRate == 0) || 460 (_recSamples == 0) || 461 (_recBytesPerSample == 0) || 462 (_recChannels == 0)) 463 { 464 assert(false); 465 return -1; 466 } 467 468 if (_ptrCbAudioTransport == NULL) 469 { 470 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to deliver recorded data (AudioTransport does not exist)"); 471 return 0; 472 } 473 474 int32_t res(0); 475 uint32_t newMicLevel(0); 476 uint32_t totalDelayMS = _playDelayMS +_recDelayMS; 477 478 res = _ptrCbAudioTransport->RecordedDataIsAvailable(&_recBuffer[0], 479 _recSamples, 480 _recBytesPerSample, 481 _recChannels, 482 _recSampleRate, 483 totalDelayMS, 484 _clockDrift, 485 _currentMicLevel, 486 _typingStatus, 487 newMicLevel); 488 if (res != -1) 489 { 490 _newMicLevel = newMicLevel; 491 } 492 493 return 0; 494 } 495 496 // ---------------------------------------------------------------------------- 497 // RequestPlayoutData 498 // ---------------------------------------------------------------------------- 499 500 int32_t AudioDeviceBuffer::RequestPlayoutData(uint32_t nSamples) 501 { 502 uint32_t playSampleRate = 0; 503 uint8_t playBytesPerSample = 0; 504 uint8_t playChannels = 0; 505 { 506 CriticalSectionScoped lock(&_critSect); 507 508 // Store copies under lock and use copies hereafter to avoid race with 509 // setter methods. 510 playSampleRate = _playSampleRate; 511 playBytesPerSample = _playBytesPerSample; 512 playChannels = _playChannels; 513 514 // Ensure that user has initialized all essential members 515 if ((playBytesPerSample == 0) || 516 (playChannels == 0) || 517 (playSampleRate == 0)) 518 { 519 assert(false); 520 return -1; 521 } 522 523 _playSamples = nSamples; 524 _playSize = playBytesPerSample * nSamples; // {2,4}*nSamples 525 if (_playSize > kMaxBufferSizeBytes) 526 { 527 assert(false); 528 return -1; 529 } 530 531 if (nSamples != _playSamples) 532 { 533 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "invalid number of samples to be played out (%d)", nSamples); 534 return -1; 535 } 536 } 537 538 uint32_t nSamplesOut(0); 539 540 CriticalSectionScoped lock(&_critSectCb); 541 542 if (_ptrCbAudioTransport == NULL) 543 { 544 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to feed data to playout (AudioTransport does not exist)"); 545 return 0; 546 } 547 548 if (_ptrCbAudioTransport) 549 { 550 uint32_t res(0); 551 int64_t elapsed_time_ms = -1; 552 int64_t ntp_time_ms = -1; 553 res = _ptrCbAudioTransport->NeedMorePlayData(_playSamples, 554 playBytesPerSample, 555 playChannels, 556 playSampleRate, 557 &_playBuffer[0], 558 nSamplesOut, 559 &elapsed_time_ms, 560 &ntp_time_ms); 561 if (res != 0) 562 { 563 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "NeedMorePlayData() failed"); 564 } 565 } 566 567 return nSamplesOut; 568 } 569 570 // ---------------------------------------------------------------------------- 571 // GetPlayoutData 572 // ---------------------------------------------------------------------------- 573 574 int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer) 575 { 576 CriticalSectionScoped lock(&_critSect); 577 578 if (_playSize > kMaxBufferSizeBytes) 579 { 580 WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "_playSize %i exceeds " 581 "kMaxBufferSizeBytes in AudioDeviceBuffer::GetPlayoutData", _playSize); 582 assert(false); 583 return -1; 584 } 585 586 memcpy(audioBuffer, &_playBuffer[0], _playSize); 587 588 if (_playFile.Open()) 589 { 590 // write to binary file in mono or stereo (interleaved) 591 _playFile.Write(&_playBuffer[0], _playSize); 592 } 593 594 return _playSamples; 595 } 596 597 } // namespace webrtc 598