1 /*
2 * Copyright (c) 2024 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 <sys/time.h>
17 #include <utility>
18
19 #include <climits>
20 #include <cmath>
21 #include <cfloat>
22 #include "securec.h"
23 #include "audio_log.h"
24 #include "audio_policy_manager.h"
25 #include "tone_player_impl.h"
26 #include "audio_utils.h"
27 #include "audio_errors.h"
28
29 namespace OHOS {
30 namespace AudioStandard {
31 namespace {
32 constexpr int32_t C20MS = 20;
33 constexpr int32_t C1000MS = 1000;
34 constexpr int32_t CDOUBLE = 2;
35 constexpr int32_t AMPLITUDE = 8000;
36 constexpr int32_t BIT8 = 8;
37 }
38
TonePlayerImpl(const std::string cachePath,const AudioRendererInfo & rendereInfo)39 TonePlayerImpl::TonePlayerImpl(const std::string cachePath, const AudioRendererInfo &rendereInfo)
40 {
41 toneState_ = TONE_IDLE;
42 rendererOptions_.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
43 rendererOptions_.streamInfo.samplingRate = SAMPLE_RATE_48000;
44 rendererOptions_.streamInfo.format = SAMPLE_S16LE;
45 rendererOptions_.streamInfo.channels = MONO;
46
47 // contentType::CONTENT_TYPE_MUSIC;
48 rendererOptions_.rendererInfo.contentType = rendereInfo.contentType;
49
50 // streamUsage::STREAM_USAGE_MEDIA;
51 rendererOptions_.rendererInfo.streamUsage = rendereInfo.streamUsage;
52 rendererOptions_.rendererInfo.rendererFlags = 0; // use 0 for normal
53 supportedTones_ = AudioPolicyManager::GetInstance().GetSupportedTones();
54 toneInfo_ = NULL;
55 initialToneInfo_ = NULL;
56 samplingRate_ = rendererOptions_.streamInfo.samplingRate;
57 if (!cachePath.empty()) {
58 AUDIO_INFO_LOG("copy application cache path");
59 cachePath_.assign(cachePath);
60 }
61 }
62
~TonePlayerImpl()63 TonePlayerImpl::~TonePlayerImpl()
64 {
65 AUDIO_INFO_LOG("TonePlayerImpl destructor");
66 if (audioRenderer_ != nullptr) {
67 audioRenderer_->Stop();
68 audioRenderer_->Release();
69 }
70 audioRenderer_ = nullptr;
71 }
72
OnInterrupt(const InterruptEvent & interruptEvent)73 void TonePlayerImpl::OnInterrupt(const InterruptEvent &interruptEvent)
74 {
75 AUDIO_INFO_LOG("ToneType %{public}d eventType: %{public}d", toneType_, interruptEvent.eventType);
76 return;
77 }
78
OnStateChange(const RendererState state,const StateChangeCmdType cmdType)79 void TonePlayerImpl::OnStateChange(const RendererState state, const StateChangeCmdType __attribute__((unused)) cmdType)
80 {
81 AUDIO_INFO_LOG("ToneType %{public}d OnStateChange state: %{public}d", toneType_, state);
82 }
83
OnWriteData(size_t length)84 void TonePlayerImpl::OnWriteData(size_t length)
85 {
86 if (toneState_ == TONE_RELEASED) {
87 AUDIO_WARNING_LOG("Tone %{public}d is already released", toneType_);
88 return;
89 }
90 std::lock_guard<std::mutex> lock(optMutex_);
91 BufferDesc bufDesc = {};
92 if (audioRenderer_ != nullptr) {
93 audioRenderer_->GetBufferDesc(bufDesc);
94 } else {
95 AUDIO_ERR_LOG("OnWriteData audioRenderer_ is null");
96 }
97 bufDesc.dataLength = 0;
98 if (bufDesc.bufLength == 0) {
99 AUDIO_WARNING_LOG(" bufDesc bufLength is 0");
100 return;
101 }
102
103 // Clear output buffer: WaveGenerator accumulates into audioBuffer buffer
104 memset_s(bufDesc.buffer, bufDesc.bufLength, 0, bufDesc.bufLength);
105 if (AudioToneSequenceGen(bufDesc) == false) {
106 AUDIO_WARNING_LOG("SequenceGen error");
107 bufDesc.dataLength = bufDesc.bufLength;
108 }
109 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(bufDesc.buffer), bufDesc.dataLength);
110 if (audioRenderer_ != nullptr) {
111 audioRenderer_->Enqueue(bufDesc);
112 } else {
113 AUDIO_ERR_LOG("AudioToneDataThreadFunc Enqueue audioRenderer_ is null");
114 }
115 }
116
LoadTone(ToneType toneType)117 bool TonePlayerImpl::LoadTone(ToneType toneType)
118 {
119 std::lock_guard<std::mutex> lock(optMutex_);
120 AUDIO_INFO_LOG("LoadTone type: %{public}d", toneType);
121 bool result = false;
122 bool checkPermission = PermissionUtil::VerifySelfPermission();
123 CHECK_AND_RETURN_RET_LOG(checkPermission, false, "LoadTone: No system permission");
124 if (toneType >= NUM_TONES) {
125 return result;
126 }
127 if (std::find(supportedTones_.begin(), supportedTones_.end(), (int32_t)toneType) == supportedTones_.end()) {
128 return result;
129 }
130 toneType_ = toneType;
131 initialToneInfo_ = AudioPolicyManager::GetInstance().GetToneConfig(toneType);
132 if (initialToneInfo_->segmentCnt == 0) {
133 AUDIO_ERR_LOG("LoadTone failed, calling GetToneConfig returned invalid");
134 return result;
135 }
136 if (!isRendererInited_) {
137 isRendererInited_ = InitAudioRenderer();
138 CHECK_AND_RETURN_RET_LOG(isRendererInited_, false, "InitAudioRenderer failed");
139 }
140 result = InitToneWaveInfo();
141 CHECK_AND_RETURN_RET_LOG(result, false, "InitToneWaveInfo failed");
142 toneState_ = TONE_INIT;
143 DumpFileUtil::OpenDumpFile(DUMP_CLIENT_PARA, DUMP_TONEPLAYER_FILENAME, &dumpFile_);
144 return result;
145 }
146
StartTone()147 bool TonePlayerImpl::StartTone()
148 {
149 std::lock_guard<std::mutex> lock(optMutex_);
150 AUDIO_INFO_LOG("STARTTONE ToneType %{public}d", toneType_);
151 CHECK_AND_RETURN_RET_LOG(toneState_ == TONE_INIT || toneState_ == TONE_STOPPED, false,
152 "Start audioRenderer_ is null");
153
154 if (!isRendererInited_ || audioRenderer_ == nullptr) {
155 AUDIO_ERR_LOG("Start audioRenderer_ is null");
156 return false;
157 }
158 bool result = audioRenderer_->Start();
159 CHECK_AND_RETURN_RET_LOG(result, result, "Start audioRenderer_ failed");
160 toneState_ = TONE_STARTING;
161 return result;
162 }
163
StopTone()164 bool TonePlayerImpl::StopTone()
165 {
166 std::lock_guard<std::mutex> lock(optMutex_);
167 AUDIO_INFO_LOG("STOPTONE ToneType %{public}d", toneType_);
168
169 if (!isRendererInited_ || audioRenderer_ == nullptr) {
170 AUDIO_ERR_LOG("Stop audioRenderer_ is null");
171 return false;
172 }
173 // in plan: mark state stopping, smooth volume in onwritedata
174 bool result = audioRenderer_->Stop();
175 CHECK_AND_RETURN_RET_LOG(result, result, "Stop audioRenderer_ failed");
176 toneState_ = TONE_STOPPING;
177 return result;
178 }
179
Release()180 bool TonePlayerImpl::Release()
181 {
182 std::unique_lock<std::mutex> lock(optMutex_);
183 toneState_ = TONE_RELEASED;
184 lock.unlock();
185 if (audioRenderer_ != nullptr) {
186 audioRenderer_->Stop();
187 audioRenderer_->Release();
188 audioRenderer_ = nullptr;
189 }
190 DumpFileUtil::CloseDumpFile(&dumpFile_);
191 return true;
192 }
193
GetCurrentSegmentUpdated()194 void TonePlayerImpl::GetCurrentSegmentUpdated()
195 {
196 if (toneInfo_->segments[currSegment_].loopCnt) {
197 if (loopCounter_ < toneInfo_->segments[currSegment_].loopCnt) {
198 currSegment_ = toneInfo_->segments[currSegment_].loopIndx;
199 ++loopCounter_;
200 } else {
201 // completed loop. go to next segment
202 loopCounter_ = 0;
203 currSegment_++;
204 }
205 } else {
206 // no looping required , go to next segment
207 currSegment_++;
208 }
209 AUDIO_INFO_LOG("GetCurrentSegmentUpdated loopCounter_: %{public}d, currSegment_: %{public}d",
210 loopCounter_, currSegment_);
211 }
212
CheckToneContinuity()213 bool TonePlayerImpl::CheckToneContinuity()
214 {
215 AUDIO_INFO_LOG("CheckToneContinuity Entry loopCounter_: %{public}d, currSegment_: %{public}d",
216 loopCounter_, currSegment_);
217 bool retVal = false;
218 GetCurrentSegmentUpdated();
219
220 // Handle loop if last segment reached
221 if (toneInfo_->segments[currSegment_].duration == 0) {
222 AUDIO_DEBUG_LOG("Last Seg: %{public}d", currSegment_);
223 if (currCount_ < toneInfo_->repeatCnt) {
224 currSegment_ = toneInfo_->repeatSegment;
225 ++currCount_;
226 retVal = true;
227 } else {
228 retVal = false;
229 }
230 } else {
231 retVal = true;
232 }
233 AUDIO_DEBUG_LOG("CheckToneContinuity End loopCounter_: %{public}d, currSegment_: %{public}d currCount_: %{public}d",
234 loopCounter_, currSegment_, currCount_);
235 return retVal;
236 }
237
ContinueToneplay(uint32_t reqSample,int8_t * audioBuffer)238 bool TonePlayerImpl::ContinueToneplay(uint32_t reqSample, int8_t *audioBuffer)
239 {
240 if (toneState_ != TONE_RUNNING) {
241 return false;
242 }
243 if (totalSample_ <= nextSegSample_) {
244 if (toneInfo_->segments[currSegment_].duration != 0) {
245 GetSamples(toneInfo_->segments[currSegment_].waveFreq, audioBuffer, reqSample);
246 }
247 return true;
248 }
249
250 if (CheckToneContinuity()) {
251 if (toneInfo_->segments[currSegment_].duration != 0) {
252 sampleCount_ = 0;
253 GetSamples(toneInfo_->segments[currSegment_].waveFreq, audioBuffer, reqSample);
254 }
255 }
256 nextSegSample_ += (toneInfo_->segments[currSegment_].duration * samplingRate_) / C1000MS;
257 AUDIO_INFO_LOG("ContinueToneplay nextSegSample_: %{public}d", nextSegSample_);
258 return true;
259 }
260
GetSamples(uint16_t * freqs,int8_t * buffer,uint32_t reqSamples)261 int32_t TonePlayerImpl::GetSamples(uint16_t *freqs, int8_t *buffer, uint32_t reqSamples)
262 {
263 uint32_t index;
264 uint8_t *data;
265 uint16_t freqVal;
266 float pi = 3.1428f;
267 for (uint32_t i = 0; i <= TONEINFO_MAX_WAVES; i++) {
268 if (freqs[i] == 0) {
269 break;
270 }
271 freqVal = freqs[i];
272 AUDIO_DEBUG_LOG("GetSamples Freq: %{public}d sampleCount_: %{public}d", freqVal, sampleCount_);
273 index = sampleCount_;
274 data = reinterpret_cast<uint8_t*>(buffer);
275 double factor = freqVal * 2 * pi / samplingRate_; // 2 is a parameter in the sine wave formula
276 for (uint32_t idx = 0; idx < reqSamples; idx++) {
277 int16_t sample = AMPLITUDE * sin(factor * index);
278 uint32_t result;
279 if (i == 0) {
280 result = (sample & 0xFF);
281 *data = result & 0xFF;
282 data++;
283 *data = ((sample & 0xFF00) >> BIT8);
284 data++;
285 } else {
286 result = *data + (sample & 0xFF);
287 *data = result & 0xFF;
288 data++;
289 *data += (result >> BIT8) + ((sample & 0xFF00) >> BIT8);
290 data++;
291 }
292 index++;
293 }
294 }
295 sampleCount_ += reqSamples;
296 return 0;
297 }
298
CheckToneStarted(uint32_t reqSample,int8_t * audioBuffer)299 bool TonePlayerImpl::CheckToneStarted(uint32_t reqSample, int8_t *audioBuffer)
300 {
301 if (toneState_ != TONE_STARTING) {
302 return false;
303 }
304 toneState_ = TONE_RUNNING;
305 if (toneInfo_->segments[currSegment_].duration != 0) {
306 sampleCount_ = 0;
307 GetSamples(toneInfo_->segments[currSegment_].waveFreq, audioBuffer, reqSample);
308 }
309 return true;
310 }
311
CheckToneStopped()312 bool TonePlayerImpl::CheckToneStopped()
313 {
314 if (toneState_ == TONE_STOPPED) {
315 return true;
316 }
317 if (toneInfo_->segments[currSegment_].duration == 0 || totalSample_ > maxSample_ || toneState_ == TONE_STOPPING) {
318 if (toneState_ == TONE_RUNNING) {
319 toneState_ = TONE_STOPPING;
320 AUDIO_DEBUG_LOG("Audicallback move playing to stoping");
321 }
322 return true;
323 }
324 return false;
325 }
326
AudioToneSequenceGen(BufferDesc & bufDesc)327 bool TonePlayerImpl::AudioToneSequenceGen(BufferDesc &bufDesc)
328 {
329 int8_t *audioBuffer = reinterpret_cast<int8_t *>(bufDesc.buffer);
330 uint32_t totalBufAvailable = bufDesc.bufLength / sizeof(int16_t);
331 bool retVal = true;
332 while (totalBufAvailable) {
333 uint32_t reqSamples = totalBufAvailable < processSize_ * CDOUBLE ? totalBufAvailable : processSize_;
334 AUDIO_DEBUG_LOG("AudioToneDataThreadFunc, lReqSmp: %{public}d totalBufAvailable: %{public}d",
335 reqSamples, totalBufAvailable);
336 // Update pcm frame count and end time (current time at the end of this process)
337 totalSample_ += reqSamples;
338 if (CheckToneStopped()) {
339 // in plan: do smooth works
340 AUDIO_INFO_LOG("CheckToneStopped true toneType_ %{public}d", toneType_);
341 if (toneState_ == TONE_STOPPING) {
342 toneState_ = TONE_STOPPED;
343 totalBufAvailable = 0;
344 }
345 return false;
346 } else if (CheckToneStarted(reqSamples, audioBuffer)) {
347 bufDesc.dataLength += reqSamples * sizeof(int16_t);
348 } else {
349 if (ContinueToneplay(reqSamples, audioBuffer)) {
350 bufDesc.dataLength += reqSamples * sizeof(int16_t);
351 }
352 }
353 totalBufAvailable -= reqSamples;
354 audioBuffer += reqSamples * sizeof(int16_t);
355 }
356 return retVal;
357 }
358
InitToneWaveInfo()359 bool TonePlayerImpl::InitToneWaveInfo()
360 {
361 AUDIO_INFO_LOG("InitToneWaveInfo ToneType %{public}d", toneType_);
362 if (initialToneInfo_ == NULL) {
363 return false;
364 }
365 toneInfo_ = initialToneInfo_;
366 maxSample_ = TONEINFO_INF;
367
368 // Initialize tone sequencer
369 totalSample_ = 0;
370 currSegment_ = 0;
371 currCount_ = 0;
372 loopCounter_ = 0;
373 if (toneInfo_->segments[0].duration == TONEINFO_INF) {
374 nextSegSample_ = TONEINFO_INF;
375 } else {
376 nextSegSample_ = (toneInfo_->segments[0].duration * samplingRate_) / C1000MS;
377 }
378 AUDIO_INFO_LOG("Prepare wave, nextSegSample_: %{public}d", nextSegSample_);
379 return true;
380 }
381
382
InitAudioRenderer()383 bool TonePlayerImpl::InitAudioRenderer()
384 {
385 processSize_ = (rendererOptions_.streamInfo.samplingRate * C20MS) / C1000MS;
386 if (!cachePath_.empty()) {
387 audioRenderer_ = AudioRenderer::Create(cachePath_, rendererOptions_);
388 } else {
389 audioRenderer_ = AudioRenderer::Create(rendererOptions_);
390 }
391 CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, false,
392 "Renderer create failed");
393
394 size_t targetSize = 0;
395 int32_t ret = audioRenderer_->GetBufferSize(targetSize);
396
397 AUDIO_DEBUG_LOG("Playback renderer created");
398 int32_t setRenderMode = audioRenderer_->SetRenderMode(RENDER_MODE_CALLBACK);
399 CHECK_AND_RETURN_RET_LOG(!setRenderMode, false, "initAudioRenderer: SetRenderMode failed");
400 AUDIO_DEBUG_LOG("SetRenderMode Sucessful");
401
402 if (ret == 0 && targetSize != 0) {
403 size_t bufferDuration = 20; // 20 -> 20ms
404 audioRenderer_->SetBufferDuration(bufferDuration);
405 AUDIO_INFO_LOG("Init renderer with buffer %{public}zu, duration %{public}zu", targetSize, bufferDuration);
406 }
407
408 int32_t setRendererWrite = audioRenderer_->SetRendererWriteCallback(shared_from_this());
409 CHECK_AND_RETURN_RET_LOG(!setRendererWrite, false, "SetRendererWriteCallback failed");
410 AUDIO_DEBUG_LOG("SetRendererWriteCallback Sucessful");
411
412 int32_t setRendererCallback = audioRenderer_->SetRendererCallback(shared_from_this());
413 CHECK_AND_RETURN_RET_LOG(!setRendererCallback, false, "initAudioRenderer: SetRendererCallbackfailed");
414 AUDIO_DEBUG_LOG("SetRendererCallback Sucessful");
415 return true;
416 }
417 } // end namespace AudioStandard
418 } // end OHOS
419