btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / apps / cortex / addons / common / AudioBuffer.cpp
blob92ceffb4f9ebee119b93d66ab955b4193d21eed3
1 /*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
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.
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.
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.
32 // AudioBuffer.cpp
33 // e.moon 31mar99
36 #include <Buffer.h>
37 #include <Debug.h>
38 #include <RealtimeAlloc.h>
39 #include "AudioBuffer.h"
41 #include <cmath>
42 #include <cstring>
44 #include "audio_buffer_tools.h"
46 const media_raw_audio_format AudioBuffer::defaultFormat = {
47 44100.0,
49 media_raw_audio_format::B_AUDIO_FLOAT,
50 media_raw_audio_format::wildcard.byte_order,
51 media_raw_audio_format::wildcard.buffer_size
54 // -------------------------------------------------------- //
55 // ctor/dtor/accessors
56 // -------------------------------------------------------- //
58 AudioBuffer::AudioBuffer(
59 const media_raw_audio_format& format,
60 rtm_pool* pFromPool) :
62 RawBuffer(
63 (format.format & 0x0f) * format.channel_count,
65 true,
66 pFromPool),
67 m_format(format) {}
69 AudioBuffer::AudioBuffer(
70 const media_raw_audio_format& format,
71 uint32 frames,
72 bool bCircular,
73 rtm_pool* pFromPool) :
75 RawBuffer(
76 (format.format & 0x0f) * format.channel_count,
78 bCircular,
79 pFromPool),
80 m_format(format) {
82 resize(frames);
85 AudioBuffer::AudioBuffer(
86 const media_raw_audio_format& format,
87 void* pData,
88 uint32 frames,
89 bool bCircular,
90 rtm_pool* pFromPool) :
92 RawBuffer(
93 pData,
94 (format.format & 0x0f) * format.channel_count,
95 frames,
96 bCircular,
97 pFromPool) {}
99 AudioBuffer::AudioBuffer(
100 const media_raw_audio_format& format,
101 BBuffer* pBuffer,
102 bool bCircular) :
104 RawBuffer(),
105 m_format(format)
109 if(pBuffer->Header()->type != B_MEDIA_RAW_AUDIO)
110 return;
112 // reference it:
113 m_pData = pBuffer->Data();
114 m_frameSize = (m_format.format & 0x0f) * m_format.channel_count;
115 m_frames = pBuffer->Header()->size_used / m_frameSize;
116 m_allocatedSize = 0;
117 m_bOwnData = false;
118 m_bCircular = bCircular;
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) {}
126 AudioBuffer& AudioBuffer::operator=(const AudioBuffer& clone) {
127 RawBuffer::operator=(clone);
128 m_format = clone.m_format;
129 return *this;
132 AudioBuffer::~AudioBuffer() {}
134 // format access
136 void AudioBuffer::setFormat(const media_raw_audio_format& format) {
137 m_format = format;
140 const media_raw_audio_format& AudioBuffer::format() const {
141 return m_format;
144 // extra adoption support
146 void AudioBuffer::adopt(
147 const media_raw_audio_format& format,
148 void* pData,
149 uint32 frames,
150 bool bCircular,
151 rtm_pool* pFromPool) {
153 // clean up myself first
154 free();
156 // reference
157 operator=(AudioBuffer(format, pData, frames, bCircular, pFromPool));
159 // mark ownership
160 m_bOwnData = true;
163 // as with RawBuffer::adopt(), returns false if the target
164 // doesn't own its buffer, but references it anyway
166 bool AudioBuffer::adopt(AudioBuffer& target) {
167 m_format = target.m_format;
168 return RawBuffer::adopt(target);
171 // -------------------------------------------------------- //
172 // operations
173 // -------------------------------------------------------- //
175 // test for format equivalence against target buffer
176 // (ie. determine whether any conversion would be necessary
177 // for copy/mix operations)
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;
185 // copy to target audio buffer, applying any necessary
186 // format conversions. behaves like rawCopyTo().
188 uint32 AudioBuffer::copyTo(
189 AudioBuffer& target,
190 uint32* pioFromFrame,
191 uint32* pioTargetFrame,
192 uint32 frames) const {
194 // simplest case:
195 if(formatSameAs(target))
196 return rawCopyTo(target, pioFromFrame, pioTargetFrame, frames);
198 // sanity checks
199 ASSERT(m_pData);
200 ASSERT(m_frames);
201 ASSERT(target.m_pData);
203 // figure byte offsets & sizes
204 uint32 fromOffset = *pioFromFrame * m_frameSize;
205 uint32 targetOffset = *pioTargetFrame * m_frameSize;
207 uint32 size = m_frames * m_frameSize;
208 uint32 targetSize = target.m_frames * target.m_frameSize;
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);
219 uint32 remaining = toCopy;
221 uint32 sampleSize = m_frameSize / m_format.channel_count;
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);
231 fromOffset += sampleSize;
232 if(fromOffset == size)
233 fromOffset = 0;
235 targetOffset += sampleSize;
236 if(targetOffset == targetSize)
237 targetOffset = 0;
240 // write new offsets
241 *pioFromFrame = fromOffset / m_frameSize;
242 *pioTargetFrame = targetOffset / m_frameSize;
244 return toCopy;
247 uint32 AudioBuffer::copyTo(
248 AudioBuffer& target,
249 uint32* pioFromFrame,
250 uint32* pioTargetFrame) const {
252 return copyTo(target, pioFromFrame, pioTargetFrame, m_frames);
255 // mix to target audio buffer, applying any necessary
256 // format conversions. behaves like rawCopyTo().
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
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.
271 // (if pMin isn't provided, the maximum absolute levels will
272 // be written to pMax)
274 void AudioBuffer::findMin(float* pMin, uint32* pAt /*=0*/) const {
275 findMin(0, m_frames, pMin, pAt);
278 uint32 AudioBuffer::findMin(uint32 fromFrame, uint32 frameCount,
279 float* pMin, uint32* pAt /*=0*/) const {
281 size_t channels = m_format.channel_count;
282 size_t samples = m_frames * channels;
283 size_t bytesPerSample = m_format.format & 0x0f;
285 size_t firstSample = fromFrame * channels;
286 size_t remaining = frameCount * channels;
288 if(!m_pData)
289 return fromFrame;
291 int8* pCur = (int8*)m_pData + (firstSample * bytesPerSample);
293 uint32 n;
295 if(pAt) {
296 // reset pAt
297 for(n = 0; n < channels; n++)
298 pAt[n] = UINT32_MAX;
301 // find minimum for each channel
302 for(
303 n = firstSample;
304 remaining;
305 remaining--, n++, pCur += bytesPerSample) {
307 // wrap around to start of buffer?
308 if(n == samples) {
309 pCur = (int8*)m_pData;
310 n = 0;
313 float fCur = 0;
314 convert_sample(pCur, fCur, m_format.format);
316 if(fCur < pMin[n % channels]) {
317 pMin[n % channels] = fCur;
318 if(pAt)
319 pAt[n % channels] = n / channels;
323 // return current frame
324 return n / channels;
327 void AudioBuffer::findMax(float* pMax, uint32* pAt /*=0*/) const {
328 findMax(0, m_frames, pMax, pAt);
331 uint32 AudioBuffer::findMax(uint32 fromFrame, uint32 frameCount,
332 float* pMax, uint32* pAt /*=0*/) const {
334 size_t channels = m_format.channel_count;
335 size_t samples = m_frames * channels;
336 size_t bytesPerSample = m_format.format & 0x0f;
338 size_t firstSample = fromFrame * channels;
339 size_t remaining = frameCount * channels;
341 if(!m_pData)
342 return fromFrame;
344 int8* pCur = (int8*)m_pData + (firstSample * bytesPerSample);
346 uint32 n;
348 if(pAt) {
349 // reset pAt
350 for(n = 0; n < channels; n++)
351 pAt[n] = UINT32_MAX;
354 // find minimum for each channel
355 for(
356 n = firstSample;
357 remaining;
358 remaining--, n++, pCur += bytesPerSample) {
360 // wrap around to start of buffer?
361 if(n == samples) {
362 pCur = (int8*)m_pData;
363 n = 0;
366 float fCur = 0;
367 convert_sample(pCur, fCur, m_format.format);
369 if(fCur > pMax[n % channels]) {
370 pMax[n % channels] = fCur;
371 if(pAt)
372 pAt[n % channels] = n / channels;
376 // return current frame
377 return n / channels;
380 void AudioBuffer::findPeaks(float* pPeaks, uint32* pAt /*=0*/) const {
381 findPeaks(0, m_frames, pPeaks, pAt);
384 uint32 AudioBuffer::findPeaks(uint32 fromFrame, uint32 frameCount,
385 float* pPeaks, uint32* pAt) const {
387 size_t channels = m_format.channel_count;
388 size_t samples = m_frames * channels;
389 size_t bytesPerSample = m_format.format & 0x0f;
391 size_t firstSample = fromFrame * channels;
392 size_t remaining = frameCount * channels;
394 if(!m_pData)
395 return fromFrame;
396 int8* pCur = (int8*)m_pData + (firstSample * bytesPerSample);
398 uint32 n;
400 if(pAt) {
401 // reset pAt
402 for(n = 0; n < channels; n++)
403 pAt[n] = UINT32_MAX;
406 // find peaks in both directions
407 for(
408 n = firstSample;
409 remaining;
410 remaining--, n++, pCur += bytesPerSample) {
412 // wrap around to start of buffer?
413 if(n == samples) {
414 pCur = (int8*)m_pData;
415 n = 0;
418 float fCur = 0;
419 convert_sample(pCur, fCur, m_format.format);
421 if(fabs(fCur) > pPeaks[n % channels]) {
422 pPeaks[n % channels] = fCur;
423 if(pAt)
424 pAt[n % channels] = n / channels;
428 // return current frame
429 return n / channels;
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.
437 void AudioBuffer::average(float* pAverage) const {
438 average(0, m_frames, pAverage);
441 uint32 AudioBuffer::average(uint32 fromFrame, uint32 frameCount,
442 float* pAverage) const {
444 size_t channels = m_format.channel_count;
445 size_t samples = m_frames * channels;
446 size_t bytesPerSample = m_format.format & 0x0f;
448 size_t firstSample = fromFrame * channels;
449 size_t remaining = frameCount * channels;
451 if(!m_pData)
452 return fromFrame;
453 int8* pCur = (int8*)m_pData + (firstSample * bytesPerSample);
455 // clear averages
456 memset(pAverage, 0, sizeof(float)*channels);
458 // calculate
459 uint32 n;
460 for(
461 n = firstSample;
462 remaining;
463 remaining--, n++, pCur += bytesPerSample) {
465 // wrap around to start of buffer
466 if(n == samples) {
467 pCur = (int8*)m_pData;
468 n = 0;
471 float fCur = 0;
472 convert_sample(pCur, fCur, m_format.format);
474 pAverage[n%channels] += fCur;
477 for(uint32 n = 0; n < channels; n++)
478 pAverage[n] /= frameCount;
480 // return current frame
481 return n / channels;
484 // -------------------------------------------------------- //
487 // END -- AudioBuffer.h --