xref: /haiku/src/add-ons/media/media-add-ons/mixer/Resampler.cpp (revision aed35104852941f0f6f3d1dcc5338b5f337d0a3c)
1 /*
2  * Copyright 2003 Marcus Overhagen
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "Resampler.h"
8 
9 #include <MediaDefs.h>
10 
11 #include "MixerDebug.h"
12 
13 
14 /*!	A simple resampling class for the audio mixer.
15 	You pick the conversion function on object creation,
16 	and then call the Resample() function, specifying data pointer,
17 	offset (in bytes) to the next sample, and count of samples for
18 	both source and destination.
19 */
20 
21 
22 Resampler::Resampler(uint32 src_format, uint32 dst_format)
23 	:
24 	fFunc(0)
25 {
26 	if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) {
27 		switch (src_format) {
28 			case media_raw_audio_format::B_AUDIO_FLOAT:
29 				fFunc = &Resampler::float_to_float;
30 				return;
31 			case media_raw_audio_format::B_AUDIO_INT:
32 				fFunc = &Resampler::int32_to_float;
33 				return;
34 			case media_raw_audio_format::B_AUDIO_SHORT:
35 				fFunc = &Resampler::int16_to_float;
36 				return;
37 			case media_raw_audio_format::B_AUDIO_CHAR:
38 				fFunc = &Resampler::int8_to_float;
39 				return;
40 			case media_raw_audio_format::B_AUDIO_UCHAR:
41 				fFunc = &Resampler::uint8_to_float;
42 				return;
43 			default:
44 				ERROR("Resampler::Resampler: unknown source format 0x%x\n",
45 					src_format);
46 				return;
47 		}
48 	}
49 
50 	if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) {
51 		switch (dst_format) {
52 			// float=>float already handled above
53 			case media_raw_audio_format::B_AUDIO_INT:
54 				fFunc = &Resampler::float_to_int32;
55 				return;
56 			case media_raw_audio_format::B_AUDIO_SHORT:
57 				fFunc = &Resampler::float_to_int16;
58 				return;
59 			case media_raw_audio_format::B_AUDIO_CHAR:
60 				fFunc = &Resampler::float_to_int8;
61 				return;
62 			case media_raw_audio_format::B_AUDIO_UCHAR:
63 				fFunc = &Resampler::float_to_uint8;
64 				return;
65 			default:
66 				ERROR("Resampler::Resampler: unknown destination format 0x%x\n", dst_format);
67 				return;
68 		}
69 	}
70 
71 	ERROR("Resampler::Resampler: source or destination format must be "
72 		"B_AUDIO_FLOAT\n");
73 }
74 
75 
76 Resampler::~Resampler()
77 {
78 }
79 
80 
81 status_t
82 Resampler::InitCheck() const
83 {
84 	return fFunc != 0 ? B_OK : B_ERROR;
85 }
86 
87 
88 void
89 Resampler::float_to_float(const void *_src, int32 srcSampleOffset,
90 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
91 	int32 destSampleCount, float _gain)
92 {
93 	register const char * src = (const char *)_src;
94 	register char * dest = (char *)_dest;
95 	register int32 count = destSampleCount;
96 	register float gain = _gain;
97 
98 	if (srcSampleCount == destSampleCount) {
99 		// optimized case for no resampling
100 		while (count--) {
101 			*(float *)dest = *(const float *)src * gain;
102 			src += srcSampleOffset;
103 			dest += destSampleOffset;
104 		}
105 		return;
106 	}
107 
108 	register float delta = float(srcSampleCount) / float(destSampleCount);
109 	register float current = 0.0f;
110 
111 	if (delta < 1.0) {
112 		// upsample
113 		while (count--) {
114 			*(float *)dest = *(const float *)src * gain;
115 			dest += destSampleOffset;
116 			current += delta;
117 			if (current >= 1.0f) {
118 				current -= 1.0f;
119 				src += srcSampleOffset;
120 			}
121 		}
122 	} else {
123 		// downsample
124 		while (count--) {
125 			*(float *)dest = *(const float *)src * gain;
126 			dest += destSampleOffset;
127 			current += delta;
128 			register int32 skipcount = (int32)current;
129 			current -= skipcount;
130 			src += skipcount * srcSampleOffset;
131 		}
132 	}
133 }
134 
135 
136 void
137 Resampler::int32_to_float(const void *_src, int32 srcSampleOffset,
138 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
139 	int32 destSampleCount, float _gain)
140 {
141 	register const char * src = (const char *)_src;
142 	register char * dest = (char *)_dest;
143 	register int32 count = destSampleCount;
144 	register float gain = _gain / 2147483647.0;
145 
146 	if (srcSampleCount == destSampleCount) {
147 		// optimized case for no resampling
148 		while (count--) {
149 			*(float *)dest = *(const int32 *)src * gain;
150 			src += srcSampleOffset;
151 			dest += destSampleOffset;
152 		}
153 		return;
154 	}
155 
156 	register float delta = float(srcSampleCount) / float(destSampleCount);
157 	register float current = 0.0f;
158 
159 	if (delta < 1.0) {
160 		// upsample
161 		while (count--) {
162 			*(float *)dest = *(const int32 *)src * gain;
163 			dest += destSampleOffset;
164 			current += delta;
165 			if (current >= 1.0f) {
166 				current -= 1.0f;
167 				src += srcSampleOffset;
168 			}
169 		}
170 	} else {
171 		// downsample
172 		while (count--) {
173 			*(float *)dest = *(const int32 *)src * gain;
174 			dest += destSampleOffset;
175 			current += delta;
176 			register int32 skipcount = (int32)current;
177 			current -= skipcount;
178 			src += skipcount * srcSampleOffset;
179 		}
180 	}
181 }
182 
183 
184 void
185 Resampler::int16_to_float(const void *_src, int32 srcSampleOffset,
186 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
187 	int32 destSampleCount, float _gain)
188 {
189 	register const char * src = (const char *)_src;
190 	register char * dest = (char *)_dest;
191 	register int32 count = destSampleCount;
192 	register float gain = _gain / 32767.0;
193 
194 	if (srcSampleCount == destSampleCount) {
195 		// optimized case for no resampling
196 		while (count--) {
197 			*(float *)dest = *(const int16 *)src * gain;
198 			src += srcSampleOffset;
199 			dest += destSampleOffset;
200 		}
201 		return;
202 	}
203 
204 	register float delta = float(srcSampleCount) / float(destSampleCount);
205 	register float current = 0.0f;
206 
207 	if (delta < 1.0) {
208 		// upsample
209 		while (count--) {
210 			*(float *)dest = *(const int16 *)src * gain;
211 			dest += destSampleOffset;
212 			current += delta;
213 			if (current >= 1.0f) {
214 				current -= 1.0f;
215 				src += srcSampleOffset;
216 			}
217 		}
218 	} else {
219 		// downsample
220 		while (count--) {
221 			*(float *)dest = *(const int16 *)src * gain;
222 			dest += destSampleOffset;
223 			current += delta;
224 			register int32 skipcount = (int32)current;
225 			current -= skipcount;
226 			src += skipcount * srcSampleOffset;
227 		}
228 	}
229 }
230 
231 
232 void
233 Resampler::int8_to_float(const void *_src, int32 srcSampleOffset,
234 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
235 	int32 destSampleCount, float _gain)
236 {
237 	register const char * src = (const char *)_src;
238 	register char * dest = (char *)_dest;
239 	register int32 count = destSampleCount;
240 	register float gain = _gain / 127.0;
241 
242 	if (srcSampleCount == destSampleCount) {
243 		// optimized case for no resampling
244 		while (count--) {
245 			*(float *)dest = *(const int8 *)src * gain;
246 			src += srcSampleOffset;
247 			dest += destSampleOffset;
248 		}
249 		return;
250 	}
251 
252 	register float delta = float(srcSampleCount) / float(destSampleCount);
253 	register float current = 0.0f;
254 
255 	if (delta < 1.0) {
256 		// upsample
257 		while (count--) {
258 			*(float *)dest = *(const int8 *)src * gain;
259 			dest += destSampleOffset;
260 			current += delta;
261 			if (current >= 1.0f) {
262 				current -= 1.0f;
263 				src += srcSampleOffset;
264 			}
265 		}
266 	} else {
267 		// downsample
268 		while (count--) {
269 			*(float *)dest = *(const int8 *)src * gain;
270 			dest += destSampleOffset;
271 			current += delta;
272 			register int32 skipcount = (int32)current;
273 			current -= skipcount;
274 			src += skipcount * srcSampleOffset;
275 		}
276 	}
277 }
278 
279 
280 void
281 Resampler::uint8_to_float(const void *_src, int32 srcSampleOffset,
282 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
283 	int32 destSampleCount, float _gain)
284 {
285 	register const char * src = (const char *)_src;
286 	register char * dest = (char *)_dest;
287 	register int32 count = destSampleCount;
288 	register float gain = _gain / 127.0;
289 
290 	if (srcSampleCount == destSampleCount) {
291 		// optimized case for no resampling
292 		while (count--) {
293 			*(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
294 			src += srcSampleOffset;
295 			dest += destSampleOffset;
296 		}
297 		return;
298 	}
299 
300 	register float delta = float(srcSampleCount) / float(destSampleCount);
301 	register float current = 0.0f;
302 
303 	if (delta < 1.0) {
304 		// upsample
305 		while (count--) {
306 			*(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
307 			dest += destSampleOffset;
308 			current += delta;
309 			if (current >= 1.0f) {
310 				current -= 1.0f;
311 				src += srcSampleOffset;
312 			}
313 		}
314 	} else {
315 		// downsample
316 		while (count--) {
317 			*(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
318 			dest += destSampleOffset;
319 			current += delta;
320 			register int32 skipcount = (int32)current;
321 			current -= skipcount;
322 			src += skipcount * srcSampleOffset;
323 		}
324 	}
325 }
326 
327 
328 void
329 Resampler::float_to_int32(const void *_src, int32 srcSampleOffset,
330 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
331 	int32 destSampleCount, float _gain)
332 {
333 	register const char * src = (const char *)_src;
334 	register char * dest = (char *)_dest;
335 	register int32 count = destSampleCount;
336 	register float gain = _gain * 2147483647.0;
337 
338 	if (srcSampleCount == destSampleCount) {
339 		// optimized case for no resampling
340 		while (count--) {
341 			register float sample = *(const float *)src * gain;
342 			if (sample > 2147483647.0f)
343 				*(int32 *)dest = 2147483647L;
344 			else if (sample < -2147483647.0f)
345 				*(int32 *)dest = -2147483647L;
346 			else
347 				*(int32 *)dest = (int32)sample;
348 			src += srcSampleOffset;
349 			dest += destSampleOffset;
350 		}
351 		return;
352 	}
353 
354 	register float delta = float(srcSampleCount) / float(destSampleCount);
355 	register float current = 0.0f;
356 
357 	if (delta < 1.0) {
358 		// upsample
359 		while (count--) {
360 			register float sample = *(const float *)src * gain;
361 			if (sample > 2147483647.0f)
362 				*(int32 *)dest = 2147483647L;
363 			else if (sample < -2147483647.0f)
364 				*(int32 *)dest = -2147483647L;
365 			else
366 				*(int32 *)dest = (int32)sample;
367 			dest += destSampleOffset;
368 			current += delta;
369 			if (current >= 1.0f) {
370 				current -= 1.0f;
371 				src += srcSampleOffset;
372 			}
373 		}
374 	} else {
375 		// downsample
376 		while (count--) {
377 			register float sample = *(const float *)src * gain;
378 			if (sample > 2147483647.0f)
379 				*(int32 *)dest = 2147483647L;
380 			else if (sample < -2147483647.0f)
381 				*(int32 *)dest = -2147483647L;
382 			else
383 				*(int32 *)dest = (int32)sample;
384 			dest += destSampleOffset;
385 			current += delta;
386 			register int32 skipcount = (int32)current;
387 			current -= skipcount;
388 			src += skipcount * srcSampleOffset;
389 		}
390 	}
391 }
392 
393 
394 void
395 Resampler::float_to_int16(const void *_src, int32 srcSampleOffset,
396 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
397 	int32 destSampleCount, float _gain)
398 {
399 	register const char * src = (const char *)_src;
400 	register char * dest = (char *)_dest;
401 	register int32 count = destSampleCount;
402 	register float gain = _gain * 32767.0;
403 
404 	if (srcSampleCount == destSampleCount) {
405 		// optimized case for no resampling
406 		while (count--) {
407 			register float sample = *(const float *)src * gain;
408 			if (sample > 32767.0f)
409 				*(int16 *)dest = 32767;
410 			else if (sample < -32767.0f)
411 				*(int16 *)dest = -32767;
412 			else
413 				*(int16 *)dest = (int16)sample;
414 			src += srcSampleOffset;
415 			dest += destSampleOffset;
416 		}
417 		return;
418 	}
419 
420 	register float delta = float(srcSampleCount) / float(destSampleCount);
421 	register float current = 0.0f;
422 
423 	if (delta < 1.0) {
424 		// upsample
425 		while (count--) {
426 			register float sample = *(const float *)src * gain;
427 			if (sample > 32767.0f)
428 				*(int16 *)dest = 32767;
429 			else if (sample < -32767.0f)
430 				*(int16 *)dest = -32767;
431 			else
432 				*(int16 *)dest = (int16)sample;
433 			dest += destSampleOffset;
434 			current += delta;
435 			if (current >= 1.0f) {
436 				current -= 1.0f;
437 				src += srcSampleOffset;
438 			}
439 		}
440 	} else {
441 		// downsample
442 		while (count--) {
443 			register float sample = *(const float *)src * gain;
444 			if (sample > 32767.0f)
445 				*(int16 *)dest = 32767;
446 			else if (sample < -32767.0f)
447 				*(int16 *)dest = -32767;
448 			else
449 				*(int16 *)dest = (int16)sample;
450 			dest += destSampleOffset;
451 			current += delta;
452 			register int32 skipcount = (int32)current;
453 			current -= skipcount;
454 			src += skipcount * srcSampleOffset;
455 		}
456 	}
457 }
458 
459 
460 void
461 Resampler::float_to_int8(const void *_src, int32 srcSampleOffset,
462 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
463 	int32 destSampleCount, float _gain)
464 {
465 	register const char * src = (const char *)_src;
466 	register char * dest = (char *)_dest;
467 	register int32 count = destSampleCount;
468 	register float gain = _gain * 127.0;
469 
470 	if (srcSampleCount == destSampleCount) {
471 		// optimized case for no resampling
472 		while (count--) {
473 			register float sample = *(const float *)src * gain;
474 			if (sample > 127.0f)
475 				*(int8 *)dest = 127;
476 			else if (sample < -127.0f)
477 				*(int8 *)dest = -127;
478 			else
479 				*(int8 *)dest = (int8)sample;
480 			src += srcSampleOffset;
481 			dest += destSampleOffset;
482 		}
483 		return;
484 	}
485 
486 	register float delta = float(srcSampleCount) / float(destSampleCount);
487 	register float current = 0.0f;
488 
489 	if (delta < 1.0) {
490 		// upsample
491 		while (count--) {
492 			register float sample = *(const float *)src * gain;
493 			if (sample > 127.0f)
494 				*(int8 *)dest = 127;
495 			else if (sample < -127.0f)
496 				*(int8 *)dest = -127;
497 			else
498 				*(int8 *)dest = (int8)sample;
499 			dest += destSampleOffset;
500 			current += delta;
501 			if (current >= 1.0f) {
502 				current -= 1.0f;
503 				src += srcSampleOffset;
504 			}
505 		}
506 	} else {
507 		// downsample
508 		while (count--) {
509 			register float sample = *(const float *)src * gain;
510 			if (sample > 127.0f)
511 				*(int8 *)dest = 127;
512 			else if (sample < -127.0f)
513 				*(int8 *)dest = -127;
514 			else
515 				*(int8 *)dest = (int8)sample;
516 			dest += destSampleOffset;
517 			current += delta;
518 			register int32 skipcount = (int32)current;
519 			current -= skipcount;
520 			src += skipcount * srcSampleOffset;
521 		}
522 	}
523 }
524 
525 
526 void
527 Resampler::float_to_uint8(const void *_src, int32 srcSampleOffset,
528 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
529 	int32 destSampleCount, float _gain)
530 {
531 	register const char * src = (const char *)_src;
532 	register char * dest = (char *)_dest;
533 	register int32 count = destSampleCount;
534 	register float gain = _gain * 127.0;
535 
536 	if (srcSampleCount == destSampleCount) {
537 		// optimized case for no resampling
538 		while (count--) {
539 			register float sample = 128.0f + *(const float *)src * gain;
540 			if (sample > 255.0f)
541 				*(uint8 *)dest = 255;
542 			else if (sample < 1.0f)
543 				*(uint8 *)dest = 1;
544 			else
545 				*(uint8 *)dest = (uint8)sample;
546 			src += srcSampleOffset;
547 			dest += destSampleOffset;
548 		}
549 		return;
550 	}
551 
552 	register float delta = float(srcSampleCount) / float(destSampleCount);
553 	register float current = 0.0f;
554 
555 	if (delta < 1.0) {
556 		// upsample
557 		while (count--) {
558 			register float sample = 128.0f + *(const float *)src * gain;
559 			if (sample > 255.0f)
560 				*(uint8 *)dest = 255;
561 			else if (sample < 1.0f)
562 				*(uint8 *)dest = 1;
563 			else
564 				*(uint8 *)dest = (uint8)sample;
565 			dest += destSampleOffset;
566 			current += delta;
567 			if (current >= 1.0f) {
568 				current -= 1.0f;
569 				src += srcSampleOffset;
570 			}
571 		}
572 	} else {
573 		// downsample
574 		while (count--) {
575 			register float sample = 128.0f + *(const float *)src * gain;
576 			if (sample > 255.0f)
577 				*(uint8 *)dest = 255;
578 			else if (sample < 1.0f)
579 				*(uint8 *)dest = 1;
580 			else
581 				*(uint8 *)dest = (uint8)sample;
582 			dest += destSampleOffset;
583 			current += delta;
584 			register int32 skipcount = (int32)current;
585 			current -= skipcount;
586 			src += skipcount * srcSampleOffset;
587 		}
588 	}
589 }
590