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