Home | History | Annotate | Download | only in audio_device
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      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 "webrtc/modules/audio_device/audio_device_buffer.h"
     12 
     13 #include <assert.h>
     14 #include <string.h>
     15 
     16 #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"
     19 #include "webrtc/system_wrappers/interface/logging.h"
     20 #include "webrtc/system_wrappers/interface/trace.h"
     21 
     22 namespace webrtc {
     23 
     24 static const int kHighDelayThresholdMs = 300;
     25 static const int kLogHighDelayIntervalFrames = 500;  // 5 seconds.
     26 
     27 // ----------------------------------------------------------------------------
     28 //  ctor
     29 // ----------------------------------------------------------------------------
     30 
     31 AudioDeviceBuffer::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),
     44     _recSize(0),
     45     _playSamples(0),
     46     _playSize(0),
     47     _recFile(*FileWrapper::Create()),
     48     _playFile(*FileWrapper::Create()),
     49     _currentMicLevel(0),
     50     _newMicLevel(0),
     51     _typingStatus(false),
     52     _playDelayMS(0),
     53     _recDelayMS(0),
     54     _clockDrift(0),
     55     // Set to the interval in order to log on the first occurrence.
     56     high_delay_counter_(kLogHighDelayIntervalFrames) {
     57     // valid ID will be set later by SetId, use -1 for now
     58     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s created", __FUNCTION__);
     59     memset(_recBuffer, 0, kMaxBufferSizeBytes);
     60     memset(_playBuffer, 0, kMaxBufferSizeBytes);
     61 }
     62 
     63 // ----------------------------------------------------------------------------
     64 //  dtor
     65 // ----------------------------------------------------------------------------
     66 
     67 AudioDeviceBuffer::~AudioDeviceBuffer()
     68 {
     69     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTION__);
     70     {
     71         CriticalSectionScoped lock(&_critSect);
     72 
     73         _recFile.Flush();
     74         _recFile.CloseFile();
     75         delete &_recFile;
     76 
     77         _playFile.Flush();
     78         _playFile.CloseFile();
     79         delete &_playFile;
     80     }
     81 
     82     delete &_critSect;
     83     delete &_critSectCb;
     84 }
     85 
     86 // ----------------------------------------------------------------------------
     87 //  SetId
     88 // ----------------------------------------------------------------------------
     89 
     90 void AudioDeviceBuffer::SetId(uint32_t id)
     91 {
     92     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "AudioDeviceBuffer::SetId(id=%d)", id);
     93     _id = id;
     94 }
     95 
     96 // ----------------------------------------------------------------------------
     97 //  RegisterAudioCallback
     98 // ----------------------------------------------------------------------------
     99 
    100 int32_t AudioDeviceBuffer::RegisterAudioCallback(AudioTransport* audioCallback)
    101 {
    102     CriticalSectionScoped lock(&_critSectCb);
    103     _ptrCbAudioTransport = audioCallback;
    104 
    105     return 0;
    106 }
    107 
    108 // ----------------------------------------------------------------------------
    109 //  InitPlayout
    110 // ----------------------------------------------------------------------------
    111 
    112 int32_t AudioDeviceBuffer::InitPlayout()
    113 {
    114     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    115     return 0;
    116 }
    117 
    118 // ----------------------------------------------------------------------------
    119 //  InitRecording
    120 // ----------------------------------------------------------------------------
    121 
    122 int32_t AudioDeviceBuffer::InitRecording()
    123 {
    124     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    125     return 0;
    126 }
    127 
    128 // ----------------------------------------------------------------------------
    129 //  SetRecordingSampleRate
    130 // ----------------------------------------------------------------------------
    131 
    132 int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz)
    133 {
    134     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingSampleRate(fsHz=%u)", fsHz);
    135 
    136     CriticalSectionScoped lock(&_critSect);
    137     _recSampleRate = fsHz;
    138     return 0;
    139 }
    140 
    141 // ----------------------------------------------------------------------------
    142 //  SetPlayoutSampleRate
    143 // ----------------------------------------------------------------------------
    144 
    145 int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz)
    146 {
    147     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutSampleRate(fsHz=%u)", fsHz);
    148 
    149     CriticalSectionScoped lock(&_critSect);
    150     _playSampleRate = fsHz;
    151     return 0;
    152 }
    153 
    154 // ----------------------------------------------------------------------------
    155 //  RecordingSampleRate
    156 // ----------------------------------------------------------------------------
    157 
    158 int32_t AudioDeviceBuffer::RecordingSampleRate() const
    159 {
    160     return _recSampleRate;
    161 }
    162 
    163 // ----------------------------------------------------------------------------
    164 //  PlayoutSampleRate
    165 // ----------------------------------------------------------------------------
    166 
    167 int32_t AudioDeviceBuffer::PlayoutSampleRate() const
    168 {
    169     return _playSampleRate;
    170 }
    171 
    172 // ----------------------------------------------------------------------------
    173 //  SetRecordingChannels
    174 // ----------------------------------------------------------------------------
    175 
    176 int32_t AudioDeviceBuffer::SetRecordingChannels(uint8_t channels)
    177 {
    178     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingChannels(channels=%u)", channels);
    179 
    180     CriticalSectionScoped lock(&_critSect);
    181     _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 
    190 int32_t AudioDeviceBuffer::SetPlayoutChannels(uint8_t channels)
    191 {
    192     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutChannels(channels=%u)", channels);
    193 
    194     CriticalSectionScoped lock(&_critSect);
    195     _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 
    212 int32_t AudioDeviceBuffer::SetRecordingChannel(const AudioDeviceModule::ChannelType channel)
    213 {
    214     CriticalSectionScoped lock(&_critSect);
    215 
    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 
    240 int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const
    241 {
    242     channel = _recChannel;
    243     return 0;
    244 }
    245 
    246 // ----------------------------------------------------------------------------
    247 //  RecordingChannels
    248 // ----------------------------------------------------------------------------
    249 
    250 uint8_t AudioDeviceBuffer::RecordingChannels() const
    251 {
    252     return _recChannels;
    253 }
    254 
    255 // ----------------------------------------------------------------------------
    256 //  PlayoutChannels
    257 // ----------------------------------------------------------------------------
    258 
    259 uint8_t AudioDeviceBuffer::PlayoutChannels() const
    260 {
    261     return _playChannels;
    262 }
    263 
    264 // ----------------------------------------------------------------------------
    265 //  SetCurrentMicLevel
    266 // ----------------------------------------------------------------------------
    267 
    268 int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level)
    269 {
    270     _currentMicLevel = level;
    271     return 0;
    272 }
    273 
    274 int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus)
    275 {
    276     _typingStatus = typingStatus;
    277     return 0;
    278 }
    279 
    280 // ----------------------------------------------------------------------------
    281 //  NewMicLevel
    282 // ----------------------------------------------------------------------------
    283 
    284 uint32_t AudioDeviceBuffer::NewMicLevel() const
    285 {
    286     return _newMicLevel;
    287 }
    288 
    289 // ----------------------------------------------------------------------------
    290 //  SetVQEData
    291 // ----------------------------------------------------------------------------
    292 
    293 void AudioDeviceBuffer::SetVQEData(int playDelayMs, int recDelayMs,
    294                                    int clockDrift) {
    295   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)";
    302     }
    303   }
    304 
    305   _playDelayMS = playDelayMs;
    306   _recDelayMS = recDelayMs;
    307   _clockDrift = clockDrift;
    308 }
    309 
    310 // ----------------------------------------------------------------------------
    311 //  StartInputFileRecording
    312 // ----------------------------------------------------------------------------
    313 
    314 int32_t AudioDeviceBuffer::StartInputFileRecording(
    315     const char fileName[kAdmMaxFileNameSize])
    316 {
    317     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    318 
    319     CriticalSectionScoped lock(&_critSect);
    320 
    321     _recFile.Flush();
    322     _recFile.CloseFile();
    323 
    324     return (_recFile.OpenFile(fileName, false, false, false));
    325 }
    326 
    327 // ----------------------------------------------------------------------------
    328 //  StopInputFileRecording
    329 // ----------------------------------------------------------------------------
    330 
    331 int32_t AudioDeviceBuffer::StopInputFileRecording()
    332 {
    333     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    334 
    335     CriticalSectionScoped lock(&_critSect);
    336 
    337     _recFile.Flush();
    338     _recFile.CloseFile();
    339 
    340     return 0;
    341 }
    342 
    343 // ----------------------------------------------------------------------------
    344 //  StartOutputFileRecording
    345 // ----------------------------------------------------------------------------
    346 
    347 int32_t AudioDeviceBuffer::StartOutputFileRecording(
    348     const char fileName[kAdmMaxFileNameSize])
    349 {
    350     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    351 
    352     CriticalSectionScoped lock(&_critSect);
    353 
    354     _playFile.Flush();
    355     _playFile.CloseFile();
    356 
    357     return (_playFile.OpenFile(fileName, false, false, false));
    358 }
    359 
    360 // ----------------------------------------------------------------------------
    361 //  StopOutputFileRecording
    362 // ----------------------------------------------------------------------------
    363 
    364 int32_t AudioDeviceBuffer::StopOutputFileRecording()
    365 {
    366     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    367 
    368     CriticalSectionScoped lock(&_critSect);
    369 
    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
    388 //  16-bit,48kHz stereo,10ms => nSamples=480 => _recSize=4*480=1920 bytes
    389 // ----------------------------------------------------------------------------
    390 
    391 int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer,
    392                                              uint32_t nSamples)
    393 {
    394     CriticalSectionScoped lock(&_critSect);
    395 
    396     if (_recBytesPerSample == 0)
    397     {
    398         assert(false);
    399         return -1;
    400     }
    401 
    402     _recSamples = nSamples;
    403     _recSize = _recBytesPerSample*nSamples; // {2,4}*nSamples
    404     if (_recSize > kMaxBufferSizeBytes)
    405     {
    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     {
    423         int16_t* ptr16In = (int16_t*)audioBuffer;
    424         int16_t* ptr16Out = (int16_t*)&_recBuffer[0];
    425 
    426         if (AudioDeviceModule::kChannelRight == _recChannel)
    427         {
    428             ptr16In++;
    429         }
    430 
    431         // exctract left or right channel from input buffer to the local buffer
    432         for (uint32_t i = 0; i < _recSamples; i++)
    433         {
    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 
    454 int32_t AudioDeviceBuffer::DeliverRecordedData()
    455 {
    456     CriticalSectionScoped lock(&_critSectCb);
    457 
    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 
    474     int32_t res(0);
    475     uint32_t newMicLevel(0);
    476     uint32_t totalDelayMS = _playDelayMS +_recDelayMS;
    477 
    478     res = _ptrCbAudioTransport->RecordedDataIsAvailable(&_recBuffer[0],
    479                                                         _recSamples,
    480                                                         _recBytesPerSample,
    481                                                         _recChannels,
    482                                                         _recSampleRate,
    483                                                         totalDelayMS,
    484                                                         _clockDrift,
    485                                                         _currentMicLevel,
    486                                                         _typingStatus,
    487                                                         newMicLevel);
    488     if (res != -1)
    489     {
    490         _newMicLevel = newMicLevel;
    491     }
    492 
    493     return 0;
    494 }
    495 
    496 // ----------------------------------------------------------------------------
    497 //  RequestPlayoutData
    498 // ----------------------------------------------------------------------------
    499 
    500 int32_t AudioDeviceBuffer::RequestPlayoutData(uint32_t nSamples)
    501 {
    502     uint32_t playSampleRate = 0;
    503     uint8_t playBytesPerSample = 0;
    504     uint8_t playChannels = 0;
    505     {
    506         CriticalSectionScoped lock(&_critSect);
    507 
    508         // 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 
    514         // Ensure that user has initialized all essential members
    515         if ((playBytesPerSample == 0) ||
    516             (playChannels == 0)       ||
    517             (playSampleRate == 0))
    518         {
    519             assert(false);
    520             return -1;
    521         }
    522 
    523         _playSamples = nSamples;
    524         _playSize = playBytesPerSample * nSamples;  // {2,4}*nSamples
    525         if (_playSize > kMaxBufferSizeBytes)
    526         {
    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 
    538     uint32_t nSamplesOut(0);
    539 
    540     CriticalSectionScoped lock(&_critSectCb);
    541 
    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     {
    550         uint32_t res(0);
    551         int64_t elapsed_time_ms = -1;
    552         int64_t ntp_time_ms = -1;
    553         res = _ptrCbAudioTransport->NeedMorePlayData(_playSamples,
    554                                                      playBytesPerSample,
    555                                                      playChannels,
    556                                                      playSampleRate,
    557                                                      &_playBuffer[0],
    558                                                      nSamplesOut,
    559                                                      &elapsed_time_ms,
    560                                                      &ntp_time_ms);
    561         if (res != 0)
    562         {
    563             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "NeedMorePlayData() failed");
    564         }
    565     }
    566 
    567     return nSamplesOut;
    568 }
    569 
    570 // ----------------------------------------------------------------------------
    571 //  GetPlayoutData
    572 // ----------------------------------------------------------------------------
    573 
    574 int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer)
    575 {
    576     CriticalSectionScoped lock(&_critSect);
    577 
    578     if (_playSize > kMaxBufferSizeBytes)
    579     {
    580        WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "_playSize %i exceeds "
    581        "kMaxBufferSizeBytes in AudioDeviceBuffer::GetPlayoutData", _playSize);
    582        assert(false);
    583        return -1;
    584     }
    585 
    586     memcpy(audioBuffer, &_playBuffer[0], _playSize);
    587 
    588     if (_playFile.Open())
    589     {
    590         // write to binary file in mono or stereo (interleaved)
    591         _playFile.Write(&_playBuffer[0], _playSize);
    592     }
    593 
    594     return _playSamples;
    595 }
    596 
    597 }  // namespace webrtc
    598