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 const int32_t MAX_BUFFER_SIZE = 100000;
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     LoadChangeSpeedFunc();
50 
51     return SUCCESS;
52 }
53 
LoadChangeSpeedFunc()54 int32_t AudioSpeed::LoadChangeSpeedFunc()
55 {
56     switch (format_) {
57         case SAMPLE_U8:
58             formatSize_ = 1; // size is 1
59             ChangeSpeedFunc = [this] (uint8_t *buffer, int32_t bufferSize,
60                 std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)-> int32_t {
61                     return this->ChangeSpeedFor8Bit(buffer, bufferSize, outBuffer, outBufferSize);
62                 };
63             break;
64         case SAMPLE_S16LE:
65             formatSize_ = 2; // size is 2
66             ChangeSpeedFunc = [this] (uint8_t *buffer, int32_t bufferSize,
67                 std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)-> int32_t {
68                     return this->ChangeSpeedFor16Bit(buffer, bufferSize, outBuffer, outBufferSize);
69                 };
70             break;
71         case SAMPLE_S24LE:
72             formatSize_ = 3; // size is 3
73             ChangeSpeedFunc = [this] (uint8_t *buffer, int32_t bufferSize,
74                 std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)-> int32_t {
75                     return this->ChangeSpeedFor24Bit(buffer, bufferSize, outBuffer, outBufferSize);
76                 };
77             break;
78         case SAMPLE_S32LE:
79             formatSize_ = 4; // size is 4
80             ChangeSpeedFunc = [this] (uint8_t *buffer, int32_t bufferSize,
81                 std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)-> int32_t {
82                     return this->ChangeSpeedFor32Bit(buffer, bufferSize, outBuffer, outBufferSize);
83                 };
84             break;
85         default:
86             formatSize_ = 2; // size is 2
87             ChangeSpeedFunc = [this] (uint8_t *buffer, int32_t bufferSize,
88                 std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)-> int32_t {
89                     return this->ChangeSpeedFor16Bit(buffer, bufferSize, outBuffer, outBufferSize);
90                 };
91     }
92     AUDIO_INFO_LOG("load change speed func for format %{public}zu", format_);
93     return SUCCESS;
94 }
95 
SetSpeed(float speed)96 int32_t AudioSpeed::SetSpeed(float speed)
97 {
98     AUDIO_INFO_LOG("SetSpeed %{public}f", speed);
99     speed_ = speed;
100     sonicSetSpeed(sonicStream_, speed_);
101     return SUCCESS;
102 }
103 
GetSpeed()104 float AudioSpeed::GetSpeed()
105 {
106     return speed_;
107 }
108 
ChangeSpeedFor8Bit(uint8_t * buffer,int32_t bufferSize,std::unique_ptr<uint8_t[]> & outBuffer,int32_t & outBufferSize)109 int32_t AudioSpeed::ChangeSpeedFor8Bit(uint8_t *buffer, int32_t bufferSize,
110     std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)
111 {
112     Trace trace("AudioSpeed::ChangeSpeedFor8Bit");
113     int32_t numSamples = bufferSize / static_cast<int32_t>(formatSize_ * channels_);
114     int32_t res = sonicWriteUnsignedCharToStream(sonicStream_, static_cast<unsigned char*>(buffer), numSamples);
115     CHECK_AND_RETURN_RET_LOG(res == 1, 0, "sonic write unsigned char to stream failed.");
116 
117     int32_t outSamples = sonicReadUnsignedCharFromStream(sonicStream_,
118         static_cast<unsigned char*>(outBuffer.get()), MAX_BUFFER_SIZE);
119     CHECK_AND_RETURN_RET_LOG(outSamples != 0, bufferSize, "sonic stream is not full continue to write.");
120 
121     outBufferSize = outSamples * static_cast<int32_t>(formatSize_ * channels_);
122     return bufferSize;
123 }
124 
ChangeSpeedFor16Bit(uint8_t * buffer,int32_t bufferSize,std::unique_ptr<uint8_t[]> & outBuffer,int32_t & outBufferSize)125 int32_t AudioSpeed::ChangeSpeedFor16Bit(uint8_t *buffer, int32_t bufferSize,
126     std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)
127 {
128     Trace trace("AudioSpeed::ChangeSpeedFor16Bit");
129     int32_t numSamples = bufferSize / static_cast<int32_t>(formatSize_ * channels_);
130     int32_t res = sonicWriteShortToStream(sonicStream_, reinterpret_cast<short*>(buffer), numSamples);
131     CHECK_AND_RETURN_RET_LOG(res == 1, 0, "sonic write short to stream failed.");
132 
133     int32_t outSamples = sonicReadShortFromStream(sonicStream_, reinterpret_cast<short*>(outBuffer.get()),
134         MAX_BUFFER_SIZE);
135     CHECK_AND_RETURN_RET_LOG(outSamples != 0, bufferSize, "sonic stream is not full continue to write.");
136 
137     outBufferSize = outSamples * static_cast<int32_t>(formatSize_ * channels_);
138     return bufferSize;
139 }
140 
ChangeSpeedFor24Bit(uint8_t * buffer,int32_t bufferSize,std::unique_ptr<uint8_t[]> & outBuffer,int32_t & outBufferSize)141 int32_t AudioSpeed::ChangeSpeedFor24Bit(uint8_t *buffer, int32_t bufferSize,
142     std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)
143 {
144     Trace trace("AudioSpeed::ChangeSpeedFor24Bit");
145     if (bufferSize <= 0 || bufferSize > MAX_BUFFER_SIZE) {
146         AUDIO_ERR_LOG("BufferSize is illegal");
147         return ERR_MEMORY_ALLOC_FAILED;
148     }
149     float *bitTofloat = new (std::nothrow) float[bufferSize];
150     if (bitTofloat == nullptr) {
151         AUDIO_ERR_LOG("bitTofloat nullptr, No memory");
152         return ERR_MEMORY_ALLOC_FAILED;
153     }
154     ConvertFrom24BitToFloat(bufferSize / formatSize_, buffer, bitTofloat);
155 
156     float *speedBuf = new (std::nothrow) float[MAX_BUFFER_SIZE];
157     if (speedBuf == nullptr) {
158         AUDIO_ERR_LOG("speedBuf nullptr, No memory");
159         delete [] bitTofloat;
160         return ERR_MEMORY_ALLOC_FAILED;
161     }
162     int32_t ret = ChangeSpeedForFloat(bitTofloat, bufferSize, speedBuf, outBufferSize);
163 
164     ConvertFromFloatTo24Bit(outBufferSize / formatSize_, speedBuf, outBuffer.get());
165 
166     delete [] bitTofloat;
167     delete [] speedBuf;
168     return ret;
169 }
170 
ChangeSpeedFor32Bit(uint8_t * buffer,int32_t bufferSize,std::unique_ptr<uint8_t[]> & outBuffer,int32_t & outBufferSize)171 int32_t AudioSpeed::ChangeSpeedFor32Bit(uint8_t *buffer, int32_t bufferSize,
172     std::unique_ptr<uint8_t []> &outBuffer, int32_t &outBufferSize)
173 {
174     Trace trace("AudioSpeed::ChangeSpeedFor32Bit");
175     if (bufferSize <= 0 || bufferSize > MAX_BUFFER_SIZE) {
176         AUDIO_ERR_LOG("BufferSize is illegal");
177         return ERR_MEMORY_ALLOC_FAILED;
178     }
179     float *bitTofloat = new (std::nothrow) float[bufferSize];
180     if (bitTofloat == nullptr) {
181         AUDIO_ERR_LOG("bitTofloat nullptr, No memory");
182         return ERR_MEMORY_ALLOC_FAILED;
183     }
184     ConvertFrom32BitToFloat(bufferSize / formatSize_, reinterpret_cast<int32_t *>(buffer), bitTofloat);
185 
186     float *speedBuf = new (std::nothrow) float[MAX_BUFFER_SIZE];
187     if (speedBuf == nullptr) {
188         AUDIO_ERR_LOG("speedBuf nullptr, No memory");
189         delete [] bitTofloat;
190         return ERR_MEMORY_ALLOC_FAILED;
191     }
192     int32_t ret = ChangeSpeedForFloat(bitTofloat, bufferSize, speedBuf, outBufferSize);
193 
194     ConvertFromFloatTo32Bit(outBufferSize / formatSize_, speedBuf, reinterpret_cast<int32_t *>(outBuffer.get()));
195 
196     delete [] bitTofloat;
197     delete [] speedBuf;
198     return ret;
199 }
200 
ChangeSpeedForFloat(float * buffer,int32_t bufferSize,float * outBuffer,int32_t & outBufferSize)201 int32_t AudioSpeed::ChangeSpeedForFloat(float *buffer, int32_t bufferSize,
202     float* outBuffer, int32_t &outBufferSize)
203 {
204     Trace trace("AudioSpeed::ChangeSpeedForFloat");
205     int32_t numSamples = bufferSize / static_cast<int32_t>(formatSize_ * channels_);
206     int32_t res = static_cast<int32_t>(sonicWriteFloatToStream(sonicStream_, buffer, numSamples));
207     CHECK_AND_RETURN_RET_LOG(res == 1, 0, "sonic write float to stream failed.");
208     int32_t outSamples = sonicReadFloatFromStream(sonicStream_, outBuffer, MAX_BUFFER_SIZE);
209     outBufferSize = outSamples * static_cast<int32_t>(formatSize_ * channels_);
210     return bufferSize;
211 }
212 } // namespace AudioStandard
213 } // namespace OHOS
214