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