blob: 3cfbc7d09c4da6d7f9fb88850e76ae9db104af05 [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"
pbos@webrtc.org811269d2013-07-11 13:24:38 +000017#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andrew@webrtc.org8f940132013-09-11 22:35:00 +000018#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org811269d2013-07-11 13:24:38 +000019#include "webrtc/system_wrappers/interface/trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000020
niklase@google.com470e71d2011-07-07 08:21:25 +000021namespace webrtc {
22
andrew@webrtc.org8f940132013-09-11 22:35:00 +000023static const int kHighDelayThresholdMs = 300;
24static const int kLogHighDelayIntervalFrames = 500; // 5 seconds.
25
niklase@google.com470e71d2011-07-07 08:21:25 +000026// ----------------------------------------------------------------------------
27// ctor
28// ----------------------------------------------------------------------------
29
30AudioDeviceBuffer::AudioDeviceBuffer() :
31 _id(-1),
32 _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
33 _critSectCb(*CriticalSectionWrapper::CreateCriticalSection()),
34 _ptrCbAudioTransport(NULL),
35 _recSampleRate(0),
36 _playSampleRate(0),
37 _recChannels(0),
38 _playChannels(0),
39 _recChannel(AudioDeviceModule::kChannelBoth),
40 _recBytesPerSample(0),
41 _playBytesPerSample(0),
42 _recSamples(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000043 _recSize(0),
xians@google.com88bd4402011-08-04 15:33:30 +000044 _playSamples(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000045 _playSize(0),
46 _recFile(*FileWrapper::Create()),
47 _playFile(*FileWrapper::Create()),
niklase@google.com470e71d2011-07-07 08:21:25 +000048 _currentMicLevel(0),
xians@google.com88bd4402011-08-04 15:33:30 +000049 _newMicLevel(0),
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +000050 _typingStatus(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000051 _playDelayMS(0),
52 _recDelayMS(0),
andrew@webrtc.org8f940132013-09-11 22:35:00 +000053 _clockDrift(0),
54 // Set to the interval in order to log on the first occurrence.
55 high_delay_counter_(kLogHighDelayIntervalFrames) {
niklase@google.com470e71d2011-07-07 08:21:25 +000056 // 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;
niklase@google.com470e71d2011-07-07 08:21:25 +000079 }
80
81 delete &_critSect;
82 delete &_critSectCb;
83}
84
85// ----------------------------------------------------------------------------
86// SetId
87// ----------------------------------------------------------------------------
88
pbos@webrtc.org25509882013-04-09 10:30:35 +000089void AudioDeviceBuffer::SetId(uint32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000090{
91 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "AudioDeviceBuffer::SetId(id=%d)", id);
92 _id = id;
93}
94
95// ----------------------------------------------------------------------------
96// RegisterAudioCallback
97// ----------------------------------------------------------------------------
98
pbos@webrtc.org25509882013-04-09 10:30:35 +000099int32_t AudioDeviceBuffer::RegisterAudioCallback(AudioTransport* audioCallback)
niklase@google.com470e71d2011-07-07 08:21:25 +0000100{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000101 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000102 _ptrCbAudioTransport = audioCallback;
103
104 return 0;
105}
106
107// ----------------------------------------------------------------------------
108// InitPlayout
109// ----------------------------------------------------------------------------
110
pbos@webrtc.org25509882013-04-09 10:30:35 +0000111int32_t AudioDeviceBuffer::InitPlayout()
niklase@google.com470e71d2011-07-07 08:21:25 +0000112{
113 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000114 return 0;
115}
116
117// ----------------------------------------------------------------------------
118// InitRecording
119// ----------------------------------------------------------------------------
120
pbos@webrtc.org25509882013-04-09 10:30:35 +0000121int32_t AudioDeviceBuffer::InitRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000122{
123 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000124 return 0;
125}
126
127// ----------------------------------------------------------------------------
128// SetRecordingSampleRate
129// ----------------------------------------------------------------------------
130
pbos@webrtc.org25509882013-04-09 10:30:35 +0000131int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000132{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000133 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000134 _recSampleRate = fsHz;
135 return 0;
136}
137
138// ----------------------------------------------------------------------------
139// SetPlayoutSampleRate
140// ----------------------------------------------------------------------------
141
pbos@webrtc.org25509882013-04-09 10:30:35 +0000142int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000143{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000144 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000145 _playSampleRate = fsHz;
146 return 0;
147}
148
149// ----------------------------------------------------------------------------
150// RecordingSampleRate
151// ----------------------------------------------------------------------------
152
pbos@webrtc.org25509882013-04-09 10:30:35 +0000153int32_t AudioDeviceBuffer::RecordingSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000154{
155 return _recSampleRate;
156}
157
158// ----------------------------------------------------------------------------
159// PlayoutSampleRate
160// ----------------------------------------------------------------------------
161
pbos@webrtc.org25509882013-04-09 10:30:35 +0000162int32_t AudioDeviceBuffer::PlayoutSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000163{
164 return _playSampleRate;
165}
166
167// ----------------------------------------------------------------------------
168// SetRecordingChannels
169// ----------------------------------------------------------------------------
170
pbos@webrtc.org25509882013-04-09 10:30:35 +0000171int32_t AudioDeviceBuffer::SetRecordingChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000172{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000173 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000174 _recChannels = channels;
175 _recBytesPerSample = 2*channels; // 16 bits per sample in mono, 32 bits in stereo
176 return 0;
177}
178
179// ----------------------------------------------------------------------------
180// SetPlayoutChannels
181// ----------------------------------------------------------------------------
182
pbos@webrtc.org25509882013-04-09 10:30:35 +0000183int32_t AudioDeviceBuffer::SetPlayoutChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000184{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000185 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000186 _playChannels = channels;
187 // 16 bits per sample in mono, 32 bits in stereo
188 _playBytesPerSample = 2*channels;
189 return 0;
190}
191
192// ----------------------------------------------------------------------------
193// SetRecordingChannel
194//
195// Select which channel to use while recording.
196// This API requires that stereo is enabled.
197//
198// Note that, the nChannel parameter in RecordedDataIsAvailable will be
199// set to 2 even for kChannelLeft and kChannelRight. However, nBytesPerSample
200// will be 2 instead of 4 four these cases.
201// ----------------------------------------------------------------------------
202
pbos@webrtc.org25509882013-04-09 10:30:35 +0000203int32_t AudioDeviceBuffer::SetRecordingChannel(const AudioDeviceModule::ChannelType channel)
niklase@google.com470e71d2011-07-07 08:21:25 +0000204{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000205 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000206
207 if (_recChannels == 1)
208 {
209 return -1;
210 }
211
212 if (channel == AudioDeviceModule::kChannelBoth)
213 {
214 // two bytes per channel
215 _recBytesPerSample = 4;
216 }
217 else
218 {
219 // only utilize one out of two possible channels (left or right)
220 _recBytesPerSample = 2;
221 }
222 _recChannel = channel;
223
224 return 0;
225}
226
227// ----------------------------------------------------------------------------
228// RecordingChannel
229// ----------------------------------------------------------------------------
230
pbos@webrtc.org25509882013-04-09 10:30:35 +0000231int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000232{
233 channel = _recChannel;
234 return 0;
235}
236
237// ----------------------------------------------------------------------------
238// RecordingChannels
239// ----------------------------------------------------------------------------
240
pbos@webrtc.org25509882013-04-09 10:30:35 +0000241uint8_t AudioDeviceBuffer::RecordingChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000242{
243 return _recChannels;
244}
245
246// ----------------------------------------------------------------------------
247// PlayoutChannels
248// ----------------------------------------------------------------------------
249
pbos@webrtc.org25509882013-04-09 10:30:35 +0000250uint8_t AudioDeviceBuffer::PlayoutChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000251{
252 return _playChannels;
253}
254
255// ----------------------------------------------------------------------------
256// SetCurrentMicLevel
257// ----------------------------------------------------------------------------
258
pbos@webrtc.org25509882013-04-09 10:30:35 +0000259int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level)
niklase@google.com470e71d2011-07-07 08:21:25 +0000260{
261 _currentMicLevel = level;
262 return 0;
263}
264
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000265int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus)
266{
267 _typingStatus = typingStatus;
268 return 0;
269}
270
niklase@google.com470e71d2011-07-07 08:21:25 +0000271// ----------------------------------------------------------------------------
272// NewMicLevel
273// ----------------------------------------------------------------------------
274
pbos@webrtc.org25509882013-04-09 10:30:35 +0000275uint32_t AudioDeviceBuffer::NewMicLevel() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000276{
277 return _newMicLevel;
278}
279
280// ----------------------------------------------------------------------------
281// SetVQEData
282// ----------------------------------------------------------------------------
283
andrew@webrtc.org5eb997a2013-09-12 01:01:42 +0000284void AudioDeviceBuffer::SetVQEData(int playDelayMs, int recDelayMs,
285 int clockDrift) {
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000286 if (high_delay_counter_ < kLogHighDelayIntervalFrames) {
287 ++high_delay_counter_;
288 } else {
289 if (playDelayMs + recDelayMs > kHighDelayThresholdMs) {
290 high_delay_counter_ = 0;
291 LOG(LS_WARNING) << "High audio device delay reported (render="
292 << playDelayMs << " ms, capture=" << recDelayMs << " ms)";
niklase@google.com470e71d2011-07-07 08:21:25 +0000293 }
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000294 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000295
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000296 _playDelayMS = playDelayMs;
297 _recDelayMS = recDelayMs;
298 _clockDrift = clockDrift;
niklase@google.com470e71d2011-07-07 08:21:25 +0000299}
300
301// ----------------------------------------------------------------------------
302// StartInputFileRecording
303// ----------------------------------------------------------------------------
304
pbos@webrtc.org25509882013-04-09 10:30:35 +0000305int32_t AudioDeviceBuffer::StartInputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000306 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000307{
308 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
309
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000310 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000311
312 _recFile.Flush();
313 _recFile.CloseFile();
314
315 return (_recFile.OpenFile(fileName, false, false, false));
316}
317
318// ----------------------------------------------------------------------------
319// StopInputFileRecording
320// ----------------------------------------------------------------------------
321
pbos@webrtc.org25509882013-04-09 10:30:35 +0000322int32_t AudioDeviceBuffer::StopInputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000323{
324 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
325
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000326 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000327
328 _recFile.Flush();
329 _recFile.CloseFile();
330
331 return 0;
332}
333
334// ----------------------------------------------------------------------------
335// StartOutputFileRecording
336// ----------------------------------------------------------------------------
337
pbos@webrtc.org25509882013-04-09 10:30:35 +0000338int32_t AudioDeviceBuffer::StartOutputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000339 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000340{
341 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
342
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000343 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000344
345 _playFile.Flush();
346 _playFile.CloseFile();
347
348 return (_playFile.OpenFile(fileName, false, false, false));
349}
350
351// ----------------------------------------------------------------------------
352// StopOutputFileRecording
353// ----------------------------------------------------------------------------
354
pbos@webrtc.org25509882013-04-09 10:30:35 +0000355int32_t AudioDeviceBuffer::StopOutputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000356{
357 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
358
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000359 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
361 _playFile.Flush();
362 _playFile.CloseFile();
363
364 return 0;
365}
366
367// ----------------------------------------------------------------------------
368// SetRecordedBuffer
369//
370// Store recorded audio buffer in local memory ready for the actual
371// "delivery" using a callback.
372//
373// This method can also parse out left or right channel from a stereo
374// input signal, i.e., emulate mono.
375//
376// Examples:
377//
378// 16-bit,48kHz mono, 10ms => nSamples=480 => _recSize=2*480=960 bytes
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000379// 16-bit,48kHz stereo,10ms => nSamples=480 => _recSize=4*480=1920 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000380// ----------------------------------------------------------------------------
381
pbos@webrtc.org25509882013-04-09 10:30:35 +0000382int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer,
383 uint32_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000384{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000385 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000386
387 if (_recBytesPerSample == 0)
388 {
389 assert(false);
390 return -1;
391 }
392
393 _recSamples = nSamples;
394 _recSize = _recBytesPerSample*nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000395 if (_recSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000396 {
397 assert(false);
398 return -1;
399 }
400
niklase@google.com470e71d2011-07-07 08:21:25 +0000401 if (_recChannel == AudioDeviceModule::kChannelBoth)
402 {
403 // (default) copy the complete input buffer to the local buffer
404 memcpy(&_recBuffer[0], audioBuffer, _recSize);
405 }
406 else
407 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000408 int16_t* ptr16In = (int16_t*)audioBuffer;
409 int16_t* ptr16Out = (int16_t*)&_recBuffer[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000410
411 if (AudioDeviceModule::kChannelRight == _recChannel)
412 {
413 ptr16In++;
414 }
415
416 // exctract left or right channel from input buffer to the local buffer
pbos@webrtc.org25509882013-04-09 10:30:35 +0000417 for (uint32_t i = 0; i < _recSamples; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000418 {
419 *ptr16Out = *ptr16In;
420 ptr16Out++;
421 ptr16In++;
422 ptr16In++;
423 }
424 }
425
426 if (_recFile.Open())
427 {
428 // write to binary file in mono or stereo (interleaved)
429 _recFile.Write(&_recBuffer[0], _recSize);
430 }
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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000485int32_t AudioDeviceBuffer::RequestPlayoutData(uint32_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000486{
pbos@webrtc.org25509882013-04-09 10:30:35 +0000487 uint32_t playSampleRate = 0;
488 uint8_t playBytesPerSample = 0;
489 uint8_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
pbos@webrtc.org25509882013-04-09 10:30:35 +0000523 uint32_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,
566 "_playSize %i exceeds kMaxBufferSizeBytes in "
567 "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
574 if (_playFile.Open())
575 {
576 // write to binary file in mono or stereo (interleaved)
577 _playFile.Write(&_playBuffer[0], _playSize);
578 }
579
Peter Kastingb7e50542015-06-11 12:55:50 -0700580 return static_cast<int32_t>(_playSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +0000581}
582
niklase@google.com470e71d2011-07-07 08:21:25 +0000583} // namespace webrtc