1 /*
2 * Copyright (c) 2022-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 AUDIO_UTILS_H
16 #define AUDIO_UTILS_H
17
18 #include <cstdint>
19 #include <string>
20 #include <map>
21 #include <unordered_map>
22 #include <mutex>
23 #include <ctime>
24 #include <sys/time.h>
25 #include <atomic>
26 #include <cstdio>
27 #include <queue>
28 #include <climits>
29 #include <condition_variable>
30 #include "securec.h"
31
32 #include "audio_info.h"
33 #include "audio_common_utils.h"
34
35 #define AUDIO_MS_PER_SECOND 1000
36 #define AUDIO_US_PER_SECOND 1000000
37 #define AUDIO_NS_PER_SECOND ((uint64_t)1000000000)
38
39 #define FLOAT_EPS 1e-9f
40 #define OFFSET_BIT_24 3
41 #define BIT_DEPTH_TWO 2
42 #define BIT_8 8
43 #define BIT_16 16
44 #define BIT_24 24
45 #define BIT_32 32
46 namespace OHOS {
47 namespace AudioStandard {
48 const int64_t PCM_MAYBE_SILENT = 1;
49 const int64_t PCM_MAYBE_NOT_SILENT = 5;
50 const uint32_t MAX_VALUE_OF_SIGNED_24_BIT = 8388607;
51 const int32_t SIGNAL_DATA_SIZE = 96;
52 const int32_t SIGNAL_THRESHOLD = 10;
53 const int32_t BLANK_THRESHOLD_MS = 100;
54 const int32_t DETECTED_ZERO_THRESHOLD = 1;
55 const size_t MILLISECOND_PER_SECOND = 1000;
56 const size_t MOCK_INTERVAL = 2000;
57 const int32_t GET_EXTRA_PARAM_LEN = 200;
58 const int32_t YEAR_BASE = 1900;
59 const int32_t DECIMAL_EXPONENT = 10;
60 const size_t DATE_LENGTH = 17;
61 static uint32_t g_sessionToMock = 0;
62 const uint32_t STRING_BUFFER_SIZE = 4096;
63
64 // Ringer or alarmer dual tone
65 const size_t AUDIO_CONCURRENT_ACTIVE_DEVICES_LIMIT = 2;
66
67 /* Define AudioXcollie timeout flag, consistent with xcollie_define.h in hiviewdfx */
68 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_DEFAULT = (~0); // do all callback function
69 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_NOOP = (0); // do nothing but the caller defined function
70 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_LOG = (1 << 0); // generate log file
71 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_RECOVERY = (1 << 1); // die when timeout
72
73 class Util {
74 public:
IsDualToneStreamType(const AudioStreamType streamType)75 static bool IsDualToneStreamType(const AudioStreamType streamType)
76 {
77 return streamType == STREAM_RING || streamType == STREAM_VOICE_RING || streamType == STREAM_ALARM;
78 }
79
IsRingerOrAlarmerStreamUsage(const StreamUsage &usage)80 static bool IsRingerOrAlarmerStreamUsage(const StreamUsage &usage)
81 {
82 return usage == STREAM_USAGE_ALARM || usage == STREAM_USAGE_VOICE_RINGTONE || usage == STREAM_USAGE_RINGTONE;
83 }
84
IsRingerAudioScene(const AudioScene &audioScene)85 static bool IsRingerAudioScene(const AudioScene &audioScene)
86 {
87 return audioScene == AUDIO_SCENE_RINGING || audioScene == AUDIO_SCENE_VOICE_RINGING;
88 }
89 };
90
91 class Trace {
92 public:
93 static void Count(const std::string &value, int64_t count);
94 // Show if data is silent.
95 static void CountVolume(const std::string &value, uint8_t data);
96 Trace(const std::string &value);
97 void End();
98 ~Trace();
99 private:
100 std::string value_;
101 bool isFinished_;
102 };
103
104 class AudioXCollie {
105 public:
106 AudioXCollie(const std::string &tag, uint32_t timeoutSeconds,
107 std::function<void(void *)> func = nullptr, void *arg = nullptr, uint32_t flag = 1);
108 ~AudioXCollie();
109 void CancelXCollieTimer();
110 private:
111 int32_t id_;
112 std::string tag_;
113 bool isCanceled_;
114 };
115
116 class ClockTime {
117 public:
118 static int64_t GetCurNano();
119 static int32_t AbsoluteSleep(int64_t nanoTime);
120 static int32_t RelativeSleep(int64_t nanoTime);
121 };
122
123 class PermissionUtil {
124 public:
125 static bool VerifyIsAudio();
126 static bool VerifyIsShell();
127 static bool VerifyIsSystemApp();
128 static bool VerifySelfPermission();
129 static bool VerifySystemPermission();
130 static bool VerifyPermission(const std::string &permissionName, uint32_t tokenId);
131 static bool NeedVerifyBackgroundCapture(int32_t callingUid, SourceType sourceType);
132 static bool VerifyBackgroundCapture(uint32_t tokenId, uint64_t fullTokenId);
133 static bool NotifyPrivacy(uint32_t targetTokenId, AudioPermissionState state);
134 };
135
136 void AdjustStereoToMonoForPCM8Bit(int8_t *data, uint64_t len);
137 void AdjustStereoToMonoForPCM16Bit(int16_t *data, uint64_t len);
138 void AdjustStereoToMonoForPCM24Bit(uint8_t *data, uint64_t len);
139 void AdjustStereoToMonoForPCM32Bit(int32_t *data, uint64_t len);
140 void AdjustAudioBalanceForPCM8Bit(int8_t *data, uint64_t len, float left, float right);
141 void AdjustAudioBalanceForPCM16Bit(int16_t *data, uint64_t len, float left, float right);
142 void AdjustAudioBalanceForPCM24Bit(uint8_t *data, uint64_t len, float left, float right);
143 void AdjustAudioBalanceForPCM32Bit(int32_t *data, uint64_t len, float left, float right);
144
145 void ConvertFrom24BitToFloat(unsigned n, const uint8_t *a, float *b);
146 void ConvertFrom32BitToFloat(unsigned n, const int32_t *a, float *b);
147 void ConvertFromFloatTo24Bit(unsigned n, const float *a, uint8_t *b);
148 void ConvertFromFloatTo32Bit(unsigned n, const float *a, int32_t *b);
149
150 std::string GetEncryptStr(const std::string &str);
151 std::string ConvertNetworkId(const std::string &networkId);
152
153 enum ConvertHdiFormat {
154 SAMPLE_U8_C = 0,
155 SAMPLE_S16_C = 1,
156 SAMPLE_S24_C = 2,
157 SAMPLE_S32_C = 3,
158 SAMPLE_F32_C = 4,
159 INVALID_WIDTH_C = -1
160 }; // same with HdiAdapterFormat
161
162 float UpdateMaxAmplitude(ConvertHdiFormat adapterFormat, char *frame, uint64_t replyBytes);
163 float CalculateMaxAmplitudeForPCM8Bit(int8_t *frame, uint64_t nSamples);
164 float CalculateMaxAmplitudeForPCM16Bit(int16_t *frame, uint64_t nSamples);
165 float CalculateMaxAmplitudeForPCM24Bit(char *frame, uint64_t nSamples);
166 float CalculateMaxAmplitudeForPCM32Bit(int32_t *frame, uint64_t nSamples);
167
168 template <typename T>
isEqual(T a, T b, double precision = 0.01)169 bool isEqual(T a, T b, double precision = 0.01)
170 {
171 return std::abs(a - b) < precision;
172 }
173
174 // return true if value is not in the array.
175 template <typename V>
NotContain(const std::vector<V> &array, const V &value)176 inline bool NotContain(const std::vector<V> &array, const V &value)
177 {
178 return std::find(array.begin(), array.end(), value) == array.end();
179 }
180
181 template <typename T>
182 bool GetSysPara(const char *key, T &value);
183
184 enum AudioDumpFileType {
185 AUDIO_APP = 0,
186 OTHER_NATIVE_SERVICE = 1,
187 AUDIO_PULSE = 2,
188 };
189
190 const std::string DUMP_SERVER_PARA = "sys.audio.dump.writeserver.enable";
191 const std::string DUMP_CLIENT_PARA = "sys.audio.dump.writeclient.enable";
192 const std::string DUMP_PULSE_DIR = "/data/data/.pulse_dir/";
193 const std::string DUMP_SERVICE_DIR = "/data/local/tmp/";
194 const std::string DUMP_APP_DIR = "/data/storage/el2/base/cache/";
195 const std::string DUMP_BLUETOOTH_RENDER_SINK_FILENAME = "dump_bluetooth_audiosink.pcm";
196 const std::string DUMP_RENDER_SINK_FILENAME = "dump_audiosink.pcm";
197 const std::string DUMP_MCH_SINK_FILENAME = "dump_mchaudiosink.pcm";
198 const std::string DUMP_DIRECT_RENDER_SINK_FILENAME = "dump_direct_audiosink.pcm";
199 const std::string DUMP_OFFLOAD_RENDER_SINK_FILENAME = "dump_offloadaudiosink.pcm";
200 const std::string DUMP_CAPTURER_SOURCE_FILENAME = "dump_capture_audiosource.pcm";
201 const std::string DUMP_TONEPLAYER_FILENAME = "dump_toneplayer_audio.pcm";
202 const std::string DUMP_PROCESS_IN_CLIENT_FILENAME = "dump_process_client_audio.pcm";
203 const std::string DUMP_REMOTE_RENDER_SINK_FILENAME = "dump_remote_audiosink";
204 const std::string DUMP_REMOTE_CAPTURE_SOURCE_FILENAME = "dump_remote_capture_audiosource.pcm";
205 const std::string DUMP_ENDPOINT_DCP_FILENAME = "dump_endpoint_dcp_audio.pcm";
206 const std::string DUMP_ENDPOINT_HDI_FILENAME = "dump_endpoint_hdi_audio.pcm";
207 const uint32_t PARAM_VALUE_LENTH = 150;
208 const std::string BETA_VERSION = "beta";
209
210 class DumpFileUtil {
211 public:
212 static void WriteDumpFile(FILE *dumpFile, void *buffer, size_t bufferSize);
213 static void CloseDumpFile(FILE **dumpFile);
214 static std::map<std::string, std::string> g_lastPara;
215 static void OpenDumpFile(std::string para, std::string fileName, FILE **file);
216 private:
217 static FILE *OpenDumpFileInner(std::string para, std::string fileName, AudioDumpFileType fileType);
218 static void ChangeDumpFileState(std::string para, FILE **dumpFile, std::string fileName);
219 };
220
221 template <typename...Args>
AppendFormat(std::string& out, const char* fmt, Args&& ... args)222 void AppendFormat(std::string& out, const char* fmt, Args&& ... args)
223 {
224 char buf[STRING_BUFFER_SIZE] = {0};
225 int len = ::sprintf_s(buf, sizeof(buf), fmt, args...);
226 if (len <= 0) {
227 return;
228 }
229 out += buf;
230 }
231
232 class AudioInfoDumpUtils {
233 public:
234 static const std::string GetStreamName(AudioStreamType streamType);
235 static const std::string GetDeviceTypeName(DeviceType deviceType);
236 static const std::string GetConnectTypeName(ConnectType connectType);
237 static const std::string GetSourceName(SourceType sourceType);
238 static const std::string GetDeviceVolumeTypeName(DeviceVolumeType deviceType);
239 };
240
241 template<typename T>
242 class ObjectRefMap {
243 public:
244 static std::mutex allObjLock;
245 static std::map<T*, uint32_t> refMap;
246 static void Insert(T *obj);
247 static void Erase(T *obj);
248 static T *IncreaseRef(T *obj);
249 static void DecreaseRef(T *obj);
250
251 ObjectRefMap(T *obj);
252 ~ObjectRefMap();
253 T *GetPtr();
254
255 private:
256 T *obj_ = nullptr;
257 };
258
259 template <typename T>
260 std::mutex ObjectRefMap<T>::allObjLock;
261
262 template <typename T>
263 std::map<T *, uint32_t> ObjectRefMap<T>::refMap;
264
265 template <typename T>
Insert(T *obj)266 void ObjectRefMap<T>::Insert(T *obj)
267 {
268 std::lock_guard<std::mutex> lock(allObjLock);
269 refMap[obj] = 1;
270 }
271
272 template <typename T>
Erase(T *obj)273 void ObjectRefMap<T>::Erase(T *obj)
274 {
275 std::lock_guard<std::mutex> lock(allObjLock);
276 auto it = refMap.find(obj);
277 if (it != refMap.end()) {
278 refMap.erase(it);
279 }
280 }
281
282 template <typename T>
IncreaseRef(T *obj)283 T *ObjectRefMap<T>::IncreaseRef(T *obj)
284 {
285 std::lock_guard<std::mutex> lock(allObjLock);
286 if (refMap.count(obj)) {
287 refMap[obj]++;
288 return obj;
289 } else {
290 return nullptr;
291 }
292 }
293
294 template <typename T>
DecreaseRef(T *obj)295 void ObjectRefMap<T>::DecreaseRef(T *obj)
296 {
297 std::lock_guard<std::mutex> lock(allObjLock);
298 if (refMap.count(obj) && --refMap[obj] == 0) {
299 refMap.erase(obj);
300 delete obj;
301 obj = nullptr;
302 }
303 }
304
305 template <typename T>
ObjectRefMap(T *obj)306 ObjectRefMap<T>::ObjectRefMap(T *obj)
307 {
308 if (obj != nullptr) {
309 obj_ = ObjectRefMap::IncreaseRef(obj);
310 }
311 }
312
313 template <typename T>
~ObjectRefMap()314 ObjectRefMap<T>::~ObjectRefMap()
315 {
316 if (obj_ != nullptr) {
317 ObjectRefMap::DecreaseRef(obj_);
318 }
319 }
320
321 template <typename T>
GetPtr()322 T *ObjectRefMap<T>::GetPtr()
323 {
324 return obj_;
325 }
326
327 std::string GetTime();
328
329 int32_t GetFormatByteSize(int32_t format);
330
331 struct SignalDetectAgent {
332 bool CheckAudioData(uint8_t *buffer, size_t bufferLen);
333 bool DetectSignalData(int32_t *buffer, size_t bufferLen);
334 void ResetDetectResult();
335 int32_t channels_ = STEREO;
336 int32_t sampleRate_ = SAMPLE_RATE_48000;
337 int32_t sampleFormat_ = SAMPLE_S16LE;
338 int32_t formatByteSize_;
339 int32_t lastPeakSignal_ = SHRT_MIN;
340 int32_t lastPeakSignalPos_ = 0;
341 int32_t blankPeriod_ = 0;
342 size_t frameCountIgnoreChannel_;
343 bool hasFirstNoneZero_ = false;
344 bool blankHaveOutput_ = true;
345 bool dspTimestampGot_ = false;
346 bool signalDetected_ = false;
347 std::string lastPeakBufferTime_ = "";
348 std::vector<int32_t> cacheAudioData_;
349 };
350
351 class AudioLatencyMeasurement {
352 public:
353 // static methods, invoked without instantiation in sinks and sources
354 static bool CheckIfEnabled();
355 AudioLatencyMeasurement(const int32_t &sampleRate, const int32_t &channelCount,
356 const int32_t &sampleFormat, const std::string &appName, const uint32_t &sessionId);
357 ~AudioLatencyMeasurement();
358
359 // non-static methods, invoked after instantiation in AudioRenderer and AudioCapturer
360 void InitSignalData();
361 bool MockPcmData(uint8_t *buffer, size_t bufferLen); // mute data and insert signal data
362 private:
363 int32_t format_ = SAMPLE_S16LE;
364 int32_t formatByteSize_;
365 int32_t sampleRate_;
366 int32_t channelCount_;
367 uint32_t sessionId_;
368 size_t mockedTime_ = 0;
369 bool mockThisStream_ = false;
370 std::string appName_;
371 std::unique_ptr<int16_t[]> signalData_ = nullptr;
372 };
373
374 class LatencyMonitor {
375 public:
376 static LatencyMonitor& GetInstance();
377 void ShowTimestamp(bool isRenderer);
378 void ShowBluetoothTimestamp();
379 void UpdateClientTime(bool isRenderer, std::string ×tamp);
380 void UpdateSinkOrSourceTime(bool isRenderer, std::string ×tamp);
381 void UpdateDspTime(std::string dspTime);
382 private:
383 std::string rendererMockTime_ = "";
384 std::string sinkDetectedTime_ = "";
385 std::string dspDetectedTime_ = "";
386 std::string capturerDetectedTime_ = "";
387 std::string sourceDetectedTime_ = "";
388 std::string dspBeforeSmartPa_ = "";
389 std::string dspAfterSmartPa_ = "";
390 std::string dspMockTime_ = "";
391 size_t extraStrLen_ = 0;
392 };
393
394 class AudioDump {
395 public:
396 static AudioDump& GetInstance();
397 void SetVersionType(const std::string& versionType);
398 std::string GetVersionType();
399 private:
AudioDump()400 AudioDump() {}
~AudioDump()401 ~AudioDump() {}
402 std::string versionType_ = "commercial";
403 };
404
405 template <typename EnumType, typename V>
GetKeyFromValue(const std::unordered_map<EnumType, V> &map, const V &value)406 int32_t GetKeyFromValue(const std::unordered_map<EnumType, V> &map, const V &value)
407 {
408 for (auto it : map) {
409 if (it.second == value) {
410 return it.first;
411 }
412 }
413 return -1;
414 }
415
416 template <typename T, typename Compare>
CasWithCompare(std::atomic<T> &atomicVar, T newValue, Compare compare)417 bool CasWithCompare(std::atomic<T> &atomicVar, T newValue, Compare compare)
418 {
419 T old = atomicVar;
420 do {
421 if (!compare(old, newValue)) {
422 return false;
423 }
424 } while (!atomicVar.compare_exchange_weak(old, newValue));
425
426 return true;
427 }
428
429 /**
430 * @brief Provides interfaces for thread-safe blocking queues.
431 *
432 * The interfaces can be used to perform blocking and non-blocking push and
433 * pop operations on queues.
434 */
435 template <typename T>
436 class AudioSafeBlockQueue {
437 public:
AudioSafeBlockQueue(int capacity)438 explicit AudioSafeBlockQueue(int capacity) : maxSize_(capacity)
439 {
440 }
441
442 /**
443 * @brief Inserts an element at the end of this queue in blocking mode.
444 *
445 * If the queue is full, the thread of the push operation will be blocked
446 * until the queue has space.
447 * If the queue is not full, the push operation can be performed and one of the
448 * pop threads (blocked when the queue is empty) is woken up.
449 *
450 * @param elem Indicates the element to insert.
451 */
Push(T const& elem)452 virtual void Push(T const& elem)
453 {
454 std::unique_lock<std::mutex> lock(mutexLock_);
455 while (queueT_.size() >= maxSize_) {
456 // If the queue is full, wait for jobs to be taken.
457 cvNotFull_.wait(lock, [&]() { return (queueT_.size() < maxSize_); });
458 }
459
460 // Insert the element into the queue if the queue is not full.
461 queueT_.push(elem);
462 cvNotEmpty_.notify_all();
463 }
464
465 /**
466 * @brief Removes the first element from this queue in blocking mode.
467 *
468 * If the queue is empty, the thread of the pop operation will be blocked
469 * until the queue has elements.
470 * If the queue is not empty, the pop operation can be performed, the first
471 * element of the queue is returned, and one of the push threads (blocked
472 * when the queue is full) is woken up.
473 */
Pop()474 T Pop()
475 {
476 std::unique_lock<std::mutex> lock(mutexLock_);
477
478 while (queueT_.empty()) {
479 // If the queue is empty, wait for elements to be pushed in.
480 cvNotEmpty_.wait(lock, [&] { return !queueT_.empty(); });
481 }
482
483 T elem = queueT_.front();
484 queueT_.pop();
485 cvNotFull_.notify_all();
486 return elem;
487 }
488
489 /**
490 * @brief Inserts an element at the end of this queue in non-blocking mode.
491 *
492 * If the queue is full, <b>false</b> is returned directly.
493 * If the queue is not full, the push operation can be performed, one of the
494 * pop threads (blocked when the queue is empty) is woken up, and <b>true</b>
495 * is returned.
496 *
497 * @param elem Indicates the element to insert.
498 */
PushNoWait(T const& elem)499 virtual bool PushNoWait(T const& elem)
500 {
501 std::unique_lock<std::mutex> lock(mutexLock_);
502 if (queueT_.size() >= maxSize_) {
503 return false;
504 }
505 // Insert the element if the queue is not full.
506 queueT_.push(elem);
507 cvNotEmpty_.notify_all();
508 return true;
509 }
510
511 /**
512 * @brief Removes the first element from this queue in non-blocking mode.
513 *
514 * If the queue is empty, <b>false</b> is returned directly.
515 * If the queue is not empty, the pop operation can be performed, one of the
516 * push threads (blocked when the queue is full) is woken up, and <b>true</b>
517 * is returned.
518 *
519 * @param outtask Indicates the data of the pop operation.
520 */
PopNotWait(T& outtask)521 bool PopNotWait(T& outtask)
522 {
523 std::unique_lock<std::mutex> lock(mutexLock_);
524 if (queueT_.empty()) {
525 return false;
526 }
527 outtask = queueT_.front();
528 queueT_.pop();
529
530 cvNotFull_.notify_all();
531
532 return true;
533 }
534
PopAllNotWait()535 std::queue<T> PopAllNotWait()
536 {
537 std::queue<T> retQueue = {};
538 std::unique_lock<std::mutex> lock(mutexLock_);
539 retQueue.swap(queueT_);
540
541 cvNotFull_.notify_all();
542
543 return retQueue;
544 }
545
Size()546 unsigned int Size()
547 {
548 std::unique_lock<std::mutex> lock(mutexLock_);
549 return queueT_.size();
550 }
551
552 template< class Rep, class Period >
WaitNotEmptyFor(const std::chrono::duration<Rep, Period>& rel_time)553 void WaitNotEmptyFor(const std::chrono::duration<Rep, Period>& rel_time)
554 {
555 std::unique_lock<std::mutex> lock(mutexLock_);
556 cvNotEmpty_.wait_for(lock, rel_time, [this] {
557 return !queueT_.empty();
558 });
559 }
560
IsEmpty()561 bool IsEmpty()
562 {
563 std::unique_lock<std::mutex> lock(mutexLock_);
564 return queueT_.empty();
565 }
566
IsFull()567 bool IsFull()
568 {
569 std::unique_lock<std::mutex> lock(mutexLock_);
570 return queueT_.size() == maxSize_;
571 }
572
Clear()573 void Clear()
574 {
575 std::unique_lock<std::mutex> lock(mutexLock_);
576 queueT_ = {};
577 cvNotFull_.notify_all();
578 }
579
~AudioSafeBlockQueue()580 virtual ~AudioSafeBlockQueue() {}
581
582 protected:
583 unsigned long maxSize_; // Capacity of the queue
584 std::mutex mutexLock_;
585 std::condition_variable cvNotEmpty_;
586 std::condition_variable cvNotFull_;
587 std::queue<T> queueT_;
588 };
589
590 enum AudioHdiUniqueIDBase : uint32_t {
591 // 0-4 is reserved for other modules
592 AUDIO_HDI_RENDER_ID_BASE = 5,
593 AUDIO_HDI_CAPTURE_ID_BASE = 6,
594 };
595
596 enum HdiCaptureOffset : uint32_t {
597 HDI_CAPTURE_OFFSET_PRIMARY = 1,
598 HDI_CAPTURE_OFFSET_FAST = 2,
599 HDI_CAPTURE_OFFSET_REMOTE = 3,
600 HDI_CAPTURE_OFFSET_REMOTE_FAST = 4,
601 HDI_CAPTURE_OFFSET_USB = 5,
602 HDI_CAPTURE_OFFSET_EC = 6,
603 HDI_CAPTURE_OFFSET_MIC_REF = 7,
604 HDI_CAPTURE_OFFSET_WAKEUP = 8,
605 };
606
607 enum HdiRenderOffset : uint32_t {
608 HDI_RENDER_OFFSET_PRIMARY = 1,
609 HDI_RENDER_OFFSET_FAST = 2,
610 HDI_RENDER_OFFSET_REMOTE = 3,
611 HDI_RENDER_OFFSET_REMOTE_FAST = 4,
612 HDI_RENDER_OFFSET_BLUETOOTH = 5,
613 HDI_RENDER_OFFSET_OFFLOAD = 6,
614 HDI_RENDER_OFFSET_MULTICHANNEL = 7,
615 HDI_RENDER_OFFSET_DIRECT = 8,
616 HDI_RENDER_OFFSET_VOIP = 9,
617 HDI_RENDER_OFFSET_DP = 10,
618 HDI_RENDER_OFFSET_USB = 11,
619 HDI_RENDER_OFFSET_VOIP_FAST = 12,
620 };
621
622 uint32_t GenerateUniqueID(AudioHdiUniqueIDBase base, uint32_t offset);
623
624 } // namespace AudioStandard
625 } // namespace OHOS
626 #endif // AUDIO_UTILS_H
627