1 /* 2 * Copyright (c) 2025 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 #ifndef HPAE_PCM_BUFFER_H 17 #define HPAE_PCM_BUFFER_H 18 #include <vector> 19 #include <type_traits> 20 #include <memory> 21 #include <algorithm> 22 #include "hpae_pcm_process.h" 23 namespace OHOS { 24 namespace AudioStandard { 25 namespace HPAE { 26 constexpr size_t MEMORY_ALIGN_BYTE_NUM = 64; 27 28 enum HpaeSourceBufferType { 29 HPAE_SOURCE_BUFFER_TYPE_DEFAULT, 30 HPAE_SOURCE_BUFFER_TYPE_MIC, 31 HPAE_SOURCE_BUFFER_TYPE_EC, 32 HPAE_SOURCE_BUFFER_TYPE_MICREF, 33 }; 34 35 enum HpaeSplitStreamType { 36 STREAM_TYPE_DEFAULT = 0, 37 STREAM_TYPE_MEDIA = 1, 38 STREAM_TYPE_COMMUNICATION = 2, 39 STREAM_TYPE_NAVIGATION = 13 40 }; 41 42 enum PcmBufferState : uint32_t { 43 PCM_BUFFER_STATE_INVALID = 1, // bit 0 44 PCM_BUFFER_STATE_SILENCE = 2, // bit 1 45 }; 46 47 // redefine allocator to ensure memory alignment 48 template <typename T, size_t Alignment> 49 class AlignedAllocator : public std::allocator<T> { 50 public: 51 using pointer = T *; 52 using size_type = size_t; 53 Allocate(size_type n)54 pointer Allocate(size_type n) 55 { 56 void *ptr = std::aligned_alloc(Alignment, n * sizeof(T)); 57 return static_cast<pointer>(ptr); 58 } 59 DeAllocate(pointer p,size_type n)60 void DeAllocate(pointer p, size_type n) 61 { 62 std::free(p); 63 } 64 }; 65 66 struct PcmBufferInfo { PcmBufferInfoPcmBufferInfo67 PcmBufferInfo(uint32_t ch1, uint32_t frameLen1, uint32_t rate1) 68 : ch(ch1), frameLen(frameLen1), rate(rate1) 69 {} PcmBufferInfoPcmBufferInfo70 PcmBufferInfo(uint32_t ch1, uint32_t frameLen1, uint32_t rate1, uint64_t channelLayout1) 71 : ch(ch1), frameLen(frameLen1), rate(rate1), channelLayout(channelLayout1) 72 {} PcmBufferInfoPcmBufferInfo73 PcmBufferInfo(uint32_t ch1, uint32_t frameLen1, uint32_t rate1, uint64_t channelLayout1, 74 uint32_t frames1) 75 : ch(ch1), frameLen(frameLen1), rate(rate1), channelLayout(channelLayout1), frames(frames1) 76 {} 77 PcmBufferInfo() = default; 78 uint32_t ch; 79 uint32_t frameLen; 80 uint32_t rate; 81 uint64_t channelLayout = 0; 82 uint32_t frames = 1; 83 bool isMultiFrames = false; 84 uint32_t state = 0; 85 }; 86 87 // todo: multithread access? 88 class HpaePcmBuffer { 89 public: 90 HpaePcmBuffer() = delete; 91 explicit HpaePcmBuffer(PcmBufferInfo &pcmBufferInfo); 92 HpaePcmBuffer(HpaePcmBuffer &&other); 93 HpaePcmBuffer(const HpaePcmBuffer &other) = delete; ~HpaePcmBuffer()94 ~HpaePcmBuffer() 95 { 96 } 97 HpaePcmBuffer &operator=(HpaePcmBuffer &other); 98 HpaePcmBuffer &operator=(HpaePcmBuffer &&other) = delete; 99 GetPcmBufferInfo()100 PcmBufferInfo GetPcmBufferInfo() const 101 { 102 return pcmBufferInfo_; 103 } 104 GetChannelCount()105 uint32_t GetChannelCount() const 106 { 107 return pcmBufferInfo_.ch; 108 } 109 GetFrameLen()110 uint32_t GetFrameLen() const 111 { 112 return pcmBufferInfo_.frameLen; 113 } 114 GetSampleRate()115 uint32_t GetSampleRate() const 116 { 117 return pcmBufferInfo_.rate; 118 } 119 IsMultiFrames()120 bool IsMultiFrames() const 121 { 122 return pcmBufferInfo_.isMultiFrames; 123 } 124 IsValid()125 bool IsValid() const 126 { 127 return (pcmBufferInfo_.state & PCM_BUFFER_STATE_INVALID) != PCM_BUFFER_STATE_INVALID; 128 } 129 IsSilence()130 bool IsSilence() const 131 { 132 return (pcmBufferInfo_.state & PCM_BUFFER_STATE_SILENCE) == PCM_BUFFER_STATE_SILENCE; 133 } 134 GetBufferState()135 uint32_t GetBufferState() const 136 { 137 return pcmBufferInfo_.state; 138 } 139 GetChannelLayout()140 uint64_t GetChannelLayout() const 141 { 142 return pcmBufferInfo_.channelLayout; 143 } 144 ReConfig(const PcmBufferInfo & pcmBufferInfo)145 void ReConfig(const PcmBufferInfo &pcmBufferInfo) 146 { 147 pcmBufferInfo_ = pcmBufferInfo; 148 InitPcmProcess(); 149 } 150 151 bool GetFrameData(std::vector<float> &frameData); 152 bool GetFrameData(HpaePcmBuffer &frameData); 153 bool PushFrameData(std::vector<float> &frameData); 154 bool PushFrameData(HpaePcmBuffer &frameData); 155 // store history frame for offload 156 bool StoreFrameData(HpaePcmBuffer &frameData); 157 // rewind history frame for offload, return frames that rewinded 158 size_t RewindBuffer(size_t frames); 159 160 HpaePcmProcess &operator[](size_t index) 161 { 162 return pcmProcessVec_[index]; 163 } 164 165 const HpaePcmProcess &operator[](size_t index) const 166 { 167 return pcmProcessVec_[index]; 168 } 169 Size()170 size_t Size() const 171 { 172 return bufferByteSize_; 173 } 174 DataSize()175 size_t DataSize() const 176 { 177 return dataByteSize_; 178 } 179 GetFrames()180 size_t GetFrames() const 181 { 182 return pcmBufferInfo_.frames; 183 } 184 GetReadPos()185 size_t GetReadPos() const 186 { 187 return readPos_.load(); 188 } 189 GetWritePos()190 size_t GetWritePos() const 191 { 192 return writePos_.load(); 193 } 194 195 bool UpdateReadPos(size_t readPos); 196 bool UpdateWritePos(size_t writePos); 197 void SetBufferValid(bool valid); 198 void SetBufferSilence(bool silence); 199 void SetBufferState(uint32_t state); 200 size_t GetCurFrames() const; 201 202 HpaePcmBuffer &operator=(const std::vector<std::vector<float>> &other); 203 HpaePcmBuffer &operator=(const std::vector<float> &other); 204 205 HpaePcmBuffer &operator+=(HpaePcmBuffer &other); 206 HpaePcmBuffer &operator-=(HpaePcmBuffer &other); 207 HpaePcmBuffer &operator*=(HpaePcmBuffer &other); 208 void Reset(); 209 begin()210 std::vector<HpaePcmProcess>::iterator begin() 211 { 212 return pcmProcessVec_.begin(); 213 } 214 end()215 std::vector<HpaePcmProcess>::iterator end() 216 { 217 return pcmProcessVec_.end(); 218 } 219 begin()220 std::vector<HpaePcmProcess>::const_iterator begin() const 221 { 222 return pcmProcessVec_.begin(); 223 } 224 end()225 std::vector<HpaePcmProcess>::const_iterator end() const 226 { 227 return pcmProcessVec_.end(); 228 } 229 GetPcmDataBuffer()230 float *GetPcmDataBuffer() 231 { 232 return pcmDataBuffer_.data(); 233 } 234 GetFrameSample()235 size_t GetFrameSample() 236 { 237 return frameSample_; 238 } 239 GetSourceBufferType()240 HpaeSourceBufferType GetSourceBufferType() 241 { 242 return sourceBufferType_; 243 } 244 SetSourceBufferType(HpaeSourceBufferType type)245 void SetSourceBufferType(HpaeSourceBufferType type) 246 { 247 sourceBufferType_ = type; 248 } 249 GetSplitStreamType()250 HpaeSplitStreamType GetSplitStreamType() 251 { 252 return splitStreamType_; 253 } 254 SetSplitStreamType(HpaeSplitStreamType type)255 void SetSplitStreamType(HpaeSplitStreamType type) 256 { 257 splitStreamType_ = type; 258 } 259 260 private: 261 void InitPcmProcess(); 262 263 // todo: add err to deal with operator override 264 std::vector<float, AlignedAllocator<float, MEMORY_ALIGN_BYTE_NUM>> pcmDataBuffer_; 265 size_t bufferFloatSize_; 266 size_t bufferByteSize_; 267 size_t frameFloatSize_; 268 size_t frameByteSize_; 269 size_t frameSample_; 270 size_t dataByteSize_; 271 std::atomic<size_t> readPos_; 272 std::atomic<size_t> writePos_; 273 std::atomic<size_t> curFrames_; 274 std::vector<HpaePcmProcess> pcmProcessVec_; 275 PcmBufferInfo pcmBufferInfo_; 276 HpaeSourceBufferType sourceBufferType_ = HPAE_SOURCE_BUFFER_TYPE_DEFAULT; 277 HpaeSplitStreamType splitStreamType_ = STREAM_TYPE_DEFAULT; 278 }; 279 } // namespace HPAE 280 } // namespace AudioStandard 281 } // namespace OHOS 282 #endif