1 // RawBuffer.cpp 2 // e.moon 31mar99 3 4 #include "RawBuffer.h" 5 6 #include <RealtimeAlloc.h> 7 #include <Debug.h> 8 #include <cstring> 9 10 // -------------------------------------------------------- // 11 // ctor/dtor/accessors 12 // -------------------------------------------------------- // 13 14 // allocate buffer (if frames > 0) 15 RawBuffer::RawBuffer( 16 uint32 frameSize, 17 uint32 frames, 18 bool bCircular, 19 rtm_pool* pFromPool) : 20 21 m_pData(0), 22 m_allocatedSize(0), 23 m_frameSize(frameSize), 24 m_frames(frames), 25 m_bCircular(bCircular), 26 m_bOwnData(true), 27 m_pPool(pFromPool) { 28 29 if(m_frames) 30 resize(m_frames); 31 } 32 33 // point to given data (does NOT take responsibility for 34 // deleting it; use adopt() for that.) 35 RawBuffer::RawBuffer( 36 void* pData, 37 uint32 frameSize, 38 uint32 frames, 39 bool bCircular, 40 rtm_pool* pFromPool) : 41 42 m_pData(pData), 43 m_allocatedSize(0), 44 m_frameSize(frameSize), 45 m_frames(frames), 46 m_bOwnData(false), 47 m_bCircular(bCircular), 48 m_pPool(pFromPool) {} 49 50 RawBuffer::RawBuffer(const RawBuffer& clone) { 51 operator=(clone); 52 } 53 54 // generate a reference to the buffer 55 RawBuffer& RawBuffer::operator=(const RawBuffer& clone) { 56 m_pData = clone.m_pData; 57 m_allocatedSize = clone.m_allocatedSize; 58 m_frameSize = clone.m_frameSize; 59 m_frames = clone.m_frames; 60 m_bCircular = clone.m_bCircular; 61 m_pPool = clone.m_pPool; 62 m_bOwnData = false; 63 64 return *this; 65 } 66 67 // deallocate if I own the data 68 RawBuffer::~RawBuffer() { 69 free(); 70 } 71 72 char* RawBuffer::data() const { return (char*)m_pData; } 73 // returns pointer to given frame 74 char* RawBuffer::frame(uint32 frame) const { 75 return data() + (frame * frameSize()); 76 } 77 uint32 RawBuffer::frameSize() const { return m_frameSize; } 78 uint32 RawBuffer::frames() const { return m_frames; } 79 uint32 RawBuffer::size() const { return m_frames * m_frameSize; } 80 81 bool RawBuffer::isCircular() const { return m_bCircular; } 82 bool RawBuffer::ownsBuffer() const { return m_bOwnData; } 83 84 rtm_pool* RawBuffer::pool() const { return m_pPool; } 85 86 // resize buffer, re-allocating if necessary to contain 87 // designated number of frames. 88 // Does not preserve buffer contents. 89 90 void RawBuffer::resize(uint32 frames) { 91 uint32 sizeRequired = frames * m_frameSize; 92 93 // already have enough storage? 94 if(sizeRequired < m_allocatedSize && 95 m_bOwnData) { 96 m_frames = frames; 97 return; 98 } 99 100 // free existing storage 101 free(); 102 103 // allocate 104 m_pData = (m_pPool) ? 105 rtm_alloc(m_pPool, sizeRequired) : 106 new int8[sizeRequired]; 107 108 m_bOwnData = true; 109 m_allocatedSize = sizeRequired; 110 m_frames = frames; 111 112 } 113 114 // take ownership of buffer from target 115 // (deletes current buffer data, if any owned) 116 117 void RawBuffer::adopt( 118 void* pData, 119 uint32 frameSize, 120 uint32 frames, 121 bool bCircular, 122 rtm_pool* pPool) { 123 124 // clean up myself first 125 free(); 126 127 // reference 128 operator=(RawBuffer(pData, frameSize, frames, bCircular, pPool)); 129 130 // mark ownership 131 m_bOwnData = true; 132 } 133 134 // returns false if the target doesn't own the data, but references it 135 // one way or the other 136 137 bool RawBuffer::adopt(RawBuffer& target) { 138 139 // reference 140 operator=(target); 141 142 // take ownership if possible 143 144 if(!target.m_bOwnData) { 145 m_bOwnData = false; 146 return false; 147 } 148 149 target.m_bOwnData = false; 150 m_bOwnData = true; 151 return true; 152 } 153 154 // adopt currently ref'd data (if any; returns false if no buffer data or 155 // already owned) 156 157 bool RawBuffer::adopt() { 158 if(!m_pData || m_bOwnData) 159 return false; 160 161 m_bOwnData = true; 162 return true; 163 } 164 165 // -------------------------------------------------------- // 166 // operations 167 // -------------------------------------------------------- // 168 169 // fill the buffer with zeroes 170 171 void RawBuffer::zero() { 172 if(!m_pData || !m_frames) 173 return; 174 175 memset(m_pData, 0, m_frames * m_frameSize); 176 } 177 178 // raw copy to destination buffer, returning the number of 179 // frames written, and adjusting both offsets accordingly. 180 // 181 // no frames will be written if the buffers' frame sizes 182 // differ. 183 184 uint32 RawBuffer::rawCopyTo( 185 RawBuffer& target, 186 uint32* pioFromFrame, 187 uint32* pioTargetFrame, 188 uint32 frames) const { 189 190 if(m_frameSize != target.m_frameSize) 191 return 0; 192 193 ASSERT(m_pData); 194 ASSERT(m_frames); 195 ASSERT(target.m_pData); 196 197 // convert frame counts to byte offsets 198 uint32 fromOffset = *pioFromFrame * m_frameSize; 199 uint32 targetOffset = *pioTargetFrame * m_frameSize; 200 201 // figure buffer sizes in bytes 202 uint32 size = m_frames * m_frameSize; 203 uint32 targetSize = target.m_frames * target.m_frameSize; 204 205 // figure amount to write 206 uint32 toCopy = frames * m_frameSize; 207 if(target.m_bCircular) { 208 if(toCopy > targetSize) 209 toCopy = targetSize; 210 } else { 211 if(toCopy > (targetSize-targetOffset)) 212 toCopy = (targetSize-targetOffset); 213 } 214 uint32 remaining = toCopy; 215 216 // do it 217 while(remaining) { 218 219 // figure a contiguous area to fill 220 uint32 targetChunk = targetSize - targetOffset; 221 222 if(targetChunk > remaining) 223 targetChunk = remaining; 224 225 // fill it (from one or more source areas) 226 while(targetChunk > 0) { 227 228 // figure a contiguous source area 229 uint32 sourceChunk = size - fromOffset; 230 if(sourceChunk > targetChunk) 231 sourceChunk = targetChunk; 232 233 // copy it 234 memcpy( 235 (int8*)target.m_pData + targetOffset, 236 (int8*)m_pData + fromOffset, 237 sourceChunk); 238 239 // advance offsets 240 targetOffset += sourceChunk; 241 if(targetOffset == targetSize) 242 targetOffset = 0; 243 244 fromOffset += sourceChunk; 245 if(fromOffset == size) 246 fromOffset = 0; 247 248 // figure remaining portion of target area to fill 249 targetChunk -= sourceChunk; 250 remaining -= sourceChunk; 251 } 252 } 253 254 // write new offsets 255 *pioFromFrame = fromOffset / m_frameSize; 256 *pioTargetFrame = targetOffset / m_frameSize; 257 258 return toCopy; 259 } 260 261 // more convenient version of above if you don't care 262 // how the offsets change. 263 264 uint32 RawBuffer::rawCopyTo( 265 RawBuffer& target, 266 uint32 fromOffset, 267 uint32 targetOffset, 268 uint32 frames) const { 269 270 return rawCopyTo(target, &fromOffset, &targetOffset, frames); 271 } 272 273 // -------------------------------------------------------- // 274 // internal operations 275 // -------------------------------------------------------- // 276 277 // free owned data, if any 278 // [16jun99] uses proper rtm_free() call if needed 279 void RawBuffer::free() { 280 if(!(m_bOwnData && m_pData)) 281 return; 282 283 if(m_pPool) 284 rtm_free(m_pData); 285 else 286 delete [] m_pData; 287 288 m_pData = 0; 289 } 290 291 292 // END -- RawBuffer.cpp --