1 /*
2 * Copyright (c) 2023-2024 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 #ifndef LOG_TAG
16 #define LOG_TAG "VolumeTools"
17 #endif
18
19 #include <cmath>
20
21 #include "volume_tools.h"
22 #include "volume_tools_c.h"
23 #include "audio_errors.h"
24 #include "audio_service_log.h"
25
26 namespace {
27 static const int32_t UINT8_SHIFT = 0x80;
28 static const int32_t INT24_SHIFT = 8;
29 static const int32_t INT24_MAX_VALUE = 8388607;
30 static const uint32_t SHIFT_EIGHT = 8;
31 static const uint32_t SHIFT_SIXTEEN = 16;
32 static const uint32_t ARRAY_INDEX_TWO = 2;
33 static const size_t MIN_FRAME_SIZE = 1;
34 static const size_t MAX_FRAME_SIZE = 100000; // max to about 2s for 48khz
35 }
36 namespace OHOS {
37 namespace AudioStandard {
IsVolumeValid(float volFloat)38 bool VolumeTools::IsVolumeValid(float volFloat)
39 {
40 return volFloat >= 0.0 && volFloat <= 1.0;
41 }
42
IsVolumeValid(int32_t volInt)43 bool VolumeTools::IsVolumeValid(int32_t volInt)
44 {
45 return volInt >= INT32_VOLUME_MIN && volInt <= INT32_VOLUME_MAX;
46 }
IsVolumeValid(ChannelVolumes vols)47 bool VolumeTools::IsVolumeValid(ChannelVolumes vols)
48 {
49 if (vols.channel > CHANNEL_16 || vols.channel < MONO) {
50 return false;
51 }
52 for (size_t i = 0; i < vols.channel; i++) {
53 if (!IsVolumeValid(vols.volStart[i]) || !IsVolumeValid(vols.volEnd[i])) {
54 return false;
55 }
56 }
57
58 return true;
59 }
60
GetInt32Vol(float volFloat)61 int32_t VolumeTools::GetInt32Vol(float volFloat)
62 {
63 if (IsVolumeValid(volFloat)) {
64 return volFloat * INT32_VOLUME_MAX;
65 }
66 if (volFloat < 0.0) {
67 return INT32_VOLUME_MIN;
68 }
69 return INT32_VOLUME_MAX;
70 }
71
GetChannelVolumes(AudioChannel channel,int32_t volStart,int32_t volEnd)72 ChannelVolumes VolumeTools::GetChannelVolumes(AudioChannel channel, int32_t volStart, int32_t volEnd)
73 {
74 ChannelVolumes vols = {};
75 if (!IsVolumeValid(volStart) || !IsVolumeValid(volEnd) || channel > CHANNEL_16 || channel < MONO) {
76 AUDIO_ERR_LOG("GetChannelVolumes failed with invalid vol:%{public}d %{public}d channel: %{public}d", volStart,
77 volEnd, channel);
78 return vols;
79 }
80 for (size_t i = 0; i < channel; i++) {
81 vols.volStart[i] = volStart;
82 vols.volEnd[i] = volEnd;
83 }
84 vols.channel = channel;
85 return vols;
86 }
87
GetChannelVolumes(AudioChannel channel,float volStart,float volEnd)88 ChannelVolumes VolumeTools::GetChannelVolumes(AudioChannel channel, float volStart, float volEnd)
89 {
90 ChannelVolumes vols = {};
91 if (!IsVolumeValid(volStart) || !IsVolumeValid(volEnd) || channel > CHANNEL_16 || channel < MONO) {
92 AUDIO_ERR_LOG("GetChannelVolumes failed with invalid vol:%{public}f %{public}f channel: %{public}d", volStart,
93 volEnd, channel);
94 return vols;
95 }
96 for (size_t i = 0; i < channel; i++) {
97 vols.volStart[i] = GetInt32Vol(volStart);
98 vols.volEnd[i] = GetInt32Vol(volEnd);
99 }
100 vols.channel = channel;
101 return vols;
102 }
103
GetByteSize(AudioSampleFormat format)104 size_t VolumeTools::GetByteSize(AudioSampleFormat format)
105 {
106 size_t bitWidthSize = 0;
107 switch (format) {
108 case SAMPLE_U8:
109 bitWidthSize = 1; // size is 1
110 break;
111 case SAMPLE_S16LE:
112 bitWidthSize = 2; // size is 2
113 break;
114 case SAMPLE_S24LE:
115 bitWidthSize = 3; // size is 3
116 break;
117 case SAMPLE_S32LE:
118 bitWidthSize = 4; // size is 4
119 break;
120 case SAMPLE_F32LE:
121 bitWidthSize = 4; // size is 4
122 break;
123 default:
124 bitWidthSize = 2; // default size is 2
125 break;
126 }
127 return bitWidthSize;
128 }
129
ReadInt24LE(const uint8_t * p)130 static inline uint32_t ReadInt24LE(const uint8_t *p)
131 {
132 return ((uint32_t) p[ARRAY_INDEX_TWO] << SHIFT_SIXTEEN) | ((uint32_t) p[1] << SHIFT_EIGHT) | ((uint32_t) p[0]);
133 }
134
WriteInt24LE(uint8_t * p,uint32_t u)135 static inline void WriteInt24LE(uint8_t *p, uint32_t u)
136 {
137 p[ARRAY_INDEX_TWO] = (uint8_t) (u >> SHIFT_SIXTEEN);
138 p[1] = (uint8_t) (u >> SHIFT_EIGHT);
139 p[0] = (uint8_t) u;
140 }
141
VolumeFlatten(int32_t vol)142 inline int32_t VolumeFlatten(int32_t vol)
143 {
144 return vol < INT32_VOLUME_MIN ? 0 : (vol > INT32_VOLUME_MAX ? INT32_VOLUME_MAX : vol);
145 }
146
ProcessOneFrame(uint8_t * ptr,AudioSampleFormat format,int32_t vol)147 void ProcessOneFrame(uint8_t *ptr, AudioSampleFormat format, int32_t vol)
148 {
149 int64_t temp = 0;
150 int16_t *raw16 = nullptr;
151 int32_t *raw32 = nullptr;
152 float *rawFloat = nullptr;
153 switch (format) {
154 case SAMPLE_U8:
155 temp = *ptr - UINT8_SHIFT;
156 temp = (temp * vol) >> VOLUME_SHIFT;
157 temp = temp < INT8_MIN ? INT8_MIN : (temp > INT8_MAX ? INT8_MAX : temp);
158 *ptr = static_cast<uint8_t>(temp + UINT8_SHIFT);
159 break;
160 case SAMPLE_S16LE:
161 raw16 = reinterpret_cast<int16_t *>(ptr);
162 temp = (*raw16 * static_cast<int64_t>(vol)) >> VOLUME_SHIFT;
163 *raw16 = temp > INT16_MAX ? INT16_MAX : (temp < INT16_MIN ? INT16_MIN : temp);
164 break;
165 case SAMPLE_S24LE:
166 temp = static_cast<int32_t>(ReadInt24LE(ptr) << INT24_SHIFT) * static_cast<int64_t>(vol) >> VOLUME_SHIFT;
167 WriteInt24LE(ptr, (static_cast<uint32_t>(temp) >> INT24_SHIFT));
168 break;
169 case SAMPLE_S32LE:
170 raw32 = reinterpret_cast<int32_t *>(ptr);
171 // int32_t * int16_t, max result is int48_t
172 temp = (*raw32 * static_cast<int64_t>(vol)) >> VOLUME_SHIFT;
173 *raw32 = temp > INT32_MAX ? INT32_MAX : (temp < INT32_MIN ? INT32_MIN : temp);
174 break;
175 case SAMPLE_F32LE:
176 rawFloat = reinterpret_cast<float *>(ptr);
177 *rawFloat = *rawFloat * (static_cast<float>(vol) / INT32_VOLUME_MAX);
178 break;
179 default:
180 AUDIO_ERR_LOG("ProcessOneFrame with invalid format");
181 break;
182 }
183 }
184
185 // |---------frame1--------|---------frame2--------|---------frame3--------|
186 // |ch1-ch2-ch3-ch4-ch5-ch6|ch1-ch2-ch3-ch4-ch5-ch6|ch1-ch2-ch3-ch4-ch5-ch6|
Process(const BufferDesc & buffer,AudioSampleFormat format,ChannelVolumes vols)187 int32_t VolumeTools::Process(const BufferDesc &buffer, AudioSampleFormat format, ChannelVolumes vols)
188 {
189 // parms check
190 if (format > SAMPLE_F32LE || !IsVolumeValid(vols)) {
191 AUDIO_ERR_LOG("Process failed with invalid params");
192 return ERR_INVALID_PARAM;
193 }
194 size_t byteSizePerData = GetByteSize(format);
195 size_t byteSizePerFrame = byteSizePerData * vols.channel;
196 if (buffer.buffer == nullptr || buffer.bufLength % byteSizePerFrame != 0) {
197 AUDIO_ERR_LOG("Process failed with invalid buffer, size is %{public}zu", buffer.bufLength);
198 return ERR_INVALID_PARAM;
199 }
200
201 size_t frameSize = buffer.bufLength / byteSizePerFrame;
202 if (frameSize < MIN_FRAME_SIZE) {
203 AUDIO_ERR_LOG("Process failed with invalid frameSize, size is %{public}zu", frameSize);
204 return ERR_INVALID_PARAM;
205 }
206
207 float volStep[CHANNEL_MAX] = {};
208 for (size_t channelIdx = 0; channelIdx < vols.channel; channelIdx++) {
209 if (vols.volEnd[channelIdx] == vols.volStart[channelIdx] || frameSize == MIN_FRAME_SIZE) {
210 volStep[channelIdx] = 0.0;
211 } else {
212 volStep[channelIdx] = (static_cast<float>(vols.volEnd[channelIdx] - vols.volStart[channelIdx])) /
213 (frameSize - MIN_FRAME_SIZE);
214 }
215 }
216 for (size_t frameIndex = 0; frameIndex < frameSize; frameIndex++) {
217 for (size_t channelIdx = 0; channelIdx < vols.channel; channelIdx++) {
218 int32_t vol = volStep[channelIdx] * frameIndex + vols.volStart[channelIdx];
219 vol = VolumeFlatten(vol);
220 uint8_t *samplePtr = buffer.buffer + frameIndex * byteSizePerFrame + channelIdx * byteSizePerData;
221 ProcessOneFrame(samplePtr, format, vol);
222 }
223 }
224
225 return SUCCESS;
226 }
227
GetVolDb(AudioSampleFormat format,int32_t vol)228 double VolumeTools::GetVolDb(AudioSampleFormat format, int32_t vol)
229 {
230 double volume = static_cast<double>(vol);
231 switch (format) {
232 case SAMPLE_U8:
233 volume = volume / INT8_MAX;
234 break;
235 case SAMPLE_S16LE:
236 volume = volume / INT16_MAX;
237 break;
238 case SAMPLE_S24LE:
239 volume = volume / INT24_MAX_VALUE;
240 break;
241 case SAMPLE_S32LE:
242 volume = volume / INT32_MAX;
243 break;
244 case SAMPLE_F32LE:
245 volume = volume / INT32_MAX;
246 break;
247 default:
248 break;
249 }
250 return std::log10(volume);
251 }
252
CountU8Volume(const BufferDesc & buffer,AudioChannel channel,ChannelVolumes & volMaps,size_t split,AudioSampleFormat format)253 static void CountU8Volume(const BufferDesc &buffer, AudioChannel channel, ChannelVolumes &volMaps, size_t split,
254 AudioSampleFormat format)
255 {
256 if (split <= 0) {
257 AUDIO_ERR_LOG("invalid split");
258 return;
259 }
260 size_t byteSizePerData = VolumeTools::GetByteSize(format);
261 size_t byteSizePerFrame = byteSizePerData * channel;
262 if (buffer.buffer == nullptr || byteSizePerFrame == 0 || buffer.bufLength % byteSizePerFrame != 0) {
263 AUDIO_ERR_LOG("invalid buffer, size is %{public}zu", buffer.bufLength);
264 return;
265 }
266 size_t frameSize = buffer.bufLength / byteSizePerFrame;
267 if (frameSize <= MIN_FRAME_SIZE || frameSize >= MAX_FRAME_SIZE) {
268 AUDIO_ERR_LOG("invalid frameSize, size is %{public}zu", frameSize);
269 return;
270 }
271
272 // reset maps
273 for (size_t index = 0; index < channel; index++) {
274 volMaps.volStart[index] = 0;
275 volMaps.volEnd[index] = 0;
276 }
277 uint8_t *raw8 = buffer.buffer;
278 for (size_t frameIndex = 0; frameIndex < frameSize - (split - 1); frameIndex += split) {
279 for (size_t channelIdx = 0; channelIdx < channel; channelIdx++) {
280 volMaps.volStart[channelIdx] += (*raw8 >= UINT8_SHIFT ? *raw8 - UINT8_SHIFT : UINT8_SHIFT - *raw8);
281 raw8++;
282 }
283 raw8 += (split - 1) * channel;
284 }
285 // Calculate the average value
286 size_t size = frameSize / split;
287 if (size == 0) {
288 AUDIO_ERR_LOG("invalid size");
289 return;
290 }
291 for (size_t index = 0; index < channel; index++) {
292 volMaps.volStart[index] /= static_cast<int32_t>(size);
293 }
294 return;
295 }
296
CountS16Volume(const BufferDesc & buffer,AudioChannel channel,ChannelVolumes & volMaps,size_t split,AudioSampleFormat format)297 static void CountS16Volume(const BufferDesc &buffer, AudioChannel channel, ChannelVolumes &volMaps, size_t split,
298 AudioSampleFormat format)
299 {
300 if (split <= 0) {
301 AUDIO_ERR_LOG("invalid split");
302 return;
303 }
304 size_t byteSizePerData = VolumeTools::GetByteSize(format);
305 size_t byteSizePerFrame = byteSizePerData * channel;
306 if (buffer.buffer == nullptr || byteSizePerFrame == 0 || buffer.bufLength % byteSizePerFrame != 0) {
307 AUDIO_ERR_LOG("invalid buffer, size is %{public}zu", buffer.bufLength);
308 return;
309 }
310 size_t frameSize = buffer.bufLength / byteSizePerFrame;
311 if (frameSize <= MIN_FRAME_SIZE || frameSize >= MAX_FRAME_SIZE) {
312 AUDIO_ERR_LOG("invalid frameSize, size is %{public}zu", frameSize);
313 return;
314 }
315
316 // reset maps
317 for (size_t index = 0; index < channel; index++) {
318 volMaps.volStart[index] = 0;
319 volMaps.volEnd[index] = 0;
320 }
321 int16_t *raw16 = reinterpret_cast<int16_t *>(buffer.buffer);
322 for (size_t frameIndex = 0; frameIndex < frameSize - (split - 1); frameIndex += split) {
323 for (size_t channelIdx = 0; channelIdx < channel; channelIdx++) {
324 volMaps.volStart[channelIdx] += (*raw16 >= 0 ? *raw16: (-*raw16));
325 raw16++;
326 }
327 raw16 += (split - 1) * channel;
328 }
329 // Calculate the average value
330 size_t size = frameSize / split;
331 if (size == 0) {
332 AUDIO_ERR_LOG("invalid size");
333 return;
334 }
335 for (size_t index = 0; index < channel; index++) {
336 volMaps.volStart[index] /= static_cast<int32_t>(size);
337 }
338 return;
339 }
340
CountS24Volume(const BufferDesc & buffer,AudioChannel channel,ChannelVolumes & volMaps,size_t split,AudioSampleFormat format)341 static void CountS24Volume(const BufferDesc &buffer, AudioChannel channel, ChannelVolumes &volMaps, size_t split,
342 AudioSampleFormat format)
343 {
344 if (split <= 0) {
345 AUDIO_ERR_LOG("invalid split");
346 return;
347 }
348 const size_t byteSizePerData = VolumeTools::GetByteSize(format);
349 size_t byteSizePerFrame = byteSizePerData * channel;
350 if (buffer.buffer == nullptr || byteSizePerFrame == 0 || buffer.bufLength % byteSizePerFrame != 0) {
351 AUDIO_ERR_LOG("invalid buffer, size is %{public}zu", buffer.bufLength);
352 return;
353 }
354 size_t frameSize = buffer.bufLength / byteSizePerFrame;
355 if (frameSize <= MIN_FRAME_SIZE || frameSize >= MAX_FRAME_SIZE) {
356 AUDIO_ERR_LOG("invalid frameSize, size is %{public}zu", frameSize);
357 return;
358 }
359
360 // reset maps
361 for (size_t index = 0; index < channel; index++) {
362 volMaps.volStart[index] = 0;
363 volMaps.volEnd[index] = 0;
364 }
365 uint8_t *raw8 = buffer.buffer;
366 for (size_t frameIndex = 0; frameIndex < frameSize - (split - 1); frameIndex += split) {
367 for (size_t channelIdx = 0; channelIdx < channel; channelIdx++) {
368 int32_t sample = static_cast<int32_t>(ReadInt24LE(raw8));
369 uint32_t sampleAbs = static_cast<uint32_t>(sample >= 0 ? sample: (-sample)) >>
370 SHIFT_EIGHT;
371 volMaps.volStart[channelIdx] += static_cast<int32_t>(sampleAbs);
372 raw8 += byteSizePerData;
373 }
374 raw8 += (split - 1) * channel * byteSizePerData;
375 }
376 // Calculate the average value
377 size_t size = frameSize / split;
378 if (size == 0) {
379 AUDIO_ERR_LOG("invalid size");
380 return;
381 }
382 for (size_t index = 0; index < channel; index++) {
383 volMaps.volStart[index] /= static_cast<int32_t>(size);
384 }
385 return;
386 }
387
CountS32Volume(const BufferDesc & buffer,AudioChannel channel,ChannelVolumes & volMaps,size_t split,AudioSampleFormat format)388 static void CountS32Volume(const BufferDesc &buffer, AudioChannel channel, ChannelVolumes &volMaps, size_t split,
389 AudioSampleFormat format)
390 {
391 if (split <= 0) {
392 AUDIO_ERR_LOG("invalid split");
393 return;
394 }
395 const size_t byteSizePerData = VolumeTools::GetByteSize(format);
396 size_t byteSizePerFrame = byteSizePerData * channel;
397 if (buffer.buffer == nullptr || byteSizePerFrame == 0 || buffer.bufLength % byteSizePerFrame != 0) {
398 AUDIO_ERR_LOG("invalid buffer, size is %{public}zu", buffer.bufLength);
399 return;
400 }
401 size_t frameSize = buffer.bufLength / byteSizePerFrame;
402 if (frameSize <= MIN_FRAME_SIZE || frameSize >= MAX_FRAME_SIZE) {
403 AUDIO_ERR_LOG("invalid frameSize, size is %{public}zu", frameSize);
404 return;
405 }
406
407 // reset maps
408 int64_t volSums[CHANNEL_MAX] = {0};
409 for (size_t index = 0; index < CHANNEL_MAX; index++) {
410 volSums[index] = 0;
411 }
412 int32_t *raw32 = reinterpret_cast<int32_t *>(buffer.buffer);
413 for (size_t frameIndex = 0; frameIndex < frameSize - (split - 1); frameIndex += split) {
414 for (size_t channelIdx = 0; channelIdx < channel; channelIdx++) {
415 uint32_t sampleAbs = static_cast<uint32_t>(*raw32 >= 0 ? *raw32: (-*raw32)) >>
416 SHIFT_SIXTEEN;
417 volSums[channelIdx] += static_cast<int32_t>(sampleAbs);
418 raw32++;
419 }
420 raw32 += (split - 1) * channel;
421 }
422
423 // Calculate the average value
424 size_t size = frameSize / split;
425 if (size == 0) {
426 AUDIO_ERR_LOG("invalid size");
427 return;
428 }
429 for (size_t index = 0; index < channel; index++) {
430 volSums[index] /= static_cast<int32_t>(size);
431 volMaps.volStart[index] = volSums[index];
432 }
433 return;
434 }
435
CountF32Volume(const BufferDesc & buffer,AudioChannel channel,ChannelVolumes & volMaps,size_t split,AudioSampleFormat format)436 static void CountF32Volume(const BufferDesc &buffer, AudioChannel channel, ChannelVolumes &volMaps, size_t split,
437 AudioSampleFormat format)
438 {
439 if (split <= 0) {
440 AUDIO_ERR_LOG("invalid split");
441 return;
442 }
443 size_t byteSizePerData = VolumeTools::GetByteSize(format);
444 size_t byteSizePerFrame = byteSizePerData * channel;
445 if (buffer.buffer == nullptr || byteSizePerFrame == 0 || buffer.bufLength % byteSizePerFrame != 0) {
446 AUDIO_ERR_LOG("invalid buffer, size is %{public}zu", buffer.bufLength);
447 return;
448 }
449 size_t frameSize = buffer.bufLength / byteSizePerFrame;
450 if (frameSize <= MIN_FRAME_SIZE || frameSize >= MAX_FRAME_SIZE) {
451 AUDIO_ERR_LOG("invalid frameSize, size is %{public}zu", frameSize);
452 return;
453 }
454
455 // reset maps
456 double volSums[CHANNEL_MAX] = {0};
457 for (size_t index = 0; index < CHANNEL_MAX; index++) {
458 volSums[index] = 0.0;
459 }
460 float *raw32 = reinterpret_cast<float *>(buffer.buffer);
461 for (size_t frameIndex = 0; frameIndex < frameSize - (split - 1); frameIndex += split) {
462 for (size_t channelIdx = 0; channelIdx < channel; channelIdx++) {
463 volSums[channelIdx] += (*raw32 >= 0 ? *raw32: (-*raw32));
464 raw32++;
465 }
466 raw32 += (split - 1) * channel;
467 }
468 // Calculate the average value
469 size_t size = frameSize / split;
470 if (size == 0) {
471 AUDIO_ERR_LOG("invalid size");
472 return;
473 }
474 for (size_t index = 0; index < channel; index++) {
475 volSums[index] /= static_cast<int32_t>(size);
476 volMaps.volStart[index] = static_cast<int32_t>(volSums[index]);
477 }
478 return;
479 }
480
CountVolumeLevel(const BufferDesc & buffer,AudioSampleFormat format,AudioChannel channel,size_t split)481 ChannelVolumes VolumeTools::CountVolumeLevel(const BufferDesc &buffer, AudioSampleFormat format, AudioChannel channel,
482 size_t split)
483 {
484 ChannelVolumes channelVols = {};
485 channelVols.channel = channel;
486 if (format > SAMPLE_F32LE || channel > CHANNEL_16) {
487 AUDIO_ERR_LOG("failed with invalid params");
488 return channelVols;
489 }
490 switch (format) {
491 case SAMPLE_U8:
492 CountU8Volume(buffer, channel, channelVols, split, format);
493 break;
494 case SAMPLE_S16LE:
495 CountS16Volume(buffer, channel, channelVols, split, format);
496 break;
497 case SAMPLE_S24LE:
498 CountS24Volume(buffer, channel, channelVols, split, format);
499 break;
500 case SAMPLE_S32LE:
501 CountS32Volume(buffer, channel, channelVols, split, format);
502 break;
503 case SAMPLE_F32LE:
504 CountF32Volume(buffer, channel, channelVols, split, format);
505 break;
506 default:
507 break;
508 }
509
510 return channelVols;
511 }
512 } // namespace AudioStandard
513 } // namespace OHOS
514
515 #ifdef __cplusplus
516 extern "C" {
517 #endif
518 using namespace OHOS::AudioStandard;
519
ProcessVol(uint8_t * buffer,size_t length,AudioRawFormat rawformat,float volStart,float volEnd)520 int32_t ProcessVol(uint8_t *buffer, size_t length, AudioRawFormat rawformat, float volStart, float volEnd)
521 {
522 BufferDesc desc = {0};
523 desc.buffer = buffer;
524 desc.bufLength = length;
525 desc.dataLength = length;
526 ChannelVolumes mapVols = VolumeTools::GetChannelVolumes(static_cast<AudioChannel>(rawformat.channels), volStart,
527 volEnd);
528 return VolumeTools::Process(desc, static_cast<AudioSampleFormat>(rawformat.format), mapVols);
529 }
530
531 #ifdef __cplusplus
532 }
533 #endif