• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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