• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
34 #define AUDIO_MS_PER_SECOND 1000
35 #define AUDIO_US_PER_SECOND 1000000
36 #define AUDIO_NS_PER_SECOND ((uint64_t)1000000000)
37 
38 #define FLOAT_EPS 1e-9f
39 #define OFFSET_BIT_24 3
40 #define BIT_DEPTH_TWO 2
41 #define BIT_8 8
42 #define BIT_16 16
43 #define BIT_24 24
44 #define BIT_32 32
45 namespace OHOS {
46 namespace AudioStandard {
47 const int64_t PCM_MAYBE_SILENT = 1;
48 const int64_t PCM_MAYBE_NOT_SILENT = 5;
49 const int32_t SIGNAL_DATA_SIZE = 96;
50 const int32_t SIGNAL_THRESHOLD = 10;
51 const int32_t BLANK_THRESHOLD_MS = 100;
52 const int32_t DETECTED_ZERO_THRESHOLD = 1;
53 const size_t MILLISECOND_PER_SECOND = 1000;
54 const size_t MOCK_INTERVAL = 2000;
55 const int32_t GET_EXTRA_PARAM_LEN = 200;
56 const int32_t YEAR_BASE = 1900;
57 const int32_t DECIMAL_EXPONENT = 10;
58 const size_t DATE_LENGTH = 17;
59 static uint32_t g_sessionToMock = 0;
60 const uint32_t MAX_VALUE_OF_SIGNED_24_BIT = 8388607;
61 const uint32_t STRING_BUFFER_SIZE = 4096;
62 
63 // Ringer or alarmer dual tone
64 const size_t AUDIO_CONCURRENT_ACTIVE_DEVICES_LIMIT = 2;
65 
66 /* Define AudioXcollie timeout flag, consistent with xcollie_define.h in hiviewdfx  */
67 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_DEFAULT = (~0); // do all callback function
68 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_NOOP = (0); // do nothing but the caller defined function
69 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_LOG = (1 << 0); // generate log file
70 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_RECOVERY = (1 << 1); // die when timeout
71 
72 class Util {
73 public:
74     static bool IsDualToneStreamType(const AudioStreamType streamType);
75 
76     static bool IsRingerOrAlarmerStreamUsage(const StreamUsage &usage);
77 
78     static bool IsRingerAudioScene(const AudioScene &audioScene);
79 
80     static uint32_t GetSamplePerFrame(const AudioSampleFormat &format);
81 };
82 
83 class Trace {
84 public:
85     static void Count(const std::string &value, int64_t count);
86     // Show if data is silent.
87     static void CountVolume(const std::string &value, uint8_t data);
88     Trace(const std::string &value);
89     void End();
90     ~Trace();
91 private:
92     std::string value_;
93     bool isFinished_;
94 };
95 
96 class AudioXCollie {
97 public:
98     AudioXCollie(const std::string &tag, uint32_t timeoutSeconds,
99         std::function<void(void *)> func = nullptr, void *arg = nullptr, uint32_t flag = 1);
100     ~AudioXCollie();
101     void CancelXCollieTimer();
102 private:
103     int32_t id_;
104     std::string tag_;
105     bool isCanceled_;
106 };
107 
108 class ClockTime {
109 public:
110     static int64_t GetCurNano();
111     static int32_t AbsoluteSleep(int64_t nanoTime);
112     static int32_t RelativeSleep(int64_t nanoTime);
113 };
114 
115 class PermissionUtil {
116 public:
117     static bool VerifyIsAudio();
118     static bool VerifyIsShell();
119     static bool VerifyIsSystemApp();
120     static bool VerifySelfPermission();
121     static bool VerifySystemPermission();
122     static bool VerifyPermission(const std::string &permissionName, uint32_t tokenId);
123     static bool NeedVerifyBackgroundCapture(int32_t callingUid, SourceType sourceType);
124     static bool VerifyBackgroundCapture(uint32_t tokenId, uint64_t fullTokenId);
125     static bool NotifyStart(uint32_t targetTokenId, uint32_t sessionId);
126     static bool NotifyStop(uint32_t targetTokenId, uint32_t sessionId);
127 };
128 
129 void AdjustStereoToMonoForPCM8Bit(int8_t *data, uint64_t len);
130 void AdjustStereoToMonoForPCM16Bit(int16_t *data, uint64_t len);
131 void AdjustStereoToMonoForPCM24Bit(int8_t *data, uint64_t len);
132 void AdjustStereoToMonoForPCM32Bit(int32_t *data, uint64_t len);
133 void AdjustAudioBalanceForPCM8Bit(int8_t *data, uint64_t len, float left, float right);
134 void AdjustAudioBalanceForPCM16Bit(int16_t *data, uint64_t len, float left, float right);
135 void AdjustAudioBalanceForPCM24Bit(int8_t *data, uint64_t len, float left, float right);
136 void AdjustAudioBalanceForPCM32Bit(int32_t *data, uint64_t len, float left, float right);
137 
138 void ConvertFrom24BitToFloat(unsigned n, const uint8_t *a, float *b);
139 void ConvertFrom32BitToFloat(unsigned n, const int32_t *a, float *b);
140 void ConvertFromFloatTo24Bit(unsigned n, const float *a, uint8_t *b);
141 void ConvertFromFloatTo32Bit(unsigned n, const float *a, int32_t *b);
142 
143 std::string GetEncryptStr(const std::string &str);
144 std::string ConvertNetworkId(const std::string &networkId);
145 
146 enum ConvertHdiFormat {
147     SAMPLE_U8_C = 0,
148     SAMPLE_S16_C = 1,
149     SAMPLE_S24_C = 2,
150     SAMPLE_S32_C = 3,
151     SAMPLE_F32_C = 4,
152     INVALID_WIDTH_C = -1
153 }; // same with HdiAdapterFormat
154 
155 float UpdateMaxAmplitude(ConvertHdiFormat adapterFormat, char *frame, uint64_t replyBytes);
156 float CalculateMaxAmplitudeForPCM8Bit(int8_t *frame, uint64_t nSamples);
157 float CalculateMaxAmplitudeForPCM16Bit(int16_t *frame, uint64_t nSamples);
158 float CalculateMaxAmplitudeForPCM24Bit(char *frame, uint64_t nSamples);
159 float CalculateMaxAmplitudeForPCM32Bit(int32_t *frame, uint64_t nSamples);
160 
161 template <typename T>
162 bool isEqual(T a, T b, double precision = 0.01)
163 {
164     return std::abs(a - b) < precision;
165 }
166 
167 // return true if value is not in the array.
168 template <typename V>
NotContain(const std::vector<V> & array,const V & value)169 inline bool NotContain(const std::vector<V> &array, const V &value)
170 {
171     return std::find(array.begin(), array.end(), value) == array.end();
172 }
173 
174 template <typename T>
175 bool GetSysPara(const char *key, T &value);
176 
177 enum AudioDumpFileType {
178     AUDIO_APP = 0,
179     OTHER_NATIVE_SERVICE = 1,
180     AUDIO_PULSE = 2,
181 };
182 
183 const std::string DUMP_SERVER_PARA = "sys.audio.dump.writeserver.enable";
184 const std::string DUMP_CLIENT_PARA = "sys.audio.dump.writeclient.enable";
185 const std::string DUMP_PULSE_DIR = "/data/data/.pulse_dir/";
186 const std::string DUMP_SERVICE_DIR = "/data/local/tmp/";
187 const std::string DUMP_APP_DIR = "/data/storage/el2/base/cache/";
188 const std::string DUMP_BLUETOOTH_RENDER_SINK_FILENAME = "dump_bluetooth_audiosink.pcm";
189 const std::string DUMP_RENDER_SINK_FILENAME = "dump_audiosink.pcm";
190 const std::string DUMP_MCH_SINK_FILENAME = "dump_mchaudiosink.pcm";
191 const std::string DUMP_DIRECT_RENDER_SINK_FILENAME = "dump_direct_audiosink.pcm";
192 const std::string DUMP_OFFLOAD_RENDER_SINK_FILENAME = "dump_offloadaudiosink.pcm";
193 const std::string DUMP_CAPTURER_SOURCE_FILENAME = "dump_capture_audiosource.pcm";
194 const std::string DUMP_TONEPLAYER_FILENAME = "dump_toneplayer_audio.pcm";
195 const std::string DUMP_PROCESS_IN_CLIENT_FILENAME = "dump_process_client_audio.pcm";
196 const std::string DUMP_REMOTE_RENDER_SINK_FILENAME = "dump_remote_audiosink";
197 const std::string DUMP_REMOTE_CAPTURE_SOURCE_FILENAME = "dump_remote_capture_audiosource.pcm";
198 const uint32_t PARAM_VALUE_LENTH = 150;
199 const std::string BETA_VERSION = "beta";
200 
201 class DumpFileUtil {
202 public:
203     static void WriteDumpFile(FILE *dumpFile, void *buffer, size_t bufferSize);
204     static void CloseDumpFile(FILE **dumpFile);
205     static std::map<std::string, std::string> g_lastPara;
206     static void OpenDumpFile(std::string para, std::string fileName, FILE **file);
207 private:
208     static FILE *OpenDumpFileInner(std::string para, std::string fileName, AudioDumpFileType fileType);
209     static void ChangeDumpFileState(std::string para, FILE **dumpFile, std::string fileName);
210 };
211 
212 template <typename...Args>
AppendFormat(std::string & out,const char * fmt,Args &&...args)213 void AppendFormat(std::string& out, const char* fmt, Args&& ... args)
214 {
215     char buf[STRING_BUFFER_SIZE] = {0};
216     int len = ::sprintf_s(buf, sizeof(buf), fmt, args...);
217     if (len <= 0) {
218         return;
219     }
220     out += buf;
221 }
222 
223 class AudioInfoDumpUtils {
224 public:
225     static const std::string GetStreamName(AudioStreamType streamType);
226     static const std::string GetDeviceTypeName(DeviceType deviceType);
227     static const std::string GetConnectTypeName(ConnectType connectType);
228     static const std::string GetSourceName(SourceType sourceType);
229     static const std::string GetDeviceVolumeTypeName(DeviceVolumeType deviceType);
230 };
231 
232 class VolumeUtils {
233 public:
234     static AudioVolumeType GetVolumeTypeFromStreamType(AudioStreamType streamType);
235 
236 private:
237     static std::unordered_map<AudioStreamType, AudioVolumeType> defaultVolumeMap_;
238     static std::unordered_map<AudioStreamType, AudioVolumeType>& GetVolumeMap();
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 &timestamp);
380     void UpdateSinkOrSourceTime(bool isRenderer, std::string &timestamp);
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 } // namespace AudioStandard
624 } // namespace OHOS
625 #endif // AUDIO_UTILS_H
626