blob: db5cc322f98be0a744fd2dfe9449aabcdfb22007 [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
pbos@webrtc.org811269d2013-07-11 13:24:38 +000016#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"
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{
134 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingSampleRate(fsHz=%u)", fsHz);
135
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000136 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000137 _recSampleRate = fsHz;
138 return 0;
139}
140
141// ----------------------------------------------------------------------------
142// SetPlayoutSampleRate
143// ----------------------------------------------------------------------------
144
pbos@webrtc.org25509882013-04-09 10:30:35 +0000145int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000146{
147 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutSampleRate(fsHz=%u)", fsHz);
148
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000149 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000150 _playSampleRate = fsHz;
151 return 0;
152}
153
154// ----------------------------------------------------------------------------
155// RecordingSampleRate
156// ----------------------------------------------------------------------------
157
pbos@webrtc.org25509882013-04-09 10:30:35 +0000158int32_t AudioDeviceBuffer::RecordingSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000159{
160 return _recSampleRate;
161}
162
163// ----------------------------------------------------------------------------
164// PlayoutSampleRate
165// ----------------------------------------------------------------------------
166
pbos@webrtc.org25509882013-04-09 10:30:35 +0000167int32_t AudioDeviceBuffer::PlayoutSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000168{
169 return _playSampleRate;
170}
171
172// ----------------------------------------------------------------------------
173// SetRecordingChannels
174// ----------------------------------------------------------------------------
175
pbos@webrtc.org25509882013-04-09 10:30:35 +0000176int32_t AudioDeviceBuffer::SetRecordingChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000177{
178 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingChannels(channels=%u)", channels);
179
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000180 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000181 _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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000190int32_t AudioDeviceBuffer::SetPlayoutChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000191{
192 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutChannels(channels=%u)", channels);
193
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000194 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000195 _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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000212int32_t AudioDeviceBuffer::SetRecordingChannel(const AudioDeviceModule::ChannelType channel)
niklase@google.com470e71d2011-07-07 08:21:25 +0000213{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000214 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000215
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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000240int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000241{
242 channel = _recChannel;
243 return 0;
244}
245
246// ----------------------------------------------------------------------------
247// RecordingChannels
248// ----------------------------------------------------------------------------
249
pbos@webrtc.org25509882013-04-09 10:30:35 +0000250uint8_t AudioDeviceBuffer::RecordingChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000251{
252 return _recChannels;
253}
254
255// ----------------------------------------------------------------------------
256// PlayoutChannels
257// ----------------------------------------------------------------------------
258
pbos@webrtc.org25509882013-04-09 10:30:35 +0000259uint8_t AudioDeviceBuffer::PlayoutChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000260{
261 return _playChannels;
262}
263
264// ----------------------------------------------------------------------------
265// SetCurrentMicLevel
266// ----------------------------------------------------------------------------
267
pbos@webrtc.org25509882013-04-09 10:30:35 +0000268int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level)
niklase@google.com470e71d2011-07-07 08:21:25 +0000269{
270 _currentMicLevel = level;
271 return 0;
272}
273
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000274int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus)
275{
276 _typingStatus = typingStatus;
277 return 0;
278}
279
niklase@google.com470e71d2011-07-07 08:21:25 +0000280// ----------------------------------------------------------------------------
281// NewMicLevel
282// ----------------------------------------------------------------------------
283
pbos@webrtc.org25509882013-04-09 10:30:35 +0000284uint32_t AudioDeviceBuffer::NewMicLevel() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000285{
286 return _newMicLevel;
287}
288
289// ----------------------------------------------------------------------------
290// SetVQEData
291// ----------------------------------------------------------------------------
292
andrew@webrtc.org5eb997a2013-09-12 01:01:42 +0000293void AudioDeviceBuffer::SetVQEData(int playDelayMs, int recDelayMs,
294 int clockDrift) {
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000295 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)";
niklase@google.com470e71d2011-07-07 08:21:25 +0000302 }
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000303 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000304
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000305 _playDelayMS = playDelayMs;
306 _recDelayMS = recDelayMs;
307 _clockDrift = clockDrift;
niklase@google.com470e71d2011-07-07 08:21:25 +0000308}
309
310// ----------------------------------------------------------------------------
311// StartInputFileRecording
312// ----------------------------------------------------------------------------
313
pbos@webrtc.org25509882013-04-09 10:30:35 +0000314int32_t AudioDeviceBuffer::StartInputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000315 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000316{
317 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
318
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000319 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000320
321 _recFile.Flush();
322 _recFile.CloseFile();
323
324 return (_recFile.OpenFile(fileName, false, false, false));
325}
326
327// ----------------------------------------------------------------------------
328// StopInputFileRecording
329// ----------------------------------------------------------------------------
330
pbos@webrtc.org25509882013-04-09 10:30:35 +0000331int32_t AudioDeviceBuffer::StopInputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000332{
333 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
334
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000335 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000336
337 _recFile.Flush();
338 _recFile.CloseFile();
339
340 return 0;
341}
342
343// ----------------------------------------------------------------------------
344// StartOutputFileRecording
345// ----------------------------------------------------------------------------
346
pbos@webrtc.org25509882013-04-09 10:30:35 +0000347int32_t AudioDeviceBuffer::StartOutputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000348 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000349{
350 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
351
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000352 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000353
354 _playFile.Flush();
355 _playFile.CloseFile();
356
357 return (_playFile.OpenFile(fileName, false, false, false));
358}
359
360// ----------------------------------------------------------------------------
361// StopOutputFileRecording
362// ----------------------------------------------------------------------------
363
pbos@webrtc.org25509882013-04-09 10:30:35 +0000364int32_t AudioDeviceBuffer::StopOutputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000365{
366 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
367
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000368 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
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
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000388// 16-bit,48kHz stereo,10ms => nSamples=480 => _recSize=4*480=1920 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000389// ----------------------------------------------------------------------------
390
pbos@webrtc.org25509882013-04-09 10:30:35 +0000391int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer,
392 uint32_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000393{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000394 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000395
396 if (_recBytesPerSample == 0)
397 {
398 assert(false);
399 return -1;
400 }
401
402 _recSamples = nSamples;
403 _recSize = _recBytesPerSample*nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000404 if (_recSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000405 {
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 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000423 int16_t* ptr16In = (int16_t*)audioBuffer;
424 int16_t* ptr16Out = (int16_t*)&_recBuffer[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000425
426 if (AudioDeviceModule::kChannelRight == _recChannel)
427 {
428 ptr16In++;
429 }
430
431 // exctract left or right channel from input buffer to the local buffer
pbos@webrtc.org25509882013-04-09 10:30:35 +0000432 for (uint32_t i = 0; i < _recSamples; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000433 {
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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000454int32_t AudioDeviceBuffer::DeliverRecordedData()
niklase@google.com470e71d2011-07-07 08:21:25 +0000455{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000456 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000457
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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000474 int32_t res(0);
475 uint32_t newMicLevel(0);
476 uint32_t totalDelayMS = _playDelayMS +_recDelayMS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000477
niklase@google.com470e71d2011-07-07 08:21:25 +0000478 res = _ptrCbAudioTransport->RecordedDataIsAvailable(&_recBuffer[0],
479 _recSamples,
480 _recBytesPerSample,
481 _recChannels,
482 _recSampleRate,
483 totalDelayMS,
484 _clockDrift,
485 _currentMicLevel,
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000486 _typingStatus,
niklase@google.com470e71d2011-07-07 08:21:25 +0000487 newMicLevel);
488 if (res != -1)
489 {
490 _newMicLevel = newMicLevel;
491 }
492
493 return 0;
494}
495
496// ----------------------------------------------------------------------------
497// RequestPlayoutData
498// ----------------------------------------------------------------------------
499
pbos@webrtc.org25509882013-04-09 10:30:35 +0000500int32_t AudioDeviceBuffer::RequestPlayoutData(uint32_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000501{
pbos@webrtc.org25509882013-04-09 10:30:35 +0000502 uint32_t playSampleRate = 0;
503 uint8_t playBytesPerSample = 0;
504 uint8_t playChannels = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000505 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000506 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000507
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000508 // 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
niklase@google.com470e71d2011-07-07 08:21:25 +0000514 // Ensure that user has initialized all essential members
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000515 if ((playBytesPerSample == 0) ||
516 (playChannels == 0) ||
517 (playSampleRate == 0))
niklase@google.com470e71d2011-07-07 08:21:25 +0000518 {
519 assert(false);
520 return -1;
521 }
522
523 _playSamples = nSamples;
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000524 _playSize = playBytesPerSample * nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000525 if (_playSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000526 {
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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000538 uint32_t nSamplesOut(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000539
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000540 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000541
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 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000550 uint32_t res(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000551
552 res = _ptrCbAudioTransport->NeedMorePlayData(_playSamples,
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000553 playBytesPerSample,
554 playChannels,
555 playSampleRate,
niklase@google.com470e71d2011-07-07 08:21:25 +0000556 &_playBuffer[0],
557 nSamplesOut);
558 if (res != 0)
559 {
560 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "NeedMorePlayData() failed");
561 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000562 }
563
564 return nSamplesOut;
565}
566
567// ----------------------------------------------------------------------------
568// GetPlayoutData
569// ----------------------------------------------------------------------------
570
pbos@webrtc.org25509882013-04-09 10:30:35 +0000571int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer)
niklase@google.com470e71d2011-07-07 08:21:25 +0000572{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000573 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000574
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000575 if (_playSize > kMaxBufferSizeBytes)
576 {
577 WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "_playSize %i exceeds "
578 "kMaxBufferSizeBytes in AudioDeviceBuffer::GetPlayoutData", _playSize);
579 assert(false);
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000580 return -1;
581 }
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000582
niklase@google.com470e71d2011-07-07 08:21:25 +0000583 memcpy(audioBuffer, &_playBuffer[0], _playSize);
584
585 if (_playFile.Open())
586 {
587 // write to binary file in mono or stereo (interleaved)
588 _playFile.Write(&_playBuffer[0], _playSize);
589 }
590
591 return _playSamples;
592}
593
niklase@google.com470e71d2011-07-07 08:21:25 +0000594} // namespace webrtc