blob: ff9fd93f4b5941bfe5b013e2647b898facdc02ad [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
11#include "trace.h"
12#include "critical_section_wrapper.h"
13#include "audio_device_buffer.h"
14#include "audio_device_utility.h"
15#include "audio_device_config.h"
16
17#include <stdlib.h>
18#include <string.h>
19#include <cassert>
20
21#include "signal_processing_library.h"
22
23namespace webrtc {
24
25// ----------------------------------------------------------------------------
26// ctor
27// ----------------------------------------------------------------------------
28
29AudioDeviceBuffer::AudioDeviceBuffer() :
30 _id(-1),
31 _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
32 _critSectCb(*CriticalSectionWrapper::CreateCriticalSection()),
33 _ptrCbAudioTransport(NULL),
34 _recSampleRate(0),
35 _playSampleRate(0),
36 _recChannels(0),
37 _playChannels(0),
38 _recChannel(AudioDeviceModule::kChannelBoth),
39 _recBytesPerSample(0),
40 _playBytesPerSample(0),
41 _recSamples(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000042 _recSize(0),
xians@google.com88bd4402011-08-04 15:33:30 +000043 _playSamples(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000044 _playSize(0),
45 _recFile(*FileWrapper::Create()),
46 _playFile(*FileWrapper::Create()),
niklase@google.com470e71d2011-07-07 08:21:25 +000047 _currentMicLevel(0),
xians@google.com88bd4402011-08-04 15:33:30 +000048 _newMicLevel(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000049 _playDelayMS(0),
50 _recDelayMS(0),
51 _clockDrift(0),
52 _measureDelay(false), // should always be 'false' (EXPERIMENTAL)
53 _pulseList(),
54 _lastPulseTime(AudioDeviceUtility::GetTimeInMS())
55{
56 // valid ID will be set later by SetId, use -1 for now
57 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s created", __FUNCTION__);
xians@webrtc.orgeff3c892011-12-06 10:02:56 +000058 memset(_recBuffer, 0, kMaxBufferSizeBytes);
59 memset(_playBuffer, 0, kMaxBufferSizeBytes);
niklase@google.com470e71d2011-07-07 08:21:25 +000060}
61
62// ----------------------------------------------------------------------------
63// dtor
64// ----------------------------------------------------------------------------
65
66AudioDeviceBuffer::~AudioDeviceBuffer()
67{
68 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTION__);
69 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +000070 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +000071
72 _recFile.Flush();
73 _recFile.CloseFile();
74 delete &_recFile;
75
76 _playFile.Flush();
77 _playFile.CloseFile();
78 delete &_playFile;
79
80 _EmptyList();
81 }
82
83 delete &_critSect;
84 delete &_critSectCb;
85}
86
87// ----------------------------------------------------------------------------
88// SetId
89// ----------------------------------------------------------------------------
90
pbos@webrtc.org25509882013-04-09 10:30:35 +000091void AudioDeviceBuffer::SetId(uint32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000092{
93 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "AudioDeviceBuffer::SetId(id=%d)", id);
94 _id = id;
95}
96
97// ----------------------------------------------------------------------------
98// RegisterAudioCallback
99// ----------------------------------------------------------------------------
100
pbos@webrtc.org25509882013-04-09 10:30:35 +0000101int32_t AudioDeviceBuffer::RegisterAudioCallback(AudioTransport* audioCallback)
niklase@google.com470e71d2011-07-07 08:21:25 +0000102{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000103 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000104 _ptrCbAudioTransport = audioCallback;
105
106 return 0;
107}
108
109// ----------------------------------------------------------------------------
110// InitPlayout
111// ----------------------------------------------------------------------------
112
pbos@webrtc.org25509882013-04-09 10:30:35 +0000113int32_t AudioDeviceBuffer::InitPlayout()
niklase@google.com470e71d2011-07-07 08:21:25 +0000114{
115 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
116
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000117 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000118
119 if (_measureDelay)
120 {
121 _EmptyList();
122 _lastPulseTime = AudioDeviceUtility::GetTimeInMS();
123 }
124
125 return 0;
126}
127
128// ----------------------------------------------------------------------------
129// InitRecording
130// ----------------------------------------------------------------------------
131
pbos@webrtc.org25509882013-04-09 10:30:35 +0000132int32_t AudioDeviceBuffer::InitRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000133{
134 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
135
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000136 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000137
138 if (_measureDelay)
139 {
140 _EmptyList();
141 _lastPulseTime = AudioDeviceUtility::GetTimeInMS();
142 }
143
144 return 0;
145}
146
147// ----------------------------------------------------------------------------
148// SetRecordingSampleRate
149// ----------------------------------------------------------------------------
150
pbos@webrtc.org25509882013-04-09 10:30:35 +0000151int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000152{
153 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingSampleRate(fsHz=%u)", fsHz);
154
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000155 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000156 _recSampleRate = fsHz;
157 return 0;
158}
159
160// ----------------------------------------------------------------------------
161// SetPlayoutSampleRate
162// ----------------------------------------------------------------------------
163
pbos@webrtc.org25509882013-04-09 10:30:35 +0000164int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000165{
166 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutSampleRate(fsHz=%u)", fsHz);
167
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000168 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000169 _playSampleRate = fsHz;
170 return 0;
171}
172
173// ----------------------------------------------------------------------------
174// RecordingSampleRate
175// ----------------------------------------------------------------------------
176
pbos@webrtc.org25509882013-04-09 10:30:35 +0000177int32_t AudioDeviceBuffer::RecordingSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000178{
179 return _recSampleRate;
180}
181
182// ----------------------------------------------------------------------------
183// PlayoutSampleRate
184// ----------------------------------------------------------------------------
185
pbos@webrtc.org25509882013-04-09 10:30:35 +0000186int32_t AudioDeviceBuffer::PlayoutSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000187{
188 return _playSampleRate;
189}
190
191// ----------------------------------------------------------------------------
192// SetRecordingChannels
193// ----------------------------------------------------------------------------
194
pbos@webrtc.org25509882013-04-09 10:30:35 +0000195int32_t AudioDeviceBuffer::SetRecordingChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000196{
197 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingChannels(channels=%u)", channels);
198
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000199 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000200 _recChannels = channels;
201 _recBytesPerSample = 2*channels; // 16 bits per sample in mono, 32 bits in stereo
202 return 0;
203}
204
205// ----------------------------------------------------------------------------
206// SetPlayoutChannels
207// ----------------------------------------------------------------------------
208
pbos@webrtc.org25509882013-04-09 10:30:35 +0000209int32_t AudioDeviceBuffer::SetPlayoutChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000210{
211 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutChannels(channels=%u)", channels);
212
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000213 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000214 _playChannels = channels;
215 // 16 bits per sample in mono, 32 bits in stereo
216 _playBytesPerSample = 2*channels;
217 return 0;
218}
219
220// ----------------------------------------------------------------------------
221// SetRecordingChannel
222//
223// Select which channel to use while recording.
224// This API requires that stereo is enabled.
225//
226// Note that, the nChannel parameter in RecordedDataIsAvailable will be
227// set to 2 even for kChannelLeft and kChannelRight. However, nBytesPerSample
228// will be 2 instead of 4 four these cases.
229// ----------------------------------------------------------------------------
230
pbos@webrtc.org25509882013-04-09 10:30:35 +0000231int32_t AudioDeviceBuffer::SetRecordingChannel(const AudioDeviceModule::ChannelType channel)
niklase@google.com470e71d2011-07-07 08:21:25 +0000232{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000233 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000234
235 if (_recChannels == 1)
236 {
237 return -1;
238 }
239
240 if (channel == AudioDeviceModule::kChannelBoth)
241 {
242 // two bytes per channel
243 _recBytesPerSample = 4;
244 }
245 else
246 {
247 // only utilize one out of two possible channels (left or right)
248 _recBytesPerSample = 2;
249 }
250 _recChannel = channel;
251
252 return 0;
253}
254
255// ----------------------------------------------------------------------------
256// RecordingChannel
257// ----------------------------------------------------------------------------
258
pbos@webrtc.org25509882013-04-09 10:30:35 +0000259int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000260{
261 channel = _recChannel;
262 return 0;
263}
264
265// ----------------------------------------------------------------------------
266// RecordingChannels
267// ----------------------------------------------------------------------------
268
pbos@webrtc.org25509882013-04-09 10:30:35 +0000269uint8_t AudioDeviceBuffer::RecordingChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000270{
271 return _recChannels;
272}
273
274// ----------------------------------------------------------------------------
275// PlayoutChannels
276// ----------------------------------------------------------------------------
277
pbos@webrtc.org25509882013-04-09 10:30:35 +0000278uint8_t AudioDeviceBuffer::PlayoutChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000279{
280 return _playChannels;
281}
282
283// ----------------------------------------------------------------------------
284// SetCurrentMicLevel
285// ----------------------------------------------------------------------------
286
pbos@webrtc.org25509882013-04-09 10:30:35 +0000287int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level)
niklase@google.com470e71d2011-07-07 08:21:25 +0000288{
289 _currentMicLevel = level;
290 return 0;
291}
292
293// ----------------------------------------------------------------------------
294// NewMicLevel
295// ----------------------------------------------------------------------------
296
pbos@webrtc.org25509882013-04-09 10:30:35 +0000297uint32_t AudioDeviceBuffer::NewMicLevel() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000298{
299 return _newMicLevel;
300}
301
302// ----------------------------------------------------------------------------
303// SetVQEData
304// ----------------------------------------------------------------------------
305
pbos@webrtc.org25509882013-04-09 10:30:35 +0000306int32_t AudioDeviceBuffer::SetVQEData(uint32_t playDelayMS, uint32_t recDelayMS, int32_t clockDrift)
niklase@google.com470e71d2011-07-07 08:21:25 +0000307{
308 if ((playDelayMS + recDelayMS) > 300)
309 {
310 WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "too long delay (play:%i rec:%i)", playDelayMS, recDelayMS, clockDrift);
311 }
312
313 _playDelayMS = playDelayMS;
314 _recDelayMS = recDelayMS;
315 _clockDrift = clockDrift;
316
317 return 0;
318}
319
320// ----------------------------------------------------------------------------
321// StartInputFileRecording
322// ----------------------------------------------------------------------------
323
pbos@webrtc.org25509882013-04-09 10:30:35 +0000324int32_t AudioDeviceBuffer::StartInputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000325 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000326{
327 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
328
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000329 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000330
331 _recFile.Flush();
332 _recFile.CloseFile();
333
334 return (_recFile.OpenFile(fileName, false, false, false));
335}
336
337// ----------------------------------------------------------------------------
338// StopInputFileRecording
339// ----------------------------------------------------------------------------
340
pbos@webrtc.org25509882013-04-09 10:30:35 +0000341int32_t AudioDeviceBuffer::StopInputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000342{
343 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
344
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000345 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000346
347 _recFile.Flush();
348 _recFile.CloseFile();
349
350 return 0;
351}
352
353// ----------------------------------------------------------------------------
354// StartOutputFileRecording
355// ----------------------------------------------------------------------------
356
pbos@webrtc.org25509882013-04-09 10:30:35 +0000357int32_t AudioDeviceBuffer::StartOutputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000358 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000359{
360 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
361
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000362 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000363
364 _playFile.Flush();
365 _playFile.CloseFile();
366
367 return (_playFile.OpenFile(fileName, false, false, false));
368}
369
370// ----------------------------------------------------------------------------
371// StopOutputFileRecording
372// ----------------------------------------------------------------------------
373
pbos@webrtc.org25509882013-04-09 10:30:35 +0000374int32_t AudioDeviceBuffer::StopOutputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000375{
376 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
377
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000378 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000379
380 _playFile.Flush();
381 _playFile.CloseFile();
382
383 return 0;
384}
385
386// ----------------------------------------------------------------------------
387// SetRecordedBuffer
388//
389// Store recorded audio buffer in local memory ready for the actual
390// "delivery" using a callback.
391//
392// This method can also parse out left or right channel from a stereo
393// input signal, i.e., emulate mono.
394//
395// Examples:
396//
397// 16-bit,48kHz mono, 10ms => nSamples=480 => _recSize=2*480=960 bytes
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000398// 16-bit,48kHz stereo,10ms => nSamples=480 => _recSize=4*480=1920 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000399// ----------------------------------------------------------------------------
400
pbos@webrtc.org25509882013-04-09 10:30:35 +0000401int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer,
402 uint32_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000403{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000404 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
406 if (_recBytesPerSample == 0)
407 {
408 assert(false);
409 return -1;
410 }
411
412 _recSamples = nSamples;
413 _recSize = _recBytesPerSample*nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000414 if (_recSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000415 {
416 assert(false);
417 return -1;
418 }
419
420 if (nSamples != _recSamples)
421 {
422 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "invalid number of recorded samples (%d)", nSamples);
423 return -1;
424 }
425
426 if (_recChannel == AudioDeviceModule::kChannelBoth)
427 {
428 // (default) copy the complete input buffer to the local buffer
429 memcpy(&_recBuffer[0], audioBuffer, _recSize);
430 }
431 else
432 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000433 int16_t* ptr16In = (int16_t*)audioBuffer;
434 int16_t* ptr16Out = (int16_t*)&_recBuffer[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000435
436 if (AudioDeviceModule::kChannelRight == _recChannel)
437 {
438 ptr16In++;
439 }
440
441 // exctract left or right channel from input buffer to the local buffer
pbos@webrtc.org25509882013-04-09 10:30:35 +0000442 for (uint32_t i = 0; i < _recSamples; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 {
444 *ptr16Out = *ptr16In;
445 ptr16Out++;
446 ptr16In++;
447 ptr16In++;
448 }
449 }
450
451 if (_recFile.Open())
452 {
453 // write to binary file in mono or stereo (interleaved)
454 _recFile.Write(&_recBuffer[0], _recSize);
455 }
456
457 return 0;
458}
459
460// ----------------------------------------------------------------------------
461// DeliverRecordedData
462// ----------------------------------------------------------------------------
463
pbos@webrtc.org25509882013-04-09 10:30:35 +0000464int32_t AudioDeviceBuffer::DeliverRecordedData()
niklase@google.com470e71d2011-07-07 08:21:25 +0000465{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000466 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000467
468 // Ensure that user has initialized all essential members
469 if ((_recSampleRate == 0) ||
470 (_recSamples == 0) ||
471 (_recBytesPerSample == 0) ||
472 (_recChannels == 0))
473 {
474 assert(false);
475 return -1;
476 }
477
478 if (_ptrCbAudioTransport == NULL)
479 {
480 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to deliver recorded data (AudioTransport does not exist)");
481 return 0;
482 }
483
pbos@webrtc.org25509882013-04-09 10:30:35 +0000484 int32_t res(0);
485 uint32_t newMicLevel(0);
486 uint32_t totalDelayMS = _playDelayMS +_recDelayMS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000487
488 if (_measureDelay)
489 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000490 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000491
492 memset(&_recBuffer[0], 0, _recSize);
pbos@webrtc.org25509882013-04-09 10:30:35 +0000493 uint32_t time = AudioDeviceUtility::GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000494 if (time - _lastPulseTime > 500)
495 {
496 _pulseList.PushBack(time);
497 _lastPulseTime = time;
498
pbos@webrtc.org25509882013-04-09 10:30:35 +0000499 int16_t* ptr16 = (int16_t*)&_recBuffer[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000500 *ptr16 = 30000;
501 }
502 }
503
504 res = _ptrCbAudioTransport->RecordedDataIsAvailable(&_recBuffer[0],
505 _recSamples,
506 _recBytesPerSample,
507 _recChannels,
508 _recSampleRate,
509 totalDelayMS,
510 _clockDrift,
511 _currentMicLevel,
512 newMicLevel);
513 if (res != -1)
514 {
515 _newMicLevel = newMicLevel;
516 }
517
518 return 0;
519}
520
521// ----------------------------------------------------------------------------
522// RequestPlayoutData
523// ----------------------------------------------------------------------------
524
pbos@webrtc.org25509882013-04-09 10:30:35 +0000525int32_t AudioDeviceBuffer::RequestPlayoutData(uint32_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000526{
pbos@webrtc.org25509882013-04-09 10:30:35 +0000527 uint32_t playSampleRate = 0;
528 uint8_t playBytesPerSample = 0;
529 uint8_t playChannels = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000530 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000531 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000532
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000533 // Store copies under lock and use copies hereafter to avoid race with
534 // setter methods.
535 playSampleRate = _playSampleRate;
536 playBytesPerSample = _playBytesPerSample;
537 playChannels = _playChannels;
538
niklase@google.com470e71d2011-07-07 08:21:25 +0000539 // Ensure that user has initialized all essential members
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000540 if ((playBytesPerSample == 0) ||
541 (playChannels == 0) ||
542 (playSampleRate == 0))
niklase@google.com470e71d2011-07-07 08:21:25 +0000543 {
544 assert(false);
545 return -1;
546 }
547
548 _playSamples = nSamples;
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000549 _playSize = playBytesPerSample * nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000550 if (_playSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000551 {
552 assert(false);
553 return -1;
554 }
555
556 if (nSamples != _playSamples)
557 {
558 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "invalid number of samples to be played out (%d)", nSamples);
559 return -1;
560 }
561 }
562
pbos@webrtc.org25509882013-04-09 10:30:35 +0000563 uint32_t nSamplesOut(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000564
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000565 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000566
567 if (_ptrCbAudioTransport == NULL)
568 {
569 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to feed data to playout (AudioTransport does not exist)");
570 return 0;
571 }
572
573 if (_ptrCbAudioTransport)
574 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000575 uint32_t res(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000576
577 res = _ptrCbAudioTransport->NeedMorePlayData(_playSamples,
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000578 playBytesPerSample,
579 playChannels,
580 playSampleRate,
niklase@google.com470e71d2011-07-07 08:21:25 +0000581 &_playBuffer[0],
582 nSamplesOut);
583 if (res != 0)
584 {
585 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "NeedMorePlayData() failed");
586 }
587
588 // --- Experimental delay-measurement implementation
589 // *** not be used in released code ***
590
591 if (_measureDelay)
592 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000593 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000594
pbos@webrtc.org25509882013-04-09 10:30:35 +0000595 int16_t maxAbs = WebRtcSpl_MaxAbsValueW16((const int16_t*)&_playBuffer[0], (int16_t)nSamplesOut*_playChannels);
niklase@google.com470e71d2011-07-07 08:21:25 +0000596 if (maxAbs > 1000)
597 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000598 uint32_t nowTime = AudioDeviceUtility::GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000599
600 if (!_pulseList.Empty())
601 {
602 ListItem* item = _pulseList.First();
603 if (item)
604 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000605 int16_t maxIndex = WebRtcSpl_MaxAbsIndexW16((const int16_t*)&_playBuffer[0], (int16_t)nSamplesOut*_playChannels);
606 uint32_t pulseTime = item->GetUnsignedItem();
607 uint32_t diff = nowTime - pulseTime + (10*maxIndex)/(nSamplesOut*_playChannels);
xians@google.com3ab5d5f2011-08-15 11:07:54 +0000608 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "diff time in playout delay (%d)", diff);
niklase@google.com470e71d2011-07-07 08:21:25 +0000609 }
610 _pulseList.PopFront();
611 }
612 }
613 }
614 }
615
616 return nSamplesOut;
617}
618
619// ----------------------------------------------------------------------------
620// GetPlayoutData
621// ----------------------------------------------------------------------------
622
pbos@webrtc.org25509882013-04-09 10:30:35 +0000623int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer)
niklase@google.com470e71d2011-07-07 08:21:25 +0000624{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000625 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000626
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000627 if (_playSize > kMaxBufferSizeBytes)
628 {
629 WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "_playSize %i exceeds "
630 "kMaxBufferSizeBytes in AudioDeviceBuffer::GetPlayoutData", _playSize);
631 assert(false);
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000632 return -1;
633 }
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000634
niklase@google.com470e71d2011-07-07 08:21:25 +0000635 memcpy(audioBuffer, &_playBuffer[0], _playSize);
636
637 if (_playFile.Open())
638 {
639 // write to binary file in mono or stereo (interleaved)
640 _playFile.Write(&_playBuffer[0], _playSize);
641 }
642
643 return _playSamples;
644}
645
646// ----------------------------------------------------------------------------
647// _EmptyList
648// ----------------------------------------------------------------------------
649
650void AudioDeviceBuffer::_EmptyList()
651{
652 while (!_pulseList.Empty())
653 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000654 ListItem* item = _pulseList.First();
655 if (item)
656 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000657 // uint32_t ts = item->GetUnsignedItem();
niklase@google.com470e71d2011-07-07 08:21:25 +0000658 }
659 _pulseList.PopFront();
660 }
661}
662
663} // namespace webrtc