blob: b4f3c371ace369cdcfd45bb932616480830bd401 [file] [log] [blame]
henrika86d907c2015-09-07 16:09:50 +02001/*
2 * Copyright (c) 2013 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_device/fine_audio_buffer.h"
henrika86d907c2015-09-07 16:09:50 +020012
Yves Gerey988cc082018-10-23 12:03:01 +020013#include <cstdint>
14#include <cstring>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/audio_device/audio_device_buffer.h"
17#include "rtc_base/checks.h"
18#include "rtc_base/logging.h"
henrika29e865a2018-04-24 13:22:31 +020019#include "rtc_base/numerics/safe_conversions.h"
henrika86d907c2015-09-07 16:09:50 +020020
21namespace webrtc {
22
henrika29e865a2018-04-24 13:22:31 +020023FineAudioBuffer::FineAudioBuffer(AudioDeviceBuffer* audio_device_buffer)
24 : audio_device_buffer_(audio_device_buffer),
25 playout_samples_per_channel_10ms_(rtc::dchecked_cast<size_t>(
26 audio_device_buffer->PlayoutSampleRate() * 10 / 1000)),
27 record_samples_per_channel_10ms_(rtc::dchecked_cast<size_t>(
28 audio_device_buffer->RecordingSampleRate() * 10 / 1000)),
29 playout_channels_(audio_device_buffer->PlayoutChannels()),
30 record_channels_(audio_device_buffer->RecordingChannels()) {
31 RTC_DCHECK(audio_device_buffer_);
henrika5b6afc02018-09-05 14:34:40 +020032 RTC_DLOG(INFO) << __FUNCTION__;
henrika29e865a2018-04-24 13:22:31 +020033 if (IsReadyForPlayout()) {
34 RTC_DLOG(INFO) << "playout_samples_per_channel_10ms: "
35 << playout_samples_per_channel_10ms_;
36 RTC_DLOG(INFO) << "playout_channels: " << playout_channels_;
37 }
38 if (IsReadyForRecord()) {
39 RTC_DLOG(INFO) << "record_samples_per_channel_10ms: "
40 << record_samples_per_channel_10ms_;
41 RTC_DLOG(INFO) << "record_channels: " << record_channels_;
42 }
henrika86d907c2015-09-07 16:09:50 +020043}
44
henrika5b6afc02018-09-05 14:34:40 +020045FineAudioBuffer::~FineAudioBuffer() {
46 RTC_DLOG(INFO) << __FUNCTION__;
47}
henrika86d907c2015-09-07 16:09:50 +020048
henrika86d907c2015-09-07 16:09:50 +020049void FineAudioBuffer::ResetPlayout() {
henrikab3ebc1a2017-02-27 05:14:17 -080050 playout_buffer_.Clear();
henrika86d907c2015-09-07 16:09:50 +020051}
52
53void FineAudioBuffer::ResetRecord() {
henrikaf166e1b2017-02-23 02:44:55 -080054 record_buffer_.Clear();
henrika86d907c2015-09-07 16:09:50 +020055}
56
henrika29e865a2018-04-24 13:22:31 +020057bool FineAudioBuffer::IsReadyForPlayout() const {
58 return playout_samples_per_channel_10ms_ > 0 && playout_channels_ > 0;
59}
60
61bool FineAudioBuffer::IsReadyForRecord() const {
62 return record_samples_per_channel_10ms_ > 0 && record_channels_ > 0;
63}
64
henrika8d7393b2018-04-19 13:40:15 +020065void FineAudioBuffer::GetPlayoutData(rtc::ArrayView<int16_t> audio_buffer,
henrika883d00f2018-03-16 10:09:49 +010066 int playout_delay_ms) {
henrika29e865a2018-04-24 13:22:31 +020067 RTC_DCHECK(IsReadyForPlayout());
henrikab3ebc1a2017-02-27 05:14:17 -080068 // Ask WebRTC for new data in chunks of 10ms until we have enough to
69 // fulfill the request. It is possible that the buffer already contains
70 // enough samples from the last round.
henrika8d7393b2018-04-19 13:40:15 +020071 while (playout_buffer_.size() < audio_buffer.size()) {
henrika29e865a2018-04-24 13:22:31 +020072 // Get 10ms decoded audio from WebRTC. The ADB knows about number of
73 // channels; hence we can ask for number of samples per channel here.
henrikaec9c7452018-06-08 16:10:03 +020074 if (audio_device_buffer_->RequestPlayoutData(
75 playout_samples_per_channel_10ms_) ==
76 static_cast<int32_t>(playout_samples_per_channel_10ms_)) {
77 // Append 10ms to the end of the local buffer taking number of channels
78 // into account.
79 const size_t num_elements_10ms =
80 playout_channels_ * playout_samples_per_channel_10ms_;
81 const size_t written_elements = playout_buffer_.AppendData(
82 num_elements_10ms, [&](rtc::ArrayView<int16_t> buf) {
83 const size_t samples_per_channel_10ms =
84 audio_device_buffer_->GetPlayoutData(buf.data());
85 return playout_channels_ * samples_per_channel_10ms;
86 });
87 RTC_DCHECK_EQ(num_elements_10ms, written_elements);
88 } else {
89 // Provide silence if AudioDeviceBuffer::RequestPlayoutData() fails.
90 // Can e.g. happen when an AudioTransport has not been registered.
91 const size_t num_bytes = audio_buffer.size() * sizeof(int16_t);
92 std::memset(audio_buffer.data(), 0, num_bytes);
93 return;
94 }
henrika86d907c2015-09-07 16:09:50 +020095 }
henrika8d7393b2018-04-19 13:40:15 +020096
henrikab3ebc1a2017-02-27 05:14:17 -080097 // Provide the requested number of bytes to the consumer.
henrika29e865a2018-04-24 13:22:31 +020098 const size_t num_bytes = audio_buffer.size() * sizeof(int16_t);
henrikabb6f7522017-05-30 02:01:30 -070099 memcpy(audio_buffer.data(), playout_buffer_.data(), num_bytes);
henrikab3ebc1a2017-02-27 05:14:17 -0800100 // Move remaining samples to start of buffer to prepare for next round.
henrika8d7393b2018-04-19 13:40:15 +0200101 memmove(playout_buffer_.data(), playout_buffer_.data() + audio_buffer.size(),
102 (playout_buffer_.size() - audio_buffer.size()) * sizeof(int16_t));
103 playout_buffer_.SetSize(playout_buffer_.size() - audio_buffer.size());
henrika883d00f2018-03-16 10:09:49 +0100104 // Cache playout latency for usage in DeliverRecordedData();
105 playout_delay_ms_ = playout_delay_ms;
henrika86d907c2015-09-07 16:09:50 +0200106}
107
henrikabb6f7522017-05-30 02:01:30 -0700108void FineAudioBuffer::DeliverRecordedData(
henrika8d7393b2018-04-19 13:40:15 +0200109 rtc::ArrayView<const int16_t> audio_buffer,
henrikabb6f7522017-05-30 02:01:30 -0700110 int record_delay_ms) {
henrika29e865a2018-04-24 13:22:31 +0200111 RTC_DCHECK(IsReadyForRecord());
112 // Always append new data and grow the buffer when needed.
henrikabb6f7522017-05-30 02:01:30 -0700113 record_buffer_.AppendData(audio_buffer.data(), audio_buffer.size());
henrikaf166e1b2017-02-23 02:44:55 -0800114 // Consume samples from buffer in chunks of 10ms until there is not
henrika8d7393b2018-04-19 13:40:15 +0200115 // enough data left. The number of remaining samples in the cache is given by
henrika29e865a2018-04-24 13:22:31 +0200116 // the new size of the internal |record_buffer_|.
117 const size_t num_elements_10ms =
118 record_channels_ * record_samples_per_channel_10ms_;
119 while (record_buffer_.size() >= num_elements_10ms) {
120 audio_device_buffer_->SetRecordedBuffer(record_buffer_.data(),
121 record_samples_per_channel_10ms_);
122 audio_device_buffer_->SetVQEData(playout_delay_ms_, record_delay_ms);
123 audio_device_buffer_->DeliverRecordedData();
124 memmove(record_buffer_.data(), record_buffer_.data() + num_elements_10ms,
125 (record_buffer_.size() - num_elements_10ms) * sizeof(int16_t));
126 record_buffer_.SetSize(record_buffer_.size() - num_elements_10ms);
henrika86d907c2015-09-07 16:09:50 +0200127 }
128}
129
130} // namespace webrtc