2 * Copyright (c) 1999-2000, Eric Moon.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
38 #include <RealtimeAlloc.h>
39 #include "AudioBuffer.h"
44 #include "audio_buffer_tools.h"
46 const media_raw_audio_format
AudioBuffer::defaultFormat
= {
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
) :
63 (format
.format
& 0x0f) * format
.channel_count
,
69 AudioBuffer::AudioBuffer(
70 const media_raw_audio_format
& format
,
73 rtm_pool
* pFromPool
) :
76 (format
.format
& 0x0f) * format
.channel_count
,
85 AudioBuffer::AudioBuffer(
86 const media_raw_audio_format
& format
,
90 rtm_pool
* pFromPool
) :
94 (format
.format
& 0x0f) * format
.channel_count
,
99 AudioBuffer::AudioBuffer(
100 const media_raw_audio_format
& format
,
109 if(pBuffer
->Header()->type
!= B_MEDIA_RAW_AUDIO
)
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
;
118 m_bCircular
= bCircular
;
121 // generate a reference (point) to the target's buffer
122 AudioBuffer::AudioBuffer(const AudioBuffer
& clone
) :
124 m_format(clone
.m_format
) {}
126 AudioBuffer
& AudioBuffer::operator=(const AudioBuffer
& clone
) {
127 RawBuffer::operator=(clone
);
128 m_format
= clone
.m_format
;
132 AudioBuffer::~AudioBuffer() {}
136 void AudioBuffer::setFormat(const media_raw_audio_format
& format
) {
140 const media_raw_audio_format
& AudioBuffer::format() const {
144 // extra adoption support
146 void AudioBuffer::adopt(
147 const media_raw_audio_format
& format
,
151 rtm_pool
* pFromPool
) {
153 // clean up myself first
157 operator=(AudioBuffer(format
, pData
, frames
, bCircular
, pFromPool
));
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 // -------------------------------------------------------- //
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 {
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(
190 uint32
* pioFromFrame
,
191 uint32
* pioTargetFrame
,
192 uint32 frames
) const {
195 if(formatSameAs(target
))
196 return rawCopyTo(target
, pioFromFrame
, pioTargetFrame
, 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
)
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
) {
226 (void*) ((int8
*)m_pData
+ fromOffset
),
227 (void*) ((int8
*)target
.m_pData
+ targetOffset
),
229 target
.m_format
.format
);
231 fromOffset
+= sampleSize
;
232 if(fromOffset
== size
)
235 targetOffset
+= sampleSize
;
236 if(targetOffset
== targetSize
)
241 *pioFromFrame
= fromOffset
/ m_frameSize
;
242 *pioTargetFrame
= targetOffset
/ m_frameSize
;
247 uint32
AudioBuffer::copyTo(
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(
260 uint32
* pioFromFrame
,
261 uint32
* pioTargetFrame
,
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
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
;
291 int8
* pCur
= (int8
*)m_pData
+ (firstSample
* bytesPerSample
);
297 for(n
= 0; n
< channels
; n
++)
301 // find minimum for each channel
305 remaining
--, n
++, pCur
+= bytesPerSample
) {
307 // wrap around to start of buffer?
309 pCur
= (int8
*)m_pData
;
314 convert_sample(pCur
, fCur
, m_format
.format
);
316 if(fCur
< pMin
[n
% channels
]) {
317 pMin
[n
% channels
] = fCur
;
319 pAt
[n
% channels
] = n
/ channels
;
323 // return current frame
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
;
344 int8
* pCur
= (int8
*)m_pData
+ (firstSample
* bytesPerSample
);
350 for(n
= 0; n
< channels
; n
++)
354 // find minimum for each channel
358 remaining
--, n
++, pCur
+= bytesPerSample
) {
360 // wrap around to start of buffer?
362 pCur
= (int8
*)m_pData
;
367 convert_sample(pCur
, fCur
, m_format
.format
);
369 if(fCur
> pMax
[n
% channels
]) {
370 pMax
[n
% channels
] = fCur
;
372 pAt
[n
% channels
] = n
/ channels
;
376 // return current frame
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
;
396 int8
* pCur
= (int8
*)m_pData
+ (firstSample
* bytesPerSample
);
402 for(n
= 0; n
< channels
; n
++)
406 // find peaks in both directions
410 remaining
--, n
++, pCur
+= bytesPerSample
) {
412 // wrap around to start of buffer?
414 pCur
= (int8
*)m_pData
;
419 convert_sample(pCur
, fCur
, m_format
.format
);
421 if(fabs(fCur
) > pPeaks
[n
% channels
]) {
422 pPeaks
[n
% channels
] = fCur
;
424 pAt
[n
% channels
] = n
/ channels
;
428 // return current frame
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
;
453 int8
* pCur
= (int8
*)m_pData
+ (firstSample
* bytesPerSample
);
456 memset(pAverage
, 0, sizeof(float)*channels
);
463 remaining
--, n
++, pCur
+= bytesPerSample
) {
465 // wrap around to start of buffer
467 pCur
= (int8
*)m_pData
;
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
484 // -------------------------------------------------------- //
487 // END -- AudioBuffer.h --