1 // AudioBuffer.cpp 2 // e.moon 31mar99 3 // 4 5 #include <Buffer.h> 6 #include <Debug.h> 7 #include <RealtimeAlloc.h> 8 #include "AudioBuffer.h" 9 10 #include <cmath> 11 #include <cstring> 12 13 #include "audio_buffer_tools.h" 14 15 const media_raw_audio_format AudioBuffer::defaultFormat = { 16 44100.0, 17 2, 18 media_raw_audio_format::B_AUDIO_FLOAT, 19 media_raw_audio_format::wildcard.byte_order, 20 media_raw_audio_format::wildcard.buffer_size 21 }; 22 23 // -------------------------------------------------------- // 24 // ctor/dtor/accessors 25 // -------------------------------------------------------- // 26 27 AudioBuffer::AudioBuffer( 28 const media_raw_audio_format& format, 29 rtm_pool* pFromPool) : 30 31 RawBuffer( 32 (format.format & 0x0f) * format.channel_count, 33 0, 34 true, 35 pFromPool), 36 m_format(format) {} 37 38 AudioBuffer::AudioBuffer( 39 const media_raw_audio_format& format, 40 uint32 frames, 41 bool bCircular, 42 rtm_pool* pFromPool) : 43 44 RawBuffer( 45 (format.format & 0x0f) * format.channel_count, 46 0, 47 bCircular, 48 pFromPool), 49 m_format(format) { 50 51 resize(frames); 52 } 53 54 AudioBuffer::AudioBuffer( 55 const media_raw_audio_format& format, 56 void* pData, 57 uint32 frames, 58 bool bCircular, 59 rtm_pool* pFromPool) : 60 61 RawBuffer( 62 pData, 63 (format.format & 0x0f) * format.channel_count, 64 frames, 65 bCircular, 66 pFromPool) {} 67 68 AudioBuffer::AudioBuffer( 69 const media_raw_audio_format& format, 70 BBuffer* pBuffer, 71 bool bCircular) : 72 73 RawBuffer(), 74 m_format(format) 75 76 { 77 78 if(pBuffer->Header()->type != B_MEDIA_RAW_AUDIO) 79 return; 80 81 // reference it: 82 m_pData = pBuffer->Data(); 83 m_frameSize = (m_format.format & 0x0f) * m_format.channel_count; 84 m_frames = pBuffer->Header()->size_used / m_frameSize; 85 m_allocatedSize = 0; 86 m_bOwnData = false; 87 m_bCircular = bCircular; 88 } 89 90 // generate a reference (point) to the target's buffer 91 AudioBuffer::AudioBuffer(const AudioBuffer& clone) : 92 RawBuffer(clone), 93 m_format(clone.m_format) {} 94 95 AudioBuffer& AudioBuffer::operator=(const AudioBuffer& clone) { 96 RawBuffer::operator=(clone); 97 m_format = clone.m_format; 98 return *this; 99 } 100 101 AudioBuffer::~AudioBuffer() {} 102 103 // format access 104 105 void AudioBuffer::setFormat(const media_raw_audio_format& format) { 106 m_format = format; 107 } 108 109 const media_raw_audio_format& AudioBuffer::format() const { 110 return m_format; 111 } 112 113 // extra adoption support 114 115 void AudioBuffer::adopt( 116 const media_raw_audio_format& format, 117 void* pData, 118 uint32 frames, 119 bool bCircular, 120 rtm_pool* pFromPool) { 121 122 // clean up myself first 123 free(); 124 125 // reference 126 operator=(AudioBuffer(format, pData, frames, bCircular, pFromPool)); 127 128 // mark ownership 129 m_bOwnData = true; 130 } 131 132 // as with RawBuffer::adopt(), returns false if the target 133 // doesn't own its buffer, but references it anyway 134 135 bool AudioBuffer::adopt(AudioBuffer& target) { 136 m_format = target.m_format; 137 return RawBuffer::adopt(target); 138 } 139 140 // -------------------------------------------------------- // 141 // operations 142 // -------------------------------------------------------- // 143 144 // test for format equivalence against target buffer 145 // (ie. determine whether any conversion would be necessary 146 // for copy/mix operations) 147 148 bool AudioBuffer::formatSameAs(const AudioBuffer& target) const { 149 return 150 m_format.format == target.m_format.format && 151 m_format.channel_count == target.m_format.channel_count; 152 } 153 154 // copy to target audio buffer, applying any necessary 155 // format conversions. behaves like rawCopyTo(). 156 157 uint32 AudioBuffer::copyTo( 158 AudioBuffer& target, 159 uint32* pioFromFrame, 160 uint32* pioTargetFrame, 161 uint32 frames) const { 162 163 // simplest case: 164 if(formatSameAs(target)) 165 return rawCopyTo(target, pioFromFrame, pioTargetFrame, frames); 166 167 // sanity checks 168 ASSERT(m_pData); 169 ASSERT(m_frames); 170 ASSERT(target.m_pData); 171 172 // figure byte offsets & sizes 173 uint32 fromOffset = *pioFromFrame * m_frameSize; 174 uint32 targetOffset = *pioTargetFrame * m_frameSize; 175 176 uint32 size = m_frames * m_frameSize; 177 uint32 targetSize = target.m_frames * target.m_frameSize; 178 179 // figure number of samples to convert 180 uint32 toCopy = frames * m_format.channel_count; 181 if(target.m_bCircular) { 182 if(toCopy > targetSize) 183 toCopy = targetSize; 184 } else { 185 if(toCopy > (targetSize-targetOffset)) 186 toCopy = (targetSize-targetOffset); 187 } 188 uint32 remaining = toCopy; 189 190 uint32 sampleSize = m_frameSize / m_format.channel_count; 191 192 // convert and copy a sample at a time 193 for(; remaining; remaining -= sampleSize) { 194 convert_sample( 195 (void*) *((int8*)m_pData + fromOffset), 196 (void*) *((int8*)target.m_pData + targetOffset), 197 m_format.format, 198 target.m_format.format); 199 200 fromOffset += sampleSize; 201 if(fromOffset == size) 202 fromOffset = 0; 203 204 targetOffset += sampleSize; 205 if(targetOffset == targetSize) 206 targetOffset = 0; 207 } 208 209 // write new offsets 210 *pioFromFrame = fromOffset / m_frameSize; 211 *pioTargetFrame = targetOffset / m_frameSize; 212 213 return toCopy; 214 } 215 216 uint32 AudioBuffer::copyTo( 217 AudioBuffer& target, 218 uint32* pioFromFrame, 219 uint32* pioTargetFrame) const { 220 221 return copyTo(target, pioFromFrame, pioTargetFrame, m_frames); 222 } 223 224 // mix to target audio buffer, applying any necessary 225 // format conversions. behaves like rawCopyTo(). 226 227 uint32 AudioBuffer::mixTo( 228 AudioBuffer& target, 229 uint32* pioFromFrame, 230 uint32* pioTargetFrame, 231 uint32 frames, 232 float fGain /*=1.0*/) const { return 0; } //nyi 233 234 // calculate minimum & maximum peak levels 235 // (converted/scaled to given type if necessary) 236 // pMax and pMin must point to arrays with enough room 237 // for one value per channel. existing array values aren't 238 // cleared first. 239 // 240 // (if pMin isn't provided, the maximum absolute levels will 241 // be written to pMax) 242 243 void AudioBuffer::findMin(float* pMin, uint32* pAt /*=0*/) const { 244 findMin(0, m_frames, pMin, pAt); 245 } 246 247 uint32 AudioBuffer::findMin(uint32 fromFrame, uint32 frameCount, 248 float* pMin, uint32* pAt /*=0*/) const { 249 250 size_t channels = m_format.channel_count; 251 size_t samples = m_frames * channels; 252 size_t bytesPerSample = m_format.format & 0x0f; 253 254 size_t firstSample = fromFrame * channels; 255 size_t remaining = frameCount * channels; 256 257 if(!m_pData) 258 return fromFrame; 259 260 int8* pCur = (int8*)m_pData + (firstSample * bytesPerSample); 261 262 uint32 n; 263 264 if(pAt) { 265 // reset pAt 266 for(n = 0; n < channels; n++) 267 pAt[n] = ULONG_MAX; 268 } 269 270 // find minimum for each channel 271 for( 272 n = firstSample; 273 remaining; 274 remaining--, n++, pCur += bytesPerSample) { 275 276 // wrap around to start of buffer? 277 if(n == samples) { 278 pCur = (int8*)m_pData; 279 n = 0; 280 } 281 282 float fCur; 283 convert_sample(pCur, fCur, m_format.format); 284 285 if(fCur < pMin[n % channels]) { 286 pMin[n % channels] = fCur; 287 if(pAt) 288 pAt[n % channels] = n / channels; 289 } 290 } 291 292 // return current frame 293 return n / channels; 294 } 295 296 void AudioBuffer::findMax(float* pMax, uint32* pAt /*=0*/) const { 297 findMax(0, m_frames, pMax, pAt); 298 } 299 300 uint32 AudioBuffer::findMax(uint32 fromFrame, uint32 frameCount, 301 float* pMax, uint32* pAt /*=0*/) const { 302 303 size_t channels = m_format.channel_count; 304 size_t samples = m_frames * channels; 305 size_t bytesPerSample = m_format.format & 0x0f; 306 307 size_t firstSample = fromFrame * channels; 308 size_t remaining = frameCount * channels; 309 310 if(!m_pData) 311 return fromFrame; 312 313 int8* pCur = (int8*)m_pData + (firstSample * bytesPerSample); 314 315 uint32 n; 316 317 if(pAt) { 318 // reset pAt 319 for(n = 0; n < channels; n++) 320 pAt[n] = ULONG_MAX; 321 } 322 323 // find minimum for each channel 324 for( 325 n = firstSample; 326 remaining; 327 remaining--, n++, pCur += bytesPerSample) { 328 329 // wrap around to start of buffer? 330 if(n == samples) { 331 pCur = (int8*)m_pData; 332 n = 0; 333 } 334 335 float fCur; 336 convert_sample(pCur, fCur, m_format.format); 337 338 if(fCur > pMax[n % channels]) { 339 pMax[n % channels] = fCur; 340 if(pAt) 341 pAt[n % channels] = n / channels; 342 } 343 } 344 345 // return current frame 346 return n / channels; 347 } 348 349 void AudioBuffer::findPeaks(float* pPeaks, uint32* pAt /*=0*/) const { 350 findPeaks(0, m_frames, pPeaks, pAt); 351 } 352 353 uint32 AudioBuffer::findPeaks(uint32 fromFrame, uint32 frameCount, 354 float* pPeaks, uint32* pAt) const { 355 356 size_t channels = m_format.channel_count; 357 size_t samples = m_frames * channels; 358 size_t bytesPerSample = m_format.format & 0x0f; 359 360 size_t firstSample = fromFrame * channels; 361 size_t remaining = frameCount * channels; 362 363 if(!m_pData) 364 return fromFrame; 365 int8* pCur = (int8*)m_pData + (firstSample * bytesPerSample); 366 367 uint32 n; 368 369 if(pAt) { 370 // reset pAt 371 for(n = 0; n < channels; n++) 372 pAt[n] = ULONG_MAX; 373 } 374 375 // find peaks in both directions 376 for( 377 n = firstSample; 378 remaining; 379 remaining--, n++, pCur += bytesPerSample) { 380 381 // wrap around to start of buffer? 382 if(n == samples) { 383 pCur = (int8*)m_pData; 384 n = 0; 385 } 386 387 float fCur; 388 convert_sample(pCur, fCur, m_format.format); 389 390 if(fabs(fCur) > pPeaks[n % channels]) { 391 pPeaks[n % channels] = fCur; 392 if(pAt) 393 pAt[n % channels] = n / channels; 394 } 395 } 396 397 // return current frame 398 return n / channels; 399 } 400 401 // find average level 402 // (converted/scaled as necessary) 403 // pAverage must point to an array with enough room 404 // for one value per channel. 405 406 void AudioBuffer::average(float* pAverage) const { 407 average(0, m_frames, pAverage); 408 } 409 410 uint32 AudioBuffer::average(uint32 fromFrame, uint32 frameCount, 411 float* pAverage) const { 412 413 size_t channels = m_format.channel_count; 414 size_t samples = m_frames * channels; 415 size_t bytesPerSample = m_format.format & 0x0f; 416 417 size_t firstSample = fromFrame * channels; 418 size_t remaining = frameCount * channels; 419 420 if(!m_pData) 421 return fromFrame; 422 int8* pCur = (int8*)m_pData + (firstSample * bytesPerSample); 423 424 // clear averages 425 memset(pAverage, 0, sizeof(float)*channels); 426 427 // calculate 428 uint32 n; 429 for( 430 n = firstSample; 431 remaining; 432 remaining--, n++, pCur += bytesPerSample) { 433 434 // wrap around to start of buffer 435 if(n == samples) { 436 pCur = (int8*)m_pData; 437 n = 0; 438 } 439 440 float fCur; 441 convert_sample(pCur, fCur, m_format.format); 442 443 pAverage[n%channels] += fCur; 444 } 445 446 for(uint32 n = 0; n < channels; n++) 447 pAverage[n] /= frameCount; 448 449 // return current frame 450 return n / channels; 451 } 452 453 // -------------------------------------------------------- // 454 455 456 // END -- AudioBuffer.h --