xref: /haiku/src/add-ons/media/media-add-ons/mixer/Resampler.cpp (revision 4f2fd49bdc6078128b1391191e4edac647044c3d)
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 conversion 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 "MixerDebug.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 
371 void
372 Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_sample_count,
373 				  		  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
374 {
375 	register const char * src = (const char *) _src;
376 	register char * dst = (char *) _dst;
377 	register int32 count = dst_sample_count;
378 	register float gain = _gain * 32767.0;
379 
380 	if (src_sample_count == dst_sample_count) {
381 		// optimized case for no resampling
382 		while (count--) {
383 			register float sample = *(const float *)src * gain;
384 			if (sample > 32767.0f)
385 				*(int16 *)dst = 32767;
386 			else if (sample < -32767.0f)
387 				*(int16 *)dst = -32767;
388 			else
389 				*(int16 *)dst = (int16)sample;
390 			src += src_sample_offset;
391 			dst += dst_sample_offset;
392 		}
393 		return;
394 	}
395 
396 	register float delta = float(src_sample_count) / float(dst_sample_count);
397 	register float current = 0.0f;
398 
399 	if (delta < 1.0) {
400 		// upsample
401 		while (count--) {
402 			register float sample = *(const float *)src * gain;
403 			if (sample > 32767.0f)
404 				*(int16 *)dst = 32767;
405 			else if (sample < -32767.0f)
406 				*(int16 *)dst = -32767;
407 			else
408 				*(int16 *)dst = (int16)sample;
409 			dst += dst_sample_offset;
410 			current += delta;
411 			if (current >= 1.0f) {
412 				current -= 1.0f;
413 				src += src_sample_offset;
414 			}
415 		}
416 	} else {
417 		// downsample
418 		while (count--) {
419 			register float sample = *(const float *)src * gain;
420 			if (sample > 32767.0f)
421 				*(int16 *)dst = 32767;
422 			else if (sample < -32767.0f)
423 				*(int16 *)dst = -32767;
424 			else
425 				*(int16 *)dst = (int16)sample;
426 			dst += dst_sample_offset;
427 			current += delta;
428 			register int32 skipcount = (int32)current;
429 			current -= skipcount;
430 			src += skipcount * src_sample_offset;
431 		}
432 	}
433 }
434 
435 void
436 Resampler::float_to_int8(const void *_src, int32 src_sample_offset, int32 src_sample_count,
437 			 			 void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
438 {
439 	register const char * src = (const char *) _src;
440 	register char * dst = (char *) _dst;
441 	register int32 count = dst_sample_count;
442 	register float gain = _gain * 127.0;
443 
444 	if (src_sample_count == dst_sample_count) {
445 		// optimized case for no resampling
446 		while (count--) {
447 			register float sample = *(const float *)src * gain;
448 			if (sample > 127.0f)
449 				*(int8 *)dst = 127;
450 			else if (sample < -127.0f)
451 				*(int8 *)dst = -127;
452 			else
453 				*(int8 *)dst = (int8)sample;
454 			src += src_sample_offset;
455 			dst += dst_sample_offset;
456 		}
457 		return;
458 	}
459 
460 	register float delta = float(src_sample_count) / float(dst_sample_count);
461 	register float current = 0.0f;
462 
463 	if (delta < 1.0) {
464 		// upsample
465 		while (count--) {
466 			register float sample = *(const float *)src * gain;
467 			if (sample > 127.0f)
468 				*(int8 *)dst = 127;
469 			else if (sample < -127.0f)
470 				*(int8 *)dst = -127;
471 			else
472 				*(int8 *)dst = (int8)sample;
473 			dst += dst_sample_offset;
474 			current += delta;
475 			if (current >= 1.0f) {
476 				current -= 1.0f;
477 				src += src_sample_offset;
478 			}
479 		}
480 	} else {
481 		// downsample
482 		while (count--) {
483 			register float sample = *(const float *)src * gain;
484 			if (sample > 127.0f)
485 				*(int8 *)dst = 127;
486 			else if (sample < -127.0f)
487 				*(int8 *)dst = -127;
488 			else
489 				*(int8 *)dst = (int8)sample;
490 			dst += dst_sample_offset;
491 			current += delta;
492 			register int32 skipcount = (int32)current;
493 			current -= skipcount;
494 			src += skipcount * src_sample_offset;
495 		}
496 	}
497 }
498 
499 void
500 Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_sample_count,
501 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
502 {
503 	register const char * src = (const char *) _src;
504 	register char * dst = (char *) _dst;
505 	register int32 count = dst_sample_count;
506 	register float gain = _gain * 127.0;
507 
508 	if (src_sample_count == dst_sample_count) {
509 		// optimized case for no resampling
510 		while (count--) {
511 			register float sample = 128.0f + *(const float *)src * gain;
512 			if (sample > 255.0f)
513 				*(uint8 *)dst = 255;
514 			else if (sample < 1.0f)
515 				*(uint8 *)dst = 1;
516 			else
517 				*(uint8 *)dst = (uint8)sample;
518 			src += src_sample_offset;
519 			dst += dst_sample_offset;
520 		}
521 		return;
522 	}
523 
524 	register float delta = float(src_sample_count) / float(dst_sample_count);
525 	register float current = 0.0f;
526 
527 	if (delta < 1.0) {
528 		// upsample
529 		while (count--) {
530 			register float sample = 128.0f + *(const float *)src * gain;
531 			if (sample > 255.0f)
532 				*(uint8 *)dst = 255;
533 			else if (sample < 1.0f)
534 				*(uint8 *)dst = 1;
535 			else
536 				*(uint8 *)dst = (uint8)sample;
537 			dst += dst_sample_offset;
538 			current += delta;
539 			if (current >= 1.0f) {
540 				current -= 1.0f;
541 				src += src_sample_offset;
542 			}
543 		}
544 	} else {
545 		// downsample
546 		while (count--) {
547 			register float sample = 128.0f + *(const float *)src * gain;
548 			if (sample > 255.0f)
549 				*(uint8 *)dst = 255;
550 			else if (sample < 1.0f)
551 				*(uint8 *)dst = 1;
552 			else
553 				*(uint8 *)dst = (uint8)sample;
554 			dst += dst_sample_offset;
555 			current += delta;
556 			register int32 skipcount = (int32)current;
557 			current -= skipcount;
558 			src += skipcount * src_sample_offset;
559 		}
560 	}
561 }
562