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 #include "wakeup_source_process.h"
16 #include "intell_voice_log.h"
17
18 #define LOG_TAG "WakeupSourceProc"
19
20 using namespace OHOS::IntellVoiceUtils;
21
22 namespace OHOS {
23 namespace IntellVoiceEngine {
24 static constexpr uint32_t WAIT_TIME = 1000; // 1000ms
25 static constexpr uint32_t CHANNEL_CNT_1 = 1;
26 static constexpr uint32_t CHANNEL_CNT_4 = 4;
27 static constexpr uint32_t MAX_CHANNEL_CNT = 4;
28 static const std::string WRITE_SOURCE = "_write_source";
29 static const std::string READ_SOURCE = "_read_source";
30
~WakeupSourceProcess()31 WakeupSourceProcess::~WakeupSourceProcess()
32 {
33 Release();
34 }
35
Init(uint32_t channelCnt)36 void WakeupSourceProcess::Init(uint32_t channelCnt)
37 {
38 if (channelCnt_ != 0) {
39 INTELL_VOICE_LOG_WARN("need to release before init, channel cnt:%{public}u", channelCnt_);
40 Release();
41 }
42 for (uint32_t i = 0; i < channelCnt; i++) {
43 auto queue = std::make_unique<Uint8ArrayBufferQueue>();
44 if (queue == nullptr) {
45 INTELL_VOICE_LOG_ERROR("failed to create buffer queue");
46 return;
47 }
48 queue->Init();
49 bufferQueue_.push_back(std::move(queue));
50 }
51 channelCnt_ = channelCnt;
52 InitDebugFile(channelCnt);
53 }
54
Write(const std::vector<std::vector<uint8_t>> & audioData)55 void WakeupSourceProcess::Write(const std::vector<std::vector<uint8_t>> &audioData)
56 {
57 if ((static_cast<uint32_t>(audioData.size()) != channelCnt_) ||
58 (static_cast<uint32_t>(bufferQueue_.size()) != channelCnt_)) {
59 INTELL_VOICE_LOG_ERROR("data size:%{public}u, queue size:%{public}u, channel cnt:%{public}u",
60 static_cast<uint32_t>(audioData.size()), static_cast<uint32_t>(bufferQueue_.size()), channelCnt_);
61 return;
62 }
63
64 if (channelCnt_ == CHANNEL_CNT_1) {
65 WriteChannelData(audioData[CHANNEL_ID_0], CHANNEL_ID_0);
66 } else if (channelCnt_ == CHANNEL_CNT_4) {
67 WriteChannelData(audioData[CHANNEL_ID_0], CHANNEL_ID_0);
68 WriteChannelData(audioData[CHANNEL_ID_1], CHANNEL_ID_1);
69 WriteChannelData(audioData[CHANNEL_ID_2], CHANNEL_ID_2);
70 WriteChannelData(audioData[CHANNEL_ID_3], CHANNEL_ID_3);
71 } else {
72 INTELL_VOICE_LOG_WARN("not support channel cnt:%{public}u", channelCnt_);
73 }
74 }
75
Read(std::vector<uint8_t> & data,int32_t readChannel)76 int32_t WakeupSourceProcess::Read(std::vector<uint8_t> &data, int32_t readChannel)
77 {
78 INTELL_VOICE_LOG_INFO("enter, read channel:%{public}d", readChannel);
79 if ((readChannel == 0) || (readChannel >= (0x1 << MAX_CHANNEL_CNT))) {
80 return -1;
81 }
82
83 for (uint32_t i = 0; i < CHANNEL_CNT_4; i++) {
84 if (!(readChannel & (0x1 << i))) {
85 continue;
86 }
87 if (!ReadChannelData(data, i)) {
88 return -1;
89 }
90 }
91
92 return 0;
93 }
94
Release()95 void WakeupSourceProcess::Release()
96 {
97 for (auto &queue : bufferQueue_) {
98 queue ->Uninit();
99 }
100 std::vector<std::unique_ptr<Uint8ArrayBufferQueue>>().swap(bufferQueue_);
101 ReleaseDebugFile();
102 channelCnt_ = 0;
103 }
104
WriteChannelData(const std::vector<uint8_t> & channelData,uint32_t channelId)105 void WakeupSourceProcess::WriteChannelData(const std::vector<uint8_t> &channelData, uint32_t channelId)
106 {
107 if ((channelId >= bufferQueue_.size()) || (bufferQueue_[channelId] == nullptr)) {
108 INTELL_VOICE_LOG_ERROR("no buffer queue, channel id:%{public}d", channelId);
109 return;
110 }
111
112 auto arrayBuffer = CreateArrayBuffer<uint8_t>(channelData.size(), &channelData[0]);
113 if (arrayBuffer == nullptr) {
114 INTELL_VOICE_LOG_ERROR("failed to create array buffer");
115 return;
116 }
117 if (!bufferQueue_[channelId]->Push(std::move(arrayBuffer), false)) {
118 INTELL_VOICE_LOG_ERROR("failed to push array buffer");
119 return;
120 }
121
122 WriteDebugData(writeDebug_, channelData, channelId);
123 }
124
ReadChannelData(std::vector<uint8_t> & channelData,uint32_t channelId)125 bool WakeupSourceProcess::ReadChannelData(std::vector<uint8_t> &channelData, uint32_t channelId)
126 {
127 if ((channelId >= bufferQueue_.size()) || (bufferQueue_[channelId] == nullptr)) {
128 INTELL_VOICE_LOG_ERROR("no buffer queue, channel id:%{public}d", channelId);
129 return false;
130 }
131
132 std::unique_ptr<Uint8ArrayBuffer> arrayBuffer = nullptr;
133 bufferQueue_[channelId]->PopUntilTimeout(WAIT_TIME, arrayBuffer);
134 if (arrayBuffer == nullptr) {
135 INTELL_VOICE_LOG_ERROR("failed to pop data");
136 return false;
137 }
138
139 channelData.insert(channelData.end(), arrayBuffer->GetData(), arrayBuffer->GetData() + arrayBuffer->GetSize());
140 WriteDebugData(readDebug_, channelData, channelId);
141 return true;
142 }
143
InitDebugFile(uint32_t channelCnt)144 void WakeupSourceProcess::InitDebugFile(uint32_t channelCnt)
145 {
146 for (uint32_t i = 0; i < channelCnt; i++) {
147 auto writeObj = std::make_shared<AudioDebug>();
148 auto readObj = std::make_shared<AudioDebug>();
149 if ((writeObj == nullptr) || (readObj == nullptr)) {
150 INTELL_VOICE_LOG_ERROR("failed to create audio debug obj");
151 return;
152 }
153
154 writeObj->CreateAudioDebugFile(WRITE_SOURCE + std::to_string(i));
155 readObj->CreateAudioDebugFile(READ_SOURCE + std::to_string(i));
156 writeDebug_.emplace_back(writeObj);
157 readDebug_.emplace_back(readObj);
158 }
159 }
160
WriteDebugData(const std::vector<std::shared_ptr<AudioDebug>> & debugVec,const std::vector<uint8_t> & channelData,uint32_t channelId)161 void WakeupSourceProcess::WriteDebugData(const std::vector<std::shared_ptr<AudioDebug>> &debugVec,
162 const std::vector<uint8_t> &channelData, uint32_t channelId)
163 {
164 if ((channelId >= debugVec.size()) || (debugVec[channelId] == nullptr)) {
165 INTELL_VOICE_LOG_ERROR("no debug obj, channel id:%{public}d", channelId);
166 return;
167 }
168
169 debugVec[channelId]->WriteData(reinterpret_cast<const char *>(channelData.data()), channelData.size());
170 }
171
ReleaseDebugFile()172 void WakeupSourceProcess::ReleaseDebugFile()
173 {
174 for (auto writeObj : writeDebug_) {
175 writeObj->DestroyAudioDebugFile();
176 }
177 for (auto readObj : readDebug_) {
178 readObj->DestroyAudioDebugFile();
179 }
180 writeDebug_.clear();
181 readDebug_.clear();
182 }
183 }
184 }
185