xref: /haiku/src/add-ons/media/media-add-ons/mixer/Resampler.cpp (revision f0a85f978d3a208d80c5fc14e51e4a395aa38e66)
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"
14f916862cSMarcus Overhagen #include "MixerDebug.h"
15575526ffSbeveloper 
16*f0a85f97SJérôme Duval Resampler::Resampler(uint32 src_format, uint32 dst_format)
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:
46*f0a85f97SJérôme Duval 				fFunc = &Resampler::float_to_int32;
47575526ffSbeveloper 				return;
48575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_SHORT:
49575526ffSbeveloper 				fFunc = &Resampler::float_to_int16;
50575526ffSbeveloper 				return;
51575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_CHAR:
52575526ffSbeveloper 				fFunc = &Resampler::float_to_int8;
53575526ffSbeveloper 				return;
54575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_UCHAR:
55575526ffSbeveloper 				fFunc = &Resampler::float_to_uint8;
56575526ffSbeveloper 				return;
57575526ffSbeveloper 			default:
58e6c7c99fSbeveloper 				ERROR("Resampler::Resampler: unknown destination format 0x%x\n", dst_format);
59575526ffSbeveloper 				return;
60575526ffSbeveloper 		}
61575526ffSbeveloper 	}
62575526ffSbeveloper 
63e6c7c99fSbeveloper 	ERROR("Resampler::Resampler: source or destination format must be B_AUDIO_FLOAT\n");
64575526ffSbeveloper }
65575526ffSbeveloper 
66575526ffSbeveloper Resampler::~Resampler()
67575526ffSbeveloper {
68575526ffSbeveloper }
69575526ffSbeveloper 
70575526ffSbeveloper status_t
71575526ffSbeveloper Resampler::InitCheck()
72575526ffSbeveloper {
73575526ffSbeveloper 	return (fFunc != 0) ? B_OK : B_ERROR;
74575526ffSbeveloper }
75575526ffSbeveloper 
76575526ffSbeveloper void
777ca83dacSbeveloper Resampler::float_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
787ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
797ca83dacSbeveloper {
807ca83dacSbeveloper 	register const char * src = (const char *) _src;
817ca83dacSbeveloper 	register char * dst = (char *) _dst;
827ca83dacSbeveloper 	register int32 count = dst_sample_count;
837ca83dacSbeveloper 	register float gain = _gain;
847ca83dacSbeveloper 
857ca83dacSbeveloper 	if (src_sample_count == dst_sample_count) {
867ca83dacSbeveloper 		// optimized case for no resampling
877ca83dacSbeveloper 		while (count--) {
887ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
897ca83dacSbeveloper 			src += src_sample_offset;
907ca83dacSbeveloper 			dst += dst_sample_offset;
917ca83dacSbeveloper 		}
927ca83dacSbeveloper 		return;
937ca83dacSbeveloper 	}
947ca83dacSbeveloper 
95fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
967ca83dacSbeveloper 	register float current = 0.0f;
977ca83dacSbeveloper 
987ca83dacSbeveloper 	if (delta < 1.0) {
997ca83dacSbeveloper 		// upsample
1007ca83dacSbeveloper 		while (count--) {
1017ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
1027ca83dacSbeveloper 			dst += dst_sample_offset;
1037ca83dacSbeveloper 			current += delta;
1046b5e1508Sbeveloper 			if (current >= 1.0f) {
1057ca83dacSbeveloper 				current -= 1.0f;
1067ca83dacSbeveloper 				src += src_sample_offset;
1077ca83dacSbeveloper 			}
1087ca83dacSbeveloper 		}
1097ca83dacSbeveloper 	} else {
1107ca83dacSbeveloper 		// downsample
1117ca83dacSbeveloper 		while (count--) {
1127ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
1137ca83dacSbeveloper 			dst += dst_sample_offset;
1146b5e1508Sbeveloper 			current += delta;
1156b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
1166b5e1508Sbeveloper 			current -= skipcount;
1176b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
1187ca83dacSbeveloper 		}
1197ca83dacSbeveloper 	}
1207ca83dacSbeveloper }
1217ca83dacSbeveloper 
1227ca83dacSbeveloper void
1237ca83dacSbeveloper Resampler::int32_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
1247ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
125575526ffSbeveloper {
12688e430cbSbeveloper 	register const char * src = (const char *) _src;
12788e430cbSbeveloper 	register char * dst = (char *) _dst;
12888e430cbSbeveloper 	register int32 count = dst_sample_count;
12988e430cbSbeveloper 	register float gain = _gain / 2147483647.0;
13088e430cbSbeveloper 
13188e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
13288e430cbSbeveloper 		// optimized case for no resampling
13388e430cbSbeveloper 		while (count--) {
13488e430cbSbeveloper 			*(float *)dst = *(const int32 *)src * gain;
13588e430cbSbeveloper 			src += src_sample_offset;
13688e430cbSbeveloper 			dst += dst_sample_offset;
13788e430cbSbeveloper 		}
13888e430cbSbeveloper 		return;
13988e430cbSbeveloper 	}
14088e430cbSbeveloper 
141fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
14288e430cbSbeveloper 	register float current = 0.0f;
14388e430cbSbeveloper 
14488e430cbSbeveloper 	if (delta < 1.0) {
14588e430cbSbeveloper 		// upsample
14688e430cbSbeveloper 		while (count--) {
14788e430cbSbeveloper 			*(float *)dst = *(const int32 *)src * gain;
14888e430cbSbeveloper 			dst += dst_sample_offset;
14988e430cbSbeveloper 			current += delta;
1506b5e1508Sbeveloper 			if (current >= 1.0f) {
15188e430cbSbeveloper 				current -= 1.0f;
15288e430cbSbeveloper 				src += src_sample_offset;
15388e430cbSbeveloper 			}
15488e430cbSbeveloper 		}
15588e430cbSbeveloper 	} else {
15688e430cbSbeveloper 		// downsample
15788e430cbSbeveloper 		while (count--) {
15888e430cbSbeveloper 			*(float *)dst = *(const int32 *)src * gain;
15988e430cbSbeveloper 			dst += dst_sample_offset;
1606b5e1508Sbeveloper 			current += delta;
1616b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
1626b5e1508Sbeveloper 			current -= skipcount;
1636b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
16488e430cbSbeveloper 		}
16588e430cbSbeveloper 	}
166575526ffSbeveloper }
167575526ffSbeveloper 
168575526ffSbeveloper void
1697ca83dacSbeveloper Resampler::int16_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
1707ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
171575526ffSbeveloper {
17288e430cbSbeveloper 	register const char * src = (const char *) _src;
17388e430cbSbeveloper 	register char * dst = (char *) _dst;
17488e430cbSbeveloper 	register int32 count = dst_sample_count;
17588e430cbSbeveloper 	register float gain = _gain / 32767.0;
17688e430cbSbeveloper 
17788e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
17888e430cbSbeveloper 		// optimized case for no resampling
17988e430cbSbeveloper 		while (count--) {
18088e430cbSbeveloper 			*(float *)dst = *(const int16 *)src * gain;
18188e430cbSbeveloper 			src += src_sample_offset;
18288e430cbSbeveloper 			dst += dst_sample_offset;
18388e430cbSbeveloper 		}
18488e430cbSbeveloper 		return;
18588e430cbSbeveloper 	}
18688e430cbSbeveloper 
187fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
18888e430cbSbeveloper 	register float current = 0.0f;
18988e430cbSbeveloper 
19088e430cbSbeveloper 	if (delta < 1.0) {
19188e430cbSbeveloper 		// upsample
19288e430cbSbeveloper 		while (count--) {
19388e430cbSbeveloper 			*(float *)dst = *(const int16 *)src * gain;
19488e430cbSbeveloper 			dst += dst_sample_offset;
19588e430cbSbeveloper 			current += delta;
1966b5e1508Sbeveloper 			if (current >= 1.0f) {
19788e430cbSbeveloper 				current -= 1.0f;
19888e430cbSbeveloper 				src += src_sample_offset;
19988e430cbSbeveloper 			}
20088e430cbSbeveloper 		}
20188e430cbSbeveloper 	} else {
20288e430cbSbeveloper 		// downsample
20388e430cbSbeveloper 		while (count--) {
20488e430cbSbeveloper 			*(float *)dst = *(const int16 *)src * gain;
20588e430cbSbeveloper 			dst += dst_sample_offset;
2066b5e1508Sbeveloper 			current += delta;
2076b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
2086b5e1508Sbeveloper 			current -= skipcount;
2096b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
21088e430cbSbeveloper 		}
21188e430cbSbeveloper 	}
212575526ffSbeveloper }
213575526ffSbeveloper 
214575526ffSbeveloper void
2157ca83dacSbeveloper Resampler::int8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
2167ca83dacSbeveloper 				  		 void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
217575526ffSbeveloper {
21888e430cbSbeveloper 	register const char * src = (const char *) _src;
21988e430cbSbeveloper 	register char * dst = (char *) _dst;
22088e430cbSbeveloper 	register int32 count = dst_sample_count;
22188e430cbSbeveloper 	register float gain = _gain / 127.0;
22288e430cbSbeveloper 
22388e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
22488e430cbSbeveloper 		// optimized case for no resampling
22588e430cbSbeveloper 		while (count--) {
22688e430cbSbeveloper 			*(float *)dst = *(const int8 *)src * gain;
22788e430cbSbeveloper 			src += src_sample_offset;
22888e430cbSbeveloper 			dst += dst_sample_offset;
22988e430cbSbeveloper 		}
23088e430cbSbeveloper 		return;
23188e430cbSbeveloper 	}
23288e430cbSbeveloper 
233fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
23488e430cbSbeveloper 	register float current = 0.0f;
23588e430cbSbeveloper 
23688e430cbSbeveloper 	if (delta < 1.0) {
23788e430cbSbeveloper 		// upsample
23888e430cbSbeveloper 		while (count--) {
23988e430cbSbeveloper 			*(float *)dst = *(const int8 *)src * gain;
24088e430cbSbeveloper 			dst += dst_sample_offset;
24188e430cbSbeveloper 			current += delta;
2426b5e1508Sbeveloper 			if (current >= 1.0f) {
24388e430cbSbeveloper 				current -= 1.0f;
24488e430cbSbeveloper 				src += src_sample_offset;
24588e430cbSbeveloper 			}
24688e430cbSbeveloper 		}
24788e430cbSbeveloper 	} else {
24888e430cbSbeveloper 		// downsample
24988e430cbSbeveloper 		while (count--) {
25088e430cbSbeveloper 			*(float *)dst = *(const int8 *)src * gain;
25188e430cbSbeveloper 			dst += dst_sample_offset;
2526b5e1508Sbeveloper 			current += delta;
2536b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
2546b5e1508Sbeveloper 			current -= skipcount;
2556b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
25688e430cbSbeveloper 		}
25788e430cbSbeveloper 	}
258575526ffSbeveloper }
259575526ffSbeveloper 
260575526ffSbeveloper void
2617ca83dacSbeveloper Resampler::uint8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
2627ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
263575526ffSbeveloper {
26488e430cbSbeveloper 	register const char * src = (const char *) _src;
26588e430cbSbeveloper 	register char * dst = (char *) _dst;
26688e430cbSbeveloper 	register int32 count = dst_sample_count;
26788e430cbSbeveloper 	register float gain = _gain / 127.0;
26888e430cbSbeveloper 
26988e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
27088e430cbSbeveloper 		// optimized case for no resampling
27188e430cbSbeveloper 		while (count--) {
27288e430cbSbeveloper 			*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain;
27388e430cbSbeveloper 			src += src_sample_offset;
27488e430cbSbeveloper 			dst += dst_sample_offset;
27588e430cbSbeveloper 		}
27688e430cbSbeveloper 		return;
27788e430cbSbeveloper 	}
27888e430cbSbeveloper 
279fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
28088e430cbSbeveloper 	register float current = 0.0f;
28188e430cbSbeveloper 
28288e430cbSbeveloper 	if (delta < 1.0) {
28388e430cbSbeveloper 		// upsample
28488e430cbSbeveloper 		while (count--) {
28588e430cbSbeveloper 			*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain;
28688e430cbSbeveloper 			dst += dst_sample_offset;
28788e430cbSbeveloper 			current += delta;
2886b5e1508Sbeveloper 			if (current >= 1.0f) {
28988e430cbSbeveloper 				current -= 1.0f;
29088e430cbSbeveloper 				src += src_sample_offset;
29188e430cbSbeveloper 			}
29288e430cbSbeveloper 		}
29388e430cbSbeveloper 	} else {
29488e430cbSbeveloper 		// downsample
29588e430cbSbeveloper 		while (count--) {
29688e430cbSbeveloper 			*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain;
29788e430cbSbeveloper 			dst += dst_sample_offset;
2986b5e1508Sbeveloper 			current += delta;
2996b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
3006b5e1508Sbeveloper 			current -= skipcount;
3016b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
30288e430cbSbeveloper 		}
30388e430cbSbeveloper 	}
304575526ffSbeveloper }
305575526ffSbeveloper 
306575526ffSbeveloper void
307*f0a85f97SJérôme Duval Resampler::float_to_int32(const void *_src, int32 src_sample_offset, int32 src_sample_count,
3087ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
309575526ffSbeveloper {
3109b875fbaSbeveloper 	register const char * src = (const char *) _src;
3119b875fbaSbeveloper 	register char * dst = (char *) _dst;
3129b875fbaSbeveloper 	register int32 count = dst_sample_count;
3139b875fbaSbeveloper 	register float gain = _gain * 2147483647.0;
3149b875fbaSbeveloper 
3159b875fbaSbeveloper 	if (src_sample_count == dst_sample_count) {
3169b875fbaSbeveloper 		// optimized case for no resampling
3179b875fbaSbeveloper 		while (count--) {
3189b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
3199b875fbaSbeveloper 			if (sample > 2147483647.0f)
3209b875fbaSbeveloper 				*(int32 *)dst = 2147483647L;
3219b875fbaSbeveloper 			else if (sample < -2147483647.0f)
3229b875fbaSbeveloper 				*(int32 *)dst = -2147483647L;
3239b875fbaSbeveloper 			else
3249b875fbaSbeveloper 				*(int32 *)dst = (int32)sample;
3259b875fbaSbeveloper 			src += src_sample_offset;
3269b875fbaSbeveloper 			dst += dst_sample_offset;
3279b875fbaSbeveloper 		}
3289b875fbaSbeveloper 		return;
3299b875fbaSbeveloper 	}
3309b875fbaSbeveloper 
331fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
3329b875fbaSbeveloper 	register float current = 0.0f;
3339b875fbaSbeveloper 
3349b875fbaSbeveloper 	if (delta < 1.0) {
3359b875fbaSbeveloper 		// upsample
3369b875fbaSbeveloper 		while (count--) {
3379b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
3389b875fbaSbeveloper 			if (sample > 2147483647.0f)
3399b875fbaSbeveloper 				*(int32 *)dst = 2147483647L;
3409b875fbaSbeveloper 			else if (sample < -2147483647.0f)
3419b875fbaSbeveloper 				*(int32 *)dst = -2147483647L;
3429b875fbaSbeveloper 			else
3439b875fbaSbeveloper 				*(int32 *)dst = (int32)sample;
3449b875fbaSbeveloper 			dst += dst_sample_offset;
3459b875fbaSbeveloper 			current += delta;
3466b5e1508Sbeveloper 			if (current >= 1.0f) {
3479b875fbaSbeveloper 				current -= 1.0f;
3489b875fbaSbeveloper 				src += src_sample_offset;
3499b875fbaSbeveloper 			}
3509b875fbaSbeveloper 		}
3519b875fbaSbeveloper 	} else {
3529b875fbaSbeveloper 		// downsample
3539b875fbaSbeveloper 		while (count--) {
3549b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
3559b875fbaSbeveloper 			if (sample > 2147483647.0f)
3569b875fbaSbeveloper 				*(int32 *)dst = 2147483647L;
3579b875fbaSbeveloper 			else if (sample < -2147483647.0f)
3589b875fbaSbeveloper 				*(int32 *)dst = -2147483647L;
3599b875fbaSbeveloper 			else
3609b875fbaSbeveloper 				*(int32 *)dst = (int32)sample;
3619b875fbaSbeveloper 			dst += dst_sample_offset;
3626b5e1508Sbeveloper 			current += delta;
3636b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
3646b5e1508Sbeveloper 			current -= skipcount;
3656b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
3669b875fbaSbeveloper 		}
3679b875fbaSbeveloper 	}
368575526ffSbeveloper }
369575526ffSbeveloper 
370ff14d245SJérôme Duval 
371ff14d245SJérôme Duval void
3727ca83dacSbeveloper Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_sample_count,
3737ca83dacSbeveloper 				  		  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
374575526ffSbeveloper {
3759b875fbaSbeveloper 	register const char * src = (const char *) _src;
3769b875fbaSbeveloper 	register char * dst = (char *) _dst;
3779b875fbaSbeveloper 	register int32 count = dst_sample_count;
3789b875fbaSbeveloper 	register float gain = _gain * 32767.0;
3799b875fbaSbeveloper 
3809b875fbaSbeveloper 	if (src_sample_count == dst_sample_count) {
3819b875fbaSbeveloper 		// optimized case for no resampling
3829b875fbaSbeveloper 		while (count--) {
3839b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
3849b875fbaSbeveloper 			if (sample > 32767.0f)
3859b875fbaSbeveloper 				*(int16 *)dst = 32767;
3869b875fbaSbeveloper 			else if (sample < -32767.0f)
3879b875fbaSbeveloper 				*(int16 *)dst = -32767;
3889b875fbaSbeveloper 			else
3899b875fbaSbeveloper 				*(int16 *)dst = (int16)sample;
3909b875fbaSbeveloper 			src += src_sample_offset;
3919b875fbaSbeveloper 			dst += dst_sample_offset;
3929b875fbaSbeveloper 		}
3939b875fbaSbeveloper 		return;
3949b875fbaSbeveloper 	}
3959b875fbaSbeveloper 
396fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
3979b875fbaSbeveloper 	register float current = 0.0f;
3989b875fbaSbeveloper 
3999b875fbaSbeveloper 	if (delta < 1.0) {
4009b875fbaSbeveloper 		// upsample
4019b875fbaSbeveloper 		while (count--) {
4029b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
4039b875fbaSbeveloper 			if (sample > 32767.0f)
4049b875fbaSbeveloper 				*(int16 *)dst = 32767;
4059b875fbaSbeveloper 			else if (sample < -32767.0f)
4069b875fbaSbeveloper 				*(int16 *)dst = -32767;
4079b875fbaSbeveloper 			else
4089b875fbaSbeveloper 				*(int16 *)dst = (int16)sample;
4099b875fbaSbeveloper 			dst += dst_sample_offset;
4109b875fbaSbeveloper 			current += delta;
4116b5e1508Sbeveloper 			if (current >= 1.0f) {
4129b875fbaSbeveloper 				current -= 1.0f;
4139b875fbaSbeveloper 				src += src_sample_offset;
4149b875fbaSbeveloper 			}
4159b875fbaSbeveloper 		}
4169b875fbaSbeveloper 	} else {
4179b875fbaSbeveloper 		// downsample
4189b875fbaSbeveloper 		while (count--) {
4199b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
4209b875fbaSbeveloper 			if (sample > 32767.0f)
4219b875fbaSbeveloper 				*(int16 *)dst = 32767;
4229b875fbaSbeveloper 			else if (sample < -32767.0f)
4239b875fbaSbeveloper 				*(int16 *)dst = -32767;
4249b875fbaSbeveloper 			else
4259b875fbaSbeveloper 				*(int16 *)dst = (int16)sample;
4269b875fbaSbeveloper 			dst += dst_sample_offset;
4276b5e1508Sbeveloper 			current += delta;
4286b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
4296b5e1508Sbeveloper 			current -= skipcount;
4306b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
4319b875fbaSbeveloper 		}
4329b875fbaSbeveloper 	}
433575526ffSbeveloper }
434575526ffSbeveloper 
435575526ffSbeveloper void
4369b875fbaSbeveloper Resampler::float_to_int8(const void *_src, int32 src_sample_offset, int32 src_sample_count,
4377ca83dacSbeveloper 			 			 void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
438575526ffSbeveloper {
4399b875fbaSbeveloper 	register const char * src = (const char *) _src;
4409b875fbaSbeveloper 	register char * dst = (char *) _dst;
4419b875fbaSbeveloper 	register int32 count = dst_sample_count;
4429b875fbaSbeveloper 	register float gain = _gain * 127.0;
4439b875fbaSbeveloper 
4449b875fbaSbeveloper 	if (src_sample_count == dst_sample_count) {
4459b875fbaSbeveloper 		// optimized case for no resampling
4469b875fbaSbeveloper 		while (count--) {
4479b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
4489b875fbaSbeveloper 			if (sample > 127.0f)
4499b875fbaSbeveloper 				*(int8 *)dst = 127;
4509b875fbaSbeveloper 			else if (sample < -127.0f)
4519b875fbaSbeveloper 				*(int8 *)dst = -127;
4529b875fbaSbeveloper 			else
4539b875fbaSbeveloper 				*(int8 *)dst = (int8)sample;
4549b875fbaSbeveloper 			src += src_sample_offset;
4559b875fbaSbeveloper 			dst += dst_sample_offset;
4569b875fbaSbeveloper 		}
4579b875fbaSbeveloper 		return;
4589b875fbaSbeveloper 	}
4599b875fbaSbeveloper 
460fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
4619b875fbaSbeveloper 	register float current = 0.0f;
4629b875fbaSbeveloper 
4639b875fbaSbeveloper 	if (delta < 1.0) {
4649b875fbaSbeveloper 		// upsample
4659b875fbaSbeveloper 		while (count--) {
4669b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
4679b875fbaSbeveloper 			if (sample > 127.0f)
4689b875fbaSbeveloper 				*(int8 *)dst = 127;
4699b875fbaSbeveloper 			else if (sample < -127.0f)
4709b875fbaSbeveloper 				*(int8 *)dst = -127;
4719b875fbaSbeveloper 			else
4729b875fbaSbeveloper 				*(int8 *)dst = (int8)sample;
4739b875fbaSbeveloper 			dst += dst_sample_offset;
4749b875fbaSbeveloper 			current += delta;
4756b5e1508Sbeveloper 			if (current >= 1.0f) {
4769b875fbaSbeveloper 				current -= 1.0f;
4779b875fbaSbeveloper 				src += src_sample_offset;
4789b875fbaSbeveloper 			}
4799b875fbaSbeveloper 		}
4809b875fbaSbeveloper 	} else {
4819b875fbaSbeveloper 		// downsample
4829b875fbaSbeveloper 		while (count--) {
4839b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
4849b875fbaSbeveloper 			if (sample > 127.0f)
4859b875fbaSbeveloper 				*(int8 *)dst = 127;
4869b875fbaSbeveloper 			else if (sample < -127.0f)
4879b875fbaSbeveloper 				*(int8 *)dst = -127;
4889b875fbaSbeveloper 			else
4899b875fbaSbeveloper 				*(int8 *)dst = (int8)sample;
4909b875fbaSbeveloper 			dst += dst_sample_offset;
4916b5e1508Sbeveloper 			current += delta;
4926b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
4936b5e1508Sbeveloper 			current -= skipcount;
4946b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
4959b875fbaSbeveloper 		}
4969b875fbaSbeveloper 	}
497575526ffSbeveloper }
498575526ffSbeveloper 
499575526ffSbeveloper void
5007ca83dacSbeveloper Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_sample_count,
5017ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
502575526ffSbeveloper {
5039b875fbaSbeveloper 	register const char * src = (const char *) _src;
5049b875fbaSbeveloper 	register char * dst = (char *) _dst;
5059b875fbaSbeveloper 	register int32 count = dst_sample_count;
5069b875fbaSbeveloper 	register float gain = _gain * 127.0;
5079b875fbaSbeveloper 
5089b875fbaSbeveloper 	if (src_sample_count == dst_sample_count) {
5099b875fbaSbeveloper 		// optimized case for no resampling
5109b875fbaSbeveloper 		while (count--) {
5119b875fbaSbeveloper 			register float sample = 128.0f + *(const float *)src * gain;
5129b875fbaSbeveloper 			if (sample > 255.0f)
5139b875fbaSbeveloper 				*(uint8 *)dst = 255;
5149b875fbaSbeveloper 			else if (sample < 1.0f)
5159b875fbaSbeveloper 				*(uint8 *)dst = 1;
5169b875fbaSbeveloper 			else
5179b875fbaSbeveloper 				*(uint8 *)dst = (uint8)sample;
5189b875fbaSbeveloper 			src += src_sample_offset;
5199b875fbaSbeveloper 			dst += dst_sample_offset;
520575526ffSbeveloper 		}
5219b875fbaSbeveloper 		return;
5229b875fbaSbeveloper 	}
5239b875fbaSbeveloper 
524fb71d3a9Sbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_count);
5259b875fbaSbeveloper 	register float current = 0.0f;
5269b875fbaSbeveloper 
5279b875fbaSbeveloper 	if (delta < 1.0) {
5289b875fbaSbeveloper 		// upsample
5299b875fbaSbeveloper 		while (count--) {
5309b875fbaSbeveloper 			register float sample = 128.0f + *(const float *)src * gain;
5319b875fbaSbeveloper 			if (sample > 255.0f)
5329b875fbaSbeveloper 				*(uint8 *)dst = 255;
5339b875fbaSbeveloper 			else if (sample < 1.0f)
5349b875fbaSbeveloper 				*(uint8 *)dst = 1;
5359b875fbaSbeveloper 			else
5369b875fbaSbeveloper 				*(uint8 *)dst = (uint8)sample;
5379b875fbaSbeveloper 			dst += dst_sample_offset;
5389b875fbaSbeveloper 			current += delta;
5396b5e1508Sbeveloper 			if (current >= 1.0f) {
5409b875fbaSbeveloper 				current -= 1.0f;
5419b875fbaSbeveloper 				src += src_sample_offset;
5429b875fbaSbeveloper 			}
5439b875fbaSbeveloper 		}
5449b875fbaSbeveloper 	} else {
5459b875fbaSbeveloper 		// downsample
5469b875fbaSbeveloper 		while (count--) {
5479b875fbaSbeveloper 			register float sample = 128.0f + *(const float *)src * gain;
5489b875fbaSbeveloper 			if (sample > 255.0f)
5499b875fbaSbeveloper 				*(uint8 *)dst = 255;
5509b875fbaSbeveloper 			else if (sample < 1.0f)
5519b875fbaSbeveloper 				*(uint8 *)dst = 1;
5529b875fbaSbeveloper 			else
5539b875fbaSbeveloper 				*(uint8 *)dst = (uint8)sample;
5549b875fbaSbeveloper 			dst += dst_sample_offset;
5556b5e1508Sbeveloper 			current += delta;
5566b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
5576b5e1508Sbeveloper 			current -= skipcount;
5586b5e1508Sbeveloper 			src += skipcount * src_sample_offset;
5599b875fbaSbeveloper 		}
5609b875fbaSbeveloper 	}
5619b875fbaSbeveloper }
562