• 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/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 
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     CriticalSectionScoped lock(&_critSect);
135     _recSampleRate = fsHz;
136     return 0;
137 }
138 
139 // ----------------------------------------------------------------------------
140 //  SetPlayoutSampleRate
141 // ----------------------------------------------------------------------------
142 
SetPlayoutSampleRate(uint32_t fsHz)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 
RecordingSampleRate() const154 int32_t AudioDeviceBuffer::RecordingSampleRate() const
155 {
156     return _recSampleRate;
157 }
158 
159 // ----------------------------------------------------------------------------
160 //  PlayoutSampleRate
161 // ----------------------------------------------------------------------------
162 
PlayoutSampleRate() const163 int32_t AudioDeviceBuffer::PlayoutSampleRate() const
164 {
165     return _playSampleRate;
166 }
167 
168 // ----------------------------------------------------------------------------
169 //  SetRecordingChannels
170 // ----------------------------------------------------------------------------
171 
SetRecordingChannels(size_t channels)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 
SetPlayoutChannels(size_t channels)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 
SetRecordingChannel(const AudioDeviceModule::ChannelType channel)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 
RecordingChannel(AudioDeviceModule::ChannelType & channel) const232 int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const
233 {
234     channel = _recChannel;
235     return 0;
236 }
237 
238 // ----------------------------------------------------------------------------
239 //  RecordingChannels
240 // ----------------------------------------------------------------------------
241 
RecordingChannels() const242 size_t AudioDeviceBuffer::RecordingChannels() const
243 {
244     return _recChannels;
245 }
246 
247 // ----------------------------------------------------------------------------
248 //  PlayoutChannels
249 // ----------------------------------------------------------------------------
250 
PlayoutChannels() const251 size_t AudioDeviceBuffer::PlayoutChannels() const
252 {
253     return _playChannels;
254 }
255 
256 // ----------------------------------------------------------------------------
257 //  SetCurrentMicLevel
258 // ----------------------------------------------------------------------------
259 
SetCurrentMicLevel(uint32_t level)260 int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level)
261 {
262     _currentMicLevel = level;
263     return 0;
264 }
265 
SetTypingStatus(bool typingStatus)266 int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus)
267 {
268     _typingStatus = typingStatus;
269     return 0;
270 }
271 
272 // ----------------------------------------------------------------------------
273 //  NewMicLevel
274 // ----------------------------------------------------------------------------
275 
NewMicLevel() const276 uint32_t AudioDeviceBuffer::NewMicLevel() const
277 {
278     return _newMicLevel;
279 }
280 
281 // ----------------------------------------------------------------------------
282 //  SetVQEData
283 // ----------------------------------------------------------------------------
284 
SetVQEData(int playDelayMs,int recDelayMs,int clockDrift)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 
StartInputFileRecording(const char fileName[kAdmMaxFileNameSize])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 
StopInputFileRecording()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 
StartOutputFileRecording(const char fileName[kAdmMaxFileNameSize])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 
StopOutputFileRecording()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 
SetRecordedBuffer(const void * audioBuffer,size_t nSamples)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 
DeliverRecordedData()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 
RequestPlayoutData(size_t nSamples)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 
GetPlayoutData(void * audioBuffer)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