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