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