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