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/base/format_macros.h" 17 #include "webrtc/modules/audio_device/audio_device_config.h" 18 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" 19 #include "webrtc/system_wrappers/include/logging.h" 20 #include "webrtc/system_wrappers/include/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 CriticalSectionScoped lock(&_critSect); 135 _recSampleRate = fsHz; 136 return 0; 137 } 138 139 // ---------------------------------------------------------------------------- 140 // SetPlayoutSampleRate 141 // ---------------------------------------------------------------------------- 142 143 int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz) 144 { 145 CriticalSectionScoped lock(&_critSect); 146 _playSampleRate = fsHz; 147 return 0; 148 } 149 150 // ---------------------------------------------------------------------------- 151 // RecordingSampleRate 152 // ---------------------------------------------------------------------------- 153 154 int32_t AudioDeviceBuffer::RecordingSampleRate() const 155 { 156 return _recSampleRate; 157 } 158 159 // ---------------------------------------------------------------------------- 160 // PlayoutSampleRate 161 // ---------------------------------------------------------------------------- 162 163 int32_t AudioDeviceBuffer::PlayoutSampleRate() const 164 { 165 return _playSampleRate; 166 } 167 168 // ---------------------------------------------------------------------------- 169 // SetRecordingChannels 170 // ---------------------------------------------------------------------------- 171 172 int32_t AudioDeviceBuffer::SetRecordingChannels(size_t channels) 173 { 174 CriticalSectionScoped lock(&_critSect); 175 _recChannels = channels; 176 _recBytesPerSample = 2*channels; // 16 bits per sample in mono, 32 bits in stereo 177 return 0; 178 } 179 180 // ---------------------------------------------------------------------------- 181 // SetPlayoutChannels 182 // ---------------------------------------------------------------------------- 183 184 int32_t AudioDeviceBuffer::SetPlayoutChannels(size_t channels) 185 { 186 CriticalSectionScoped lock(&_critSect); 187 _playChannels = channels; 188 // 16 bits per sample in mono, 32 bits in stereo 189 _playBytesPerSample = 2*channels; 190 return 0; 191 } 192 193 // ---------------------------------------------------------------------------- 194 // SetRecordingChannel 195 // 196 // Select which channel to use while recording. 197 // This API requires that stereo is enabled. 198 // 199 // Note that, the nChannel parameter in RecordedDataIsAvailable will be 200 // set to 2 even for kChannelLeft and kChannelRight. However, nBytesPerSample 201 // will be 2 instead of 4 four these cases. 202 // ---------------------------------------------------------------------------- 203 204 int32_t AudioDeviceBuffer::SetRecordingChannel(const AudioDeviceModule::ChannelType channel) 205 { 206 CriticalSectionScoped lock(&_critSect); 207 208 if (_recChannels == 1) 209 { 210 return -1; 211 } 212 213 if (channel == AudioDeviceModule::kChannelBoth) 214 { 215 // two bytes per channel 216 _recBytesPerSample = 4; 217 } 218 else 219 { 220 // only utilize one out of two possible channels (left or right) 221 _recBytesPerSample = 2; 222 } 223 _recChannel = channel; 224 225 return 0; 226 } 227 228 // ---------------------------------------------------------------------------- 229 // RecordingChannel 230 // ---------------------------------------------------------------------------- 231 232 int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const 233 { 234 channel = _recChannel; 235 return 0; 236 } 237 238 // ---------------------------------------------------------------------------- 239 // RecordingChannels 240 // ---------------------------------------------------------------------------- 241 242 size_t AudioDeviceBuffer::RecordingChannels() const 243 { 244 return _recChannels; 245 } 246 247 // ---------------------------------------------------------------------------- 248 // PlayoutChannels 249 // ---------------------------------------------------------------------------- 250 251 size_t AudioDeviceBuffer::PlayoutChannels() const 252 { 253 return _playChannels; 254 } 255 256 // ---------------------------------------------------------------------------- 257 // SetCurrentMicLevel 258 // ---------------------------------------------------------------------------- 259 260 int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level) 261 { 262 _currentMicLevel = level; 263 return 0; 264 } 265 266 int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus) 267 { 268 _typingStatus = typingStatus; 269 return 0; 270 } 271 272 // ---------------------------------------------------------------------------- 273 // NewMicLevel 274 // ---------------------------------------------------------------------------- 275 276 uint32_t AudioDeviceBuffer::NewMicLevel() const 277 { 278 return _newMicLevel; 279 } 280 281 // ---------------------------------------------------------------------------- 282 // SetVQEData 283 // ---------------------------------------------------------------------------- 284 285 void AudioDeviceBuffer::SetVQEData(int playDelayMs, int recDelayMs, 286 int clockDrift) { 287 if (high_delay_counter_ < kLogHighDelayIntervalFrames) { 288 ++high_delay_counter_; 289 } else { 290 if (playDelayMs + recDelayMs > kHighDelayThresholdMs) { 291 high_delay_counter_ = 0; 292 LOG(LS_WARNING) << "High audio device delay reported (render=" 293 << playDelayMs << " ms, capture=" << recDelayMs << " ms)"; 294 } 295 } 296 297 _playDelayMS = playDelayMs; 298 _recDelayMS = recDelayMs; 299 _clockDrift = clockDrift; 300 } 301 302 // ---------------------------------------------------------------------------- 303 // StartInputFileRecording 304 // ---------------------------------------------------------------------------- 305 306 int32_t AudioDeviceBuffer::StartInputFileRecording( 307 const char fileName[kAdmMaxFileNameSize]) 308 { 309 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__); 310 311 CriticalSectionScoped lock(&_critSect); 312 313 _recFile.Flush(); 314 _recFile.CloseFile(); 315 316 return (_recFile.OpenFile(fileName, false, false, false)); 317 } 318 319 // ---------------------------------------------------------------------------- 320 // StopInputFileRecording 321 // ---------------------------------------------------------------------------- 322 323 int32_t AudioDeviceBuffer::StopInputFileRecording() 324 { 325 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__); 326 327 CriticalSectionScoped lock(&_critSect); 328 329 _recFile.Flush(); 330 _recFile.CloseFile(); 331 332 return 0; 333 } 334 335 // ---------------------------------------------------------------------------- 336 // StartOutputFileRecording 337 // ---------------------------------------------------------------------------- 338 339 int32_t AudioDeviceBuffer::StartOutputFileRecording( 340 const char fileName[kAdmMaxFileNameSize]) 341 { 342 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__); 343 344 CriticalSectionScoped lock(&_critSect); 345 346 _playFile.Flush(); 347 _playFile.CloseFile(); 348 349 return (_playFile.OpenFile(fileName, false, false, false)); 350 } 351 352 // ---------------------------------------------------------------------------- 353 // StopOutputFileRecording 354 // ---------------------------------------------------------------------------- 355 356 int32_t AudioDeviceBuffer::StopOutputFileRecording() 357 { 358 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__); 359 360 CriticalSectionScoped lock(&_critSect); 361 362 _playFile.Flush(); 363 _playFile.CloseFile(); 364 365 return 0; 366 } 367 368 // ---------------------------------------------------------------------------- 369 // SetRecordedBuffer 370 // 371 // Store recorded audio buffer in local memory ready for the actual 372 // "delivery" using a callback. 373 // 374 // This method can also parse out left or right channel from a stereo 375 // input signal, i.e., emulate mono. 376 // 377 // Examples: 378 // 379 // 16-bit,48kHz mono, 10ms => nSamples=480 => _recSize=2*480=960 bytes 380 // 16-bit,48kHz stereo,10ms => nSamples=480 => _recSize=4*480=1920 bytes 381 // ---------------------------------------------------------------------------- 382 383 int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer, 384 size_t nSamples) 385 { 386 CriticalSectionScoped lock(&_critSect); 387 388 if (_recBytesPerSample == 0) 389 { 390 assert(false); 391 return -1; 392 } 393 394 _recSamples = nSamples; 395 _recSize = _recBytesPerSample*nSamples; // {2,4}*nSamples 396 if (_recSize > kMaxBufferSizeBytes) 397 { 398 assert(false); 399 return -1; 400 } 401 402 if (_recChannel == AudioDeviceModule::kChannelBoth) 403 { 404 // (default) copy the complete input buffer to the local buffer 405 memcpy(&_recBuffer[0], audioBuffer, _recSize); 406 } 407 else 408 { 409 int16_t* ptr16In = (int16_t*)audioBuffer; 410 int16_t* ptr16Out = (int16_t*)&_recBuffer[0]; 411 412 if (AudioDeviceModule::kChannelRight == _recChannel) 413 { 414 ptr16In++; 415 } 416 417 // exctract left or right channel from input buffer to the local buffer 418 for (size_t i = 0; i < _recSamples; i++) 419 { 420 *ptr16Out = *ptr16In; 421 ptr16Out++; 422 ptr16In++; 423 ptr16In++; 424 } 425 } 426 427 if (_recFile.Open()) 428 { 429 // write to binary file in mono or stereo (interleaved) 430 _recFile.Write(&_recBuffer[0], _recSize); 431 } 432 433 return 0; 434 } 435 436 // ---------------------------------------------------------------------------- 437 // DeliverRecordedData 438 // ---------------------------------------------------------------------------- 439 440 int32_t AudioDeviceBuffer::DeliverRecordedData() 441 { 442 CriticalSectionScoped lock(&_critSectCb); 443 444 // Ensure that user has initialized all essential members 445 if ((_recSampleRate == 0) || 446 (_recSamples == 0) || 447 (_recBytesPerSample == 0) || 448 (_recChannels == 0)) 449 { 450 assert(false); 451 return -1; 452 } 453 454 if (_ptrCbAudioTransport == NULL) 455 { 456 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to deliver recorded data (AudioTransport does not exist)"); 457 return 0; 458 } 459 460 int32_t res(0); 461 uint32_t newMicLevel(0); 462 uint32_t totalDelayMS = _playDelayMS +_recDelayMS; 463 464 res = _ptrCbAudioTransport->RecordedDataIsAvailable(&_recBuffer[0], 465 _recSamples, 466 _recBytesPerSample, 467 _recChannels, 468 _recSampleRate, 469 totalDelayMS, 470 _clockDrift, 471 _currentMicLevel, 472 _typingStatus, 473 newMicLevel); 474 if (res != -1) 475 { 476 _newMicLevel = newMicLevel; 477 } 478 479 return 0; 480 } 481 482 // ---------------------------------------------------------------------------- 483 // RequestPlayoutData 484 // ---------------------------------------------------------------------------- 485 486 int32_t AudioDeviceBuffer::RequestPlayoutData(size_t nSamples) 487 { 488 uint32_t playSampleRate = 0; 489 size_t playBytesPerSample = 0; 490 size_t playChannels = 0; 491 { 492 CriticalSectionScoped lock(&_critSect); 493 494 // Store copies under lock and use copies hereafter to avoid race with 495 // setter methods. 496 playSampleRate = _playSampleRate; 497 playBytesPerSample = _playBytesPerSample; 498 playChannels = _playChannels; 499 500 // Ensure that user has initialized all essential members 501 if ((playBytesPerSample == 0) || 502 (playChannels == 0) || 503 (playSampleRate == 0)) 504 { 505 assert(false); 506 return -1; 507 } 508 509 _playSamples = nSamples; 510 _playSize = playBytesPerSample * nSamples; // {2,4}*nSamples 511 if (_playSize > kMaxBufferSizeBytes) 512 { 513 assert(false); 514 return -1; 515 } 516 517 if (nSamples != _playSamples) 518 { 519 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "invalid number of samples to be played out (%d)", nSamples); 520 return -1; 521 } 522 } 523 524 size_t nSamplesOut(0); 525 526 CriticalSectionScoped lock(&_critSectCb); 527 528 if (_ptrCbAudioTransport == NULL) 529 { 530 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to feed data to playout (AudioTransport does not exist)"); 531 return 0; 532 } 533 534 if (_ptrCbAudioTransport) 535 { 536 uint32_t res(0); 537 int64_t elapsed_time_ms = -1; 538 int64_t ntp_time_ms = -1; 539 res = _ptrCbAudioTransport->NeedMorePlayData(_playSamples, 540 playBytesPerSample, 541 playChannels, 542 playSampleRate, 543 &_playBuffer[0], 544 nSamplesOut, 545 &elapsed_time_ms, 546 &ntp_time_ms); 547 if (res != 0) 548 { 549 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "NeedMorePlayData() failed"); 550 } 551 } 552 553 return static_cast<int32_t>(nSamplesOut); 554 } 555 556 // ---------------------------------------------------------------------------- 557 // GetPlayoutData 558 // ---------------------------------------------------------------------------- 559 560 int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer) 561 { 562 CriticalSectionScoped lock(&_critSect); 563 564 if (_playSize > kMaxBufferSizeBytes) 565 { 566 WEBRTC_TRACE(kTraceError, kTraceUtility, _id, 567 "_playSize %" PRIuS " exceeds kMaxBufferSizeBytes in " 568 "AudioDeviceBuffer::GetPlayoutData", _playSize); 569 assert(false); 570 return -1; 571 } 572 573 memcpy(audioBuffer, &_playBuffer[0], _playSize); 574 575 if (_playFile.Open()) 576 { 577 // write to binary file in mono or stereo (interleaved) 578 _playFile.Write(&_playBuffer[0], _playSize); 579 } 580 581 return static_cast<int32_t>(_playSamples); 582 } 583 584 } // namespace webrtc 585