xref: /haiku/src/add-ons/media/media-add-ons/mixer/Resampler.cpp (revision 27606dae3658767f5995699ada7fc8a645677ee5)
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 
22*27606daeSAdrien Destugues template<typename inType, typename outType, int gnum, int gden, int offset,
23*27606daeSAdrien Destugues 	int32 min, int32 max> static void
24*27606daeSAdrien Destugues kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
25*27606daeSAdrien Destugues 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
26*27606daeSAdrien Destugues 	int32 destSampleCount, float _gain)
27*27606daeSAdrien Destugues {
28*27606daeSAdrien Destugues 	register const char * src = (const char *)_src;
29*27606daeSAdrien Destugues 	register char * dest = (char *)_dest;
30*27606daeSAdrien Destugues 	register int32 count = destSampleCount;
31*27606daeSAdrien Destugues 	register float gain = _gain * gnum / gden;
32*27606daeSAdrien Destugues 
33*27606daeSAdrien Destugues 	if (srcSampleCount == destSampleCount) {
34*27606daeSAdrien Destugues 		// optimized case for no resampling
35*27606daeSAdrien Destugues 		while (count--) {
36*27606daeSAdrien Destugues 			float tmp = *(const inType*)src * gain + offset;
37*27606daeSAdrien Destugues 			if (tmp < min) tmp = min;
38*27606daeSAdrien Destugues 			if (tmp > max) tmp = max;
39*27606daeSAdrien Destugues 			*(outType *)dest = (outType)tmp;
40*27606daeSAdrien Destugues 			src += srcSampleOffset;
41*27606daeSAdrien Destugues 			dest += destSampleOffset;
42*27606daeSAdrien Destugues 		}
43*27606daeSAdrien Destugues 		return;
44*27606daeSAdrien Destugues 	}
45*27606daeSAdrien Destugues 
46*27606daeSAdrien Destugues 	register float delta = float(srcSampleCount) / float(destSampleCount);
47*27606daeSAdrien Destugues 	register float current = 0.0f;
48*27606daeSAdrien Destugues 
49*27606daeSAdrien Destugues 	// downsample
50*27606daeSAdrien Destugues 	while (count--) {
51*27606daeSAdrien Destugues 		float tmp = *(const inType*)src * gain + offset;
52*27606daeSAdrien Destugues 		if (tmp < min) tmp = min;
53*27606daeSAdrien Destugues 		if (tmp > max) tmp = max;
54*27606daeSAdrien Destugues 		*(outType *)dest = (outType)tmp;
55*27606daeSAdrien Destugues 
56*27606daeSAdrien Destugues 		dest += destSampleOffset;
57*27606daeSAdrien Destugues 		current += delta;
58*27606daeSAdrien Destugues 		register int32 skipcount = (int32)current;
59*27606daeSAdrien Destugues 		current -= skipcount;
60*27606daeSAdrien Destugues 		src += skipcount * srcSampleOffset;
61*27606daeSAdrien Destugues 	}
62*27606daeSAdrien Destugues }
63*27606daeSAdrien Destugues 
64*27606daeSAdrien Destugues 
65f0a85f97SJérôme Duval Resampler::Resampler(uint32 src_format, uint32 dst_format)
66a9cf57cfSAxel Dörfler 	:
6778341a93SJohn Scipione 	fFunc(0)
68575526ffSbeveloper {
69575526ffSbeveloper 	if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) {
70575526ffSbeveloper 		switch (src_format) {
71575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_FLOAT:
72*27606daeSAdrien Destugues 				fFunc = &kernel<float, float, 1, 1, 0, -1, 1>;
73575526ffSbeveloper 				return;
74575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_INT:
75*27606daeSAdrien Destugues 				fFunc = &kernel<int32, float, 1, INT32_MAX, 0, -1, 1>;
76575526ffSbeveloper 				return;
77575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_SHORT:
78*27606daeSAdrien Destugues 				fFunc = &kernel<int16, float, 1, INT16_MAX, 0, -1, 1>;
79575526ffSbeveloper 				return;
80575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_CHAR:
81*27606daeSAdrien Destugues 				fFunc = &kernel<int8, float, 1, INT8_MAX, 0, -1, 1>;
82575526ffSbeveloper 				return;
83575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_UCHAR:
84*27606daeSAdrien Destugues 				fFunc = &kernel<uint8, float, 2, UINT8_MAX, -128, -1, 1>;
85575526ffSbeveloper 				return;
86575526ffSbeveloper 			default:
87a9cf57cfSAxel Dörfler 				ERROR("Resampler::Resampler: unknown source format 0x%x\n",
88a9cf57cfSAxel Dörfler 					src_format);
89575526ffSbeveloper 				return;
90575526ffSbeveloper 		}
91575526ffSbeveloper 	}
92575526ffSbeveloper 
93575526ffSbeveloper 	if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) {
94575526ffSbeveloper 		switch (dst_format) {
95575526ffSbeveloper 			// float=>float already handled above
96575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_INT:
97*27606daeSAdrien Destugues 				fFunc = &kernel<float, int32, INT32_MAX, 1, 0,
98*27606daeSAdrien Destugues 					INT32_MIN, INT32_MAX>;
99575526ffSbeveloper 				return;
100575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_SHORT:
101*27606daeSAdrien Destugues 				fFunc = &kernel<float, int16, INT16_MAX, 1, 0,
102*27606daeSAdrien Destugues 					INT16_MIN, INT16_MAX>;
103575526ffSbeveloper 				return;
104575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_CHAR:
105*27606daeSAdrien Destugues 				fFunc = &kernel<float, int8, INT8_MAX, 1, 0,
106*27606daeSAdrien Destugues 					INT8_MIN, INT8_MAX>;
107575526ffSbeveloper 				return;
108575526ffSbeveloper 			case media_raw_audio_format::B_AUDIO_UCHAR:
109*27606daeSAdrien Destugues 				fFunc = &kernel<float, uint8, UINT8_MAX, 2, 1,
110*27606daeSAdrien Destugues 					0, UINT8_MAX>;
111575526ffSbeveloper 				return;
112575526ffSbeveloper 			default:
113*27606daeSAdrien Destugues 				ERROR("Resampler::Resampler: unknown destination format 0x%x\n",
114*27606daeSAdrien Destugues 					dst_format);
115575526ffSbeveloper 				return;
116575526ffSbeveloper 		}
117575526ffSbeveloper 	}
118575526ffSbeveloper 
119a9cf57cfSAxel Dörfler 	ERROR("Resampler::Resampler: source or destination format must be "
120a9cf57cfSAxel Dörfler 		"B_AUDIO_FLOAT\n");
121575526ffSbeveloper }
122575526ffSbeveloper 
123a9cf57cfSAxel Dörfler 
124*27606daeSAdrien Destugues Resampler::Resampler()
125*27606daeSAdrien Destugues 	:
126*27606daeSAdrien Destugues 	fFunc(0)
127575526ffSbeveloper {
128575526ffSbeveloper }
129575526ffSbeveloper 
130a9cf57cfSAxel Dörfler 
131