xref: /haiku/src/add-ons/media/media-add-ons/mixer/Resampler.cpp (revision 78341a9351713b13dc9097957d467dfe6e4b636c)
1a9cf57cfSAxel Dörfler /*
2a9cf57cfSAxel Dörfler  * Copyright 2003 Marcus Overhagen
3a9cf57cfSAxel Dörfler  * Distributed under the terms of the MIT License.
4575526ffSbeveloper  */
5575526ffSbeveloper 
6a9cf57cfSAxel Dörfler 
7575526ffSbeveloper #include "Resampler.h"
8a9cf57cfSAxel Dörfler 
9a9cf57cfSAxel Dörfler #include <MediaDefs.h>
10a9cf57cfSAxel Dörfler 
11f916862cSMarcus Overhagen #include "MixerDebug.h"
12575526ffSbeveloper 
13a9cf57cfSAxel Dörfler 
14a9cf57cfSAxel Dörfler /*!	A simple resampling class for the audio mixer.
15a9cf57cfSAxel Dörfler 	You pick the conversion function on object creation,
16a9cf57cfSAxel Dörfler 	and then call the Resample() function, specifying data pointer,
17a9cf57cfSAxel Dörfler 	offset (in bytes) to the next sample, and count of samples for
18a9cf57cfSAxel Dörfler 	both source and destination.
19a9cf57cfSAxel Dörfler */
20a9cf57cfSAxel Dörfler 
21a9cf57cfSAxel Dörfler 
22f0a85f97SJérôme Duval Resampler::Resampler(uint32 src_format, uint32 dst_format)
23a9cf57cfSAxel Dörfler 	:
24*78341a93SJohn Scipione 	fFunc(0)
25575526ffSbeveloper {
26575526ffSbeveloper 	if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) {
27575526ffSbeveloper 		switch (src_format) {
28575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_FLOAT:
29575526ffSbeveloper 				fFunc = &Resampler::float_to_float;
30575526ffSbeveloper 				return;
31575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_INT:
32575526ffSbeveloper 				fFunc = &Resampler::int32_to_float;
33575526ffSbeveloper 				return;
34575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_SHORT:
35575526ffSbeveloper 				fFunc = &Resampler::int16_to_float;
36575526ffSbeveloper 				return;
37575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_CHAR:
38575526ffSbeveloper 				fFunc = &Resampler::int8_to_float;
39575526ffSbeveloper 				return;
40575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_UCHAR:
41575526ffSbeveloper 				fFunc = &Resampler::uint8_to_float;
42575526ffSbeveloper 				return;
43575526ffSbeveloper 			default:
44a9cf57cfSAxel Dörfler 				ERROR("Resampler::Resampler: unknown source format 0x%x\n",
45a9cf57cfSAxel Dörfler 					src_format);
46575526ffSbeveloper 				return;
47575526ffSbeveloper 		}
48575526ffSbeveloper 	}
49575526ffSbeveloper 
50575526ffSbeveloper 	if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) {
51575526ffSbeveloper 		switch (dst_format) {
52575526ffSbeveloper 			// float=>float already handled above
53575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_INT:
54f0a85f97SJérôme Duval 				fFunc = &Resampler::float_to_int32;
55575526ffSbeveloper 				return;
56575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_SHORT:
57575526ffSbeveloper 				fFunc = &Resampler::float_to_int16;
58575526ffSbeveloper 				return;
59575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_CHAR:
60575526ffSbeveloper 				fFunc = &Resampler::float_to_int8;
61575526ffSbeveloper 				return;
62575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_UCHAR:
63575526ffSbeveloper 				fFunc = &Resampler::float_to_uint8;
64575526ffSbeveloper 				return;
65575526ffSbeveloper 			default:
66e6c7c99fSbeveloper 				ERROR("Resampler::Resampler: unknown destination format 0x%x\n", dst_format);
67575526ffSbeveloper 				return;
68575526ffSbeveloper 		}
69575526ffSbeveloper 	}
70575526ffSbeveloper 
71a9cf57cfSAxel Dörfler 	ERROR("Resampler::Resampler: source or destination format must be "
72a9cf57cfSAxel Dörfler 		"B_AUDIO_FLOAT\n");
73575526ffSbeveloper }
74575526ffSbeveloper 
75a9cf57cfSAxel Dörfler 
76575526ffSbeveloper Resampler::~Resampler()
77575526ffSbeveloper {
78575526ffSbeveloper }
79575526ffSbeveloper 
80a9cf57cfSAxel Dörfler 
81575526ffSbeveloper status_t
82a9cf57cfSAxel Dörfler Resampler::InitCheck() const
83575526ffSbeveloper {
84*78341a93SJohn Scipione 	return fFunc != 0 ? B_OK : B_ERROR;
85575526ffSbeveloper }
86575526ffSbeveloper 
87a9cf57cfSAxel Dörfler 
88575526ffSbeveloper void
89a9cf57cfSAxel Dörfler Resampler::float_to_float(const void *_src, int32 srcSampleOffset,
90a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
91a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
927ca83dacSbeveloper {
937ca83dacSbeveloper 	register const char * src = (const char *)_src;
94a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
95a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
967ca83dacSbeveloper 	register float gain = _gain;
977ca83dacSbeveloper 
98a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
997ca83dacSbeveloper 		// optimized case for no resampling
1007ca83dacSbeveloper 		while (count--) {
101a9cf57cfSAxel Dörfler 			*(float *)dest = *(const float *)src * gain;
102a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
103a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
1047ca83dacSbeveloper 		}
1057ca83dacSbeveloper 		return;
1067ca83dacSbeveloper 	}
1077ca83dacSbeveloper 
108a9cf57cfSAxel Dörfler 	register float delta = float(srcSampleCount) / float(destSampleCount);
1097ca83dacSbeveloper 	register float current = 0.0f;
1107ca83dacSbeveloper 
1117ca83dacSbeveloper 	if (delta < 1.0) {
1127ca83dacSbeveloper 		// upsample
1137ca83dacSbeveloper 		while (count--) {
114a9cf57cfSAxel Dörfler 			*(float *)dest = *(const float *)src * gain;
115a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
1167ca83dacSbeveloper 			current += delta;
1176b5e1508Sbeveloper 			if (current >= 1.0f) {
1187ca83dacSbeveloper 				current -= 1.0f;
119a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
1207ca83dacSbeveloper 			}
1217ca83dacSbeveloper 		}
1227ca83dacSbeveloper 	} else {
1237ca83dacSbeveloper 		// downsample
1247ca83dacSbeveloper 		while (count--) {
125a9cf57cfSAxel Dörfler 			*(float *)dest = *(const float *)src * gain;
126a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
1276b5e1508Sbeveloper 			current += delta;
1286b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
1296b5e1508Sbeveloper 			current -= skipcount;
130a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
1317ca83dacSbeveloper 		}
1327ca83dacSbeveloper 	}
1337ca83dacSbeveloper }
1347ca83dacSbeveloper 
135a9cf57cfSAxel Dörfler 
1367ca83dacSbeveloper void
137a9cf57cfSAxel Dörfler Resampler::int32_to_float(const void *_src, int32 srcSampleOffset,
138a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
139a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
140575526ffSbeveloper {
14188e430cbSbeveloper 	register const char * src = (const char *)_src;
142a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
143a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
14488e430cbSbeveloper 	register float gain = _gain / 2147483647.0;
14588e430cbSbeveloper 
146a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
14788e430cbSbeveloper 		// optimized case for no resampling
14888e430cbSbeveloper 		while (count--) {
149a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int32 *)src * gain;
150a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
151a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
15288e430cbSbeveloper 		}
15388e430cbSbeveloper 		return;
15488e430cbSbeveloper 	}
15588e430cbSbeveloper 
156a9cf57cfSAxel Dörfler 	register float delta = float(srcSampleCount) / float(destSampleCount);
15788e430cbSbeveloper 	register float current = 0.0f;
15888e430cbSbeveloper 
15988e430cbSbeveloper 	if (delta < 1.0) {
16088e430cbSbeveloper 		// upsample
16188e430cbSbeveloper 		while (count--) {
162a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int32 *)src * gain;
163a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
16488e430cbSbeveloper 			current += delta;
1656b5e1508Sbeveloper 			if (current >= 1.0f) {
16688e430cbSbeveloper 				current -= 1.0f;
167a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
16888e430cbSbeveloper 			}
16988e430cbSbeveloper 		}
17088e430cbSbeveloper 	} else {
17188e430cbSbeveloper 		// downsample
17288e430cbSbeveloper 		while (count--) {
173a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int32 *)src * gain;
174a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
1756b5e1508Sbeveloper 			current += delta;
1766b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
1776b5e1508Sbeveloper 			current -= skipcount;
178a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
17988e430cbSbeveloper 		}
18088e430cbSbeveloper 	}
181575526ffSbeveloper }
182575526ffSbeveloper 
183a9cf57cfSAxel Dörfler 
184575526ffSbeveloper void
185a9cf57cfSAxel Dörfler Resampler::int16_to_float(const void *_src, int32 srcSampleOffset,
186a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
187a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
188575526ffSbeveloper {
18988e430cbSbeveloper 	register const char * src = (const char *)_src;
190a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
191a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
19288e430cbSbeveloper 	register float gain = _gain / 32767.0;
19388e430cbSbeveloper 
194a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
19588e430cbSbeveloper 		// optimized case for no resampling
19688e430cbSbeveloper 		while (count--) {
197a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int16 *)src * gain;
198a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
199a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
20088e430cbSbeveloper 		}
20188e430cbSbeveloper 		return;
20288e430cbSbeveloper 	}
20388e430cbSbeveloper 
204a9cf57cfSAxel Dörfler 	register float delta = float(srcSampleCount) / float(destSampleCount);
20588e430cbSbeveloper 	register float current = 0.0f;
20688e430cbSbeveloper 
20788e430cbSbeveloper 	if (delta < 1.0) {
20888e430cbSbeveloper 		// upsample
20988e430cbSbeveloper 		while (count--) {
210a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int16 *)src * gain;
211a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
21288e430cbSbeveloper 			current += delta;
2136b5e1508Sbeveloper 			if (current >= 1.0f) {
21488e430cbSbeveloper 				current -= 1.0f;
215a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
21688e430cbSbeveloper 			}
21788e430cbSbeveloper 		}
21888e430cbSbeveloper 	} else {
21988e430cbSbeveloper 		// downsample
22088e430cbSbeveloper 		while (count--) {
221a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int16 *)src * gain;
222a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
2236b5e1508Sbeveloper 			current += delta;
2246b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
2256b5e1508Sbeveloper 			current -= skipcount;
226a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
22788e430cbSbeveloper 		}
22888e430cbSbeveloper 	}
229575526ffSbeveloper }
230575526ffSbeveloper 
231a9cf57cfSAxel Dörfler 
232575526ffSbeveloper void
233a9cf57cfSAxel Dörfler Resampler::int8_to_float(const void *_src, int32 srcSampleOffset,
234a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
235a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
236575526ffSbeveloper {
23788e430cbSbeveloper 	register const char * src = (const char *)_src;
238a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
239a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
24088e430cbSbeveloper 	register float gain = _gain / 127.0;
24188e430cbSbeveloper 
242a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
24388e430cbSbeveloper 		// optimized case for no resampling
24488e430cbSbeveloper 		while (count--) {
245a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int8 *)src * gain;
246a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
247a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
24888e430cbSbeveloper 		}
24988e430cbSbeveloper 		return;
25088e430cbSbeveloper 	}
25188e430cbSbeveloper 
252a9cf57cfSAxel Dörfler 	register float delta = float(srcSampleCount) / float(destSampleCount);
25388e430cbSbeveloper 	register float current = 0.0f;
25488e430cbSbeveloper 
25588e430cbSbeveloper 	if (delta < 1.0) {
25688e430cbSbeveloper 		// upsample
25788e430cbSbeveloper 		while (count--) {
258a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int8 *)src * gain;
259a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
26088e430cbSbeveloper 			current += delta;
2616b5e1508Sbeveloper 			if (current >= 1.0f) {
26288e430cbSbeveloper 				current -= 1.0f;
263a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
26488e430cbSbeveloper 			}
26588e430cbSbeveloper 		}
26688e430cbSbeveloper 	} else {
26788e430cbSbeveloper 		// downsample
26888e430cbSbeveloper 		while (count--) {
269a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int8 *)src * gain;
270a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
2716b5e1508Sbeveloper 			current += delta;
2726b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
2736b5e1508Sbeveloper 			current -= skipcount;
274a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
27588e430cbSbeveloper 		}
27688e430cbSbeveloper 	}
277575526ffSbeveloper }
278575526ffSbeveloper 
279a9cf57cfSAxel Dörfler 
280575526ffSbeveloper void
281a9cf57cfSAxel Dörfler Resampler::uint8_to_float(const void *_src, int32 srcSampleOffset,
282a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
283a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
284575526ffSbeveloper {
28588e430cbSbeveloper 	register const char * src = (const char *)_src;
286a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
287a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
28888e430cbSbeveloper 	register float gain = _gain / 127.0;
28988e430cbSbeveloper 
290a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
29188e430cbSbeveloper 		// optimized case for no resampling
29288e430cbSbeveloper 		while (count--) {
293a9cf57cfSAxel Dörfler 			*(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
294a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
295a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
29688e430cbSbeveloper 		}
29788e430cbSbeveloper 		return;
29888e430cbSbeveloper 	}
29988e430cbSbeveloper 
300a9cf57cfSAxel Dörfler 	register float delta = float(srcSampleCount) / float(destSampleCount);
30188e430cbSbeveloper 	register float current = 0.0f;
30288e430cbSbeveloper 
30388e430cbSbeveloper 	if (delta < 1.0) {
30488e430cbSbeveloper 		// upsample
30588e430cbSbeveloper 		while (count--) {
306a9cf57cfSAxel Dörfler 			*(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
307a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
30888e430cbSbeveloper 			current += delta;
3096b5e1508Sbeveloper 			if (current >= 1.0f) {
31088e430cbSbeveloper 				current -= 1.0f;
311a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
31288e430cbSbeveloper 			}
31388e430cbSbeveloper 		}
31488e430cbSbeveloper 	} else {
31588e430cbSbeveloper 		// downsample
31688e430cbSbeveloper 		while (count--) {
317a9cf57cfSAxel Dörfler 			*(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
318a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
3196b5e1508Sbeveloper 			current += delta;
3206b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
3216b5e1508Sbeveloper 			current -= skipcount;
322a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
32388e430cbSbeveloper 		}
32488e430cbSbeveloper 	}
325575526ffSbeveloper }
326575526ffSbeveloper 
327a9cf57cfSAxel Dörfler 
328575526ffSbeveloper void
329a9cf57cfSAxel Dörfler Resampler::float_to_int32(const void *_src, int32 srcSampleOffset,
330a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
331a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
332575526ffSbeveloper {
3339b875fbaSbeveloper 	register const char * src = (const char *)_src;
334a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
335a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
3369b875fbaSbeveloper 	register float gain = _gain * 2147483647.0;
3379b875fbaSbeveloper 
338a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
3399b875fbaSbeveloper 		// optimized case for no resampling
3409b875fbaSbeveloper 		while (count--) {
3419b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
3429b875fbaSbeveloper 			if (sample > 2147483647.0f)
343a9cf57cfSAxel Dörfler 				*(int32 *)dest = 2147483647L;
3449b875fbaSbeveloper 			else if (sample < -2147483647.0f)
345a9cf57cfSAxel Dörfler 				*(int32 *)dest = -2147483647L;
3469b875fbaSbeveloper 			else
347a9cf57cfSAxel Dörfler 				*(int32 *)dest = (int32)sample;
348a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
349a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
3509b875fbaSbeveloper 		}
3519b875fbaSbeveloper 		return;
3529b875fbaSbeveloper 	}
3539b875fbaSbeveloper 
354a9cf57cfSAxel Dörfler 	register float delta = float(srcSampleCount) / float(destSampleCount);
3559b875fbaSbeveloper 	register float current = 0.0f;
3569b875fbaSbeveloper 
3579b875fbaSbeveloper 	if (delta < 1.0) {
3589b875fbaSbeveloper 		// upsample
3599b875fbaSbeveloper 		while (count--) {
3609b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
3619b875fbaSbeveloper 			if (sample > 2147483647.0f)
362a9cf57cfSAxel Dörfler 				*(int32 *)dest = 2147483647L;
3639b875fbaSbeveloper 			else if (sample < -2147483647.0f)
364a9cf57cfSAxel Dörfler 				*(int32 *)dest = -2147483647L;
3659b875fbaSbeveloper 			else
366a9cf57cfSAxel Dörfler 				*(int32 *)dest = (int32)sample;
367a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
3689b875fbaSbeveloper 			current += delta;
3696b5e1508Sbeveloper 			if (current >= 1.0f) {
3709b875fbaSbeveloper 				current -= 1.0f;
371a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
3729b875fbaSbeveloper 			}
3739b875fbaSbeveloper 		}
3749b875fbaSbeveloper 	} else {
3759b875fbaSbeveloper 		// downsample
3769b875fbaSbeveloper 		while (count--) {
3779b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
3789b875fbaSbeveloper 			if (sample > 2147483647.0f)
379a9cf57cfSAxel Dörfler 				*(int32 *)dest = 2147483647L;
3809b875fbaSbeveloper 			else if (sample < -2147483647.0f)
381a9cf57cfSAxel Dörfler 				*(int32 *)dest = -2147483647L;
3829b875fbaSbeveloper 			else
383a9cf57cfSAxel Dörfler 				*(int32 *)dest = (int32)sample;
384a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
3856b5e1508Sbeveloper 			current += delta;
3866b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
3876b5e1508Sbeveloper 			current -= skipcount;
388a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
3899b875fbaSbeveloper 		}
3909b875fbaSbeveloper 	}
391575526ffSbeveloper }
392575526ffSbeveloper 
393ff14d245SJérôme Duval 
394ff14d245SJérôme Duval void
395a9cf57cfSAxel Dörfler Resampler::float_to_int16(const void *_src, int32 srcSampleOffset,
396a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
397a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
398575526ffSbeveloper {
3999b875fbaSbeveloper 	register const char * src = (const char *)_src;
400a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
401a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
4029b875fbaSbeveloper 	register float gain = _gain * 32767.0;
4039b875fbaSbeveloper 
404a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
4059b875fbaSbeveloper 		// optimized case for no resampling
4069b875fbaSbeveloper 		while (count--) {
4079b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
4089b875fbaSbeveloper 			if (sample > 32767.0f)
409a9cf57cfSAxel Dörfler 				*(int16 *)dest = 32767;
4109b875fbaSbeveloper 			else if (sample < -32767.0f)
411a9cf57cfSAxel Dörfler 				*(int16 *)dest = -32767;
4129b875fbaSbeveloper 			else
413a9cf57cfSAxel Dörfler 				*(int16 *)dest = (int16)sample;
414a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
415a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
4169b875fbaSbeveloper 		}
4179b875fbaSbeveloper 		return;
4189b875fbaSbeveloper 	}
4199b875fbaSbeveloper 
420a9cf57cfSAxel Dörfler 	register float delta = float(srcSampleCount) / float(destSampleCount);
4219b875fbaSbeveloper 	register float current = 0.0f;
4229b875fbaSbeveloper 
4239b875fbaSbeveloper 	if (delta < 1.0) {
4249b875fbaSbeveloper 		// upsample
4259b875fbaSbeveloper 		while (count--) {
4269b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
4279b875fbaSbeveloper 			if (sample > 32767.0f)
428a9cf57cfSAxel Dörfler 				*(int16 *)dest = 32767;
4299b875fbaSbeveloper 			else if (sample < -32767.0f)
430a9cf57cfSAxel Dörfler 				*(int16 *)dest = -32767;
4319b875fbaSbeveloper 			else
432a9cf57cfSAxel Dörfler 				*(int16 *)dest = (int16)sample;
433a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
4349b875fbaSbeveloper 			current += delta;
4356b5e1508Sbeveloper 			if (current >= 1.0f) {
4369b875fbaSbeveloper 				current -= 1.0f;
437a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
4389b875fbaSbeveloper 			}
4399b875fbaSbeveloper 		}
4409b875fbaSbeveloper 	} else {
4419b875fbaSbeveloper 		// downsample
4429b875fbaSbeveloper 		while (count--) {
4439b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
4449b875fbaSbeveloper 			if (sample > 32767.0f)
445a9cf57cfSAxel Dörfler 				*(int16 *)dest = 32767;
4469b875fbaSbeveloper 			else if (sample < -32767.0f)
447a9cf57cfSAxel Dörfler 				*(int16 *)dest = -32767;
4489b875fbaSbeveloper 			else
449a9cf57cfSAxel Dörfler 				*(int16 *)dest = (int16)sample;
450a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
4516b5e1508Sbeveloper 			current += delta;
4526b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
4536b5e1508Sbeveloper 			current -= skipcount;
454a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
4559b875fbaSbeveloper 		}
4569b875fbaSbeveloper 	}
457575526ffSbeveloper }
458575526ffSbeveloper 
459a9cf57cfSAxel Dörfler 
460575526ffSbeveloper void
461a9cf57cfSAxel Dörfler Resampler::float_to_int8(const void *_src, int32 srcSampleOffset,
462a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
463a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
464575526ffSbeveloper {
4659b875fbaSbeveloper 	register const char * src = (const char *)_src;
466a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
467a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
4689b875fbaSbeveloper 	register float gain = _gain * 127.0;
4699b875fbaSbeveloper 
470a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
4719b875fbaSbeveloper 		// optimized case for no resampling
4729b875fbaSbeveloper 		while (count--) {
4739b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
4749b875fbaSbeveloper 			if (sample > 127.0f)
475a9cf57cfSAxel Dörfler 				*(int8 *)dest = 127;
4769b875fbaSbeveloper 			else if (sample < -127.0f)
477a9cf57cfSAxel Dörfler 				*(int8 *)dest = -127;
4789b875fbaSbeveloper 			else
479a9cf57cfSAxel Dörfler 				*(int8 *)dest = (int8)sample;
480a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
481a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
4829b875fbaSbeveloper 		}
4839b875fbaSbeveloper 		return;
4849b875fbaSbeveloper 	}
4859b875fbaSbeveloper 
486a9cf57cfSAxel Dörfler 	register float delta = float(srcSampleCount) / float(destSampleCount);
4879b875fbaSbeveloper 	register float current = 0.0f;
4889b875fbaSbeveloper 
4899b875fbaSbeveloper 	if (delta < 1.0) {
4909b875fbaSbeveloper 		// upsample
4919b875fbaSbeveloper 		while (count--) {
4929b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
4939b875fbaSbeveloper 			if (sample > 127.0f)
494a9cf57cfSAxel Dörfler 				*(int8 *)dest = 127;
4959b875fbaSbeveloper 			else if (sample < -127.0f)
496a9cf57cfSAxel Dörfler 				*(int8 *)dest = -127;
4979b875fbaSbeveloper 			else
498a9cf57cfSAxel Dörfler 				*(int8 *)dest = (int8)sample;
499a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
5009b875fbaSbeveloper 			current += delta;
5016b5e1508Sbeveloper 			if (current >= 1.0f) {
5029b875fbaSbeveloper 				current -= 1.0f;
503a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
5049b875fbaSbeveloper 			}
5059b875fbaSbeveloper 		}
5069b875fbaSbeveloper 	} else {
5079b875fbaSbeveloper 		// downsample
5089b875fbaSbeveloper 		while (count--) {
5099b875fbaSbeveloper 			register float sample = *(const float *)src * gain;
5109b875fbaSbeveloper 			if (sample > 127.0f)
511a9cf57cfSAxel Dörfler 				*(int8 *)dest = 127;
5129b875fbaSbeveloper 			else if (sample < -127.0f)
513a9cf57cfSAxel Dörfler 				*(int8 *)dest = -127;
5149b875fbaSbeveloper 			else
515a9cf57cfSAxel Dörfler 				*(int8 *)dest = (int8)sample;
516a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
5176b5e1508Sbeveloper 			current += delta;
5186b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
5196b5e1508Sbeveloper 			current -= skipcount;
520a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
5219b875fbaSbeveloper 		}
5229b875fbaSbeveloper 	}
523575526ffSbeveloper }
524575526ffSbeveloper 
525a9cf57cfSAxel Dörfler 
526575526ffSbeveloper void
527a9cf57cfSAxel Dörfler Resampler::float_to_uint8(const void *_src, int32 srcSampleOffset,
528a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
529a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
530575526ffSbeveloper {
5319b875fbaSbeveloper 	register const char * src = (const char *)_src;
532a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
533a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
5349b875fbaSbeveloper 	register float gain = _gain * 127.0;
5359b875fbaSbeveloper 
536a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
5379b875fbaSbeveloper 		// optimized case for no resampling
5389b875fbaSbeveloper 		while (count--) {
5399b875fbaSbeveloper 			register float sample = 128.0f + *(const float *)src * gain;
5409b875fbaSbeveloper 			if (sample > 255.0f)
541a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 255;
5429b875fbaSbeveloper 			else if (sample < 1.0f)
543a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 1;
5449b875fbaSbeveloper 			else
545a9cf57cfSAxel Dörfler 				*(uint8 *)dest = (uint8)sample;
546a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
547a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
548575526ffSbeveloper 		}
5499b875fbaSbeveloper 		return;
5509b875fbaSbeveloper 	}
5519b875fbaSbeveloper 
552a9cf57cfSAxel Dörfler 	register float delta = float(srcSampleCount) / float(destSampleCount);
5539b875fbaSbeveloper 	register float current = 0.0f;
5549b875fbaSbeveloper 
5559b875fbaSbeveloper 	if (delta < 1.0) {
5569b875fbaSbeveloper 		// upsample
5579b875fbaSbeveloper 		while (count--) {
5589b875fbaSbeveloper 			register float sample = 128.0f + *(const float *)src * gain;
5599b875fbaSbeveloper 			if (sample > 255.0f)
560a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 255;
5619b875fbaSbeveloper 			else if (sample < 1.0f)
562a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 1;
5639b875fbaSbeveloper 			else
564a9cf57cfSAxel Dörfler 				*(uint8 *)dest = (uint8)sample;
565a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
5669b875fbaSbeveloper 			current += delta;
5676b5e1508Sbeveloper 			if (current >= 1.0f) {
5689b875fbaSbeveloper 				current -= 1.0f;
569a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
5709b875fbaSbeveloper 			}
5719b875fbaSbeveloper 		}
5729b875fbaSbeveloper 	} else {
5739b875fbaSbeveloper 		// downsample
5749b875fbaSbeveloper 		while (count--) {
5759b875fbaSbeveloper 			register float sample = 128.0f + *(const float *)src * gain;
5769b875fbaSbeveloper 			if (sample > 255.0f)
577a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 255;
5789b875fbaSbeveloper 			else if (sample < 1.0f)
579a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 1;
5809b875fbaSbeveloper 			else
581a9cf57cfSAxel Dörfler 				*(uint8 *)dest = (uint8)sample;
582a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
5836b5e1508Sbeveloper 			current += delta;
5846b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
5856b5e1508Sbeveloper 			current -= skipcount;
586a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
5879b875fbaSbeveloper 		}
5889b875fbaSbeveloper 	}
5899b875fbaSbeveloper }
590