xref: /haiku/src/apps/cortex/addons/common/AudioBuffer.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
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