xref: /haiku/src/add-ons/media/media-add-ons/mixer/Resampler.cpp (revision 7ca83dacf00d14a9424026a2b038497c3e1e58f0)
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
76*7ca83dacSbeveloper Resampler::float_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
77*7ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
78*7ca83dacSbeveloper {
79*7ca83dacSbeveloper 	register const char * src = (const char *) _src;
80*7ca83dacSbeveloper 	register char * dst = (char *) _dst;
81*7ca83dacSbeveloper 	register int32 count = dst_sample_count;
82*7ca83dacSbeveloper 	register float gain = _gain;
83*7ca83dacSbeveloper 
84*7ca83dacSbeveloper 	if (src_sample_count == dst_sample_count) {
85*7ca83dacSbeveloper 		// optimized case for no resampling
86*7ca83dacSbeveloper 		while (count--) {
87*7ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
88*7ca83dacSbeveloper 			src += src_sample_offset;
89*7ca83dacSbeveloper 			dst += dst_sample_offset;
90*7ca83dacSbeveloper 		}
91*7ca83dacSbeveloper 		return;
92*7ca83dacSbeveloper 	}
93*7ca83dacSbeveloper 
94*7ca83dacSbeveloper 	register double delta = double(src_sample_count) / double(dst_sample_offset);
95*7ca83dacSbeveloper 	register float current = 0.0f;
96*7ca83dacSbeveloper 
97*7ca83dacSbeveloper 	if (delta < 1.0) {
98*7ca83dacSbeveloper 		// upsample
99*7ca83dacSbeveloper 		while (count--) {
100*7ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
101*7ca83dacSbeveloper 			dst += dst_sample_offset;
102*7ca83dacSbeveloper 			current += delta;
103*7ca83dacSbeveloper 			if (current > 1.0f) {
104*7ca83dacSbeveloper 				current -= 1.0f;
105*7ca83dacSbeveloper 				src += src_sample_offset;
106*7ca83dacSbeveloper 			}
107*7ca83dacSbeveloper 		}
108*7ca83dacSbeveloper 	} else {
109*7ca83dacSbeveloper 		// downsample
110*7ca83dacSbeveloper 		while (count--) {
111*7ca83dacSbeveloper 			*(float *)dst = *(const float *)src * gain;
112*7ca83dacSbeveloper 			src += src_sample_offset;
113*7ca83dacSbeveloper 			current += delta; // delta is always > 1.0
114*7ca83dacSbeveloper 			if (current < 2.0f) {
115*7ca83dacSbeveloper 				current -= 1.0f;
116*7ca83dacSbeveloper 				dst += dst_sample_offset;
117*7ca83dacSbeveloper 			} else {
118*7ca83dacSbeveloper 				int32 inc_count = (int32) current;
119*7ca83dacSbeveloper 				current -= (float) inc_count;
120*7ca83dacSbeveloper 				dst += inc_count * dst_sample_offset;
121*7ca83dacSbeveloper 			}
122*7ca83dacSbeveloper 		}
123*7ca83dacSbeveloper 	}
124*7ca83dacSbeveloper }
125*7ca83dacSbeveloper 
126*7ca83dacSbeveloper void
127*7ca83dacSbeveloper Resampler::int32_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
128*7ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
129575526ffSbeveloper {
130575526ffSbeveloper }
131575526ffSbeveloper 
132575526ffSbeveloper void
133*7ca83dacSbeveloper Resampler::int16_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
134*7ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
135575526ffSbeveloper {
136575526ffSbeveloper }
137575526ffSbeveloper 
138575526ffSbeveloper void
139*7ca83dacSbeveloper Resampler::int8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
140*7ca83dacSbeveloper 				  		 void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
141575526ffSbeveloper {
142575526ffSbeveloper }
143575526ffSbeveloper 
144575526ffSbeveloper void
145*7ca83dacSbeveloper Resampler::uint8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count,
146*7ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
147575526ffSbeveloper {
148575526ffSbeveloper }
149575526ffSbeveloper 
150575526ffSbeveloper void
151*7ca83dacSbeveloper Resampler::float_to_int32(const void *_src, int32 src_sample_offset, int32 src_sample_count,
152*7ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
153575526ffSbeveloper {
154575526ffSbeveloper }
155575526ffSbeveloper 
156575526ffSbeveloper void
157*7ca83dacSbeveloper Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_sample_count,
158*7ca83dacSbeveloper 				  		  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
159575526ffSbeveloper {
160575526ffSbeveloper }
161575526ffSbeveloper 
162575526ffSbeveloper void
163575526ffSbeveloper Resampler::float_to_int8(const void *src, int32 src_sample_offset, int32 src_sample_count,
164*7ca83dacSbeveloper 			 			 void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
165575526ffSbeveloper {
166575526ffSbeveloper }
167575526ffSbeveloper 
168575526ffSbeveloper void
169*7ca83dacSbeveloper Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_sample_count,
170*7ca83dacSbeveloper 						  void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain)
171575526ffSbeveloper {
172575526ffSbeveloper }
173575526ffSbeveloper 
174