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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioProResampler"
17 #endif
18 #include "audio_proresampler.h"
19 #include "audio_stream_info.h"
20 #include "securec.h"
21 #include "audio_engine_log.h"
22
23 namespace OHOS {
24 namespace AudioStandard {
25 namespace HPAE {
26 constexpr uint32_t BUFFER_EXPAND_SIZE = 2;
27 constexpr uint32_t SAMPLE_RATE_11025 = 11025;
28 constexpr uint32_t FRAME_LEN_20MS = 20;
29 constexpr uint32_t MS_PER_SECOND = 1000;
30 constexpr uint32_t ADD_SIZE = 100;
31 // for now ProResampler accept input 20ms for other sample rates, 40ms input for 11025hz
32 // output 20ms for all sample rates
ProResampler(uint32_t inRate,uint32_t outRate,uint32_t channels,uint32_t quality)33 ProResampler::ProResampler(uint32_t inRate, uint32_t outRate, uint32_t channels, uint32_t quality)
34 : inRate_(inRate), outRate_(outRate), channels_(channels), quality_(quality),
35 expectedOutFrameLen_(outRate_ * FRAME_LEN_20MS / MS_PER_SECOND)
36 {
37 if (inRate_ == SAMPLE_RATE_11025) { // for 11025, process input 40ms per time and output 20ms per time
38 buf11025_.reserve(expectedOutFrameLen_ * channels_ * BUFFER_EXPAND_SIZE + ADD_SIZE);
39 AUDIO_INFO_LOG("Proresampler input 11025hz, output resample rate %{public}d, buf11025_ size %{public}d",
40 outRate_, expectedOutFrameLen_ * channels_ * BUFFER_EXPAND_SIZE + ADD_SIZE);
41 expectedInFrameLen_ = inRate_ * FRAME_LEN_20MS * BUFFER_EXPAND_SIZE / MS_PER_SECOND;
42 } else {
43 expectedInFrameLen_ = inRate_ * FRAME_LEN_20MS / MS_PER_SECOND;
44 }
45 int32_t errRet;
46 state_ = SingleStagePolyphaseResamplerInit(channels_, inRate_, outRate_, quality_, &errRet);
47 CHECK_AND_RETURN_LOG(state_, "Proresampler: Init failed! failed with error %{public}s.",
48 ErrCodeToString(errRet).c_str());
49
50 SingleStagePolyphaseResamplerSkipHalfTaps(state_);
51 AUDIO_INFO_LOG("Proresampler: Init success inRate: %{public}d, outRate: %{public}d, channels: %{public}d, "
52 "quality: %{public}d.", inRate_, outRate_, channels_, quality_);
53 }
54
Process(const float * inBuffer,uint32_t inFrameSize,float * outBuffer,uint32_t outFrameSize)55 int32_t ProResampler::Process(const float *inBuffer, uint32_t inFrameSize, float *outBuffer,
56 uint32_t outFrameSize)
57 {
58 CHECK_AND_RETURN_RET_LOG(state_ != nullptr, RESAMPLER_ERR_ALLOC_FAILED,
59 "ProResampler Process: resampler is %{public}s", ErrCodeToString(RESAMPLER_ERR_ALLOC_FAILED).c_str());
60 if (inRate_ == SAMPLE_RATE_11025) {
61 return Process11025SampleRate(inBuffer, inFrameSize, outBuffer, outFrameSize);
62 } else {
63 return ProcessOtherSampleRate(inBuffer, inFrameSize, outBuffer, outFrameSize);
64 }
65 }
66
ProcessOtherSampleRate(const float * inBuffer,uint32_t inFrameSize,float * outBuffer,uint32_t outFrameSize)67 int32_t ProResampler::ProcessOtherSampleRate(const float *inBuffer, uint32_t inFrameSize, float *outBuffer,
68 uint32_t outFrameSize)
69 {
70 uint32_t expectedOutFrameSize = outFrameSize;
71 std::vector<float> tmpOutBuf(expectedOutFrameSize * channels_, 0.0f);
72 int32_t ret =
73 SingleStagePolyphaseResamplerProcess(state_, inBuffer, &inFrameSize, tmpOutBuf.data(), &outFrameSize);
74 CHECK_AND_RETURN_RET_LOG(ret == EOK, ret, "ProResampler process failed with error %{public}s",
75 ErrCodeToString(ret).c_str());
76
77 uint32_t fillSize = expectedOutFrameSize - outFrameSize > 0 ? expectedOutFrameSize - outFrameSize : 0;
78 ret = memset_s(outBuffer, fillSize * channels_ * sizeof(float), 0, fillSize * channels_ * sizeof(float));
79 CHECK_AND_RETURN_RET_LOG(ret == EOK, ret, "memset_s failed with error %{public}d", ret);
80
81 ret = memcpy_s(outBuffer + fillSize * channels_,
82 (expectedOutFrameSize - fillSize) * channels_ * sizeof(float),
83 tmpOutBuf.data(), outFrameSize * channels_ * sizeof(float));
84 CHECK_AND_RETURN_RET_LOG(ret == EOK, ret, "memset_s failed with error %{public}d", ret);
85 return ret;
86 }
87
Process11025SampleRate(const float * inBuffer,uint32_t inFrameSize,float * outBuffer,uint32_t outFrameSize)88 int32_t ProResampler::Process11025SampleRate(const float *inBuffer, uint32_t inFrameSize, float *outBuffer,
89 uint32_t outFrameSize)
90 {
91 CHECK_AND_RETURN_RET_LOG(outFrameSize >= expectedOutFrameLen_, RESAMPLER_ERR_INVALID_ARG,
92 "output frame size %{public}d is not valid", outFrameSize);
93 CHECK_AND_RETURN_RET_LOG(((inFrameSize == 0) || (inFrameSize == expectedInFrameLen_)), RESAMPLER_ERR_INVALID_ARG,
94 "input frame size %{public}d is not valid", inFrameSize);
95 if (inFrameSize == 0) {
96 int32_t ret = RESAMPLER_ERR_SUCCESS;
97 if (buf11025Index_ > 0) { // output second half of 11025 buffer
98 ret = memcpy_s(outBuffer, outFrameSize * channels_ * sizeof(float),
99 buf11025_.data() + buf11025Index_, expectedOutFrameLen_ * channels_ * sizeof(float));
100 CHECK_AND_RETURN_RET_LOG(ret == EOK, ret, "memcpy_s failed with error %{public}d", ret);
101
102 ret = memset_s(buf11025_.data(), buf11025_.capacity() * sizeof(float), 0,
103 buf11025_.capacity() * sizeof(float));
104 buf11025Index_ = 0;
105 } else { // no data left in buffer, the only thing can be done is to return 0s
106 ret = memset_s(outBuffer, outFrameSize * channels_ * sizeof(float), 0,
107 outFrameSize * channels_ * sizeof(float));
108 }
109 return ret;
110 }
111 std::vector<float> tmpOutBuf(expectedOutFrameLen_ * channels_ * BUFFER_EXPAND_SIZE, 0.0f);
112 uint32_t tmpOutFrameLen = expectedOutFrameLen_ * BUFFER_EXPAND_SIZE;
113 uint32_t reserveOutFrameLen = tmpOutFrameLen;
114 int32_t ret =
115 SingleStagePolyphaseResamplerProcess(state_, inBuffer, &inFrameSize, tmpOutBuf.data(), &tmpOutFrameLen);
116 CHECK_AND_RETURN_RET_LOG(ret == RESAMPLER_ERR_SUCCESS, ret, "Process failed with error %{public}s",
117 ErrCodeToString(ret).c_str());
118
119 uint32_t fillSize = reserveOutFrameLen - tmpOutFrameLen > 0 ? reserveOutFrameLen - tmpOutFrameLen : 0;
120 ret = memset_s(buf11025_.data(), fillSize * channels_ * sizeof(float), 0, fillSize * channels_ * sizeof(float));
121 CHECK_AND_RETURN_RET_LOG(ret == EOK, ret, "memset_s failed with error %{public}d", ret);
122
123 ret = memcpy_s(buf11025_.data() + fillSize * channels_,
124 (reserveOutFrameLen - fillSize) * channels_ * sizeof(float),
125 tmpOutBuf.data(), tmpOutFrameLen * channels_ * sizeof(float));
126 CHECK_AND_RETURN_RET_LOG(ret == EOK, ret, "memcpy_s failed with error %{public}d", ret);
127
128 // output first half of data
129 ret = memcpy_s(outBuffer, outFrameSize * channels_ * sizeof(float),
130 buf11025_.data(), expectedOutFrameLen_ * channels_ * sizeof(float));
131 buf11025Index_ = expectedOutFrameLen_ * channels_;
132 return ret;
133 }
134
UpdateRates(uint32_t inRate,uint32_t outRate)135 int32_t ProResampler::UpdateRates(uint32_t inRate, uint32_t outRate)
136 {
137 inRate_ = inRate;
138 outRate_ = outRate;
139 expectedOutFrameLen_ = outRate_ * FRAME_LEN_20MS / MS_PER_SECOND;
140 expectedInFrameLen_ = inRate_ * FRAME_LEN_20MS / MS_PER_SECOND;
141 if (inRate_ == SAMPLE_RATE_11025) {
142 expectedInFrameLen_ = inRate_ * FRAME_LEN_20MS * BUFFER_EXPAND_SIZE / MS_PER_SECOND;
143 }
144 CHECK_AND_RETURN_RET_LOG(state_ != nullptr, RESAMPLER_ERR_ALLOC_FAILED, "ProResampler: resampler is null");
145
146 int32_t ret = SingleStagePolyphaseResamplerSetRate(state_, inRate_, outRate_);
147 CHECK_AND_RETURN_RET_LOG(ret == RESAMPLER_ERR_SUCCESS, ret,
148 "ProResampler update rate failed with error code %{public}s", ErrCodeToString(ret).c_str());
149 return ret;
150 }
151
UpdateChannels(uint32_t channels)152 int32_t ProResampler::UpdateChannels(uint32_t channels)
153 {
154 uint32_t oldChannels = channels_;
155 channels_ = channels;
156 CHECK_AND_RETURN_RET_LOG(state_ != nullptr, RESAMPLER_ERR_ALLOC_FAILED, "ProResampler: resampler is null");
157 SingleStagePolyphaseResamplerFree(state_);
158
159 int32_t errRet = RESAMPLER_ERR_SUCCESS;
160 state_ = SingleStagePolyphaseResamplerInit(channels_, inRate_, outRate_, quality_, &errRet);
161 CHECK_AND_RETURN_RET_LOG(state_ && (errRet == RESAMPLER_ERR_SUCCESS), errRet,
162 "Proresampler: update work channels failed with error %{public}s.", ErrCodeToString(errRet).c_str());
163
164 AUDIO_INFO_LOG("Proresampler: update work channel success old channels: %{public}d, new channels: %{public}d",
165 oldChannels, channels_);
166
167 return SingleStagePolyphaseResamplerSkipHalfTaps(state_);
168 }
169
ProResampler(ProResampler && other)170 ProResampler::ProResampler(ProResampler &&other) noexcept
171 : inRate_(other.inRate_), outRate_(other.outRate_), channels_(other.channels_),
172 quality_(other.quality_), expectedOutFrameLen_(other.expectedOutFrameLen_),
173 expectedInFrameLen_(other.expectedInFrameLen_), state_(other.state_)
174 {
175 other.state_ = nullptr;
176 }
177
operator =(ProResampler && other)178 ProResampler &ProResampler::operator=(ProResampler &&other) noexcept
179 {
180 if (this != &other) {
181 if (state_ != nullptr) {
182 SingleStagePolyphaseResamplerFree(state_);
183 }
184 inRate_ = other.inRate_;
185 outRate_ = other.outRate_;
186 channels_ = other.channels_;
187 quality_ = other.quality_;
188 state_ = other.state_;
189 expectedOutFrameLen_ = other.expectedOutFrameLen_;
190 expectedInFrameLen_ = other.expectedInFrameLen_;
191 other.state_ = nullptr;
192 }
193 return *this;
194 }
195
Reset()196 void ProResampler::Reset()
197 {
198 CHECK_AND_RETURN_LOG(state_ != nullptr, "ProResampler: resampler is null");
199 SingleStagePolyphaseResamplerResetMem(state_);
200 SingleStagePolyphaseResamplerSkipHalfTaps(state_);
201 }
202
GetInRate() const203 uint32_t ProResampler::GetInRate() const
204 {
205 return inRate_;
206 }
207
GetOutRate() const208 uint32_t ProResampler::GetOutRate() const
209 {
210 return outRate_;
211 }
212
GetChannels() const213 uint32_t ProResampler::GetChannels() const
214 {
215 return channels_;
216 }
217
GetQuality() const218 uint32_t ProResampler::GetQuality() const
219 {
220 return quality_;
221 }
222
~ProResampler()223 ProResampler::~ProResampler()
224 {
225 if (state_ != nullptr) {
226 SingleStagePolyphaseResamplerFree(state_);
227 state_ = nullptr;
228 }
229 }
230
ErrCodeToString(int32_t errCode)231 std::string ProResampler::ErrCodeToString(int32_t errCode)
232 {
233 switch (errCode) {
234 case RESAMPLER_ERR_SUCCESS: {
235 return "RESAMPLER_ERR_SUCCESS";
236 break;
237 }
238 case RESAMPLER_ERR_ALLOC_FAILED: {
239 return "RESAMPLER_ERR_ALLOC_FAILED";
240 break;
241 }
242 case RESAMPLER_ERR_INVALID_ARG: {
243 return "RESAMPLER_ERR_INVALID_ARG";
244 break;
245 }
246 case RESAMPLER_ERR_OVERFLOW: {
247 return "RESAMPLER_ERR_OVERFLOW";
248 break;
249 }
250 default: {
251 return "Unknown Error Code";
252 }
253 }
254 }
255
256 } // HPAE
257 } // AudioStandard
258 } // OHOS