xref: /haiku/src/add-ons/media/media-add-ons/mixer/Resampler.cpp (revision 88e430cbebce77a23304a89177ae8e9dcbd6cede)
1575526ffSbeveloper /* Copyright (C) 2003 Marcus Overhagen
2575526ffSbeveloper  * Released under terms of the MIT license.
3575526ffSbeveloper  *
4575526ffSbeveloper  * A simple resampling class for the audio mixer.
5575526ffSbeveloper  * You pick the conversation 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 
12575526ffSbeveloper #include "Resampler.h"
13575526ffSbeveloper #include "debug.h"
14575526ffSbeveloper 
15575526ffSbeveloper Resampler::Resampler(uint32 src_format, uint32 dst_format)
16575526ffSbeveloper  :	fFunc(0)
17575526ffSbeveloper {
18575526ffSbeveloper 	if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) {
19575526ffSbeveloper 		switch (src_format) {
20575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_FLOAT:
21575526ffSbeveloper 				fFunc = &Resampler::float_to_float;
22575526ffSbeveloper 				return;
23575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_INT:
24575526ffSbeveloper 				fFunc = &Resampler::int32_to_float;
25575526ffSbeveloper 				return;
26575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_SHORT:
27575526ffSbeveloper 				fFunc = &Resampler::int16_to_float;
28575526ffSbeveloper 				return;
29575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_CHAR:
30575526ffSbeveloper 				fFunc = &Resampler::int8_to_float;
31575526ffSbeveloper 				return;
32575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_UCHAR:
33575526ffSbeveloper 				fFunc = &Resampler::uint8_to_float;
34575526ffSbeveloper 				return;
35575526ffSbeveloper 			default:
36575526ffSbeveloper 				FATAL("Resampler::Resampler: unknown source format 0x%x\n", src_format);
37575526ffSbeveloper 				return;
38575526ffSbeveloper 		}
39575526ffSbeveloper 	}
40575526ffSbeveloper 
41575526ffSbeveloper 	if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) {
42575526ffSbeveloper 		switch (dst_format) {
43575526ffSbeveloper 			// float=>float already handled above
44575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_INT:
45575526ffSbeveloper 				fFunc = &Resampler::float_to_int32;
46575526ffSbeveloper 				return;
47575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_SHORT:
48575526ffSbeveloper 				fFunc = &Resampler::float_to_int16;
49575526ffSbeveloper 				return;
50575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_CHAR:
51575526ffSbeveloper 				fFunc = &Resampler::float_to_int8;
52575526ffSbeveloper 				return;
53575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_UCHAR:
54575526ffSbeveloper 				fFunc = &Resampler::float_to_uint8;
55575526ffSbeveloper 				return;
56575526ffSbeveloper 			default:
57575526ffSbeveloper 				FATAL("Resampler::Resampler: unknown destination format 0x%x\n", dst_format);
58575526ffSbeveloper 				return;
59575526ffSbeveloper 		}
60575526ffSbeveloper 	}
61575526ffSbeveloper 
62575526ffSbeveloper 	FATAL("Resampler::Resampler: source or destination format must be B_AUDIO_FLOAT\n");
63575526ffSbeveloper }
64575526ffSbeveloper 
65575526ffSbeveloper Resampler::~Resampler()
66575526ffSbeveloper {
67575526ffSbeveloper }
68575526ffSbeveloper 
69575526ffSbeveloper status_t
70575526ffSbeveloper Resampler::InitCheck()
71575526ffSbeveloper {
72575526ffSbeveloper 	return (fFunc != 0) ? B_OK : B_ERROR;
73575526ffSbeveloper }
74575526ffSbeveloper 
75575526ffSbeveloper void
767ca83dacSbeveloper Resampler::float_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
777ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
787ca83dacSbeveloper {
797ca83dacSbeveloper 	register const char * src = (const char *) _src;
807ca83dacSbeveloper 	register char * dst = (char *) _dst;
817ca83dacSbeveloper 	register int32 count = dst_sample_count;
827ca83dacSbeveloper 	register float gain = _gain;
837ca83dacSbeveloper 
847ca83dacSbeveloper 	if (src_sample_count == dst_sample_count) {
857ca83dacSbeveloper 		// optimized case for no resampling
867ca83dacSbeveloper 		while (count--) {
877ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
887ca83dacSbeveloper 			src += src_sample_offset;
897ca83dacSbeveloper 			dst += dst_sample_offset;
907ca83dacSbeveloper 		}
917ca83dacSbeveloper 		return;
927ca83dacSbeveloper 	}
937ca83dacSbeveloper 
94*88e430cbSbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_offset);
957ca83dacSbeveloper 	register float current = 0.0f;
967ca83dacSbeveloper 
977ca83dacSbeveloper 	if (delta < 1.0) {
987ca83dacSbeveloper 		// upsample
997ca83dacSbeveloper 		while (count--) {
1007ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
1017ca83dacSbeveloper 			dst += dst_sample_offset;
1027ca83dacSbeveloper 			current += delta;
1037ca83dacSbeveloper 			if (current > 1.0f) {
1047ca83dacSbeveloper 				current -= 1.0f;
1057ca83dacSbeveloper 				src += src_sample_offset;
1067ca83dacSbeveloper 			}
1077ca83dacSbeveloper 		}
1087ca83dacSbeveloper 	} else {
1097ca83dacSbeveloper 		// downsample
1107ca83dacSbeveloper 		while (count--) {
1117ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
1127ca83dacSbeveloper 			src += src_sample_offset;
1137ca83dacSbeveloper 			current += delta; // delta is always > 1.0
1147ca83dacSbeveloper 			if (current < 2.0f) {
1157ca83dacSbeveloper 				current -= 1.0f;
1167ca83dacSbeveloper 				dst += dst_sample_offset;
1177ca83dacSbeveloper 			} else {
1187ca83dacSbeveloper 				int32 inc_count = (int32) current;
1197ca83dacSbeveloper 				current -= (float) inc_count;
1207ca83dacSbeveloper 				dst += inc_count * dst_sample_offset;
1217ca83dacSbeveloper 			}
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 {
130*88e430cbSbeveloper 	register const char * src = (const char *) _src;
131*88e430cbSbeveloper 	register char * dst = (char *) _dst;
132*88e430cbSbeveloper 	register int32 count = dst_sample_count;
133*88e430cbSbeveloper 	register float gain = _gain / 2147483647.0;
134*88e430cbSbeveloper 
135*88e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
136*88e430cbSbeveloper 		// optimized case for no resampling
137*88e430cbSbeveloper 		while (count--) {
138*88e430cbSbeveloper 			*(float *)dst = *(const int32 *)src * gain;
139*88e430cbSbeveloper 			src += src_sample_offset;
140*88e430cbSbeveloper 			dst += dst_sample_offset;
141*88e430cbSbeveloper 		}
142*88e430cbSbeveloper 		return;
143*88e430cbSbeveloper 	}
144*88e430cbSbeveloper 
145*88e430cbSbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_offset);
146*88e430cbSbeveloper 	register float current = 0.0f;
147*88e430cbSbeveloper 
148*88e430cbSbeveloper 	if (delta < 1.0) {
149*88e430cbSbeveloper 		// upsample
150*88e430cbSbeveloper 		while (count--) {
151*88e430cbSbeveloper 			*(float *)dst = *(const int32 *)src * gain;
152*88e430cbSbeveloper 			dst += dst_sample_offset;
153*88e430cbSbeveloper 			current += delta;
154*88e430cbSbeveloper 			if (current > 1.0f) {
155*88e430cbSbeveloper 				current -= 1.0f;
156*88e430cbSbeveloper 				src += src_sample_offset;
157*88e430cbSbeveloper 			}
158*88e430cbSbeveloper 		}
159*88e430cbSbeveloper 	} else {
160*88e430cbSbeveloper 		// downsample
161*88e430cbSbeveloper 		while (count--) {
162*88e430cbSbeveloper 			*(float *)dst = *(const int32 *)src * gain;
163*88e430cbSbeveloper 			src += src_sample_offset;
164*88e430cbSbeveloper 			current += delta; // delta is always > 1.0
165*88e430cbSbeveloper 			if (current < 2.0f) {
166*88e430cbSbeveloper 				current -= 1.0f;
167*88e430cbSbeveloper 				dst += dst_sample_offset;
168*88e430cbSbeveloper 			} else {
169*88e430cbSbeveloper 				int32 inc_count = (int32) current;
170*88e430cbSbeveloper 				current -= (float) inc_count;
171*88e430cbSbeveloper 				dst += inc_count * dst_sample_offset;
172*88e430cbSbeveloper 			}
173*88e430cbSbeveloper 		}
174*88e430cbSbeveloper 	}
175575526ffSbeveloper }
176575526ffSbeveloper 
177575526ffSbeveloper void
1787ca83dacSbeveloper Resampler::int16_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
1797ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
180575526ffSbeveloper {
181*88e430cbSbeveloper 	register const char * src = (const char *) _src;
182*88e430cbSbeveloper 	register char * dst = (char *) _dst;
183*88e430cbSbeveloper 	register int32 count = dst_sample_count;
184*88e430cbSbeveloper 	register float gain = _gain / 32767.0;
185*88e430cbSbeveloper 
186*88e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
187*88e430cbSbeveloper 		// optimized case for no resampling
188*88e430cbSbeveloper 		while (count--) {
189*88e430cbSbeveloper 			*(float *)dst = *(const int16 *)src * gain;
190*88e430cbSbeveloper 			src += src_sample_offset;
191*88e430cbSbeveloper 			dst += dst_sample_offset;
192*88e430cbSbeveloper 		}
193*88e430cbSbeveloper 		return;
194*88e430cbSbeveloper 	}
195*88e430cbSbeveloper 
196*88e430cbSbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_offset);
197*88e430cbSbeveloper 	register float current = 0.0f;
198*88e430cbSbeveloper 
199*88e430cbSbeveloper 	if (delta < 1.0) {
200*88e430cbSbeveloper 		// upsample
201*88e430cbSbeveloper 		while (count--) {
202*88e430cbSbeveloper 			*(float *)dst = *(const int16 *)src * gain;
203*88e430cbSbeveloper 			dst += dst_sample_offset;
204*88e430cbSbeveloper 			current += delta;
205*88e430cbSbeveloper 			if (current > 1.0f) {
206*88e430cbSbeveloper 				current -= 1.0f;
207*88e430cbSbeveloper 				src += src_sample_offset;
208*88e430cbSbeveloper 			}
209*88e430cbSbeveloper 		}
210*88e430cbSbeveloper 	} else {
211*88e430cbSbeveloper 		// downsample
212*88e430cbSbeveloper 		while (count--) {
213*88e430cbSbeveloper 			*(float *)dst = *(const int16 *)src * gain;
214*88e430cbSbeveloper 			src += src_sample_offset;
215*88e430cbSbeveloper 			current += delta; // delta is always > 1.0
216*88e430cbSbeveloper 			if (current < 2.0f) {
217*88e430cbSbeveloper 				current -= 1.0f;
218*88e430cbSbeveloper 				dst += dst_sample_offset;
219*88e430cbSbeveloper 			} else {
220*88e430cbSbeveloper 				int32 inc_count = (int32) current;
221*88e430cbSbeveloper 				current -= (float) inc_count;
222*88e430cbSbeveloper 				dst += inc_count * dst_sample_offset;
223*88e430cbSbeveloper 			}
224*88e430cbSbeveloper 		}
225*88e430cbSbeveloper 	}
226575526ffSbeveloper }
227575526ffSbeveloper 
228575526ffSbeveloper void
2297ca83dacSbeveloper Resampler::int8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
2307ca83dacSbeveloper 				  		 void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
231575526ffSbeveloper {
232*88e430cbSbeveloper 	register const char * src = (const char *) _src;
233*88e430cbSbeveloper 	register char * dst = (char *) _dst;
234*88e430cbSbeveloper 	register int32 count = dst_sample_count;
235*88e430cbSbeveloper 	register float gain = _gain / 127.0;
236*88e430cbSbeveloper 
237*88e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
238*88e430cbSbeveloper 		// optimized case for no resampling
239*88e430cbSbeveloper 		while (count--) {
240*88e430cbSbeveloper 			*(float *)dst = *(const int8 *)src * gain;
241*88e430cbSbeveloper 			src += src_sample_offset;
242*88e430cbSbeveloper 			dst += dst_sample_offset;
243*88e430cbSbeveloper 		}
244*88e430cbSbeveloper 		return;
245*88e430cbSbeveloper 	}
246*88e430cbSbeveloper 
247*88e430cbSbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_offset);
248*88e430cbSbeveloper 	register float current = 0.0f;
249*88e430cbSbeveloper 
250*88e430cbSbeveloper 	if (delta < 1.0) {
251*88e430cbSbeveloper 		// upsample
252*88e430cbSbeveloper 		while (count--) {
253*88e430cbSbeveloper 			*(float *)dst = *(const int8 *)src * gain;
254*88e430cbSbeveloper 			dst += dst_sample_offset;
255*88e430cbSbeveloper 			current += delta;
256*88e430cbSbeveloper 			if (current > 1.0f) {
257*88e430cbSbeveloper 				current -= 1.0f;
258*88e430cbSbeveloper 				src += src_sample_offset;
259*88e430cbSbeveloper 			}
260*88e430cbSbeveloper 		}
261*88e430cbSbeveloper 	} else {
262*88e430cbSbeveloper 		// downsample
263*88e430cbSbeveloper 		while (count--) {
264*88e430cbSbeveloper 			*(float *)dst = *(const int8 *)src * gain;
265*88e430cbSbeveloper 			src += src_sample_offset;
266*88e430cbSbeveloper 			current += delta; // delta is always > 1.0
267*88e430cbSbeveloper 			if (current < 2.0f) {
268*88e430cbSbeveloper 				current -= 1.0f;
269*88e430cbSbeveloper 				dst += dst_sample_offset;
270*88e430cbSbeveloper 			} else {
271*88e430cbSbeveloper 				int32 inc_count = (int32) current;
272*88e430cbSbeveloper 				current -= (float) inc_count;
273*88e430cbSbeveloper 				dst += inc_count * dst_sample_offset;
274*88e430cbSbeveloper 			}
275*88e430cbSbeveloper 		}
276*88e430cbSbeveloper 	}
277575526ffSbeveloper }
278575526ffSbeveloper 
279575526ffSbeveloper void
2807ca83dacSbeveloper Resampler::uint8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
2817ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
282575526ffSbeveloper {
283*88e430cbSbeveloper 	register const char * src = (const char *) _src;
284*88e430cbSbeveloper 	register char * dst = (char *) _dst;
285*88e430cbSbeveloper 	register int32 count = dst_sample_count;
286*88e430cbSbeveloper 	register float gain = _gain / 127.0;
287*88e430cbSbeveloper 
288*88e430cbSbeveloper 	if (src_sample_count == dst_sample_count) {
289*88e430cbSbeveloper 		// optimized case for no resampling
290*88e430cbSbeveloper 		while (count--) {
291*88e430cbSbeveloper 			*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain;
292*88e430cbSbeveloper 			src += src_sample_offset;
293*88e430cbSbeveloper 			dst += dst_sample_offset;
294*88e430cbSbeveloper 		}
295*88e430cbSbeveloper 		return;
296*88e430cbSbeveloper 	}
297*88e430cbSbeveloper 
298*88e430cbSbeveloper 	register float delta = float(src_sample_count) / float(dst_sample_offset);
299*88e430cbSbeveloper 	register float current = 0.0f;
300*88e430cbSbeveloper 
301*88e430cbSbeveloper 	if (delta < 1.0) {
302*88e430cbSbeveloper 		// upsample
303*88e430cbSbeveloper 		while (count--) {
304*88e430cbSbeveloper 			*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain;
305*88e430cbSbeveloper 			dst += dst_sample_offset;
306*88e430cbSbeveloper 			current += delta;
307*88e430cbSbeveloper 			if (current > 1.0f) {
308*88e430cbSbeveloper 				current -= 1.0f;
309*88e430cbSbeveloper 				src += src_sample_offset;
310*88e430cbSbeveloper 			}
311*88e430cbSbeveloper 		}
312*88e430cbSbeveloper 	} else {
313*88e430cbSbeveloper 		// downsample
314*88e430cbSbeveloper 		while (count--) {
315*88e430cbSbeveloper 			*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain;
316*88e430cbSbeveloper 			src += src_sample_offset;
317*88e430cbSbeveloper 			current += delta; // delta is always > 1.0
318*88e430cbSbeveloper 			if (current < 2.0f) {
319*88e430cbSbeveloper 				current -= 1.0f;
320*88e430cbSbeveloper 				dst += dst_sample_offset;
321*88e430cbSbeveloper 			} else {
322*88e430cbSbeveloper 				int32 inc_count = (int32) current;
323*88e430cbSbeveloper 				current -= (float) inc_count;
324*88e430cbSbeveloper 				dst += inc_count * dst_sample_offset;
325*88e430cbSbeveloper 			}
326*88e430cbSbeveloper 		}
327*88e430cbSbeveloper 	}
328575526ffSbeveloper }
329575526ffSbeveloper 
330575526ffSbeveloper void
3317ca83dacSbeveloper Resampler::float_to_int32(const void *_src, int32 src_sample_offset, int32 src_sample_count,
3327ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
333575526ffSbeveloper {
334575526ffSbeveloper }
335575526ffSbeveloper 
336575526ffSbeveloper void
3377ca83dacSbeveloper Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_sample_count,
3387ca83dacSbeveloper 				  		  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
339575526ffSbeveloper {
340575526ffSbeveloper }
341575526ffSbeveloper 
342575526ffSbeveloper void
343575526ffSbeveloper Resampler::float_to_int8(const void *src, int32 src_sample_offset, int32 src_sample_count,
3447ca83dacSbeveloper 			 			 void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
345575526ffSbeveloper {
346575526ffSbeveloper }
347575526ffSbeveloper 
348575526ffSbeveloper void
3497ca83dacSbeveloper Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_sample_count,
3507ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
351575526ffSbeveloper {
352575526ffSbeveloper }
353575526ffSbeveloper 
354