xref: /haiku/src/add-ons/media/media-add-ons/mixer/Resampler.cpp (revision f916862c2ebbbf3a1fdeac1541fc75ded977bccf)
1575526ffSbeveloper /* Copyright (C) 2003 Marcus Overhagen
2575526ffSbeveloper  * Released under terms of the MIT license.
3575526ffSbeveloper  *
4575526ffSbeveloper  * A simple resampling class for the audio mixer.
5c6a2e89fSStefano Ceccherini  * You pick the conversion function on object creation,
6575526ffSbeveloper  * and then call the Resample() function, specifying data pointer,
7575526ffSbeveloper  * offset (in bytes) to the next sample, and count of samples for
8575526ffSbeveloper  * both source and destination.
9575526ffSbeveloper  *
10575526ffSbeveloper  */
11575526ffSbeveloper 
12fb71d3a9Sbeveloper #include <MediaDefs.h>
13575526ffSbeveloper #include "Resampler.h"
14*f916862cSMarcus Overhagen #include "MixerDebug.h"
15575526ffSbeveloper 
16ff14d245SJérôme Duval Resampler::Resampler(uint32 src_format, uint32 dst_format, int16 dst_valid_bits)
17575526ffSbeveloper  :	fFunc(0)
18575526ffSbeveloper {
19575526ffSbeveloper 	if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) {
20575526ffSbeveloper 		switch (src_format) {
21575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_FLOAT:
22575526ffSbeveloper 				fFunc = &Resampler::float_to_float;
23575526ffSbeveloper 				return;
24575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_INT:
25575526ffSbeveloper 				fFunc = &Resampler::int32_to_float;
26575526ffSbeveloper 				return;
27575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_SHORT:
28575526ffSbeveloper 				fFunc = &Resampler::int16_to_float;
29575526ffSbeveloper 				return;
30575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_CHAR:
31575526ffSbeveloper 				fFunc = &Resampler::int8_to_float;
32575526ffSbeveloper 				return;
33575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_UCHAR:
34575526ffSbeveloper 				fFunc = &Resampler::uint8_to_float;
35575526ffSbeveloper 				return;
36575526ffSbeveloper 			default:
37e6c7c99fSbeveloper 				ERROR("Resampler::Resampler: unknown source format 0x%x\n", src_format);
38575526ffSbeveloper 				return;
39575526ffSbeveloper 		}
40575526ffSbeveloper 	}
41575526ffSbeveloper 
42575526ffSbeveloper 	if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) {
43575526ffSbeveloper 		switch (dst_format) {
44575526ffSbeveloper 			// float=>float already handled above
45575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_INT:
46ff14d245SJérôme Duval 				fFunc = &Resampler::float_to_int32_32;
47ff14d245SJérôme Duval 				if (dst_valid_bits == 24)
48ff14d245SJérôme Duval 					fFunc = &Resampler::float_to_int32_24;
49ebc67ddeSJérôme Duval 				else if (dst_valid_bits == 20)
50ebc67ddeSJérôme Duval 					fFunc = &Resampler::float_to_int32_20;
51575526ffSbeveloper 				return;
52575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_SHORT:
53575526ffSbeveloper 				fFunc = &Resampler::float_to_int16;
54575526ffSbeveloper 				return;
55575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_CHAR:
56575526ffSbeveloper 				fFunc = &Resampler::float_to_int8;
57575526ffSbeveloper 				return;
58575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_UCHAR:
59575526ffSbeveloper 				fFunc = &Resampler::float_to_uint8;
60575526ffSbeveloper 				return;
61575526ffSbeveloper 			default:
62e6c7c99fSbeveloper 				ERROR("Resampler::Resampler: unknown destination format 0x%x\n", dst_format);
63575526ffSbeveloper 				return;
64575526ffSbeveloper 		}
65575526ffSbeveloper 	}
66575526ffSbeveloper 
67e6c7c99fSbeveloper 	ERROR("Resampler::Resampler: source or destination format must be B_AUDIO_FLOAT\n");
68575526ffSbeveloper }
69575526ffSbeveloper 
70575526ffSbeveloper Resampler::~Resampler()
71575526ffSbeveloper {
72575526ffSbeveloper }
73575526ffSbeveloper 
74575526ffSbeveloper status_t
75575526ffSbeveloper Resampler::InitCheck()
76575526ffSbeveloper {
77575526ffSbeveloper 	return (fFunc != 0) ? B_OK : B_ERROR;
78575526ffSbeveloper }
79575526ffSbeveloper 
80575526ffSbeveloper void
817ca83dacSbeveloper Resampler::float_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
827ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
837ca83dacSbeveloper {
847ca83dacSbeveloper 	register const char * src = (const char *) _src;
857ca83dacSbeveloper 	register char * dst = (char *) _dst;
867ca83dacSbeveloper 	register int32 count = dst_sample_count;
877ca83dacSbeveloper 	register float gain = _gain;
887ca83dacSbeveloper 
897ca83dacSbeveloper 	if (src_sample_count == dst_sample_count) {
907ca83dacSbeveloper 		// optimized case for no resampling
917ca83dacSbeveloper 		while (count--) {
927ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
937ca83dacSbeveloper 			src += src_sample_offset;
947ca83dacSbeveloper 			dst += dst_sample_offset;
957ca83dacSbeveloper 		}
967ca83dacSbeveloper 		return;
977ca83dacSbeveloper 	}
987ca83dacSbeveloper 
99fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
1007ca83dacSbeveloper 	register float current = 0.0f;
1017ca83dacSbeveloper 
1027ca83dacSbeveloper 	if (delta < 1.0) {
1037ca83dacSbeveloper 		// upsample
1047ca83dacSbeveloper 		while (count--) {
1057ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
1067ca83dacSbeveloper 			dst += dst_sample_offset;
1077ca83dacSbeveloper 			current += delta;
1086b5e1508Sbeveloper 			if (current >= 1.0f) {
1097ca83dacSbeveloper 				current -= 1.0f;
1107ca83dacSbeveloper 				src += src_sample_offset;
1117ca83dacSbeveloper 			}
1127ca83dacSbeveloper 		}
1137ca83dacSbeveloper 	} else {
1147ca83dacSbeveloper 		// downsample
1157ca83dacSbeveloper 		while (count--) {
1167ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
1177ca83dacSbeveloper 			dst += dst_sample_offset;
1186b5e1508Sbeveloper 			current += delta;
1196b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
1206b5e1508Sbeveloper 			current -= skipcount;
1216b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
1227ca83dacSbeveloper 		}
1237ca83dacSbeveloper 	}
1247ca83dacSbeveloper }
1257ca83dacSbeveloper 
1267ca83dacSbeveloper void
1277ca83dacSbeveloper Resampler::int32_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
1287ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
129575526ffSbeveloper {
13088e430cbSbeveloper 	register const char * src = (const char *) _src;
13188e430cbSbeveloper 	register char * dst = (char *) _dst;
13288e430cbSbeveloper 	register int32 count = dst_sample_count;
13388e430cbSbeveloper 	register float gain = _gain / 2147483647.0;
13488e430cbSbeveloper 
13588e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
13688e430cbSbeveloper 		// optimized case for no resampling
13788e430cbSbeveloper 		while (count--) {
13888e430cbSbeveloper 			*(float *)dst = *(const int32 *)src * gain;
13988e430cbSbeveloper 			src += src_sample_offset;
14088e430cbSbeveloper 			dst += dst_sample_offset;
14188e430cbSbeveloper 		}
14288e430cbSbeveloper 		return;
14388e430cbSbeveloper 	}
14488e430cbSbeveloper 
145fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
14688e430cbSbeveloper 	register float current = 0.0f;
14788e430cbSbeveloper 
14888e430cbSbeveloper 	if (delta < 1.0) {
14988e430cbSbeveloper 		// upsample
15088e430cbSbeveloper 		while (count--) {
15188e430cbSbeveloper 			*(float *)dst = *(const int32 *)src * gain;
15288e430cbSbeveloper 			dst += dst_sample_offset;
15388e430cbSbeveloper 			current += delta;
1546b5e1508Sbeveloper 			if (current >= 1.0f) {
15588e430cbSbeveloper 				current -= 1.0f;
15688e430cbSbeveloper 				src += src_sample_offset;
15788e430cbSbeveloper 			}
15888e430cbSbeveloper 		}
15988e430cbSbeveloper 	} else {
16088e430cbSbeveloper 		// downsample
16188e430cbSbeveloper 		while (count--) {
16288e430cbSbeveloper 			*(float *)dst = *(const int32 *)src * gain;
16388e430cbSbeveloper 			dst += dst_sample_offset;
1646b5e1508Sbeveloper 			current += delta;
1656b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
1666b5e1508Sbeveloper 			current -= skipcount;
1676b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
16888e430cbSbeveloper 		}
16988e430cbSbeveloper 	}
170575526ffSbeveloper }
171575526ffSbeveloper 
172575526ffSbeveloper void
1737ca83dacSbeveloper Resampler::int16_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
1747ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
175575526ffSbeveloper {
17688e430cbSbeveloper 	register const char * src = (const char *) _src;
17788e430cbSbeveloper 	register char * dst = (char *) _dst;
17888e430cbSbeveloper 	register int32 count = dst_sample_count;
17988e430cbSbeveloper 	register float gain = _gain / 32767.0;
18088e430cbSbeveloper 
18188e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
18288e430cbSbeveloper 		// optimized case for no resampling
18388e430cbSbeveloper 		while (count--) {
18488e430cbSbeveloper 			*(float *)dst = *(const int16 *)src * gain;
18588e430cbSbeveloper 			src += src_sample_offset;
18688e430cbSbeveloper 			dst += dst_sample_offset;
18788e430cbSbeveloper 		}
18888e430cbSbeveloper 		return;
18988e430cbSbeveloper 	}
19088e430cbSbeveloper 
191fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
19288e430cbSbeveloper 	register float current = 0.0f;
19388e430cbSbeveloper 
19488e430cbSbeveloper 	if (delta < 1.0) {
19588e430cbSbeveloper 		// upsample
19688e430cbSbeveloper 		while (count--) {
19788e430cbSbeveloper 			*(float *)dst = *(const int16 *)src * gain;
19888e430cbSbeveloper 			dst += dst_sample_offset;
19988e430cbSbeveloper 			current += delta;
2006b5e1508Sbeveloper 			if (current >= 1.0f) {
20188e430cbSbeveloper 				current -= 1.0f;
20288e430cbSbeveloper 				src += src_sample_offset;
20388e430cbSbeveloper 			}
20488e430cbSbeveloper 		}
20588e430cbSbeveloper 	} else {
20688e430cbSbeveloper 		// downsample
20788e430cbSbeveloper 		while (count--) {
20888e430cbSbeveloper 			*(float *)dst = *(const int16 *)src * gain;
20988e430cbSbeveloper 			dst += dst_sample_offset;
2106b5e1508Sbeveloper 			current += delta;
2116b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
2126b5e1508Sbeveloper 			current -= skipcount;
2136b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
21488e430cbSbeveloper 		}
21588e430cbSbeveloper 	}
216575526ffSbeveloper }
217575526ffSbeveloper 
218575526ffSbeveloper void
2197ca83dacSbeveloper Resampler::int8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
2207ca83dacSbeveloper 				  		 void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
221575526ffSbeveloper {
22288e430cbSbeveloper 	register const char * src = (const char *) _src;
22388e430cbSbeveloper 	register char * dst = (char *) _dst;
22488e430cbSbeveloper 	register int32 count = dst_sample_count;
22588e430cbSbeveloper 	register float gain = _gain / 127.0;
22688e430cbSbeveloper 
22788e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
22888e430cbSbeveloper 		// optimized case for no resampling
22988e430cbSbeveloper 		while (count--) {
23088e430cbSbeveloper 			*(float *)dst = *(const int8 *)src * gain;
23188e430cbSbeveloper 			src += src_sample_offset;
23288e430cbSbeveloper 			dst += dst_sample_offset;
23388e430cbSbeveloper 		}
23488e430cbSbeveloper 		return;
23588e430cbSbeveloper 	}
23688e430cbSbeveloper 
237fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
23888e430cbSbeveloper 	register float current = 0.0f;
23988e430cbSbeveloper 
24088e430cbSbeveloper 	if (delta < 1.0) {
24188e430cbSbeveloper 		// upsample
24288e430cbSbeveloper 		while (count--) {
24388e430cbSbeveloper 			*(float *)dst = *(const int8 *)src * gain;
24488e430cbSbeveloper 			dst += dst_sample_offset;
24588e430cbSbeveloper 			current += delta;
2466b5e1508Sbeveloper 			if (current >= 1.0f) {
24788e430cbSbeveloper 				current -= 1.0f;
24888e430cbSbeveloper 				src += src_sample_offset;
24988e430cbSbeveloper 			}
25088e430cbSbeveloper 		}
25188e430cbSbeveloper 	} else {
25288e430cbSbeveloper 		// downsample
25388e430cbSbeveloper 		while (count--) {
25488e430cbSbeveloper 			*(float *)dst = *(const int8 *)src * gain;
25588e430cbSbeveloper 			dst += dst_sample_offset;
2566b5e1508Sbeveloper 			current += delta;
2576b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
2586b5e1508Sbeveloper 			current -= skipcount;
2596b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
26088e430cbSbeveloper 		}
26188e430cbSbeveloper 	}
262575526ffSbeveloper }
263575526ffSbeveloper 
264575526ffSbeveloper void
2657ca83dacSbeveloper Resampler::uint8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
2667ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
267575526ffSbeveloper {
26888e430cbSbeveloper 	register const char * src = (const char *) _src;
26988e430cbSbeveloper 	register char * dst = (char *) _dst;
27088e430cbSbeveloper 	register int32 count = dst_sample_count;
27188e430cbSbeveloper 	register float gain = _gain / 127.0;
27288e430cbSbeveloper 
27388e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
27488e430cbSbeveloper 		// optimized case for no resampling
27588e430cbSbeveloper 		while (count--) {
27688e430cbSbeveloper 			*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain;
27788e430cbSbeveloper 			src += src_sample_offset;
27888e430cbSbeveloper 			dst += dst_sample_offset;
27988e430cbSbeveloper 		}
28088e430cbSbeveloper 		return;
28188e430cbSbeveloper 	}
28288e430cbSbeveloper 
283fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
28488e430cbSbeveloper 	register float current = 0.0f;
28588e430cbSbeveloper 
28688e430cbSbeveloper 	if (delta < 1.0) {
28788e430cbSbeveloper 		// upsample
28888e430cbSbeveloper 		while (count--) {
28988e430cbSbeveloper 			*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain;
29088e430cbSbeveloper 			dst += dst_sample_offset;
29188e430cbSbeveloper 			current += delta;
2926b5e1508Sbeveloper 			if (current >= 1.0f) {
29388e430cbSbeveloper 				current -= 1.0f;
29488e430cbSbeveloper 				src += src_sample_offset;
29588e430cbSbeveloper 			}
29688e430cbSbeveloper 		}
29788e430cbSbeveloper 	} else {
29888e430cbSbeveloper 		// downsample
29988e430cbSbeveloper 		while (count--) {
30088e430cbSbeveloper 			*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain;
30188e430cbSbeveloper 			dst += dst_sample_offset;
3026b5e1508Sbeveloper 			current += delta;
3036b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
3046b5e1508Sbeveloper 			current -= skipcount;
3056b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
30688e430cbSbeveloper 		}
30788e430cbSbeveloper 	}
308575526ffSbeveloper }
309575526ffSbeveloper 
310575526ffSbeveloper void
311ff14d245SJérôme Duval Resampler::float_to_int32_32(const void *_src, int32 src_sample_offset, int32 src_sample_count,
3127ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
313575526ffSbeveloper {
3149b875fbaSbeveloper 	register const char * src = (const char *) _src;
3159b875fbaSbeveloper 	register char * dst = (char *) _dst;
3169b875fbaSbeveloper 	register int32 count = dst_sample_count;
3179b875fbaSbeveloper 	register float gain = _gain * 2147483647.0;
3189b875fbaSbeveloper 
3199b875fbaSbeveloper 	if (src_sample_count == dst_sample_count) {
3209b875fbaSbeveloper 		// optimized case for no resampling
3219b875fbaSbeveloper 		while (count--) {
3229b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
3239b875fbaSbeveloper 			if (sample > 2147483647.0f)
3249b875fbaSbeveloper 				*(int32 *)dst = 2147483647L;
3259b875fbaSbeveloper 			else if (sample < -2147483647.0f)
3269b875fbaSbeveloper 				*(int32 *)dst = -2147483647L;
3279b875fbaSbeveloper 			else
3289b875fbaSbeveloper 				*(int32 *)dst = (int32)sample;
3299b875fbaSbeveloper 			src += src_sample_offset;
3309b875fbaSbeveloper 			dst += dst_sample_offset;
3319b875fbaSbeveloper 		}
3329b875fbaSbeveloper 		return;
3339b875fbaSbeveloper 	}
3349b875fbaSbeveloper 
335fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
3369b875fbaSbeveloper 	register float current = 0.0f;
3379b875fbaSbeveloper 
3389b875fbaSbeveloper 	if (delta < 1.0) {
3399b875fbaSbeveloper 		// upsample
3409b875fbaSbeveloper 		while (count--) {
3419b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
3429b875fbaSbeveloper 			if (sample > 2147483647.0f)
3439b875fbaSbeveloper 				*(int32 *)dst = 2147483647L;
3449b875fbaSbeveloper 			else if (sample < -2147483647.0f)
3459b875fbaSbeveloper 				*(int32 *)dst = -2147483647L;
3469b875fbaSbeveloper 			else
3479b875fbaSbeveloper 				*(int32 *)dst = (int32)sample;
3489b875fbaSbeveloper 			dst += dst_sample_offset;
3499b875fbaSbeveloper 			current += delta;
3506b5e1508Sbeveloper 			if (current >= 1.0f) {
3519b875fbaSbeveloper 				current -= 1.0f;
3529b875fbaSbeveloper 				src += src_sample_offset;
3539b875fbaSbeveloper 			}
3549b875fbaSbeveloper 		}
3559b875fbaSbeveloper 	} else {
3569b875fbaSbeveloper 		// downsample
3579b875fbaSbeveloper 		while (count--) {
3589b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
3599b875fbaSbeveloper 			if (sample > 2147483647.0f)
3609b875fbaSbeveloper 				*(int32 *)dst = 2147483647L;
3619b875fbaSbeveloper 			else if (sample < -2147483647.0f)
3629b875fbaSbeveloper 				*(int32 *)dst = -2147483647L;
3639b875fbaSbeveloper 			else
3649b875fbaSbeveloper 				*(int32 *)dst = (int32)sample;
3659b875fbaSbeveloper 			dst += dst_sample_offset;
3666b5e1508Sbeveloper 			current += delta;
3676b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
3686b5e1508Sbeveloper 			current -= skipcount;
3696b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
3709b875fbaSbeveloper 		}
3719b875fbaSbeveloper 	}
372575526ffSbeveloper }
373575526ffSbeveloper 
374ff14d245SJérôme Duval 
375ff14d245SJérôme Duval void
376ff14d245SJérôme Duval Resampler::float_to_int32_24(const void *_src, int32 src_sample_offset, int32 src_sample_count,
377ff14d245SJérôme Duval 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
378ff14d245SJérôme Duval {
379ff14d245SJérôme Duval 	register const char * src = (const char *) _src;
380ff14d245SJérôme Duval 	register char * dst = (char *) _dst;
381ff14d245SJérôme Duval 	register int32 count = dst_sample_count;
382ff14d245SJérôme Duval 	register float gain = _gain * 8388607.0;
383ff14d245SJérôme Duval 
384ff14d245SJérôme Duval 	if (src_sample_count == dst_sample_count) {
385ff14d245SJérôme Duval 		// optimized case for no resampling
386ff14d245SJérôme Duval 		while (count--) {
387ff14d245SJérôme Duval 			register float sample = *(const float *)src * gain;
388ff14d245SJérôme Duval 			if (sample > 8388607.0f)
389ff14d245SJérôme Duval 				*(int32 *)dst = 8388607L;
390ebc67ddeSJérôme Duval 			else if (sample < -8388607.0f)
391ff14d245SJérôme Duval 				*(int32 *)dst = -8388607L;
392ff14d245SJérôme Duval 			else
393ff14d245SJérôme Duval 				*(int32 *)dst = (int32)sample;
394ff14d245SJérôme Duval 			src += src_sample_offset;
395ff14d245SJérôme Duval 			dst += dst_sample_offset;
396ff14d245SJérôme Duval 		}
397ff14d245SJérôme Duval 		return;
398ff14d245SJérôme Duval 	}
399ff14d245SJérôme Duval 
400ff14d245SJérôme Duval 	register float delta = float(src_sample_count) / float(dst_sample_count);
401ff14d245SJérôme Duval 	register float current = 0.0f;
402ff14d245SJérôme Duval 
403ff14d245SJérôme Duval 	if (delta < 1.0) {
404ff14d245SJérôme Duval 		// upsample
405ff14d245SJérôme Duval 		while (count--) {
406ff14d245SJérôme Duval 			register float sample = *(const float *)src * gain;
407ff14d245SJérôme Duval 			if (sample > 8388607.0f)
408ff14d245SJérôme Duval 				*(int32 *)dst = 8388607L;
409ff14d245SJérôme Duval 			else if (sample < -8388607.0f)
410ff14d245SJérôme Duval 				*(int32 *)dst = -8388607L;
411ff14d245SJérôme Duval 			else
412ff14d245SJérôme Duval 				*(int32 *)dst = (int32)sample;
413ff14d245SJérôme Duval 			dst += dst_sample_offset;
414ff14d245SJérôme Duval 			current += delta;
415ff14d245SJérôme Duval 			if (current >= 1.0f) {
416ff14d245SJérôme Duval 				current -= 1.0f;
417ff14d245SJérôme Duval 				src += src_sample_offset;
418ff14d245SJérôme Duval 			}
419ff14d245SJérôme Duval 		}
420ff14d245SJérôme Duval 	} else {
421ff14d245SJérôme Duval 		// downsample
422ff14d245SJérôme Duval 		while (count--) {
423ff14d245SJérôme Duval 			register float sample = *(const float *)src * gain;
424ff14d245SJérôme Duval 			if (sample > 8388607.0f)
425ff14d245SJérôme Duval 				*(int32 *)dst = 8388607L;
426ff14d245SJérôme Duval 			else if (sample < -8388607.0f)
427ff14d245SJérôme Duval 				*(int32 *)dst = -8388607L;
428ff14d245SJérôme Duval 			else
429ff14d245SJérôme Duval 				*(int32 *)dst = (int32)sample;
430ff14d245SJérôme Duval 			dst += dst_sample_offset;
431ff14d245SJérôme Duval 			current += delta;
432ff14d245SJérôme Duval 			register int32 skipcount = (int32)current;
433ff14d245SJérôme Duval 			current -= skipcount;
434ff14d245SJérôme Duval 			src += skipcount * src_sample_offset;
435ff14d245SJérôme Duval 		}
436ff14d245SJérôme Duval 	}
437ff14d245SJérôme Duval }
438ff14d245SJérôme Duval 
439ff14d245SJérôme Duval 
440575526ffSbeveloper void
441ebc67ddeSJérôme Duval Resampler::float_to_int32_20(const void *_src, int32 src_sample_offset, int32 src_sample_count,
442ebc67ddeSJérôme Duval 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
443ebc67ddeSJérôme Duval {
444ebc67ddeSJérôme Duval 	register const char * src = (const char *) _src;
445ebc67ddeSJérôme Duval 	register char * dst = (char *) _dst;
446ebc67ddeSJérôme Duval 	register int32 count = dst_sample_count;
447ebc67ddeSJérôme Duval 	register float gain = _gain * 524287.0;
448ebc67ddeSJérôme Duval 
449ebc67ddeSJérôme Duval 	if (src_sample_count == dst_sample_count) {
450ebc67ddeSJérôme Duval 		// optimized case for no resampling
451ebc67ddeSJérôme Duval 		while (count--) {
452ebc67ddeSJérôme Duval 			register float sample = *(const float *)src * gain;
453ebc67ddeSJérôme Duval 			if (sample > 524287.0f)
454ebc67ddeSJérôme Duval 				*(int32 *)dst = 524287L;
455ebc67ddeSJérôme Duval 			else if (sample < -524287.0f)
456ebc67ddeSJérôme Duval 				*(int32 *)dst = -524287L;
457ebc67ddeSJérôme Duval 			else
458ebc67ddeSJérôme Duval 				*(int32 *)dst = (int32)sample;
459ebc67ddeSJérôme Duval 			src += src_sample_offset;
460ebc67ddeSJérôme Duval 			dst += dst_sample_offset;
461ebc67ddeSJérôme Duval 		}
462ebc67ddeSJérôme Duval 		return;
463ebc67ddeSJérôme Duval 	}
464ebc67ddeSJérôme Duval 
465ebc67ddeSJérôme Duval 	register float delta = float(src_sample_count) / float(dst_sample_count);
466ebc67ddeSJérôme Duval 	register float current = 0.0f;
467ebc67ddeSJérôme Duval 
468ebc67ddeSJérôme Duval 	if (delta < 1.0) {
469ebc67ddeSJérôme Duval 		// upsample
470ebc67ddeSJérôme Duval 		while (count--) {
471ebc67ddeSJérôme Duval 			register float sample = *(const float *)src * gain;
472ebc67ddeSJérôme Duval 			if (sample > 524287.0f)
473ebc67ddeSJérôme Duval 				*(int32 *)dst = 524287L;
474ebc67ddeSJérôme Duval 			else if (sample < -524287.0f)
475ebc67ddeSJérôme Duval 				*(int32 *)dst = -524287L;
476ebc67ddeSJérôme Duval 			else
477ebc67ddeSJérôme Duval 				*(int32 *)dst = (int32)sample;
478ebc67ddeSJérôme Duval 			dst += dst_sample_offset;
479ebc67ddeSJérôme Duval 			current += delta;
480ebc67ddeSJérôme Duval 			if (current >= 1.0f) {
481ebc67ddeSJérôme Duval 				current -= 1.0f;
482ebc67ddeSJérôme Duval 				src += src_sample_offset;
483ebc67ddeSJérôme Duval 			}
484ebc67ddeSJérôme Duval 		}
485ebc67ddeSJérôme Duval 	} else {
486ebc67ddeSJérôme Duval 		// downsample
487ebc67ddeSJérôme Duval 		while (count--) {
488ebc67ddeSJérôme Duval 			register float sample = *(const float *)src * gain;
489ebc67ddeSJérôme Duval 			if (sample > 524287.0f)
490ebc67ddeSJérôme Duval 				*(int32 *)dst = 524287L;
491ebc67ddeSJérôme Duval 			else if (sample < -524287.0f)
492ebc67ddeSJérôme Duval 				*(int32 *)dst = -524287L;
493ebc67ddeSJérôme Duval 			else
494ebc67ddeSJérôme Duval 				*(int32 *)dst = (int32)sample;
495ebc67ddeSJérôme Duval 			dst += dst_sample_offset;
496ebc67ddeSJérôme Duval 			current += delta;
497ebc67ddeSJérôme Duval 			register int32 skipcount = (int32)current;
498ebc67ddeSJérôme Duval 			current -= skipcount;
499ebc67ddeSJérôme Duval 			src += skipcount * src_sample_offset;
500ebc67ddeSJérôme Duval 		}
501ebc67ddeSJérôme Duval 	}
502ebc67ddeSJérôme Duval }
503ebc67ddeSJérôme Duval 
504ebc67ddeSJérôme Duval 
505ebc67ddeSJérôme Duval void
5067ca83dacSbeveloper Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_sample_count,
5077ca83dacSbeveloper 				  		  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
508575526ffSbeveloper {
5099b875fbaSbeveloper 	register const char * src = (const char *) _src;
5109b875fbaSbeveloper 	register char * dst = (char *) _dst;
5119b875fbaSbeveloper 	register int32 count = dst_sample_count;
5129b875fbaSbeveloper 	register float gain = _gain * 32767.0;
5139b875fbaSbeveloper 
5149b875fbaSbeveloper 	if (src_sample_count == dst_sample_count) {
5159b875fbaSbeveloper 		// optimized case for no resampling
5169b875fbaSbeveloper 		while (count--) {
5179b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
5189b875fbaSbeveloper 			if (sample > 32767.0f)
5199b875fbaSbeveloper 				*(int16 *)dst = 32767;
5209b875fbaSbeveloper 			else if (sample < -32767.0f)
5219b875fbaSbeveloper 				*(int16 *)dst = -32767;
5229b875fbaSbeveloper 			else
5239b875fbaSbeveloper 				*(int16 *)dst = (int16)sample;
5249b875fbaSbeveloper 			src += src_sample_offset;
5259b875fbaSbeveloper 			dst += dst_sample_offset;
5269b875fbaSbeveloper 		}
5279b875fbaSbeveloper 		return;
5289b875fbaSbeveloper 	}
5299b875fbaSbeveloper 
530fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
5319b875fbaSbeveloper 	register float current = 0.0f;
5329b875fbaSbeveloper 
5339b875fbaSbeveloper 	if (delta < 1.0) {
5349b875fbaSbeveloper 		// upsample
5359b875fbaSbeveloper 		while (count--) {
5369b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
5379b875fbaSbeveloper 			if (sample > 32767.0f)
5389b875fbaSbeveloper 				*(int16 *)dst = 32767;
5399b875fbaSbeveloper 			else if (sample < -32767.0f)
5409b875fbaSbeveloper 				*(int16 *)dst = -32767;
5419b875fbaSbeveloper 			else
5429b875fbaSbeveloper 				*(int16 *)dst = (int16)sample;
5439b875fbaSbeveloper 			dst += dst_sample_offset;
5449b875fbaSbeveloper 			current += delta;
5456b5e1508Sbeveloper 			if (current >= 1.0f) {
5469b875fbaSbeveloper 				current -= 1.0f;
5479b875fbaSbeveloper 				src += src_sample_offset;
5489b875fbaSbeveloper 			}
5499b875fbaSbeveloper 		}
5509b875fbaSbeveloper 	} else {
5519b875fbaSbeveloper 		// downsample
5529b875fbaSbeveloper 		while (count--) {
5539b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
5549b875fbaSbeveloper 			if (sample > 32767.0f)
5559b875fbaSbeveloper 				*(int16 *)dst = 32767;
5569b875fbaSbeveloper 			else if (sample < -32767.0f)
5579b875fbaSbeveloper 				*(int16 *)dst = -32767;
5589b875fbaSbeveloper 			else
5599b875fbaSbeveloper 				*(int16 *)dst = (int16)sample;
5609b875fbaSbeveloper 			dst += dst_sample_offset;
5616b5e1508Sbeveloper 			current += delta;
5626b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
5636b5e1508Sbeveloper 			current -= skipcount;
5646b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
5659b875fbaSbeveloper 		}
5669b875fbaSbeveloper 	}
567575526ffSbeveloper }
568575526ffSbeveloper 
569575526ffSbeveloper void
5709b875fbaSbeveloper Resampler::float_to_int8(const void *_src, int32 src_sample_offset, int32 src_sample_count,
5717ca83dacSbeveloper 			 			 void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
572575526ffSbeveloper {
5739b875fbaSbeveloper 	register const char * src = (const char *) _src;
5749b875fbaSbeveloper 	register char * dst = (char *) _dst;
5759b875fbaSbeveloper 	register int32 count = dst_sample_count;
5769b875fbaSbeveloper 	register float gain = _gain * 127.0;
5779b875fbaSbeveloper 
5789b875fbaSbeveloper 	if (src_sample_count == dst_sample_count) {
5799b875fbaSbeveloper 		// optimized case for no resampling
5809b875fbaSbeveloper 		while (count--) {
5819b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
5829b875fbaSbeveloper 			if (sample > 127.0f)
5839b875fbaSbeveloper 				*(int8 *)dst = 127;
5849b875fbaSbeveloper 			else if (sample < -127.0f)
5859b875fbaSbeveloper 				*(int8 *)dst = -127;
5869b875fbaSbeveloper 			else
5879b875fbaSbeveloper 				*(int8 *)dst = (int8)sample;
5889b875fbaSbeveloper 			src += src_sample_offset;
5899b875fbaSbeveloper 			dst += dst_sample_offset;
5909b875fbaSbeveloper 		}
5919b875fbaSbeveloper 		return;
5929b875fbaSbeveloper 	}
5939b875fbaSbeveloper 
594fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
5959b875fbaSbeveloper 	register float current = 0.0f;
5969b875fbaSbeveloper 
5979b875fbaSbeveloper 	if (delta < 1.0) {
5989b875fbaSbeveloper 		// upsample
5999b875fbaSbeveloper 		while (count--) {
6009b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
6019b875fbaSbeveloper 			if (sample > 127.0f)
6029b875fbaSbeveloper 				*(int8 *)dst = 127;
6039b875fbaSbeveloper 			else if (sample < -127.0f)
6049b875fbaSbeveloper 				*(int8 *)dst = -127;
6059b875fbaSbeveloper 			else
6069b875fbaSbeveloper 				*(int8 *)dst = (int8)sample;
6079b875fbaSbeveloper 			dst += dst_sample_offset;
6089b875fbaSbeveloper 			current += delta;
6096b5e1508Sbeveloper 			if (current >= 1.0f) {
6109b875fbaSbeveloper 				current -= 1.0f;
6119b875fbaSbeveloper 				src += src_sample_offset;
6129b875fbaSbeveloper 			}
6139b875fbaSbeveloper 		}
6149b875fbaSbeveloper 	} else {
6159b875fbaSbeveloper 		// downsample
6169b875fbaSbeveloper 		while (count--) {
6179b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
6189b875fbaSbeveloper 			if (sample > 127.0f)
6199b875fbaSbeveloper 				*(int8 *)dst = 127;
6209b875fbaSbeveloper 			else if (sample < -127.0f)
6219b875fbaSbeveloper 				*(int8 *)dst = -127;
6229b875fbaSbeveloper 			else
6239b875fbaSbeveloper 				*(int8 *)dst = (int8)sample;
6249b875fbaSbeveloper 			dst += dst_sample_offset;
6256b5e1508Sbeveloper 			current += delta;
6266b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
6276b5e1508Sbeveloper 			current -= skipcount;
6286b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
6299b875fbaSbeveloper 		}
6309b875fbaSbeveloper 	}
631575526ffSbeveloper }
632575526ffSbeveloper 
633575526ffSbeveloper void
6347ca83dacSbeveloper Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_sample_count,
6357ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
636575526ffSbeveloper {
6379b875fbaSbeveloper 	register const char * src = (const char *) _src;
6389b875fbaSbeveloper 	register char * dst = (char *) _dst;
6399b875fbaSbeveloper 	register int32 count = dst_sample_count;
6409b875fbaSbeveloper 	register float gain = _gain * 127.0;
6419b875fbaSbeveloper 
6429b875fbaSbeveloper 	if (src_sample_count == dst_sample_count) {
6439b875fbaSbeveloper 		// optimized case for no resampling
6449b875fbaSbeveloper 		while (count--) {
6459b875fbaSbeveloper 			register float sample = 128.0f + *(const float *)src * gain;
6469b875fbaSbeveloper 			if (sample > 255.0f)
6479b875fbaSbeveloper 				*(uint8 *)dst = 255;
6489b875fbaSbeveloper 			else if (sample < 1.0f)
6499b875fbaSbeveloper 				*(uint8 *)dst = 1;
6509b875fbaSbeveloper 			else
6519b875fbaSbeveloper 				*(uint8 *)dst = (uint8)sample;
6529b875fbaSbeveloper 			src += src_sample_offset;
6539b875fbaSbeveloper 			dst += dst_sample_offset;
654575526ffSbeveloper 		}
6559b875fbaSbeveloper 		return;
6569b875fbaSbeveloper 	}
6579b875fbaSbeveloper 
658fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
6599b875fbaSbeveloper 	register float current = 0.0f;
6609b875fbaSbeveloper 
6619b875fbaSbeveloper 	if (delta < 1.0) {
6629b875fbaSbeveloper 		// upsample
6639b875fbaSbeveloper 		while (count--) {
6649b875fbaSbeveloper 			register float sample = 128.0f + *(const float *)src * gain;
6659b875fbaSbeveloper 			if (sample > 255.0f)
6669b875fbaSbeveloper 				*(uint8 *)dst = 255;
6679b875fbaSbeveloper 			else if (sample < 1.0f)
6689b875fbaSbeveloper 				*(uint8 *)dst = 1;
6699b875fbaSbeveloper 			else
6709b875fbaSbeveloper 				*(uint8 *)dst = (uint8)sample;
6719b875fbaSbeveloper 			dst += dst_sample_offset;
6729b875fbaSbeveloper 			current += delta;
6736b5e1508Sbeveloper 			if (current >= 1.0f) {
6749b875fbaSbeveloper 				current -= 1.0f;
6759b875fbaSbeveloper 				src += src_sample_offset;
6769b875fbaSbeveloper 			}
6779b875fbaSbeveloper 		}
6789b875fbaSbeveloper 	} else {
6799b875fbaSbeveloper 		// downsample
6809b875fbaSbeveloper 		while (count--) {
6819b875fbaSbeveloper 			register float sample = 128.0f + *(const float *)src * gain;
6829b875fbaSbeveloper 			if (sample > 255.0f)
6839b875fbaSbeveloper 				*(uint8 *)dst = 255;
6849b875fbaSbeveloper 			else if (sample < 1.0f)
6859b875fbaSbeveloper 				*(uint8 *)dst = 1;
6869b875fbaSbeveloper 			else
6879b875fbaSbeveloper 				*(uint8 *)dst = (uint8)sample;
6889b875fbaSbeveloper 			dst += dst_sample_offset;
6896b5e1508Sbeveloper 			current += delta;
6906b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
6916b5e1508Sbeveloper 			current -= skipcount;
6926b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
6939b875fbaSbeveloper 		}
6949b875fbaSbeveloper 	}
6959b875fbaSbeveloper }
696