1 /* 2 * Copyright (c) 1999-2000, Eric Moon. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions, and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32 // RawBuffer.cpp 33 // e.moon 31mar99 34 35 #include "RawBuffer.h" 36 37 #include <RealtimeAlloc.h> 38 #include <Debug.h> 39 #include <cstring> 40 41 // -------------------------------------------------------- // 42 // ctor/dtor/accessors 43 // -------------------------------------------------------- // 44 45 // allocate buffer (if frames > 0) 46 RawBuffer::RawBuffer( 47 uint32 frameSize, 48 uint32 frames, 49 bool bCircular, 50 rtm_pool* pFromPool) : 51 52 m_pData(0), 53 m_pPool(pFromPool), 54 m_frameSize(frameSize), 55 m_frames(frames), 56 m_allocatedSize(0), 57 m_bCircular(bCircular), 58 m_bOwnData(true) 59 { 60 61 if(m_frames) 62 resize(m_frames); 63 } 64 65 // point to given data (does NOT take responsibility for 66 // deleting it; use adopt() for that.) 67 RawBuffer::RawBuffer( 68 void* pData, 69 uint32 frameSize, 70 uint32 frames, 71 bool bCircular, 72 rtm_pool* pFromPool) : 73 74 m_pData(pData), 75 m_pPool(pFromPool), 76 m_frameSize(frameSize), 77 m_frames(frames), 78 m_allocatedSize(0), 79 m_bCircular(bCircular), 80 m_bOwnData(false) 81 {} 82 83 RawBuffer::RawBuffer(const RawBuffer& clone) { 84 operator=(clone); 85 } 86 87 // generate a reference to the buffer 88 RawBuffer& RawBuffer::operator=(const RawBuffer& clone) { 89 m_pData = clone.m_pData; 90 m_allocatedSize = clone.m_allocatedSize; 91 m_frameSize = clone.m_frameSize; 92 m_frames = clone.m_frames; 93 m_bCircular = clone.m_bCircular; 94 m_pPool = clone.m_pPool; 95 m_bOwnData = false; 96 97 return *this; 98 } 99 100 // deallocate if I own the data 101 RawBuffer::~RawBuffer() { 102 free(); 103 } 104 105 char* RawBuffer::data() const { return (char*)m_pData; } 106 // returns pointer to given frame 107 char* RawBuffer::frame(uint32 frame) const { 108 return data() + (frame * frameSize()); 109 } 110 uint32 RawBuffer::frameSize() const { return m_frameSize; } 111 uint32 RawBuffer::frames() const { return m_frames; } 112 uint32 RawBuffer::size() const { return m_frames * m_frameSize; } 113 114 bool RawBuffer::isCircular() const { return m_bCircular; } 115 bool RawBuffer::ownsBuffer() const { return m_bOwnData; } 116 117 rtm_pool* RawBuffer::pool() const { return m_pPool; } 118 119 // resize buffer, re-allocating if necessary to contain 120 // designated number of frames. 121 // Does not preserve buffer contents. 122 123 void RawBuffer::resize(uint32 frames) { 124 uint32 sizeRequired = frames * m_frameSize; 125 126 // already have enough storage? 127 if(sizeRequired < m_allocatedSize && 128 m_bOwnData) { 129 m_frames = frames; 130 return; 131 } 132 133 // free existing storage 134 free(); 135 136 // allocate 137 m_pData = (m_pPool) ? 138 rtm_alloc(m_pPool, sizeRequired) : 139 new int8[sizeRequired]; 140 141 m_bOwnData = true; 142 m_allocatedSize = sizeRequired; 143 m_frames = frames; 144 145 } 146 147 // take ownership of buffer from target 148 // (deletes current buffer data, if any owned) 149 150 void RawBuffer::adopt( 151 void* pData, 152 uint32 frameSize, 153 uint32 frames, 154 bool bCircular, 155 rtm_pool* pPool) { 156 157 // clean up myself first 158 free(); 159 160 // reference 161 operator=(RawBuffer(pData, frameSize, frames, bCircular, pPool)); 162 163 // mark ownership 164 m_bOwnData = true; 165 } 166 167 // returns false if the target doesn't own the data, but references it 168 // one way or the other 169 170 bool RawBuffer::adopt(RawBuffer& target) { 171 172 // reference 173 operator=(target); 174 175 // take ownership if possible 176 177 if(!target.m_bOwnData) { 178 m_bOwnData = false; 179 return false; 180 } 181 182 target.m_bOwnData = false; 183 m_bOwnData = true; 184 return true; 185 } 186 187 // adopt currently ref'd data (if any; returns false if no buffer data or 188 // already owned) 189 190 bool RawBuffer::adopt() { 191 if(!m_pData || m_bOwnData) 192 return false; 193 194 m_bOwnData = true; 195 return true; 196 } 197 198 // -------------------------------------------------------- // 199 // operations 200 // -------------------------------------------------------- // 201 202 // fill the buffer with zeroes 203 204 void RawBuffer::zero() { 205 if(!m_pData || !m_frames) 206 return; 207 208 memset(m_pData, 0, m_frames * m_frameSize); 209 } 210 211 // raw copy to destination buffer, returning the number of 212 // frames written, and adjusting both offsets accordingly. 213 // 214 // no frames will be written if the buffers' frame sizes 215 // differ. 216 217 uint32 RawBuffer::rawCopyTo( 218 RawBuffer& target, 219 uint32* pioFromFrame, 220 uint32* pioTargetFrame, 221 uint32 frames) const { 222 223 if(m_frameSize != target.m_frameSize) 224 return 0; 225 226 ASSERT(m_pData); 227 ASSERT(m_frames); 228 ASSERT(target.m_pData); 229 230 // convert frame counts to byte offsets 231 uint32 fromOffset = *pioFromFrame * m_frameSize; 232 uint32 targetOffset = *pioTargetFrame * m_frameSize; 233 234 // figure buffer sizes in bytes 235 uint32 size = m_frames * m_frameSize; 236 uint32 targetSize = target.m_frames * target.m_frameSize; 237 238 // figure amount to write 239 uint32 toCopy = frames * m_frameSize; 240 if(target.m_bCircular) { 241 if(toCopy > targetSize) 242 toCopy = targetSize; 243 } else { 244 if(toCopy > (targetSize-targetOffset)) 245 toCopy = (targetSize-targetOffset); 246 } 247 uint32 remaining = toCopy; 248 249 // do it 250 while(remaining) { 251 252 // figure a contiguous area to fill 253 uint32 targetChunk = targetSize - targetOffset; 254 255 if(targetChunk > remaining) 256 targetChunk = remaining; 257 258 // fill it (from one or more source areas) 259 while(targetChunk > 0) { 260 261 // figure a contiguous source area 262 uint32 sourceChunk = size - fromOffset; 263 if(sourceChunk > targetChunk) 264 sourceChunk = targetChunk; 265 266 // copy it 267 memcpy( 268 (int8*)target.m_pData + targetOffset, 269 (int8*)m_pData + fromOffset, 270 sourceChunk); 271 272 // advance offsets 273 targetOffset += sourceChunk; 274 if(targetOffset == targetSize) 275 targetOffset = 0; 276 277 fromOffset += sourceChunk; 278 if(fromOffset == size) 279 fromOffset = 0; 280 281 // figure remaining portion of target area to fill 282 targetChunk -= sourceChunk; 283 remaining -= sourceChunk; 284 } 285 } 286 287 // write new offsets 288 *pioFromFrame = fromOffset / m_frameSize; 289 *pioTargetFrame = targetOffset / m_frameSize; 290 291 return toCopy; 292 } 293 294 // more convenient version of above if you don't care 295 // how the offsets change. 296 297 uint32 RawBuffer::rawCopyTo( 298 RawBuffer& target, 299 uint32 fromOffset, 300 uint32 targetOffset, 301 uint32 frames) const { 302 303 return rawCopyTo(target, &fromOffset, &targetOffset, frames); 304 } 305 306 // -------------------------------------------------------- // 307 // internal operations 308 // -------------------------------------------------------- // 309 310 // free owned data, if any 311 // [16jun99] uses proper rtm_free() call if needed 312 void RawBuffer::free() { 313 if(!(m_bOwnData && m_pData)) 314 return; 315 316 if(m_pPool) 317 rtm_free(m_pData); 318 else 319 delete [] (int8 *)m_pData; 320 321 m_pData = 0; 322 } 323 324 325 // END -- RawBuffer.cpp -- 326