blob: cc6d6bb1f780cf5c2ae2e5e80979c2986fa565c3 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
xians@webrtc.org20aabbb2012-02-20 09:17:41 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
pbos@webrtc.org811269d2013-07-11 13:24:38 +000011#include "webrtc/modules/audio_device/audio_device_buffer.h"
andrew@webrtc.org25534502013-09-13 00:02:13 +000012
13#include <assert.h>
14#include <string.h>
15
Peter Kastingdce40cf2015-08-24 14:52:23 -070016#include "webrtc/base/format_macros.h"
pbos@webrtc.org811269d2013-07-11 13:24:38 +000017#include "webrtc/modules/audio_device/audio_device_config.h"
pbos@webrtc.org811269d2013-07-11 13:24:38 +000018#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andrew@webrtc.org8f940132013-09-11 22:35:00 +000019#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org811269d2013-07-11 13:24:38 +000020#include "webrtc/system_wrappers/interface/trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000021
niklase@google.com470e71d2011-07-07 08:21:25 +000022namespace webrtc {
23
andrew@webrtc.org8f940132013-09-11 22:35:00 +000024static const int kHighDelayThresholdMs = 300;
25static const int kLogHighDelayIntervalFrames = 500; // 5 seconds.
26
niklase@google.com470e71d2011-07-07 08:21:25 +000027// ----------------------------------------------------------------------------
28// ctor
29// ----------------------------------------------------------------------------
30
31AudioDeviceBuffer::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),
niklase@google.com470e71d2011-07-07 08:21:25 +000044 _recSize(0),
xians@google.com88bd4402011-08-04 15:33:30 +000045 _playSamples(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000046 _playSize(0),
47 _recFile(*FileWrapper::Create()),
48 _playFile(*FileWrapper::Create()),
niklase@google.com470e71d2011-07-07 08:21:25 +000049 _currentMicLevel(0),
xians@google.com88bd4402011-08-04 15:33:30 +000050 _newMicLevel(0),
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +000051 _typingStatus(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000052 _playDelayMS(0),
53 _recDelayMS(0),
andrew@webrtc.org8f940132013-09-11 22:35:00 +000054 _clockDrift(0),
55 // Set to the interval in order to log on the first occurrence.
56 high_delay_counter_(kLogHighDelayIntervalFrames) {
niklase@google.com470e71d2011-07-07 08:21:25 +000057 // valid ID will be set later by SetId, use -1 for now
58 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s created", __FUNCTION__);
xians@webrtc.orgeff3c892011-12-06 10:02:56 +000059 memset(_recBuffer, 0, kMaxBufferSizeBytes);
60 memset(_playBuffer, 0, kMaxBufferSizeBytes);
niklase@google.com470e71d2011-07-07 08:21:25 +000061}
62
63// ----------------------------------------------------------------------------
64// dtor
65// ----------------------------------------------------------------------------
66
67AudioDeviceBuffer::~AudioDeviceBuffer()
68{
69 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTION__);
70 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +000071 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +000072
73 _recFile.Flush();
74 _recFile.CloseFile();
75 delete &_recFile;
76
77 _playFile.Flush();
78 _playFile.CloseFile();
79 delete &_playFile;
niklase@google.com470e71d2011-07-07 08:21:25 +000080 }
81
82 delete &_critSect;
83 delete &_critSectCb;
84}
85
86// ----------------------------------------------------------------------------
87// SetId
88// ----------------------------------------------------------------------------
89
pbos@webrtc.org25509882013-04-09 10:30:35 +000090void AudioDeviceBuffer::SetId(uint32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000091{
92 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "AudioDeviceBuffer::SetId(id=%d)", id);
93 _id = id;
94}
95
96// ----------------------------------------------------------------------------
97// RegisterAudioCallback
98// ----------------------------------------------------------------------------
99
pbos@webrtc.org25509882013-04-09 10:30:35 +0000100int32_t AudioDeviceBuffer::RegisterAudioCallback(AudioTransport* audioCallback)
niklase@google.com470e71d2011-07-07 08:21:25 +0000101{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000102 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000103 _ptrCbAudioTransport = audioCallback;
104
105 return 0;
106}
107
108// ----------------------------------------------------------------------------
109// InitPlayout
110// ----------------------------------------------------------------------------
111
pbos@webrtc.org25509882013-04-09 10:30:35 +0000112int32_t AudioDeviceBuffer::InitPlayout()
niklase@google.com470e71d2011-07-07 08:21:25 +0000113{
114 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000115 return 0;
116}
117
118// ----------------------------------------------------------------------------
119// InitRecording
120// ----------------------------------------------------------------------------
121
pbos@webrtc.org25509882013-04-09 10:30:35 +0000122int32_t AudioDeviceBuffer::InitRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000123{
124 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000125 return 0;
126}
127
128// ----------------------------------------------------------------------------
129// SetRecordingSampleRate
130// ----------------------------------------------------------------------------
131
pbos@webrtc.org25509882013-04-09 10:30:35 +0000132int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000133{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000134 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000135 _recSampleRate = fsHz;
136 return 0;
137}
138
139// ----------------------------------------------------------------------------
140// SetPlayoutSampleRate
141// ----------------------------------------------------------------------------
142
pbos@webrtc.org25509882013-04-09 10:30:35 +0000143int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000144{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000145 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000146 _playSampleRate = fsHz;
147 return 0;
148}
149
150// ----------------------------------------------------------------------------
151// RecordingSampleRate
152// ----------------------------------------------------------------------------
153
pbos@webrtc.org25509882013-04-09 10:30:35 +0000154int32_t AudioDeviceBuffer::RecordingSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000155{
156 return _recSampleRate;
157}
158
159// ----------------------------------------------------------------------------
160// PlayoutSampleRate
161// ----------------------------------------------------------------------------
162
pbos@webrtc.org25509882013-04-09 10:30:35 +0000163int32_t AudioDeviceBuffer::PlayoutSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000164{
165 return _playSampleRate;
166}
167
168// ----------------------------------------------------------------------------
169// SetRecordingChannels
170// ----------------------------------------------------------------------------
171
pbos@webrtc.org25509882013-04-09 10:30:35 +0000172int32_t AudioDeviceBuffer::SetRecordingChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000173{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000174 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000175 _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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000184int32_t AudioDeviceBuffer::SetPlayoutChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000185{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000186 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000187 _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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000204int32_t AudioDeviceBuffer::SetRecordingChannel(const AudioDeviceModule::ChannelType channel)
niklase@google.com470e71d2011-07-07 08:21:25 +0000205{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000206 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000207
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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000232int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000233{
234 channel = _recChannel;
235 return 0;
236}
237
238// ----------------------------------------------------------------------------
239// RecordingChannels
240// ----------------------------------------------------------------------------
241
pbos@webrtc.org25509882013-04-09 10:30:35 +0000242uint8_t AudioDeviceBuffer::RecordingChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000243{
244 return _recChannels;
245}
246
247// ----------------------------------------------------------------------------
248// PlayoutChannels
249// ----------------------------------------------------------------------------
250
pbos@webrtc.org25509882013-04-09 10:30:35 +0000251uint8_t AudioDeviceBuffer::PlayoutChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000252{
253 return _playChannels;
254}
255
256// ----------------------------------------------------------------------------
257// SetCurrentMicLevel
258// ----------------------------------------------------------------------------
259
pbos@webrtc.org25509882013-04-09 10:30:35 +0000260int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level)
niklase@google.com470e71d2011-07-07 08:21:25 +0000261{
262 _currentMicLevel = level;
263 return 0;
264}
265
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000266int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus)
267{
268 _typingStatus = typingStatus;
269 return 0;
270}
271
niklase@google.com470e71d2011-07-07 08:21:25 +0000272// ----------------------------------------------------------------------------
273// NewMicLevel
274// ----------------------------------------------------------------------------
275
pbos@webrtc.org25509882013-04-09 10:30:35 +0000276uint32_t AudioDeviceBuffer::NewMicLevel() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000277{
278 return _newMicLevel;
279}
280
281// ----------------------------------------------------------------------------
282// SetVQEData
283// ----------------------------------------------------------------------------
284
andrew@webrtc.org5eb997a2013-09-12 01:01:42 +0000285void AudioDeviceBuffer::SetVQEData(int playDelayMs, int recDelayMs,
286 int clockDrift) {
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000287 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)";
niklase@google.com470e71d2011-07-07 08:21:25 +0000294 }
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000295 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000296
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000297 _playDelayMS = playDelayMs;
298 _recDelayMS = recDelayMs;
299 _clockDrift = clockDrift;
niklase@google.com470e71d2011-07-07 08:21:25 +0000300}
301
302// ----------------------------------------------------------------------------
303// StartInputFileRecording
304// ----------------------------------------------------------------------------
305
pbos@webrtc.org25509882013-04-09 10:30:35 +0000306int32_t AudioDeviceBuffer::StartInputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000307 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000308{
309 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
310
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000311 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000312
313 _recFile.Flush();
314 _recFile.CloseFile();
315
316 return (_recFile.OpenFile(fileName, false, false, false));
317}
318
319// ----------------------------------------------------------------------------
320// StopInputFileRecording
321// ----------------------------------------------------------------------------
322
pbos@webrtc.org25509882013-04-09 10:30:35 +0000323int32_t AudioDeviceBuffer::StopInputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000324{
325 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
326
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000327 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000328
329 _recFile.Flush();
330 _recFile.CloseFile();
331
332 return 0;
333}
334
335// ----------------------------------------------------------------------------
336// StartOutputFileRecording
337// ----------------------------------------------------------------------------
338
pbos@webrtc.org25509882013-04-09 10:30:35 +0000339int32_t AudioDeviceBuffer::StartOutputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000340 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000341{
342 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
343
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000344 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000345
346 _playFile.Flush();
347 _playFile.CloseFile();
348
349 return (_playFile.OpenFile(fileName, false, false, false));
350}
351
352// ----------------------------------------------------------------------------
353// StopOutputFileRecording
354// ----------------------------------------------------------------------------
355
pbos@webrtc.org25509882013-04-09 10:30:35 +0000356int32_t AudioDeviceBuffer::StopOutputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000357{
358 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
359
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000360 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
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
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000380// 16-bit,48kHz stereo,10ms => nSamples=480 => _recSize=4*480=1920 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000381// ----------------------------------------------------------------------------
382
pbos@webrtc.org25509882013-04-09 10:30:35 +0000383int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700384 size_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000385{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000386 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000387
388 if (_recBytesPerSample == 0)
389 {
390 assert(false);
391 return -1;
392 }
393
394 _recSamples = nSamples;
395 _recSize = _recBytesPerSample*nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000396 if (_recSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000397 {
398 assert(false);
399 return -1;
400 }
401
niklase@google.com470e71d2011-07-07 08:21:25 +0000402 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 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000409 int16_t* ptr16In = (int16_t*)audioBuffer;
410 int16_t* ptr16Out = (int16_t*)&_recBuffer[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000411
412 if (AudioDeviceModule::kChannelRight == _recChannel)
413 {
414 ptr16In++;
415 }
416
417 // exctract left or right channel from input buffer to the local buffer
Peter Kastingdce40cf2015-08-24 14:52:23 -0700418 for (size_t i = 0; i < _recSamples; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000419 {
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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000440int32_t AudioDeviceBuffer::DeliverRecordedData()
niklase@google.com470e71d2011-07-07 08:21:25 +0000441{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000442 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000443
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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000460 int32_t res(0);
461 uint32_t newMicLevel(0);
462 uint32_t totalDelayMS = _playDelayMS +_recDelayMS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000463
niklase@google.com470e71d2011-07-07 08:21:25 +0000464 res = _ptrCbAudioTransport->RecordedDataIsAvailable(&_recBuffer[0],
465 _recSamples,
466 _recBytesPerSample,
467 _recChannels,
468 _recSampleRate,
469 totalDelayMS,
470 _clockDrift,
471 _currentMicLevel,
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000472 _typingStatus,
niklase@google.com470e71d2011-07-07 08:21:25 +0000473 newMicLevel);
474 if (res != -1)
475 {
476 _newMicLevel = newMicLevel;
477 }
478
479 return 0;
480}
481
482// ----------------------------------------------------------------------------
483// RequestPlayoutData
484// ----------------------------------------------------------------------------
485
Peter Kastingdce40cf2015-08-24 14:52:23 -0700486int32_t AudioDeviceBuffer::RequestPlayoutData(size_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000487{
pbos@webrtc.org25509882013-04-09 10:30:35 +0000488 uint32_t playSampleRate = 0;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700489 size_t playBytesPerSample = 0;
pbos@webrtc.org25509882013-04-09 10:30:35 +0000490 uint8_t playChannels = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000491 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000492 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000493
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000494 // 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
niklase@google.com470e71d2011-07-07 08:21:25 +0000500 // Ensure that user has initialized all essential members
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000501 if ((playBytesPerSample == 0) ||
502 (playChannels == 0) ||
503 (playSampleRate == 0))
niklase@google.com470e71d2011-07-07 08:21:25 +0000504 {
505 assert(false);
506 return -1;
507 }
508
509 _playSamples = nSamples;
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000510 _playSize = playBytesPerSample * nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000511 if (_playSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000512 {
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
Peter Kastingdce40cf2015-08-24 14:52:23 -0700524 size_t nSamplesOut(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000525
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000526 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000527
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 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000536 uint32_t res(0);
wu@webrtc.org94454b72014-06-05 20:34:08 +0000537 int64_t elapsed_time_ms = -1;
538 int64_t ntp_time_ms = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000539 res = _ptrCbAudioTransport->NeedMorePlayData(_playSamples,
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000540 playBytesPerSample,
541 playChannels,
542 playSampleRate,
niklase@google.com470e71d2011-07-07 08:21:25 +0000543 &_playBuffer[0],
wu@webrtc.orgcb711f72014-05-19 17:39:11 +0000544 nSamplesOut,
wu@webrtc.org94454b72014-06-05 20:34:08 +0000545 &elapsed_time_ms,
wu@webrtc.orgcb711f72014-05-19 17:39:11 +0000546 &ntp_time_ms);
niklase@google.com470e71d2011-07-07 08:21:25 +0000547 if (res != 0)
548 {
549 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "NeedMorePlayData() failed");
550 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000551 }
552
Peter Kastingb7e50542015-06-11 12:55:50 -0700553 return static_cast<int32_t>(nSamplesOut);
niklase@google.com470e71d2011-07-07 08:21:25 +0000554}
555
556// ----------------------------------------------------------------------------
557// GetPlayoutData
558// ----------------------------------------------------------------------------
559
pbos@webrtc.org25509882013-04-09 10:30:35 +0000560int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer)
niklase@google.com470e71d2011-07-07 08:21:25 +0000561{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000562 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000563
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000564 if (_playSize > kMaxBufferSizeBytes)
565 {
Peter Kasting728d9032015-06-11 14:31:38 -0700566 WEBRTC_TRACE(kTraceError, kTraceUtility, _id,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700567 "_playSize %" PRIuS " exceeds kMaxBufferSizeBytes in "
Peter Kasting728d9032015-06-11 14:31:38 -0700568 "AudioDeviceBuffer::GetPlayoutData", _playSize);
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000569 assert(false);
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000570 return -1;
571 }
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000572
niklase@google.com470e71d2011-07-07 08:21:25 +0000573 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
Peter Kastingb7e50542015-06-11 12:55:50 -0700581 return static_cast<int32_t>(_playSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +0000582}
583
niklase@google.com470e71d2011-07-07 08:21:25 +0000584} // namespace webrtc