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