1/*
2Copyright 2018 Google Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS-IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17// Prevent Visual Studio from complaining about std::copy_n.
18#if defined(_WIN32)
19#define _SCL_SECURE_NO_WARNINGS
20#endif
21
22#include "utils/buffer_partitioner.h"
23
24#include "utils/planar_interleaved_conversion.h"
25
26namespace vraudio {
27
28BufferPartitioner::BufferPartitioner(size_t num_channels,
29 size_t frames_per_buffer,
30 NewBufferCallback buffer_callback)
31 : num_channels_(num_channels),
32 frames_per_buffer_(frames_per_buffer),
33 buffer_callback_(std::move(buffer_callback)),
34 current_buffer_ptr_(nullptr),
35 current_buffer_write_position_frames_(0),
36 planar_channel_ptrs_(num_channels) {}
37
38size_t BufferPartitioner::GetNumGeneratedBuffersForNumInputFrames(
39 size_t num_input_frames) const {
40 return (current_buffer_write_position_frames_ + num_input_frames) /
41 frames_per_buffer_;
42}
43
44void BufferPartitioner::AddBuffer(const int16* interleaved_buffer,
45 size_t num_channels, size_t num_frames) {
46 AddBufferTemplated<const int16*>(buffer: interleaved_buffer, num_channels,
47 num_frames);
48}
49
50void BufferPartitioner::AddBuffer(const float* interleaved_buffer,
51 size_t num_channels, size_t num_frames) {
52 AddBufferTemplated<const float*>(buffer: interleaved_buffer, num_channels,
53 num_frames);
54}
55
56void BufferPartitioner::AddBuffer(const float* const* planar_buffer,
57 size_t num_channels, size_t num_frames) {
58 AddBufferTemplated<const float* const*>(buffer: planar_buffer, num_channels,
59 num_frames);
60}
61
62void BufferPartitioner::AddBuffer(const int16* const* planar_buffer,
63 size_t num_channels, size_t num_frames) {
64 AddBufferTemplated<const int16* const*>(buffer: planar_buffer, num_channels,
65 num_frames);
66}
67
68void BufferPartitioner::AddBuffer(const AudioBuffer& audio_buffer) {
69 AddBuffer(num_valid_frames: audio_buffer.num_frames(), audio_buffer);
70}
71
72void BufferPartitioner::AddBuffer(size_t num_valid_frames,
73 const AudioBuffer& audio_buffer) {
74 DCHECK_EQ(audio_buffer.num_channels(), num_channels_);
75 DCHECK_LE(num_valid_frames, audio_buffer.num_frames());
76 for (size_t channel = 0; channel < num_channels_; ++channel) {
77 planar_channel_ptrs_[channel] = &audio_buffer[channel][0];
78 }
79 AddBuffer(planar_buffer: planar_channel_ptrs_.data(), num_channels: audio_buffer.num_channels(),
80 num_frames: num_valid_frames);
81}
82
83size_t BufferPartitioner::GetNumBufferedFrames() const {
84 return current_buffer_write_position_frames_;
85}
86
87size_t BufferPartitioner::Flush() {
88 if (current_buffer_write_position_frames_ == 0 ||
89 current_buffer_ptr_ == nullptr) {
90 return 0;
91 }
92 DCHECK_LE(current_buffer_write_position_frames_,
93 current_buffer_ptr_->num_frames());
94 const size_t num_zeropadded_frames =
95 current_buffer_ptr_->num_frames() - current_buffer_write_position_frames_;
96 for (AudioBuffer::Channel& channel : *current_buffer_ptr_) {
97 DCHECK_LE(current_buffer_write_position_frames_, channel.size());
98 std::fill(first: channel.begin() + current_buffer_write_position_frames_,
99 last: channel.end(), value: 0.0f);
100 }
101 current_buffer_ptr_ = buffer_callback_(current_buffer_ptr_);
102 current_buffer_write_position_frames_ = 0;
103 return num_zeropadded_frames;
104}
105
106void BufferPartitioner::Clear() {
107 current_buffer_ptr_ = nullptr;
108 current_buffer_write_position_frames_ = 0;
109}
110
111template <typename BufferType>
112void BufferPartitioner::AddBufferTemplated(BufferType buffer,
113 size_t num_channels,
114 size_t num_frames) {
115 DCHECK_EQ(num_channels, num_channels_);
116
117 size_t input_read_frame = 0;
118 while (input_read_frame < num_frames) {
119 if (current_buffer_ptr_ == nullptr) {
120 current_buffer_ptr_ = buffer_callback_(nullptr);
121 if (current_buffer_ptr_ == nullptr) {
122 LOG(WARNING) << "No input buffer received";
123 return;
124 }
125 DCHECK_EQ(current_buffer_ptr_->num_frames(), frames_per_buffer_);
126 DCHECK_EQ(current_buffer_ptr_->num_channels(), num_channels_);
127 current_buffer_write_position_frames_ = 0;
128 }
129 DCHECK_GT(frames_per_buffer_, current_buffer_write_position_frames_);
130 const size_t remaining_frames_in_temp_buffer =
131 frames_per_buffer_ - current_buffer_write_position_frames_;
132 const size_t remaining_frames_in_input_buffer =
133 num_frames - input_read_frame;
134 const size_t num_frames_to_process = std::min(
135 a: remaining_frames_in_temp_buffer, b: remaining_frames_in_input_buffer);
136
137 FillAudioBufferWithOffset(buffer, num_frames, num_channels_,
138 input_read_frame,
139 current_buffer_write_position_frames_,
140 num_frames_to_process, current_buffer_ptr_);
141
142 input_read_frame += num_frames_to_process;
143
144 // Update write pointers in temporary buffer.
145 current_buffer_write_position_frames_ += num_frames_to_process;
146 if (current_buffer_write_position_frames_ == frames_per_buffer_) {
147 // Current buffer is filled with data -> pass it to callback.
148 current_buffer_ptr_ = buffer_callback_(current_buffer_ptr_);
149 current_buffer_write_position_frames_ = 0;
150 if (current_buffer_ptr_ == nullptr) {
151 LOG(WARNING) << "No input buffer received";
152 return;
153 }
154 DCHECK_EQ(current_buffer_ptr_->num_frames(), frames_per_buffer_);
155 DCHECK_EQ(current_buffer_ptr_->num_channels(), num_channels_);
156 }
157 }
158}
159
160} // namespace vraudio
161

source code of qtmultimedia/src/3rdparty/resonance-audio/resonance_audio/utils/buffer_partitioner.cc