• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 <cstdint>
17 #include <cstdio>
18 
19 #include "kws_manager.h"
20 
21 using namespace OHOS::AI;
22 using namespace OHOS::Audio;
23 using namespace OHOS::Media;
24 
25 namespace KWS {
26 namespace {
27     const int32_t CONFIDENCE = 2662;
28     const int32_t MAX_CACHE_SIZE = 16000;
29     const int32_t SUCCESS = 0;
30     const int32_t CHANNEL_COUNT = 1;
31 
32     using Capturer = std::shared_ptr<AudioCapturer>;
33     using Cache = std::shared_ptr<AudioCache>;
34     using Plugin = std::shared_ptr<KWSSdk>;
35 
36     // Can not create KwsManager twice
37     std::shared_ptr<std::thread> g_producer = nullptr;
38     std::shared_ptr<std::thread> g_consumer = nullptr;
__anon61e25a810202(uint8_t *array) 39     const auto DELETE_ARRAY = [](uint8_t *array) {
40         if (array != nullptr) {
41             delete[] array;
42         }
43     };
44 }
45 
46 class MyKwsCallback : public KWSCallback {
47 public:
MyKwsCallback()48     MyKwsCallback() {}
~MyKwsCallback()49     ~MyKwsCallback() {}
50 
OnError(int32_t errorCode)51     void OnError(int32_t errorCode)
52     {
53         printf("Executing error, error code: %d\n", errorCode);
54     }
55 
OnResult(const Array<int32_t> & result)56     void OnResult(const Array<int32_t> &result)
57     {
58         if (result.size != WORD_CONTENT.size()) {
59             return;
60         }
61         for (size_t i = 0; i < result.size; ++i) {
62             if (result.data[i] > CONFIDENCE) {
63                 printf("[%s]\n", WORD_CONTENT[i].c_str());
64             }
65         }
66     }
67 };
68 
AudioProducer(KwsManager * kwsManager)69 void ThreadTask::AudioProducer(KwsManager *kwsManager)
70 {
71     kwsManager->ProduceSamples();
72 }
73 
AudioConsumer(KwsManager * kwsManager)74 void ThreadTask::AudioConsumer(KwsManager *kwsManager)
75 {
76     kwsManager->ConsumeSamples();
77 }
78 
KwsManager(int32_t sampleRate,int32_t bitRate)79 KwsManager::KwsManager(int32_t sampleRate, int32_t bitRate)
80     : sampleRate_(sampleRate), bitRate_(bitRate)
81 {
82     status_ = IDLE;
83 }
84 
~KwsManager()85 KwsManager::~KwsManager()
86 {
87     OnStop();
88     status_ = IDLE;
89 }
90 
ProduceSamples()91 void KwsManager::ProduceSamples()
92 {
93     printf("[KwsManager]ProduceSamples start\n");
94     if (capturer_ == nullptr || cache_ == nullptr || aacHandler_ == -1) {
95         printf("[KwsManager]Produce AudioSample failed for nullptr\n");
96         return;
97     }
98     int32_t readLen = 0;
99     int32_t retCode = SUCCESS;
100     size_t frameSize = capturer_->GetFrameCount() * sizeof(uint16_t);
101     if (frameSize <= 0) {
102         printf("[KwsManager]Capturer get frame count failed.\n");
103         return;
104     }
105     CoderStream aacStream = {
106         .buffer = new (std::nothrow) uint8_t[frameSize],
107         .size = frameSize
108     };
109     CoderStream pcmStream = {
110         .buffer = new (std::nothrow) uint8_t[frameSize],
111         .size = frameSize
112     };
113     if (aacStream.buffer == nullptr || pcmStream.buffer == nullptr) {
114         printf("[KwsManager]Allocate buffer for aacStream and pcmStream failed.\n");
115         DELETE_ARRAY(aacStream.buffer);
116         DELETE_ARRAY(pcmStream.buffer);
117         return;
118     }
119     while (status_ == RUNNING) {
120         {
121             std::lock_guard<std::mutex> lock(mutex_);
122             if (capturer_ == nullptr) {
123                 break;
124             }
125             readLen = capturer_->Read(aacStream.buffer, frameSize, false);
126         }
127         if (readLen <= 0 || readLen > static_cast<int32_t>(frameSize)) {
128             continue;
129         }
130         aacStream.size = readLen;
131         retCode = AudioWrapper::GetInstance().Convert(aacHandler_, aacStream, pcmStream);
132         if (retCode != SUCCESS) {
133             continue;
134         }
135         {
136             std::lock_guard<std::mutex> lock(mutex_);
137             if (cache_ == nullptr) {
138                 break;
139             }
140             if (!cache_->AppendBuffer(pcmStream.size, pcmStream.buffer)) {
141                 printf("[KwsManager]Fail to append pcm into cache.\n");
142             }
143         }
144     }
145     DELETE_ARRAY(aacStream.buffer);
146     DELETE_ARRAY(pcmStream.buffer);
147 }
148 
ConsumeSamples()149 void KwsManager::ConsumeSamples()
150 {
151     uintptr_t sampleAddr = 0;
152     size_t sampleSize = 0;
153     int32_t retCode = SUCCESS;
154     while (status_ == RUNNING) {
155         {
156             std::lock_guard<std::mutex> lock(mutex_);
157             if (cache_ == nullptr) {
158                 printf("[KwsManager]cache_ is nullptr\n");
159                 break;
160             }
161             sampleSize = cache_->GetCapturedBuffer(sampleAddr);
162         }
163         if (sampleSize == 0 || sampleAddr == 0) {
164             continue;
165         }
166         Array<int16_t> input = {
167             .data = (int16_t *)sampleAddr,
168             .size = sampleSize >> 1
169         };
170         {
171             std::lock_guard<std::mutex> lock(mutex_);
172             if (plugin_ == nullptr) {
173                 printf("[KwsManager]cache_ is nullptr\n");
174                 break;
175             }
176             if ((retCode = plugin_->SyncExecute(input)) != SUCCESS) {
177                 printf("[KwsManager]SyncExecute KWS failed with retcode = [%d]\n", retCode);
178                 continue;
179             }
180         }
181     }
182 }
183 
Prepare()184 bool KwsManager::Prepare()
185 {
186     printf("[KwsManager]Prepare.\n");
187     if (status_ != IDLE) {
188         printf("[KwsManager]Already prepared.\n");
189         return false;
190     }
191     if (!PreparedAudioCapturer()) {
192         printf("[KwsManager]Fail to prepare AudioCapturer!\n");
193         OnStop();
194         return false;
195     }
196     if (!PreparedAudioWrapper()) {
197         printf("[KwsManager]Fail to prepare AudioWrapper!\n");
198         OnStop();
199         return false;
200     }
201     if (!PreparedInference()) {
202         printf("[KwsManager]Fail to prepare Inference!\n");
203         OnStop();
204         return false;
205     }
206     status_ = PREPARED;
207     return true;
208 }
209 
Start()210 void KwsManager::Start()
211 {
212     printf("[KwsManager]Start.\n");
213     if (status_ == RUNNING) {
214         printf("[KwsManager]Already running.\n");
215         return;
216     }
217     if (status_ != PREPARED && !Prepare()) {
218         printf("[KwsManager]Fail to prepare KwsManager!\n");
219         return;
220     }
221     OnStart();
222 }
223 
Stop()224 void KwsManager::Stop()
225 {
226     printf("[KwsManager]Stop.\n");
227     if (status_ == IDLE) {
228         printf("[KwsManager]Is already stopped.\n");
229         return;
230     }
231     std::lock_guard<std::mutex> lock(mutex_);
232     status_ = IDLE;
233     OnStop();
234 }
235 
OnStart()236 void KwsManager::OnStart()
237 {
238     if (!capturer_->Start()) {
239         printf("[KwsManager]Fail to start audioCapturer\n");
240         OnStop();
241         return;
242     }
243     if (aacHandler_ == -1) {
244         printf("[KwsManager]Fail to start producer for the illegal aac-to-pcm handler\n");
245         OnStop();
246         return;
247     }
248     if (cache_ == nullptr) {
249         printf("[KwsManager]Fail to start producer for the nullptr cache\n");
250         OnStop();
251         return;
252     }
253     if (plugin_ == nullptr) {
254         printf("[KwsManager]Fail to start producer for the nullptr plugin\n");
255         OnStop();
256         return;
257     }
258     status_ = RUNNING;
259     g_producer = std::make_shared<std::thread>(ThreadTask::AudioProducer, this);
260     g_consumer = std::make_shared<std::thread>(ThreadTask::AudioConsumer, this);
261 }
262 
StopAudioCapturer()263 void KwsManager::StopAudioCapturer()
264 {
265     printf("[KwsManager]StopAudioCapturer\n");
266     if (capturer_ != nullptr) {
267         capturer_->Stop();
268         capturer_ = nullptr;
269     }
270 }
271 
StopAudioWrapper()272 void KwsManager::StopAudioWrapper()
273 {
274     printf("[KwsManager]StopAudioWrapper\n");
275     AudioWrapper::GetInstance().Deinit(aacHandler_);
276 }
277 
StopInference()278 void KwsManager::StopInference()
279 {
280     printf("[KwsManager]StopInference\n");
281     if (plugin_ != nullptr) {
282         int32_t ret = plugin_->Destroy();
283         if (ret != SUCCESS) {
284             printf("[KwsManager]plugin_ destroy failed.\n");
285         }
286         plugin_ = nullptr;
287     }
288 }
289 
OnStop()290 void KwsManager::OnStop()
291 {
292     if (capturer_ != nullptr) {
293         StopAudioCapturer();
294     }
295     StopAudioWrapper();
296     if (plugin_ != nullptr) {
297         StopInference();
298     }
299     if (g_producer != nullptr) {
300         g_producer->join();
301     }
302     if (g_consumer != nullptr) {
303         g_consumer->join();
304     }
305 }
306 
PreparedAudioCapturer()307 bool KwsManager::PreparedAudioCapturer()
308 {
309     // Set audio wrapper mode before build audio capturer
310     AudioWrapper::GetInstance().SetCodecMode(false);
311     if (capturer_ != nullptr) {
312         printf("[KwsManager]Stop created AudioCapturer at first\n");
313         StopAudioCapturer();
314     }
315     capturer_ = std::make_shared<AudioCapturer>();
316     if (capturer_ == nullptr || !ConfiguredAudioCapturer()) {
317         printf("[KwsManager]Fail to create AudioCapturer.\n");
318         OnStop();
319         return false;
320     }
321     return true;
322 }
323 
PreparedAudioWrapper()324 bool KwsManager::PreparedAudioWrapper()
325 {
326     cache_ = std::make_shared<AudioCache>();
327     if (cache_ == nullptr) {
328         printf("[KwsManager]Failed to create AudioCache\n");
329         return false;
330     }
331     if (!cache_->Init(MAX_CACHE_SIZE)) {
332         printf("[KwsManager]Failed to init AudioCache\n");
333         return false;
334     }
335     if (!ConfiguredAudioWrapper()) {
336         printf("[KwsManager]Failed to prepared AudioWrapper.\n");
337         OnStop();
338         return false;
339     }
340     return true;
341 }
342 
PreparedInference()343 bool KwsManager::PreparedInference()
344 {
345     if (capturer_ == nullptr) {
346         printf("[KwsManager]Only load plugin after AudioCapturer ready.\n");
347         return false;
348     }
349     if (plugin_ != nullptr) {
350         printf("[KwsManager]Stop created Inference Plugin at first.\n");
351         StopInference();
352     }
353     plugin_ = std::make_shared<KWSSdk>();
354     if (plugin_ == nullptr) {
355         printf("[KwsManager]Failed to create InferencePlugin.\n");
356         return false;
357     }
358     if (plugin_->Create() != SUCCESS) {
359         printf("[KwsManager]Failed to create KWSSDK.\n");
360         return false;
361     }
362     std::shared_ptr<KWSCallback> callback = std::make_shared<MyKwsCallback>();
363     if (callback == nullptr) {
364         printf("[KwsManager]Create callback failed.\n");
365         return false;
366     }
367     plugin_->SetCallback(callback);
368     return true;
369 }
370 
ConfiguredAudioCapturer()371 bool KwsManager::ConfiguredAudioCapturer()
372 {
373     AudioCapturerInfo audioConfig;
374     audioConfig.inputSource = AUDIO_MIC;
375     audioConfig.audioFormat = AAC_LC;
376     audioConfig.sampleRate = AUDIO_SAMPLE_RATE;
377     audioConfig.channelCount = CHANNEL_COUNT;
378     audioConfig.bitRate = AUDIO_CODEC_BITRATE;
379     audioConfig.streamType = TYPE_MEDIA;
380     audioConfig.bitWidth = BIT_WIDTH_16;
381     int32_t ret = capturer_->SetCapturerInfo(audioConfig);
382     if (ret != SUCCESS) {
383         printf("[KwsManager]ConfiguredAudioCapturer fail with ret = 0x%.8x\n", ret);
384         return false;
385     }
386     return true;
387 }
388 
ConfiguredAudioWrapper()389 bool KwsManager::ConfiguredAudioWrapper()
390 {
391     ConvertType typo = CONVERT_AAC_TO_PCM;
392     CoderConfig codecConfig;
393     codecConfig.audioFormat = AAC_LC;
394     codecConfig.bitRate = bitRate_;
395     codecConfig.sampleRate = sampleRate_;
396     codecConfig.channelCount = CHANNEL_COUNT;
397     codecConfig.bitWidth = BIT_WIDTH_16;
398     if (AudioWrapper::GetInstance().Init(typo, aacHandler_) != SUCCESS) {
399         return false;
400     }
401     if (AudioWrapper::GetInstance().SetConfig(aacHandler_, codecConfig) != SUCCESS) {
402         return false;
403     }
404     if (AudioWrapper::GetInstance().StartCodec(aacHandler_) != SUCCESS) {
405         return false;
406     }
407     return true;
408 }
409 }