xref: /haiku/src/add-ons/media/media-add-ons/mixer/Resampler.cpp (revision a9cf57cff5dfe040f74a96705d98d6711b6b1b50)
1*a9cf57cfSAxel Dörfler /*
2*a9cf57cfSAxel Dörfler  * Copyright 2003 Marcus Overhagen
3*a9cf57cfSAxel Dörfler  * Distributed under the terms of the MIT License.
4575526ffSbeveloper  */
5575526ffSbeveloper 
6*a9cf57cfSAxel Dörfler 
7575526ffSbeveloper #include "Resampler.h"
8*a9cf57cfSAxel Dörfler 
9*a9cf57cfSAxel Dörfler #include <MediaDefs.h>
10*a9cf57cfSAxel Dörfler 
11f916862cSMarcus Overhagen #include "MixerDebug.h"
12575526ffSbeveloper 
13*a9cf57cfSAxel Dörfler 
14*a9cf57cfSAxel Dörfler /*!	A simple resampling class for the audio mixer.
15*a9cf57cfSAxel Dörfler 	You pick the conversion function on object creation,
16*a9cf57cfSAxel Dörfler 	and then call the Resample() function, specifying data pointer,
17*a9cf57cfSAxel Dörfler 	offset (in bytes) to the next sample, and count of samples for
18*a9cf57cfSAxel Dörfler 	both source and destination.
19*a9cf57cfSAxel Dörfler */
20*a9cf57cfSAxel Dörfler 
21*a9cf57cfSAxel Dörfler 
22f0a85f97SJérôme Duval Resampler::Resampler(uint32 src_format, uint32 dst_format)
23*a9cf57cfSAxel Dörfler 	:
24*a9cf57cfSAxel Dörfler 	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:
44*a9cf57cfSAxel Dörfler 				ERROR("Resampler::Resampler: unknown source format 0x%x\n",
45*a9cf57cfSAxel 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 
71*a9cf57cfSAxel Dörfler 	ERROR("Resampler::Resampler: source or destination format must be "
72*a9cf57cfSAxel Dörfler 		"B_AUDIO_FLOAT\n");
73575526ffSbeveloper }
74575526ffSbeveloper 
75*a9cf57cfSAxel Dörfler 
76575526ffSbeveloper Resampler::~Resampler()
77575526ffSbeveloper {
78575526ffSbeveloper }
79575526ffSbeveloper 
80*a9cf57cfSAxel Dörfler 
81575526ffSbeveloper status_t
82*a9cf57cfSAxel Dörfler Resampler::InitCheck() const
83575526ffSbeveloper {
84*a9cf57cfSAxel Dörfler 	return fFunc != 0 ? B_OK : B_ERROR;
85575526ffSbeveloper }
86575526ffSbeveloper 
87*a9cf57cfSAxel Dörfler 
88575526ffSbeveloper void
89*a9cf57cfSAxel Dörfler Resampler::float_to_float(const void *_src, int32 srcSampleOffset,
90*a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
91*a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
927ca83dacSbeveloper {
937ca83dacSbeveloper 	register const char * src = (const char *)_src;
94*a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
95*a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
967ca83dacSbeveloper 	register float gain = _gain;
977ca83dacSbeveloper 
98*a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
997ca83dacSbeveloper 		// optimized case for no resampling
1007ca83dacSbeveloper 		while (count--) {
101*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const float *)src * gain;
102*a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
103*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
1047ca83dacSbeveloper 		}
1057ca83dacSbeveloper 		return;
1067ca83dacSbeveloper 	}
1077ca83dacSbeveloper 
108*a9cf57cfSAxel 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--) {
114*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const float *)src * gain;
115*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
1167ca83dacSbeveloper 			current += delta;
1176b5e1508Sbeveloper 			if (current >= 1.0f) {
1187ca83dacSbeveloper 				current -= 1.0f;
119*a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
1207ca83dacSbeveloper 			}
1217ca83dacSbeveloper 		}
1227ca83dacSbeveloper 	} else {
1237ca83dacSbeveloper 		// downsample
1247ca83dacSbeveloper 		while (count--) {
125*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const float *)src * gain;
126*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
1276b5e1508Sbeveloper 			current += delta;
1286b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
1296b5e1508Sbeveloper 			current -= skipcount;
130*a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
1317ca83dacSbeveloper 		}
1327ca83dacSbeveloper 	}
1337ca83dacSbeveloper }
1347ca83dacSbeveloper 
135*a9cf57cfSAxel Dörfler 
1367ca83dacSbeveloper void
137*a9cf57cfSAxel Dörfler Resampler::int32_to_float(const void *_src, int32 srcSampleOffset,
138*a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
139*a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
140575526ffSbeveloper {
14188e430cbSbeveloper 	register const char * src = (const char *)_src;
142*a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
143*a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
14488e430cbSbeveloper 	register float gain = _gain / 2147483647.0;
14588e430cbSbeveloper 
146*a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
14788e430cbSbeveloper 		// optimized case for no resampling
14888e430cbSbeveloper 		while (count--) {
149*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int32 *)src * gain;
150*a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
151*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
15288e430cbSbeveloper 		}
15388e430cbSbeveloper 		return;
15488e430cbSbeveloper 	}
15588e430cbSbeveloper 
156*a9cf57cfSAxel 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--) {
162*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int32 *)src * gain;
163*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
16488e430cbSbeveloper 			current += delta;
1656b5e1508Sbeveloper 			if (current >= 1.0f) {
16688e430cbSbeveloper 				current -= 1.0f;
167*a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
16888e430cbSbeveloper 			}
16988e430cbSbeveloper 		}
17088e430cbSbeveloper 	} else {
17188e430cbSbeveloper 		// downsample
17288e430cbSbeveloper 		while (count--) {
173*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int32 *)src * gain;
174*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
1756b5e1508Sbeveloper 			current += delta;
1766b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
1776b5e1508Sbeveloper 			current -= skipcount;
178*a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
17988e430cbSbeveloper 		}
18088e430cbSbeveloper 	}
181575526ffSbeveloper }
182575526ffSbeveloper 
183*a9cf57cfSAxel Dörfler 
184575526ffSbeveloper void
185*a9cf57cfSAxel Dörfler Resampler::int16_to_float(const void *_src, int32 srcSampleOffset,
186*a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
187*a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
188575526ffSbeveloper {
18988e430cbSbeveloper 	register const char * src = (const char *)_src;
190*a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
191*a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
19288e430cbSbeveloper 	register float gain = _gain / 32767.0;
19388e430cbSbeveloper 
194*a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
19588e430cbSbeveloper 		// optimized case for no resampling
19688e430cbSbeveloper 		while (count--) {
197*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int16 *)src * gain;
198*a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
199*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
20088e430cbSbeveloper 		}
20188e430cbSbeveloper 		return;
20288e430cbSbeveloper 	}
20388e430cbSbeveloper 
204*a9cf57cfSAxel 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--) {
210*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int16 *)src * gain;
211*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
21288e430cbSbeveloper 			current += delta;
2136b5e1508Sbeveloper 			if (current >= 1.0f) {
21488e430cbSbeveloper 				current -= 1.0f;
215*a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
21688e430cbSbeveloper 			}
21788e430cbSbeveloper 		}
21888e430cbSbeveloper 	} else {
21988e430cbSbeveloper 		// downsample
22088e430cbSbeveloper 		while (count--) {
221*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int16 *)src * gain;
222*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
2236b5e1508Sbeveloper 			current += delta;
2246b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
2256b5e1508Sbeveloper 			current -= skipcount;
226*a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
22788e430cbSbeveloper 		}
22888e430cbSbeveloper 	}
229575526ffSbeveloper }
230575526ffSbeveloper 
231*a9cf57cfSAxel Dörfler 
232575526ffSbeveloper void
233*a9cf57cfSAxel Dörfler Resampler::int8_to_float(const void *_src, int32 srcSampleOffset,
234*a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
235*a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
236575526ffSbeveloper {
23788e430cbSbeveloper 	register const char * src = (const char *)_src;
238*a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
239*a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
24088e430cbSbeveloper 	register float gain = _gain / 127.0;
24188e430cbSbeveloper 
242*a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
24388e430cbSbeveloper 		// optimized case for no resampling
24488e430cbSbeveloper 		while (count--) {
245*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int8 *)src * gain;
246*a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
247*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
24888e430cbSbeveloper 		}
24988e430cbSbeveloper 		return;
25088e430cbSbeveloper 	}
25188e430cbSbeveloper 
252*a9cf57cfSAxel 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--) {
258*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int8 *)src * gain;
259*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
26088e430cbSbeveloper 			current += delta;
2616b5e1508Sbeveloper 			if (current >= 1.0f) {
26288e430cbSbeveloper 				current -= 1.0f;
263*a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
26488e430cbSbeveloper 			}
26588e430cbSbeveloper 		}
26688e430cbSbeveloper 	} else {
26788e430cbSbeveloper 		// downsample
26888e430cbSbeveloper 		while (count--) {
269*a9cf57cfSAxel Dörfler 			*(float *)dest = *(const int8 *)src * gain;
270*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
2716b5e1508Sbeveloper 			current += delta;
2726b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
2736b5e1508Sbeveloper 			current -= skipcount;
274*a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
27588e430cbSbeveloper 		}
27688e430cbSbeveloper 	}
277575526ffSbeveloper }
278575526ffSbeveloper 
279*a9cf57cfSAxel Dörfler 
280575526ffSbeveloper void
281*a9cf57cfSAxel Dörfler Resampler::uint8_to_float(const void *_src, int32 srcSampleOffset,
282*a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
283*a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
284575526ffSbeveloper {
28588e430cbSbeveloper 	register const char * src = (const char *)_src;
286*a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
287*a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
28888e430cbSbeveloper 	register float gain = _gain / 127.0;
28988e430cbSbeveloper 
290*a9cf57cfSAxel Dörfler 	if (srcSampleCount == destSampleCount) {
29188e430cbSbeveloper 		// optimized case for no resampling
29288e430cbSbeveloper 		while (count--) {
293*a9cf57cfSAxel Dörfler 			*(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
294*a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
295*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
29688e430cbSbeveloper 		}
29788e430cbSbeveloper 		return;
29888e430cbSbeveloper 	}
29988e430cbSbeveloper 
300*a9cf57cfSAxel 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--) {
306*a9cf57cfSAxel Dörfler 			*(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
307*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
30888e430cbSbeveloper 			current += delta;
3096b5e1508Sbeveloper 			if (current >= 1.0f) {
31088e430cbSbeveloper 				current -= 1.0f;
311*a9cf57cfSAxel Dörfler 				src += srcSampleOffset;
31288e430cbSbeveloper 			}
31388e430cbSbeveloper 		}
31488e430cbSbeveloper 	} else {
31588e430cbSbeveloper 		// downsample
31688e430cbSbeveloper 		while (count--) {
317*a9cf57cfSAxel Dörfler 			*(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
318*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
3196b5e1508Sbeveloper 			current += delta;
3206b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
3216b5e1508Sbeveloper 			current -= skipcount;
322*a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
32388e430cbSbeveloper 		}
32488e430cbSbeveloper 	}
325575526ffSbeveloper }
326575526ffSbeveloper 
327*a9cf57cfSAxel Dörfler 
328575526ffSbeveloper void
329*a9cf57cfSAxel Dörfler Resampler::float_to_int32(const void *_src, int32 srcSampleOffset,
330*a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
331*a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
332575526ffSbeveloper {
3339b875fbaSbeveloper 	register const char * src = (const char *)_src;
334*a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
335*a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
3369b875fbaSbeveloper 	register float gain = _gain * 2147483647.0;
3379b875fbaSbeveloper 
338*a9cf57cfSAxel 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)
343*a9cf57cfSAxel Dörfler 				*(int32 *)dest = 2147483647L;
3449b875fbaSbeveloper 			else if (sample < -2147483647.0f)
345*a9cf57cfSAxel Dörfler 				*(int32 *)dest = -2147483647L;
3469b875fbaSbeveloper 			else
347*a9cf57cfSAxel Dörfler 				*(int32 *)dest = (int32)sample;
348*a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
349*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
3509b875fbaSbeveloper 		}
3519b875fbaSbeveloper 		return;
3529b875fbaSbeveloper 	}
3539b875fbaSbeveloper 
354*a9cf57cfSAxel 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)
362*a9cf57cfSAxel Dörfler 				*(int32 *)dest = 2147483647L;
3639b875fbaSbeveloper 			else if (sample < -2147483647.0f)
364*a9cf57cfSAxel Dörfler 				*(int32 *)dest = -2147483647L;
3659b875fbaSbeveloper 			else
366*a9cf57cfSAxel Dörfler 				*(int32 *)dest = (int32)sample;
367*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
3689b875fbaSbeveloper 			current += delta;
3696b5e1508Sbeveloper 			if (current >= 1.0f) {
3709b875fbaSbeveloper 				current -= 1.0f;
371*a9cf57cfSAxel 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)
379*a9cf57cfSAxel Dörfler 				*(int32 *)dest = 2147483647L;
3809b875fbaSbeveloper 			else if (sample < -2147483647.0f)
381*a9cf57cfSAxel Dörfler 				*(int32 *)dest = -2147483647L;
3829b875fbaSbeveloper 			else
383*a9cf57cfSAxel Dörfler 				*(int32 *)dest = (int32)sample;
384*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
3856b5e1508Sbeveloper 			current += delta;
3866b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
3876b5e1508Sbeveloper 			current -= skipcount;
388*a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
3899b875fbaSbeveloper 		}
3909b875fbaSbeveloper 	}
391575526ffSbeveloper }
392575526ffSbeveloper 
393ff14d245SJérôme Duval 
394ff14d245SJérôme Duval void
395*a9cf57cfSAxel Dörfler Resampler::float_to_int16(const void *_src, int32 srcSampleOffset,
396*a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
397*a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
398575526ffSbeveloper {
3999b875fbaSbeveloper 	register const char * src = (const char *)_src;
400*a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
401*a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
4029b875fbaSbeveloper 	register float gain = _gain * 32767.0;
4039b875fbaSbeveloper 
404*a9cf57cfSAxel 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)
409*a9cf57cfSAxel Dörfler 				*(int16 *)dest = 32767;
4109b875fbaSbeveloper 			else if (sample < -32767.0f)
411*a9cf57cfSAxel Dörfler 				*(int16 *)dest = -32767;
4129b875fbaSbeveloper 			else
413*a9cf57cfSAxel Dörfler 				*(int16 *)dest = (int16)sample;
414*a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
415*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
4169b875fbaSbeveloper 		}
4179b875fbaSbeveloper 		return;
4189b875fbaSbeveloper 	}
4199b875fbaSbeveloper 
420*a9cf57cfSAxel 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)
428*a9cf57cfSAxel Dörfler 				*(int16 *)dest = 32767;
4299b875fbaSbeveloper 			else if (sample < -32767.0f)
430*a9cf57cfSAxel Dörfler 				*(int16 *)dest = -32767;
4319b875fbaSbeveloper 			else
432*a9cf57cfSAxel Dörfler 				*(int16 *)dest = (int16)sample;
433*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
4349b875fbaSbeveloper 			current += delta;
4356b5e1508Sbeveloper 			if (current >= 1.0f) {
4369b875fbaSbeveloper 				current -= 1.0f;
437*a9cf57cfSAxel 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)
445*a9cf57cfSAxel Dörfler 				*(int16 *)dest = 32767;
4469b875fbaSbeveloper 			else if (sample < -32767.0f)
447*a9cf57cfSAxel Dörfler 				*(int16 *)dest = -32767;
4489b875fbaSbeveloper 			else
449*a9cf57cfSAxel Dörfler 				*(int16 *)dest = (int16)sample;
450*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
4516b5e1508Sbeveloper 			current += delta;
4526b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
4536b5e1508Sbeveloper 			current -= skipcount;
454*a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
4559b875fbaSbeveloper 		}
4569b875fbaSbeveloper 	}
457575526ffSbeveloper }
458575526ffSbeveloper 
459*a9cf57cfSAxel Dörfler 
460575526ffSbeveloper void
461*a9cf57cfSAxel Dörfler Resampler::float_to_int8(const void *_src, int32 srcSampleOffset,
462*a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
463*a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
464575526ffSbeveloper {
4659b875fbaSbeveloper 	register const char * src = (const char *)_src;
466*a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
467*a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
4689b875fbaSbeveloper 	register float gain = _gain * 127.0;
4699b875fbaSbeveloper 
470*a9cf57cfSAxel 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)
475*a9cf57cfSAxel Dörfler 				*(int8 *)dest = 127;
4769b875fbaSbeveloper 			else if (sample < -127.0f)
477*a9cf57cfSAxel Dörfler 				*(int8 *)dest = -127;
4789b875fbaSbeveloper 			else
479*a9cf57cfSAxel Dörfler 				*(int8 *)dest = (int8)sample;
480*a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
481*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
4829b875fbaSbeveloper 		}
4839b875fbaSbeveloper 		return;
4849b875fbaSbeveloper 	}
4859b875fbaSbeveloper 
486*a9cf57cfSAxel 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)
494*a9cf57cfSAxel Dörfler 				*(int8 *)dest = 127;
4959b875fbaSbeveloper 			else if (sample < -127.0f)
496*a9cf57cfSAxel Dörfler 				*(int8 *)dest = -127;
4979b875fbaSbeveloper 			else
498*a9cf57cfSAxel Dörfler 				*(int8 *)dest = (int8)sample;
499*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
5009b875fbaSbeveloper 			current += delta;
5016b5e1508Sbeveloper 			if (current >= 1.0f) {
5029b875fbaSbeveloper 				current -= 1.0f;
503*a9cf57cfSAxel 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)
511*a9cf57cfSAxel Dörfler 				*(int8 *)dest = 127;
5129b875fbaSbeveloper 			else if (sample < -127.0f)
513*a9cf57cfSAxel Dörfler 				*(int8 *)dest = -127;
5149b875fbaSbeveloper 			else
515*a9cf57cfSAxel Dörfler 				*(int8 *)dest = (int8)sample;
516*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
5176b5e1508Sbeveloper 			current += delta;
5186b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
5196b5e1508Sbeveloper 			current -= skipcount;
520*a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
5219b875fbaSbeveloper 		}
5229b875fbaSbeveloper 	}
523575526ffSbeveloper }
524575526ffSbeveloper 
525*a9cf57cfSAxel Dörfler 
526575526ffSbeveloper void
527*a9cf57cfSAxel Dörfler Resampler::float_to_uint8(const void *_src, int32 srcSampleOffset,
528*a9cf57cfSAxel Dörfler 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
529*a9cf57cfSAxel Dörfler 	int32 destSampleCount, float _gain)
530575526ffSbeveloper {
5319b875fbaSbeveloper 	register const char * src = (const char *)_src;
532*a9cf57cfSAxel Dörfler 	register char * dest = (char *)_dest;
533*a9cf57cfSAxel Dörfler 	register int32 count = destSampleCount;
5349b875fbaSbeveloper 	register float gain = _gain * 127.0;
5359b875fbaSbeveloper 
536*a9cf57cfSAxel 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)
541*a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 255;
5429b875fbaSbeveloper 			else if (sample < 1.0f)
543*a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 1;
5449b875fbaSbeveloper 			else
545*a9cf57cfSAxel Dörfler 				*(uint8 *)dest = (uint8)sample;
546*a9cf57cfSAxel Dörfler 			src += srcSampleOffset;
547*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
548575526ffSbeveloper 		}
5499b875fbaSbeveloper 		return;
5509b875fbaSbeveloper 	}
5519b875fbaSbeveloper 
552*a9cf57cfSAxel 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)
560*a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 255;
5619b875fbaSbeveloper 			else if (sample < 1.0f)
562*a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 1;
5639b875fbaSbeveloper 			else
564*a9cf57cfSAxel Dörfler 				*(uint8 *)dest = (uint8)sample;
565*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
5669b875fbaSbeveloper 			current += delta;
5676b5e1508Sbeveloper 			if (current >= 1.0f) {
5689b875fbaSbeveloper 				current -= 1.0f;
569*a9cf57cfSAxel 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)
577*a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 255;
5789b875fbaSbeveloper 			else if (sample < 1.0f)
579*a9cf57cfSAxel Dörfler 				*(uint8 *)dest = 1;
5809b875fbaSbeveloper 			else
581*a9cf57cfSAxel Dörfler 				*(uint8 *)dest = (uint8)sample;
582*a9cf57cfSAxel Dörfler 			dest += destSampleOffset;
5836b5e1508Sbeveloper 			current += delta;
5846b5e1508Sbeveloper 			register int32 skipcount = (int32)current;
5856b5e1508Sbeveloper 			current -= skipcount;
586*a9cf57cfSAxel Dörfler 			src += skipcount * srcSampleOffset;
5879b875fbaSbeveloper 		}
5889b875fbaSbeveloper 	}
5899b875fbaSbeveloper }
590