• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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