xref: /haiku/src/add-ons/media/media-add-ons/mixer/Resampler.cpp (revision 22440f4105cafc95cc1d49f9bc65bb395c527d86)
1 /*
2  * Copyright 2003 Marcus Overhagen
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "Resampler.h"
8 
9 #include <MediaDefs.h>
10 
11 #include "MixerDebug.h"
12 
13 
14 /*!	A simple resampling class for the audio mixer.
15 	You pick the conversion function on object creation,
16 	and then call the Resample() function, specifying data pointer,
17 	offset (in bytes) to the next sample, and count of samples for
18 	both source and destination.
19 */
20 
21 
22 template<typename inType, typename outType, int gnum, int gden, int offset,
23 	int32 min, int32 max> static void
24 kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
25 	int32 srcSampleCount, void *_dest, int32 destSampleOffset,
26 	int32 destSampleCount, float _gain)
27 {
28 	register const char * src = (const char *)_src;
29 	register char * dest = (char *)_dest;
30 	register int32 count = destSampleCount;
31 	register float gain = _gain * gnum / gden;
32 
33 	if (srcSampleCount == destSampleCount) {
34 		// optimized case for no resampling
35 		while (count--) {
36 			float tmp = *(const inType*)src * gain + offset;
37 			if (tmp < min) tmp = min;
38 			if (tmp > max) tmp = max;
39 			*(outType *)dest = (outType)tmp;
40 			src += srcSampleOffset;
41 			dest += destSampleOffset;
42 		}
43 		return;
44 	}
45 
46 	register float delta = float(srcSampleCount) / float(destSampleCount);
47 	register float current = 0.0f;
48 
49 	// downsample
50 	while (count--) {
51 		float tmp = *(const inType*)src * gain + offset;
52 		if (tmp < min) tmp = min;
53 		if (tmp > max) tmp = max;
54 		*(outType *)dest = (outType)tmp;
55 
56 		dest += destSampleOffset;
57 		current += delta;
58 		register int32 skipcount = (int32)current;
59 		current -= skipcount;
60 		src += skipcount * srcSampleOffset;
61 	}
62 }
63 
64 
65 Resampler::Resampler(uint32 src_format, uint32 dst_format)
66 	:
67 	fFunc(0)
68 {
69 	if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) {
70 		switch (src_format) {
71 			case media_raw_audio_format::B_AUDIO_FLOAT:
72 				fFunc = &kernel<float, float, 1, 1, 0, -1, 1>;
73 				return;
74 			case media_raw_audio_format::B_AUDIO_INT:
75 				fFunc = &kernel<int32, float, 1, INT32_MAX, 0, -1, 1>;
76 				return;
77 			case media_raw_audio_format::B_AUDIO_SHORT:
78 				fFunc = &kernel<int16, float, 1, INT16_MAX, 0, -1, 1>;
79 				return;
80 			case media_raw_audio_format::B_AUDIO_CHAR:
81 				fFunc = &kernel<int8, float, 1, INT8_MAX, 0, -1, 1>;
82 				return;
83 			case media_raw_audio_format::B_AUDIO_UCHAR:
84 				fFunc = &kernel<uint8, float, 2, UINT8_MAX, -128, -1, 1>;
85 				return;
86 			default:
87 				ERROR("Resampler::Resampler: unknown source format 0x%x\n",
88 					src_format);
89 				return;
90 		}
91 	}
92 
93 	if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) {
94 		switch (dst_format) {
95 			// float=>float already handled above
96 			case media_raw_audio_format::B_AUDIO_INT:
97 				fFunc = &kernel<float, int32, INT32_MAX, 1, 0,
98 					INT32_MIN, INT32_MAX>;
99 				return;
100 			case media_raw_audio_format::B_AUDIO_SHORT:
101 				fFunc = &kernel<float, int16, INT16_MAX, 1, 0,
102 					INT16_MIN, INT16_MAX>;
103 				return;
104 			case media_raw_audio_format::B_AUDIO_CHAR:
105 				fFunc = &kernel<float, int8, INT8_MAX, 1, 0,
106 					INT8_MIN, INT8_MAX>;
107 				return;
108 			case media_raw_audio_format::B_AUDIO_UCHAR:
109 				fFunc = &kernel<float, uint8, UINT8_MAX, 2, 1,
110 					0, UINT8_MAX>;
111 				return;
112 			default:
113 				ERROR("Resampler::Resampler: unknown destination format 0x%x\n",
114 					dst_format);
115 				return;
116 		}
117 	}
118 
119 	ERROR("Resampler::Resampler: source or destination format must be "
120 		"B_AUDIO_FLOAT\n");
121 }
122 
123 
124 Resampler::Resampler()
125 	:
126 	fFunc(0)
127 {
128 }
129 
130 
131