1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef LOG_TAG
17 #define LOG_TAG "HpaePcmBuffer"
18 #endif
19
20 #include "securec.h"
21 #include "simd_utils.h"
22 #include "hpae_pcm_buffer.h"
23 #include "audio_engine_log.h"
24
25 namespace OHOS {
26 namespace AudioStandard {
27 namespace HPAE {
HpaePcmBuffer(PcmBufferInfo & pcmBufferInfo)28 HpaePcmBuffer::HpaePcmBuffer(PcmBufferInfo &pcmBufferInfo) : pcmBufferInfo_(pcmBufferInfo)
29 {
30 InitPcmProcess();
31 }
32
operator =(HpaePcmBuffer & other)33 HpaePcmBuffer &HpaePcmBuffer::operator=(HpaePcmBuffer &other)
34 {
35 if (this != &other) {
36 pcmBufferInfo_ = other.pcmBufferInfo_;
37 InitPcmProcess();
38 int32_t ret = memcpy_s(GetPcmDataBuffer(), bufferByteSize_, other.GetPcmDataBuffer(), bufferByteSize_);
39 if (ret != 0) {
40 AUDIO_ERR_LOG("memcpy failed when copy PcmBuffer");
41 }
42 }
43 return *this;
44 }
45
HpaePcmBuffer(HpaePcmBuffer && other)46 HpaePcmBuffer::HpaePcmBuffer(HpaePcmBuffer &&other)
47 {
48 pcmBufferInfo_ = other.pcmBufferInfo_;
49 bufferByteSize_ = other.bufferByteSize_;
50 bufferFloatSize_ = other.bufferFloatSize_;
51 dataByteSize_ = other.dataByteSize_;
52 pcmDataBuffer_ = std::move(other.pcmDataBuffer_);
53 pcmProcessVec_ = std::move(other.pcmProcessVec_);
54 other.pcmBufferInfo_.frames = 0;
55 other.bufferByteSize_ = 0;
56 other.bufferFloatSize_ = 0;
57 other.dataByteSize_ = 0;
58 }
59
InitPcmProcess()60 void HpaePcmBuffer::InitPcmProcess()
61 {
62 size_t ch = GetChannelCount();
63 size_t frameLen = GetFrameLen();
64 size_t frames = GetFrames();
65 size_t addBytes = MEMORY_ALIGN_BYTE_NUM - (frameLen * sizeof(float) * ch) % MEMORY_ALIGN_BYTE_NUM;
66 size_t dataSize = frameLen * sizeof(float) * ch;
67 frameByteSize_ = frameLen * sizeof(float) * ch + addBytes;
68 frameFloatSize_ = frameByteSize_ / sizeof(float);
69 bufferByteSize_ = frameByteSize_ * frames;
70 bufferFloatSize_ = frameFloatSize_ * frames;
71 dataByteSize_ = dataSize * frames;
72 frameSample_ = frameLen * ch;
73 pcmDataBuffer_.resize(bufferFloatSize_);
74 readPos_.store(0);
75 writePos_.store(0);
76 curFrames_.store(0);
77 pcmProcessVec_.clear();
78 pcmProcessVec_.reserve(frames);
79 float *itr = pcmDataBuffer_.data();
80 for (size_t i = 0; i < frames; ++i) {
81 pcmProcessVec_.push_back(HpaePcmProcess(itr, frameSample_));
82 itr += frameFloatSize_;
83 }
84 }
85
operator +=(HpaePcmBuffer & other)86 HpaePcmBuffer &HpaePcmBuffer::operator+=(HpaePcmBuffer &other)
87 {
88 for (size_t i = 0; i < pcmProcessVec_.size(); ++i) {
89 pcmProcessVec_[i] += other[i];
90 }
91 return *this;
92 }
93
operator -=(HpaePcmBuffer & other)94 HpaePcmBuffer &HpaePcmBuffer::operator-=(HpaePcmBuffer &other)
95 {
96 for (size_t i = 0; i < pcmProcessVec_.size(); ++i) {
97 pcmProcessVec_[i] -= other[i];
98 }
99 return *this;
100 }
101
operator *=(HpaePcmBuffer & other)102 HpaePcmBuffer &HpaePcmBuffer::operator*=(HpaePcmBuffer &other)
103 {
104 for (size_t i = 0; i < pcmProcessVec_.size(); ++i) {
105 pcmProcessVec_[i] *= other[i];
106 }
107 return *this;
108 }
109
operator =(const std::vector<std::vector<float>> & other)110 HpaePcmBuffer &HpaePcmBuffer::operator=(const std::vector<std::vector<float>> &other)
111 {
112 for (size_t i = 0; i < other.size() && i < pcmProcessVec_.size(); ++i) {
113 if (IsMultiFrames()) {
114 if (curFrames_.load() < GetFrames()) {
115 pcmProcessVec_[i + writePos_.load()] = other[i];
116 writePos_.store((writePos_.load() + 1) % GetFrames());
117 curFrames_.fetch_add(1);
118 } else {
119 AUDIO_WARNING_LOG("HpaePcmBuffer::operator=, frames is full index = %{public}zu", i);
120 }
121 } else {
122 pcmProcessVec_[i] = other[i];
123 }
124 }
125 return *this;
126 }
127
operator =(const std::vector<float> & other)128 HpaePcmBuffer &HpaePcmBuffer::operator=(const std::vector<float> &other)
129 {
130 if (IsMultiFrames()) {
131 if (curFrames_.load() < GetFrames()) {
132 pcmProcessVec_[writePos_.load()] = other;
133 writePos_.store((writePos_.load() + 1) % GetFrames());
134 curFrames_.fetch_add(1);
135 } else {
136 AUDIO_WARNING_LOG("HpaePcmBuffer::operator=, frames is full");
137 }
138 } else {
139 pcmProcessVec_[0] = other;
140 }
141 return *this;
142 }
143
Reset()144 void HpaePcmBuffer::Reset()
145 {
146 for (HpaePcmProcess &pcmProc : pcmProcessVec_) {
147 pcmProc.Reset();
148 }
149 readPos_.store(0);
150 writePos_.store(0);
151 curFrames_.store(0);
152 }
153
GetFrameData(std::vector<float> & frameData)154 bool HpaePcmBuffer::GetFrameData(std::vector<float> &frameData)
155 {
156 if (!IsMultiFrames()) {
157 return false;
158 }
159
160 if (curFrames_.load() <= 0) {
161 AUDIO_WARNING_LOG("GetFrameData vector frames is empty");
162 return false;
163 }
164 int32_t ret = memcpy_s(frameData.data(),
165 sizeof(float) * frameData.size(),
166 pcmProcessVec_[readPos_.load()].Begin(),
167 frameSample_ * sizeof(float));
168 if (ret != 0) {
169 return false;
170 }
171 readPos_.store((readPos_.load() + 1) % GetFrames());
172 curFrames_.fetch_sub(1);
173 return true;
174 }
175 // frameData is not MultiFrames
GetFrameData(HpaePcmBuffer & frameData)176 bool HpaePcmBuffer::GetFrameData(HpaePcmBuffer &frameData)
177 {
178 if (!IsMultiFrames() || frameData.IsMultiFrames()) {
179 return false;
180 }
181
182 if (curFrames_.load() <= 0) {
183 AUDIO_WARNING_LOG("GetFrameData HpaePcmBuffer frames is empty");
184 return false;
185 }
186 int32_t ret = memcpy_s(frameData.GetPcmDataBuffer(),
187 sizeof(float) * frameData.Size(),
188 pcmProcessVec_[readPos_.load()].Begin(),
189 frameSample_ * sizeof(float));
190 if (ret != 0) {
191 return false;
192 }
193 readPos_.store((readPos_.load() + 1) % GetFrames());
194 curFrames_.fetch_sub(1);
195 return true;
196 }
197
PushFrameData(std::vector<float> & frameData)198 bool HpaePcmBuffer::PushFrameData(std::vector<float> &frameData)
199 {
200 if (!IsMultiFrames()) {
201 return false;
202 }
203
204 if (curFrames_.load() >= GetFrames()) {
205 AUDIO_WARNING_LOG("PushFrameData vector frames is full");
206 return false;
207 }
208 int32_t ret = memcpy_s(pcmProcessVec_[writePos_.load()].Begin(), frameByteSize_,
209 frameData.data(), sizeof(float) * frameData.size());
210 if (ret != 0) {
211 AUDIO_ERR_LOG("memcpy failed when PushFrameData");
212 return false;
213 }
214 writePos_.store((writePos_.load() + 1) % GetFrames());
215 curFrames_.fetch_add(1);
216 return true;
217 }
218
PushFrameData(HpaePcmBuffer & frameData)219 bool HpaePcmBuffer::PushFrameData(HpaePcmBuffer &frameData)
220 {
221 if (!IsMultiFrames() || frameData.IsMultiFrames()) {
222 return false;
223 }
224
225 if (curFrames_.load() >= GetFrames()) {
226 AUDIO_WARNING_LOG("PushFrameData HpaePcmBuffer frames is full");
227 return false;
228 }
229 int32_t ret = memcpy_s(pcmProcessVec_[writePos_.load()].Begin(), frameByteSize_,
230 frameData.GetPcmDataBuffer(), frameData.Size());
231 if (ret != 0) {
232 AUDIO_ERR_LOG("memcpy failed when PushFrameData");
233 return false;
234 }
235 writePos_.store((writePos_.load() + 1) % GetFrames());
236 curFrames_.fetch_add(1);
237 return true;
238 }
239
StoreFrameData(HpaePcmBuffer & frameData)240 bool HpaePcmBuffer::StoreFrameData(HpaePcmBuffer &frameData)
241 {
242 if (!IsMultiFrames() || frameData.IsMultiFrames()) {
243 return false;
244 }
245
246 int32_t ret = memcpy_s(pcmProcessVec_[writePos_.load()].Begin(), frameByteSize_,
247 frameData.GetPcmDataBuffer(), frameData.Size());
248 if (ret != 0) {
249 AUDIO_ERR_LOG("memcpy failed when StoreFrameData");
250 return false;
251 }
252 writePos_.store((writePos_.load() + 1) % GetFrames());
253 readPos_.store((readPos_.load() + 1) % GetFrames());
254 return true;
255 }
256
RewindBuffer(size_t frames)257 size_t HpaePcmBuffer::RewindBuffer(size_t frames)
258 {
259 if (!IsMultiFrames()) {
260 return 0;
261 }
262 frames = curFrames_.load() + frames > GetFrames() ? GetFrames() - curFrames_.load() : frames;
263 readPos_.store((readPos_.load() - frames + GetFrames()) % GetFrames());
264 curFrames_.fetch_add(frames);
265 return frames;
266 }
267
UpdateReadPos(size_t readPos)268 bool HpaePcmBuffer::UpdateReadPos(size_t readPos)
269 {
270 readPos_.store(readPos);
271 return true;
272 }
273
UpdateWritePos(size_t writePos)274 bool HpaePcmBuffer::UpdateWritePos(size_t writePos)
275 {
276 writePos_.store(writePos);
277 return true;
278 }
279
SetBufferValid(bool valid)280 void HpaePcmBuffer::SetBufferValid(bool valid)
281 {
282 if (valid) {
283 pcmBufferInfo_.state &= ~PCM_BUFFER_STATE_INVALID;
284 } else {
285 pcmBufferInfo_.state |= PCM_BUFFER_STATE_INVALID;
286 }
287 }
288
SetBufferSilence(bool silence)289 void HpaePcmBuffer::SetBufferSilence(bool silence)
290 {
291 if (silence) {
292 pcmBufferInfo_.state |= PCM_BUFFER_STATE_SILENCE;
293 } else {
294 pcmBufferInfo_.state &= ~PCM_BUFFER_STATE_SILENCE;
295 }
296 }
297
SetBufferState(uint32_t state)298 void HpaePcmBuffer::SetBufferState(uint32_t state)
299 {
300 pcmBufferInfo_.state = state;
301 }
302
GetCurFrames() const303 size_t HpaePcmBuffer::GetCurFrames() const
304 {
305 return curFrames_.load();
306 }
307 } // namespace HPAE
308 } // namespace AudioStandard
309 } // namespace OHOS