blob: 0bc2f5c225f55a04c30e12a52e11781de9f05744 [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"
Henrik Kjellander98f53512015-10-28 18:17:40 +010018#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"
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
Peter Kasting69558702016-01-12 16:26:35 -0800172int32_t AudioDeviceBuffer::SetRecordingChannels(size_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
Peter Kasting69558702016-01-12 16:26:35 -0800184int32_t AudioDeviceBuffer::SetPlayoutChannels(size_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
Peter Kasting69558702016-01-12 16:26:35 -0800242size_t AudioDeviceBuffer::RecordingChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000243{
244 return _recChannels;
245}
246
247// ----------------------------------------------------------------------------
248// PlayoutChannels
249// ----------------------------------------------------------------------------
250
Peter Kasting69558702016-01-12 16:26:35 -0800251size_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
tommia6219cc2016-06-15 10:30:14 -0700316 return _recFile.OpenFile(fileName, false) ? 0 : -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000317}
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
tommia6219cc2016-06-15 10:30:14 -0700349 return _playFile.OpenFile(fileName, false) ? 0 : -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000350}
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
tommia6219cc2016-06-15 10:30:14 -0700427 if (_recFile.is_open()) {
428 // write to binary file in mono or stereo (interleaved)
429 _recFile.Write(&_recBuffer[0], _recSize);
niklase@google.com470e71d2011-07-07 08:21:25 +0000430 }
431
432 return 0;
433}
434
435// ----------------------------------------------------------------------------
436// DeliverRecordedData
437// ----------------------------------------------------------------------------
438
pbos@webrtc.org25509882013-04-09 10:30:35 +0000439int32_t AudioDeviceBuffer::DeliverRecordedData()
niklase@google.com470e71d2011-07-07 08:21:25 +0000440{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000441 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000442
443 // Ensure that user has initialized all essential members
444 if ((_recSampleRate == 0) ||
445 (_recSamples == 0) ||
446 (_recBytesPerSample == 0) ||
447 (_recChannels == 0))
448 {
449 assert(false);
450 return -1;
451 }
452
453 if (_ptrCbAudioTransport == NULL)
454 {
455 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to deliver recorded data (AudioTransport does not exist)");
456 return 0;
457 }
458
pbos@webrtc.org25509882013-04-09 10:30:35 +0000459 int32_t res(0);
460 uint32_t newMicLevel(0);
461 uint32_t totalDelayMS = _playDelayMS +_recDelayMS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000462
niklase@google.com470e71d2011-07-07 08:21:25 +0000463 res = _ptrCbAudioTransport->RecordedDataIsAvailable(&_recBuffer[0],
464 _recSamples,
465 _recBytesPerSample,
466 _recChannels,
467 _recSampleRate,
468 totalDelayMS,
469 _clockDrift,
470 _currentMicLevel,
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000471 _typingStatus,
niklase@google.com470e71d2011-07-07 08:21:25 +0000472 newMicLevel);
473 if (res != -1)
474 {
475 _newMicLevel = newMicLevel;
476 }
477
478 return 0;
479}
480
481// ----------------------------------------------------------------------------
482// RequestPlayoutData
483// ----------------------------------------------------------------------------
484
Peter Kastingdce40cf2015-08-24 14:52:23 -0700485int32_t AudioDeviceBuffer::RequestPlayoutData(size_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000486{
pbos@webrtc.org25509882013-04-09 10:30:35 +0000487 uint32_t playSampleRate = 0;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700488 size_t playBytesPerSample = 0;
Peter Kasting69558702016-01-12 16:26:35 -0800489 size_t playChannels = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000490 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000491 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000492
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000493 // Store copies under lock and use copies hereafter to avoid race with
494 // setter methods.
495 playSampleRate = _playSampleRate;
496 playBytesPerSample = _playBytesPerSample;
497 playChannels = _playChannels;
498
niklase@google.com470e71d2011-07-07 08:21:25 +0000499 // Ensure that user has initialized all essential members
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000500 if ((playBytesPerSample == 0) ||
501 (playChannels == 0) ||
502 (playSampleRate == 0))
niklase@google.com470e71d2011-07-07 08:21:25 +0000503 {
504 assert(false);
505 return -1;
506 }
507
508 _playSamples = nSamples;
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000509 _playSize = playBytesPerSample * nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000510 if (_playSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000511 {
512 assert(false);
513 return -1;
514 }
515
516 if (nSamples != _playSamples)
517 {
518 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "invalid number of samples to be played out (%d)", nSamples);
519 return -1;
520 }
521 }
522
Peter Kastingdce40cf2015-08-24 14:52:23 -0700523 size_t nSamplesOut(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000524
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000525 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000526
527 if (_ptrCbAudioTransport == NULL)
528 {
529 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to feed data to playout (AudioTransport does not exist)");
530 return 0;
531 }
532
533 if (_ptrCbAudioTransport)
534 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000535 uint32_t res(0);
wu@webrtc.org94454b72014-06-05 20:34:08 +0000536 int64_t elapsed_time_ms = -1;
537 int64_t ntp_time_ms = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000538 res = _ptrCbAudioTransport->NeedMorePlayData(_playSamples,
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000539 playBytesPerSample,
540 playChannels,
541 playSampleRate,
niklase@google.com470e71d2011-07-07 08:21:25 +0000542 &_playBuffer[0],
wu@webrtc.orgcb711f72014-05-19 17:39:11 +0000543 nSamplesOut,
wu@webrtc.org94454b72014-06-05 20:34:08 +0000544 &elapsed_time_ms,
wu@webrtc.orgcb711f72014-05-19 17:39:11 +0000545 &ntp_time_ms);
niklase@google.com470e71d2011-07-07 08:21:25 +0000546 if (res != 0)
547 {
548 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "NeedMorePlayData() failed");
549 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000550 }
551
Peter Kastingb7e50542015-06-11 12:55:50 -0700552 return static_cast<int32_t>(nSamplesOut);
niklase@google.com470e71d2011-07-07 08:21:25 +0000553}
554
555// ----------------------------------------------------------------------------
556// GetPlayoutData
557// ----------------------------------------------------------------------------
558
pbos@webrtc.org25509882013-04-09 10:30:35 +0000559int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer)
niklase@google.com470e71d2011-07-07 08:21:25 +0000560{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000561 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000562
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000563 if (_playSize > kMaxBufferSizeBytes)
564 {
Peter Kasting728d9032015-06-11 14:31:38 -0700565 WEBRTC_TRACE(kTraceError, kTraceUtility, _id,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700566 "_playSize %" PRIuS " exceeds kMaxBufferSizeBytes in "
Peter Kasting728d9032015-06-11 14:31:38 -0700567 "AudioDeviceBuffer::GetPlayoutData", _playSize);
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000568 assert(false);
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000569 return -1;
570 }
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000571
niklase@google.com470e71d2011-07-07 08:21:25 +0000572 memcpy(audioBuffer, &_playBuffer[0], _playSize);
573
tommia6219cc2016-06-15 10:30:14 -0700574 if (_playFile.is_open()) {
575 // write to binary file in mono or stereo (interleaved)
576 _playFile.Write(&_playBuffer[0], _playSize);
niklase@google.com470e71d2011-07-07 08:21:25 +0000577 }
578
Peter Kastingb7e50542015-06-11 12:55:50 -0700579 return static_cast<int32_t>(_playSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +0000580}
581
niklase@google.com470e71d2011-07-07 08:21:25 +0000582} // namespace webrtc