• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #include "volume_tools.h"
17 #include "audio_errors.h"
18 #include "audio_log.h"
19 
20 namespace {
21 static const int32_t UINT8_SHIFT = 0x80;
22 static const int32_t INT24_SHIFT = 8;
23 static const uint32_t SHIFT_EIGHT = 8;
24 static const uint32_t SHIFT_SIXTEEN = 16;
25 static const uint32_t ARRAY_INDEX_TWO = 2;
26 static const size_t MIN_FRAME_SIZE = 1;
27 }
28 namespace OHOS {
29 namespace AudioStandard {
IsVolumeValid(float volFloat)30 bool VolumeTools::IsVolumeValid(float volFloat)
31 {
32     return volFloat >= 0.0 && volFloat <= 1.0;
33 }
34 
IsVolumeValid(int32_t volInt)35 bool VolumeTools::IsVolumeValid(int32_t volInt)
36 {
37     return volInt >= INT32_VOLUME_MIN && volInt <= INT32_VOLUME_MAX;
38 }
IsVolumeValid(ChannelVolumes vols)39 bool VolumeTools::IsVolumeValid(ChannelVolumes vols)
40 {
41     if (vols.channel > CHANNEL_16 || vols.channel < MONO) {
42         return false;
43     }
44     for (size_t i = 0; i < vols.channel; i++) {
45         if (!IsVolumeValid(vols.volStart[i]) || !IsVolumeValid(vols.volEnd[i])) {
46             return false;
47         }
48     }
49 
50     return true;
51 }
52 
GetInt32Vol(float volFloat)53 int32_t VolumeTools::GetInt32Vol(float volFloat)
54 {
55     if (IsVolumeValid(volFloat)) {
56         return volFloat * INT32_VOLUME_MAX;
57     }
58     if (volFloat < 0.0) {
59         return INT32_VOLUME_MIN;
60     }
61     return INT32_VOLUME_MAX;
62 }
63 
GetChannelVolumes(AudioChannel channel,int32_t volStart,int32_t volEnd)64 ChannelVolumes VolumeTools::GetChannelVolumes(AudioChannel channel, int32_t volStart, int32_t volEnd)
65 {
66     ChannelVolumes vols = {};
67     if (!IsVolumeValid(volStart) || !IsVolumeValid(volEnd) || channel > CHANNEL_16 || channel < MONO) {
68         AUDIO_ERR_LOG("GetChannelVolumes failed with invalid vol:%{public}d %{public}d channel: %{public}d", volStart,
69             volEnd, channel);
70         return vols;
71     }
72     for (size_t i = 0; i < channel; i++) {
73         vols.volStart[i] = volStart;
74         vols.volEnd[i] = volEnd;
75     }
76     vols.channel = channel;
77     return vols;
78 }
79 
GetChannelVolumes(AudioChannel channel,float volStart,float volEnd)80 ChannelVolumes VolumeTools::GetChannelVolumes(AudioChannel channel, float volStart, float volEnd)
81 {
82     ChannelVolumes vols = {};
83     if (!IsVolumeValid(volStart) || !IsVolumeValid(volEnd) || channel > CHANNEL_16 || channel < MONO) {
84         AUDIO_ERR_LOG("GetChannelVolumes failed with invalid vol:%{public}f %{public}f channel: %{public}d", volStart,
85             volEnd, channel);
86         return vols;
87     }
88     for (size_t i = 0; i < channel; i++) {
89         vols.volStart[i] = GetInt32Vol(volStart);
90         vols.volEnd[i] = GetInt32Vol(volEnd);
91     }
92     vols.channel = channel;
93     return vols;
94 }
95 
GetByteSize(AudioSampleFormat format)96 size_t GetByteSize(AudioSampleFormat format)
97 {
98     size_t bitWidthSize = 0;
99     switch (format) {
100         case SAMPLE_U8:
101             bitWidthSize = 1; // size is 1
102             break;
103         case SAMPLE_S16LE:
104             bitWidthSize = 2; // size is 2
105             break;
106         case SAMPLE_S24LE:
107             bitWidthSize = 3; // size is 3
108             break;
109         case SAMPLE_S32LE:
110             bitWidthSize = 4; // size is 4
111             break;
112         case SAMPLE_F32LE:
113             bitWidthSize = 4; // size is 4
114             break;
115         default:
116             bitWidthSize = 2; // default size is 2
117             break;
118     }
119     return bitWidthSize;
120 }
121 
ReadInt24LE(const uint8_t * p)122 static inline uint32_t ReadInt24LE(const uint8_t *p)
123 {
124     return ((uint32_t) p[ARRAY_INDEX_TWO] << SHIFT_SIXTEEN) | ((uint32_t) p[1] << SHIFT_EIGHT) | ((uint32_t) p[0]);
125 }
126 
WriteInt24LE(uint8_t * p,uint32_t u)127 static inline void WriteInt24LE(uint8_t *p, uint32_t u)
128 {
129     p[ARRAY_INDEX_TWO] = (uint8_t) (u >> SHIFT_SIXTEEN);
130     p[1] = (uint8_t) (u >> SHIFT_EIGHT);
131     p[0] = (uint8_t) u;
132 }
133 
VolumeFlatten(int32_t vol)134 inline int32_t VolumeFlatten(int32_t vol)
135 {
136     return vol < INT32_VOLUME_MIN ? 0 : (vol > INT32_VOLUME_MAX ? INT32_VOLUME_MAX : vol);
137 }
138 
ProcessOneFrame(uint8_t * ptr,AudioSampleFormat format,int32_t vol)139 void ProcessOneFrame(uint8_t *ptr, AudioSampleFormat format, int32_t vol)
140 {
141     int64_t temp = 0;
142     int16_t *raw16 = nullptr;
143     int32_t *raw32 = nullptr;
144     float *rawFloat = nullptr;
145     switch (format) {
146         case SAMPLE_U8:
147             temp = *ptr - UINT8_SHIFT;
148             temp = (temp * vol) >> VOLUME_SHIFT;
149             temp = temp < INT8_MIN ? INT8_MIN : (temp > INT8_MAX ? INT8_MAX : temp);
150             *ptr = static_cast<uint8_t>(temp + UINT8_SHIFT);
151             break;
152         case SAMPLE_S16LE:
153             raw16 = reinterpret_cast<int16_t *>(ptr);
154             temp = (*raw16 * static_cast<int64_t>(vol)) >> VOLUME_SHIFT;
155             *raw16 = temp > INT16_MAX ? INT16_MAX : (temp < INT16_MIN ? INT16_MIN : temp);
156             break;
157         case SAMPLE_S24LE:
158             temp = static_cast<int32_t>(ReadInt24LE(ptr) << INT24_SHIFT) * static_cast<int64_t>(vol) >> VOLUME_SHIFT;
159             WriteInt24LE(ptr, (static_cast<uint32_t>(temp) >> INT24_SHIFT));
160             break;
161         case SAMPLE_S32LE:
162             raw32 = reinterpret_cast<int32_t *>(ptr);
163             // int32_t * int16_t, max result is int48_t
164             temp = (*raw32 * static_cast<int64_t>(vol)) >> VOLUME_SHIFT;
165             *raw32 = temp > INT32_MAX ? INT32_MAX : (temp < INT32_MIN ? INT32_MIN : temp);
166             break;
167         case SAMPLE_F32LE:
168             rawFloat = reinterpret_cast<float *>(ptr);
169             *rawFloat = *rawFloat * (static_cast<float>(vol) / INT32_VOLUME_MAX);
170             break;
171         default:
172             AUDIO_ERR_LOG("ProcessOneFrame with invalid format");
173             break;
174     }
175 }
176 
177 // |---------frame1--------|---------frame2--------|---------frame3--------|
178 // |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)179 int32_t VolumeTools::Process(const BufferDesc &buffer, AudioSampleFormat format, ChannelVolumes vols)
180 {
181     // parms check
182     if (format > SAMPLE_F32LE || !IsVolumeValid(vols)) {
183         AUDIO_ERR_LOG("Process failed with invalid params");
184         return ERR_INVALID_PARAM;
185     }
186     size_t byteSizePerData = GetByteSize(format);
187     size_t byteSizePerFrame = byteSizePerData * vols.channel;
188     if (buffer.buffer == nullptr || buffer.bufLength % byteSizePerFrame != 0) {
189         AUDIO_ERR_LOG("Process failed with invalid buffer, size is %{public}zu", buffer.bufLength);
190         return ERR_INVALID_PARAM;
191     }
192 
193     size_t frameSize = buffer.bufLength / byteSizePerFrame;
194     if (frameSize <= MIN_FRAME_SIZE) {
195         AUDIO_ERR_LOG("Process failed with invalid frameSize, size is %{public}zu", frameSize);
196         return ERR_INVALID_PARAM;
197     }
198 
199     float volStep[CHANNEL_MAX] = {};
200     for (size_t channelIdx = 0; channelIdx < vols.channel; channelIdx++) {
201         if (vols.volEnd[channelIdx] == vols.volStart[channelIdx]) {
202             volStep[channelIdx] = 0.0;
203         } else {
204             volStep[channelIdx] = (static_cast<float>(vols.volEnd[channelIdx] - vols.volStart[channelIdx])) /
205                 (frameSize - MIN_FRAME_SIZE);
206         }
207     }
208     for (size_t frameIndex = 0; frameIndex < frameSize; frameIndex++) {
209         for (size_t channelIdx = 0; channelIdx < vols.channel; channelIdx++) {
210             int32_t vol = volStep[channelIdx] * frameIndex + vols.volStart[channelIdx];
211             vol = VolumeFlatten(vol);
212             uint8_t *samplePtr = buffer.buffer + frameIndex * byteSizePerFrame + channelIdx * byteSizePerData;
213             ProcessOneFrame(samplePtr, format, vol);
214         }
215     }
216 
217     return SUCCESS;
218 }
219 } // namespace AudioStandard
220 } // namespace OHOS