1 /*
2 * Copyright (c) 2023 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 #include "audio_source.h"
16
17 #include "securec.h"
18 #include "intell_voice_log.h"
19 #include "memory_guard.h"
20 #include "array_buffer_util.h"
21
22 #define LOG_TAG "AudioSource"
23
24 using namespace OHOS::AudioStandard;
25 using namespace OHOS::IntellVoiceUtils;
26
27 namespace OHOS {
28 namespace IntellVoiceEngine {
29 static const std::string CACHE_PATH = "/data/data/intell_voice/cache/";
30
AudioSource(uint32_t minBufferSize,uint32_t bufferCnt,std::unique_ptr<AudioSourceListener> listener,const OHOS::AudioStandard::AudioCapturerOptions & capturerOptions)31 AudioSource::AudioSource(uint32_t minBufferSize, uint32_t bufferCnt,
32 std::unique_ptr<AudioSourceListener> listener, const OHOS::AudioStandard::AudioCapturerOptions &capturerOptions)
33 : minBufferSize_(minBufferSize), bufferCnt_(bufferCnt), listener_(std::move(listener))
34 {
35 capturerOptions_.streamInfo.samplingRate = capturerOptions.streamInfo.samplingRate;
36 capturerOptions_.streamInfo.encoding = capturerOptions.streamInfo.encoding;
37 capturerOptions_.streamInfo.format = capturerOptions.streamInfo.format;
38 capturerOptions_.streamInfo.channels = capturerOptions.streamInfo.channels;
39 capturerOptions_.capturerInfo.sourceType = capturerOptions.capturerInfo.sourceType;
40 capturerOptions_.capturerInfo.capturerFlags = capturerOptions.capturerInfo.capturerFlags;
41 }
42
~AudioSource()43 AudioSource::~AudioSource()
44 {
45 Stop();
46 }
47
Start()48 bool AudioSource::Start()
49 {
50 INTELL_VOICE_LOG_INFO("enter");
51 if (listener_ == nullptr) {
52 INTELL_VOICE_LOG_ERROR("listener_ is nullptr");
53 return false;
54 }
55
56 if (minBufferSize_ == 0) {
57 INTELL_VOICE_LOG_ERROR("minBufferSize_ is invalid");
58 return false;
59 }
60
61 buffer_ = std::shared_ptr<uint8_t>(new uint8_t[minBufferSize_], [](uint8_t *p) { delete[] p; });
62 if (buffer_ == nullptr) {
63 INTELL_VOICE_LOG_ERROR("malloc buffer failed");
64 return false;
65 }
66
67 audioCapturer_ = AudioCapturer::Create(capturerOptions_, CACHE_PATH);
68 if (audioCapturer_ == nullptr) {
69 INTELL_VOICE_LOG_ERROR("audioCapturer_ is nullptr");
70 return false;
71 }
72
73 if (!audioCapturer_->Start()) {
74 INTELL_VOICE_LOG_ERROR("start audio capturer failed");
75 audioCapturer_->Release();
76 audioCapturer_ = nullptr;
77 return false;
78 }
79
80 isReading_.store(true);
81 CreateAudioDebugFile("_audio_source");
82
83 #ifdef FIRST_STAGE_ONESHOT_ENABLE
84 if (!ThreadWrapper::Start("WakeUpAudioSource")) {
85 INTELL_VOICE_LOG_ERROR("failed to start wakeup source");
86 return false;
87 }
88 #else
89 std::thread t1(std::bind(&AudioSource::Run, this));
90 readThread_ = std::move(t1);
91 #endif
92 return true;
93 }
94
Run()95 void AudioSource::Run()
96 {
97 INTELL_VOICE_LOG_INFO("enter");
98 uint32_t readCnt = 0;
99 isEnd_ = false;
100 while (isReading_.load()) {
101 if (!isEnd_ && (readCnt == bufferCnt_)) {
102 INTELL_VOICE_LOG_INFO("finish reading data");
103 isEnd_ = true;
104 if (listener_ != nullptr) {
105 listener_->bufferEndCb_();
106 }
107 }
108
109 if (!Read()) {
110 INTELL_VOICE_LOG_WARN("failed to read data");
111 break;
112 }
113 ++readCnt;
114 }
115 }
116
Read()117 bool AudioSource::Read()
118 {
119 int32_t len = audioCapturer_->Read(*(buffer_.get()), minBufferSize_, 1);
120 if (len != static_cast<int32_t>(minBufferSize_)) {
121 INTELL_VOICE_LOG_ERROR("failed to read data, len is %{public}d", len);
122 return false;
123 }
124
125 WriteData(reinterpret_cast<char *>(buffer_.get()), minBufferSize_);
126
127 if ((listener_ != nullptr)) {
128 listener_->readBufferCb_(buffer_.get(), minBufferSize_, isEnd_);
129 }
130 return true;
131 }
132
Stop()133 void AudioSource::Stop()
134 {
135 INTELL_VOICE_LOG_INFO("enter");
136 if (!isReading_.load()) {
137 INTELL_VOICE_LOG_INFO("already stop");
138 return;
139 }
140
141 MemoryGuard memoryGuard;
142
143 isReading_.store(false);
144 #ifdef FIRST_STAGE_ONESHOT_ENABLE
145 ThreadWrapper::Join();
146 #else
147 readThread_.join();
148 #endif
149
150 DestroyAudioDebugFile();
151
152 if (audioCapturer_ == nullptr) {
153 INTELL_VOICE_LOG_ERROR("audioCapturer_ is nullptr");
154 return;
155 }
156
157 if (!audioCapturer_->Stop()) {
158 INTELL_VOICE_LOG_ERROR("stop audio capturer error");
159 }
160
161 if (!audioCapturer_->Release()) {
162 INTELL_VOICE_LOG_ERROR("release audio capturer error");
163 }
164
165 audioCapturer_ = nullptr;
166 listener_ = nullptr;
167 }
168 }
169 }