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