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