• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AudioDeviceBuffer()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 
~AudioDeviceBuffer()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 
SetId(uint32_t id)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 
RegisterAudioCallback(AudioTransport * audioCallback)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 
InitPlayout()112 int32_t AudioDeviceBuffer::InitPlayout()
113 {
114     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
115     return 0;
116 }
117 
118 // ----------------------------------------------------------------------------
119 //  InitRecording
120 // ----------------------------------------------------------------------------
121 
InitRecording()122 int32_t AudioDeviceBuffer::InitRecording()
123 {
124     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
125     return 0;
126 }
127 
128 // ----------------------------------------------------------------------------
129 //  SetRecordingSampleRate
130 // ----------------------------------------------------------------------------
131 
SetRecordingSampleRate(uint32_t fsHz)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 
SetPlayoutSampleRate(uint32_t fsHz)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 
RecordingSampleRate() const158 int32_t AudioDeviceBuffer::RecordingSampleRate() const
159 {
160     return _recSampleRate;
161 }
162 
163 // ----------------------------------------------------------------------------
164 //  PlayoutSampleRate
165 // ----------------------------------------------------------------------------
166 
PlayoutSampleRate() const167 int32_t AudioDeviceBuffer::PlayoutSampleRate() const
168 {
169     return _playSampleRate;
170 }
171 
172 // ----------------------------------------------------------------------------
173 //  SetRecordingChannels
174 // ----------------------------------------------------------------------------
175 
SetRecordingChannels(uint8_t channels)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 
SetPlayoutChannels(uint8_t channels)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 
SetRecordingChannel(const AudioDeviceModule::ChannelType channel)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 
RecordingChannel(AudioDeviceModule::ChannelType & channel) const240 int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const
241 {
242     channel = _recChannel;
243     return 0;
244 }
245 
246 // ----------------------------------------------------------------------------
247 //  RecordingChannels
248 // ----------------------------------------------------------------------------
249 
RecordingChannels() const250 uint8_t AudioDeviceBuffer::RecordingChannels() const
251 {
252     return _recChannels;
253 }
254 
255 // ----------------------------------------------------------------------------
256 //  PlayoutChannels
257 // ----------------------------------------------------------------------------
258 
PlayoutChannels() const259 uint8_t AudioDeviceBuffer::PlayoutChannels() const
260 {
261     return _playChannels;
262 }
263 
264 // ----------------------------------------------------------------------------
265 //  SetCurrentMicLevel
266 // ----------------------------------------------------------------------------
267 
SetCurrentMicLevel(uint32_t level)268 int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level)
269 {
270     _currentMicLevel = level;
271     return 0;
272 }
273 
SetTypingStatus(bool typingStatus)274 int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus)
275 {
276     _typingStatus = typingStatus;
277     return 0;
278 }
279 
280 // ----------------------------------------------------------------------------
281 //  NewMicLevel
282 // ----------------------------------------------------------------------------
283 
NewMicLevel() const284 uint32_t AudioDeviceBuffer::NewMicLevel() const
285 {
286     return _newMicLevel;
287 }
288 
289 // ----------------------------------------------------------------------------
290 //  SetVQEData
291 // ----------------------------------------------------------------------------
292 
SetVQEData(int playDelayMs,int recDelayMs,int clockDrift)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 
StartInputFileRecording(const char fileName[kAdmMaxFileNameSize])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 
StopInputFileRecording()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 
StartOutputFileRecording(const char fileName[kAdmMaxFileNameSize])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 
StopOutputFileRecording()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 
SetRecordedBuffer(const void * audioBuffer,uint32_t nSamples)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 
DeliverRecordedData()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 
RequestPlayoutData(uint32_t nSamples)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 
GetPlayoutData(void * audioBuffer)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