• 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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioSpeed"
17 #endif
18 
19 #include "audio_speed.h"
20 #include "audio_common_log.h"
21 #include "audio_utils.h"
22 #include "audio_errors.h"
23 
24 namespace OHOS {
25 namespace AudioStandard {
26 
27 static constexpr float SLOW_PLAY_1_8_SPEED = 0.125f;
28 
AudioSpeed(size_t rate,size_t format,size_t channels)29 AudioSpeed::AudioSpeed(size_t rate, size_t format, size_t channels):rate_(rate), format_(format), channels_(channels)
30 {
31     AUDIO_INFO_LOG("AudioSpeed construct");
32     Init();
33     streamParam_ = {};
34 }
35 
~AudioSpeed()36 AudioSpeed::~AudioSpeed()
37 {
38     AUDIO_INFO_LOG("~AudioSpeed destroy");
39     if (sonicStream_ != nullptr) {
40         sonicDestroyStream(sonicStream_);
41         sonicStream_ = nullptr;
42         AUDIO_INFO_LOG("Sonic stream destroy");
43     }
44 }
45 
Init()46 int32_t AudioSpeed::Init()
47 {
48     sonicStream_ = sonicCreateStream(rate_, channels_);
49     CHECK_AND_RETURN_RET_LOG(sonicStream_ != nullptr, ERROR, "sonicCreateStream failed.");
50     LoadChangeSpeedFunc();
51 
52     return SUCCESS;
53 }
54 
LoadChangeSpeedFunc()55 int32_t AudioSpeed::LoadChangeSpeedFunc()
56 {
57     switch (format_) {
58         case SAMPLE_U8:
59             formatSize_ = 1; // size is 1
60             ChangeSpeedFunc = [this] (uint8_t *buffer, int32_t bufferSize,
61                 std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)-> int32_t {
62                     return this->ChangeSpeedFor8Bit(buffer, bufferSize, outBuffer, outBufferSize);
63                 };
64             break;
65         case SAMPLE_S16LE:
66             formatSize_ = 2; // size is 2
67             ChangeSpeedFunc = [this] (uint8_t *buffer, int32_t bufferSize,
68                 std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)-> int32_t {
69                     return this->ChangeSpeedFor16Bit(buffer, bufferSize, outBuffer, outBufferSize);
70                 };
71             break;
72         case SAMPLE_S24LE:
73             formatSize_ = 3; // size is 3
74             ChangeSpeedFunc = [this] (uint8_t *buffer, int32_t bufferSize,
75                 std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)-> int32_t {
76                     return this->ChangeSpeedFor24Bit(buffer, bufferSize, outBuffer, outBufferSize);
77                 };
78             break;
79         case SAMPLE_S32LE:
80             formatSize_ = 4; // size is 4
81             ChangeSpeedFunc = [this] (uint8_t *buffer, int32_t bufferSize,
82                 std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)-> int32_t {
83                     return this->ChangeSpeedFor32Bit(buffer, bufferSize, outBuffer, outBufferSize);
84                 };
85             break;
86         case SAMPLE_F32LE:
87             formatSize_ = 4; // size is 4
88             ChangeSpeedFunc = [this] (uint8_t *buffer, int32_t bufferSize,
89                 std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)-> int32_t {
90                     return this->ChangeSpeedForFloat(reinterpret_cast<float*>(buffer), bufferSize,
91                         reinterpret_cast<float*>(outBuffer.get()), outBufferSize);
92                 };
93             break;
94         default:
95             formatSize_ = 2; // size is 2
96             ChangeSpeedFunc = [this] (uint8_t *buffer, int32_t bufferSize,
97                 std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)-> int32_t {
98                     return this->ChangeSpeedFor16Bit(buffer, bufferSize, outBuffer, outBufferSize);
99                 };
100     }
101     AUDIO_INFO_LOG("load change speed func for format %{public}zu", format_);
102     return SUCCESS;
103 }
104 
SetSpeed(float speed)105 int32_t AudioSpeed::SetSpeed(float speed)
106 {
107     AUDIO_INFO_LOG("SetSpeed %{public}f", speed);
108     speed_ = speed;
109     sonicSetSpeed(sonicStream_, speed_);
110     return SUCCESS;
111 }
112 
SetPitch(float pitch)113 int32_t AudioSpeed::SetPitch(float pitch)
114 {
115     AUDIO_INFO_LOG("SetPitch %{public}f", pitch);
116     sonicSetPitch(sonicStream_, pitch);
117     sonicSetRate(sonicStream_, 1.0f);
118     return SUCCESS;
119 }
120 
GetPitchForSpeed(float speed)121 float AudioSpeed::GetPitchForSpeed(float speed)
122 {
123     float noPitchPoint = 0.5f;
124     float pitch = SPEED_NORMAL;
125     if (speed > noPitchPoint) {
126         pitch = SPEED_NORMAL;
127     } else {
128         pitch = (speed - SLOW_PLAY_1_8_SPEED) * (SPEED_NORMAL - SLOW_PLAY_1_8_SPEED) /
129             (noPitchPoint - SLOW_PLAY_1_8_SPEED) + SLOW_PLAY_1_8_SPEED;
130     }
131     AUDIO_INFO_LOG("final pitch is %{public}f for speed %{public}f", pitch, speed);
132     return pitch;
133 }
134 
GetSpeed()135 float AudioSpeed::GetSpeed()
136 {
137     return speed_;
138 }
139 
ChangeSpeedFor8Bit(uint8_t * buffer,int32_t bufferSize,std::unique_ptr<uint8_t[]> & outBuffer,int32_t & outBufferSize)140 int32_t AudioSpeed::ChangeSpeedFor8Bit(uint8_t *buffer, int32_t bufferSize,
141     std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)
142 {
143     Trace trace("AudioSpeed::ChangeSpeedFor8Bit");
144     int32_t numSamples = bufferSize / static_cast<int32_t>(formatSize_ * channels_);
145     int32_t res = sonicWriteUnsignedCharToStream(sonicStream_, static_cast<unsigned char*>(buffer), numSamples);
146     CHECK_AND_RETURN_RET_LOG(res == 1, 0, "sonic write unsigned char to stream failed.");
147 
148     int32_t outSamples = sonicReadUnsignedCharFromStream(sonicStream_,
149         static_cast<unsigned char*>(outBuffer.get()), MAX_SPEED_BUFFER_SIZE);
150     CHECK_AND_RETURN_RET_LOG(outSamples != 0, bufferSize, "sonic stream is not full continue to write.");
151 
152     outBufferSize = outSamples * static_cast<int32_t>(formatSize_ * channels_);
153     return bufferSize;
154 }
155 
ChangeSpeedFor16Bit(uint8_t * buffer,int32_t bufferSize,std::unique_ptr<uint8_t[]> & outBuffer,int32_t & outBufferSize)156 int32_t AudioSpeed::ChangeSpeedFor16Bit(uint8_t *buffer, int32_t bufferSize,
157     std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)
158 {
159     Trace trace("AudioSpeed::ChangeSpeedFor16Bit");
160     int32_t numSamples = bufferSize / static_cast<int32_t>(formatSize_ * channels_);
161     int32_t res = sonicWriteShortToStream(sonicStream_, reinterpret_cast<short*>(buffer), numSamples);
162     CHECK_AND_RETURN_RET_LOG(res == 1, 0, "sonic write short to stream failed.");
163 
164     int32_t outSamples = sonicReadShortFromStream(sonicStream_, reinterpret_cast<short*>(outBuffer.get()),
165         MAX_SPEED_BUFFER_SIZE);
166     CHECK_AND_RETURN_RET_LOG(outSamples != 0, bufferSize, "sonic stream is not full continue to write.");
167 
168     outBufferSize = outSamples * static_cast<int32_t>(formatSize_ * channels_);
169     return bufferSize;
170 }
171 
ChangeSpeedFor24Bit(uint8_t * buffer,int32_t bufferSize,std::unique_ptr<uint8_t[]> & outBuffer,int32_t & outBufferSize)172 int32_t AudioSpeed::ChangeSpeedFor24Bit(uint8_t *buffer, int32_t bufferSize,
173     std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)
174 {
175     Trace trace("AudioSpeed::ChangeSpeedFor24Bit");
176     if (bufferSize <= 0 || bufferSize > MAX_SPEED_BUFFER_SIZE) {
177         AUDIO_ERR_LOG("BufferSize is illegal:%{public}d", bufferSize);
178         return ERR_MEMORY_ALLOC_FAILED;
179     }
180     float *bitTofloat = new (std::nothrow) float[bufferSize];
181     if (bitTofloat == nullptr) {
182         AUDIO_ERR_LOG("bitTofloat nullptr, No memory");
183         return ERR_MEMORY_ALLOC_FAILED;
184     }
185     ConvertFrom24BitToFloat(bufferSize / formatSize_, buffer, bitTofloat);
186 
187     float *speedBuf = new (std::nothrow) float[MAX_SPEED_BUFFER_SIZE];
188     if (speedBuf == nullptr) {
189         AUDIO_ERR_LOG("speedBuf nullptr, No memory");
190         delete [] bitTofloat;
191         return ERR_MEMORY_ALLOC_FAILED;
192     }
193     int32_t ret = ChangeSpeedForFloat(bitTofloat, bufferSize, speedBuf, outBufferSize);
194 
195     ConvertFromFloatTo24Bit(outBufferSize / formatSize_, speedBuf, outBuffer.get());
196 
197     delete [] bitTofloat;
198     delete [] speedBuf;
199     return ret;
200 }
201 
ChangeSpeedFor32Bit(uint8_t * buffer,int32_t bufferSize,std::unique_ptr<uint8_t[]> & outBuffer,int32_t & outBufferSize)202 int32_t AudioSpeed::ChangeSpeedFor32Bit(uint8_t *buffer, int32_t bufferSize,
203     std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)
204 {
205     Trace trace("AudioSpeed::ChangeSpeedFor32Bit");
206     if (bufferSize <= 0 || bufferSize > MAX_SPEED_BUFFER_SIZE) {
207         AUDIO_ERR_LOG("BufferSize is illegal:%{public}d", bufferSize);
208         return ERR_MEMORY_ALLOC_FAILED;
209     }
210     float *bitTofloat = new (std::nothrow) float[bufferSize];
211     if (bitTofloat == nullptr) {
212         AUDIO_ERR_LOG("bitTofloat nullptr, No memory");
213         return ERR_MEMORY_ALLOC_FAILED;
214     }
215     ConvertFrom32BitToFloat(bufferSize / formatSize_, reinterpret_cast<int32_t *>(buffer), bitTofloat);
216 
217     float *speedBuf = new (std::nothrow) float[MAX_SPEED_BUFFER_SIZE];
218     if (speedBuf == nullptr) {
219         AUDIO_ERR_LOG("speedBuf nullptr, No memory");
220         delete [] bitTofloat;
221         return ERR_MEMORY_ALLOC_FAILED;
222     }
223     int32_t ret = ChangeSpeedForFloat(bitTofloat, bufferSize, speedBuf, outBufferSize);
224 
225     ConvertFromFloatTo32Bit(outBufferSize / formatSize_, speedBuf, reinterpret_cast<int32_t *>(outBuffer.get()));
226 
227     delete [] bitTofloat;
228     delete [] speedBuf;
229     return ret;
230 }
231 
ChangeSpeedForFloat(float * buffer,int32_t bufferSize,float * outBuffer,int32_t & outBufferSize)232 int32_t AudioSpeed::ChangeSpeedForFloat(float *buffer, int32_t bufferSize,
233     float* outBuffer, int32_t &outBufferSize)
234 {
235     Trace trace("AudioSpeed::ChangeSpeedForFloat");
236     int32_t numSamples = bufferSize / static_cast<int32_t>(formatSize_ * channels_);
237     int32_t res = static_cast<int32_t>(sonicWriteFloatToStream(sonicStream_, buffer, numSamples));
238     CHECK_AND_RETURN_RET_LOG(res == 1, 0, "sonic write float to stream failed.");
239     int32_t outSamples = sonicReadFloatFromStream(sonicStream_, outBuffer, MAX_SPEED_BUFFER_SIZE);
240     outBufferSize = outSamples * static_cast<int32_t>(formatSize_ * channels_);
241     return bufferSize;
242 }
243 
Flush()244 int32_t AudioSpeed::Flush()
245 {
246     Trace trace("AudioSpeed::Flush");
247     sonicFlushStream(sonicStream_);
248     std::unique_ptr<uint8_t[]> tmpBuffer = std::make_unique<uint8_t[]>(MAX_SPEED_BUFFER_SIZE);
249 
250     int samplesWritten = 0;
251     const size_t channelMultiplier = static_cast<size_t>(channels_);
252     do {
253         switch (format_) {
254             case SAMPLE_U8:
255                 samplesWritten = sonicReadUnsignedCharFromStream(sonicStream_,
256                     reinterpret_cast<uint8_t*>(tmpBuffer.get()),
257                     MAX_SPEED_BUFFER_SIZE / channelMultiplier);
258                 break;
259             case SAMPLE_S24LE:
260             case SAMPLE_S32LE:
261             case SAMPLE_F32LE:
262                 samplesWritten = sonicReadFloatFromStream(sonicStream_,
263                     reinterpret_cast<float*>(tmpBuffer.get()),
264                     MAX_SPEED_BUFFER_SIZE / (channelMultiplier * sizeof(float)));
265                 break;
266             case SAMPLE_S16LE:
267                 samplesWritten = sonicReadShortFromStream(sonicStream_,
268                     reinterpret_cast<short*>(tmpBuffer.get()),
269                     MAX_SPEED_BUFFER_SIZE / (channelMultiplier * sizeof(short)));
270                 break;
271             default:
272                 AUDIO_ERR_LOG("invalid format_");
273                 samplesWritten = 0;
274                 break;
275         }
276     } while (samplesWritten > 0);
277     return SUCCESS;
278 }
279 } // namespace AudioStandard
280 } // namespace OHOS
281