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