xref: /haiku/src/add-ons/media/media-add-ons/mixer/MixerUtils.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
1 /*
2  * Copyright 2003-2009 Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Marcus Overhagen
7  */
8 
9 
10 #include <MediaDefs.h>
11 #include <OS.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <math.h>
15 
16 #include "MixerUtils.h"
17 #include "MixerInput.h"
18 #include "MixerOutput.h"
19 #include "MixerCore.h"
20 #include "MixerDebug.h"
21 
22 const char *StringForFormat(char *str, const media_format & format);
23 
24 const char *
25 StringForChannelMask(char *str, uint32 mask)
26 {
27 	if (mask == 0) {
28 		strcpy(str, "<none>");
29 		return str;
30 	}
31 	str[0] = 0;
32 	#define DECODE(type, text)	if (mask & (type)) \
33 		 do { strcat(str, text); mask &= ~(type); if (mask != 0) strcat(str, ", "); } while (0)
34 	DECODE(B_CHANNEL_LEFT, "Left");
35 	DECODE(B_CHANNEL_RIGHT, "Right");
36 	DECODE(B_CHANNEL_CENTER, "Center");
37 	DECODE(B_CHANNEL_SUB, "Sub");
38 	DECODE(B_CHANNEL_REARLEFT, "Rear-Left");
39 	DECODE(B_CHANNEL_REARRIGHT, "Rear-Right");
40 	DECODE(B_CHANNEL_FRONT_LEFT_CENTER, "Front-Left-Center");
41 	DECODE(B_CHANNEL_FRONT_RIGHT_CENTER, "Front-Right-Center");
42 	DECODE(B_CHANNEL_BACK_CENTER, "Back-Center");
43 	DECODE(B_CHANNEL_SIDE_LEFT, "Side-Left");
44 	DECODE(B_CHANNEL_SIDE_RIGHT, "Side-Right");
45 // XXX disabled for mono workaround
46 //	DECODE(B_CHANNEL_TOP_CENTER, "Top-Center");
47 	DECODE(B_CHANNEL_TOP_FRONT_LEFT, "Top-Front-Left");
48 	DECODE(B_CHANNEL_TOP_FRONT_CENTER, "Top-Front-Center");
49 	DECODE(B_CHANNEL_TOP_FRONT_RIGHT, "Top-Front-Right");
50 	DECODE(B_CHANNEL_TOP_BACK_LEFT, "Top-Back-Left");
51 	DECODE(B_CHANNEL_TOP_BACK_CENTER, "Top-Back-Center");
52 	DECODE(B_CHANNEL_TOP_BACK_RIGHT, "Top-Back-Right");
53 	DECODE(B_CHANNEL_MONO, "Mono");
54 	#undef DECODE
55 	if (mask)
56 		sprintf(str + strlen(str), "0x%08" B_PRIx32, mask);
57 	return str;
58 }
59 
60 int
61 count_nonzero_bits(uint32 value)
62 {
63 	int count = 0;
64 	for (int i = 0; i < 32; i++)
65 		if (value & (1 << i))
66 			count++;
67 	return count;
68 }
69 
70 void
71 fix_multiaudio_format(media_multi_audio_format *format)
72 {
73 	if (format->format == media_raw_audio_format::B_AUDIO_INT) {
74 		if (format->valid_bits != 0 && (format->valid_bits < 16 || format->valid_bits >= 32))
75 			format->valid_bits = 0;
76 	}
77 	switch (format->channel_count) {
78 		case 0:
79 			format->channel_mask = 0;
80 			format->matrix_mask = 0;
81 			break;
82 		case 1:
83 			if (count_nonzero_bits(format->channel_mask) != 1) {
84 				format->channel_mask = B_CHANNEL_LEFT;
85 				format->matrix_mask = 0;
86 			}
87 			break;
88 		case 2:
89 			if (count_nonzero_bits(format->channel_mask) != 2) {
90 				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT;
91 				format->matrix_mask = 0;
92 			}
93 			break;
94 		case 3:
95 			if (count_nonzero_bits(format->channel_mask) != 3) {
96 				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_CENTER;
97 				format->matrix_mask = 0;
98 			}
99 			break;
100 		case 4:
101 			if (count_nonzero_bits(format->channel_mask) != 4) {
102 				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT;
103 				format->matrix_mask = 0;
104 			}
105 			break;
106 		case 5:
107 			if (count_nonzero_bits(format->channel_mask) != 5) {
108 				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT | B_CHANNEL_CENTER;
109 				format->matrix_mask = 0;
110 			}
111 			break;
112 		case 6:
113 			if (count_nonzero_bits(format->channel_mask) != 6) {
114 				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT | B_CHANNEL_CENTER | B_CHANNEL_SUB;
115 				format->matrix_mask = 0;
116 			}
117 			break;
118 		case 7:
119 			if (count_nonzero_bits(format->channel_mask) != 7) {
120 				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT | B_CHANNEL_CENTER | B_CHANNEL_SUB | B_CHANNEL_BACK_CENTER;
121 				format->matrix_mask = 0;
122 			}
123 			break;
124 		case 8:
125 			if (count_nonzero_bits(format->channel_mask) != 8) {
126 				// XXX not sure if 7.1 is like that:
127 				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT | B_CHANNEL_CENTER | B_CHANNEL_SUB | B_CHANNEL_SIDE_LEFT | B_CHANNEL_SIDE_RIGHT;
128 				format->matrix_mask = 0;
129 			}
130 			break;
131 
132 		default:
133 			if (count_nonzero_bits(format->channel_mask) != (int)format->channel_count) {
134 				format->channel_mask = 0xffffffff;
135 				format->matrix_mask = 0;
136 			}
137 			break;
138 	}
139 
140 	// XXX Workaround for broken BeOS R5 quicktime extractor media node
141 	if (format->channel_count == 1
142 			&& format->format == media_multi_audio_format::B_AUDIO_UCHAR
143 			&& int(format->frame_rate + 0.5) == 11025
144 			&& format->byte_order == B_MEDIA_BIG_ENDIAN
145 			&& format->buffer_size == 548) {
146 		ERROR("Mixer: quicktime extractor bug workaround activated, changing buffer size from 548 into 4096\n");
147 		format->buffer_size = 4096;
148 	}
149 }
150 
151 uint32
152 GetChannelMask(int channel, uint32 all_channel_masks)
153 {
154 	if (all_channel_masks == 0) {
155 		debugger("Mixer: GetChannelMask: all_channel_masks == 0\n");
156 		return 0;
157 	}
158 	if (channel > count_nonzero_bits(all_channel_masks)) {
159 		debugger("Mixer: GetChannelMask: channel > count_nonzero_bits(all_channel_masks)\n");
160 		return 0;
161 	}
162 
163 	uint32 mask = 1;
164 	int pos = 0;
165 	for (;;) {
166 		while ((all_channel_masks & mask) == 0)
167 			mask <<= 1;
168 		if (pos == channel)
169 			return mask;
170 		pos++;
171 		mask <<= 1;
172 		if (mask == 0)
173 			return 0;
174 	}
175 }
176 
177 int ChannelMaskToChannelType(uint32 mask)
178 {
179 	for (int i = 0; i < 32; i++)
180 		if (mask & (1 << i))
181 			return i;
182 	return -1;
183 }
184 
185 uint32 ChannelTypeToChannelMask(int type)
186 {
187 	if (type < 0 || type > 31)
188 		return 0;
189 	return 1 << type;
190 }
191 
192 int
193 GetChannelType(int channel, uint32 all_channel_masks)
194 {
195 	return ChannelMaskToChannelType(GetChannelMask(channel, all_channel_masks));
196 }
197 
198 bool
199 HasKawamba()
200 {
201 	team_info i;
202 	int32 c = 0;
203 	while (!get_next_team_info(&c, &i))
204 		if (i.argc && strstr(i.args, "\x42\x65\x54\x75\x6e\x65\x73"))
205 			return true;
206 	return false;
207 }
208 
209 void
210 ZeroFill(float *_dst, int32 _dst_sample_offset, int32 _sample_count)
211 {
212 	char * dst = (char *) _dst;
213 	int32 sample_count = _sample_count;
214 	int32 dst_sample_offset = _dst_sample_offset;
215 	while (sample_count--) {
216 		*(float *)dst = 0.0f;
217 		dst += dst_sample_offset;
218 	}
219 }
220 
221 int64
222 frames_for_duration(double framerate, bigtime_t duration)
223 {
224 	if (duration <= 0 || framerate <= 0.0)
225 		return 0;
226 	return (int64) ceil(framerate * double(duration) / 1000000.0);
227 }
228 
229 bigtime_t
230 duration_for_frames(double framerate, int64 frames)
231 {
232 	if (frames <= 0 || framerate <= 0.0)
233 		return 0;
234 	return (bigtime_t)((1000000.0 * frames) / framerate);
235 }
236 
237 int
238 bytes_per_sample(const media_multi_audio_format & format)
239 {
240 	return format.format & 0xf;
241 }
242 
243 int
244 bytes_per_frame(const media_multi_audio_format & format)
245 {
246 	return format.channel_count * (format.format & 0xf);
247 }
248 
249 int
250 frames_per_buffer(const media_multi_audio_format & format)
251 {
252 	int frames = 0;
253 	if (bytes_per_frame(format) > 0) {
254 		frames = format.buffer_size / bytes_per_frame(format);
255 	}
256 	return frames;
257 }
258 
259 bigtime_t
260 buffer_duration(const media_multi_audio_format & format)
261 {
262 	bigtime_t duration = 0;
263 	if (format.buffer_size > 0 && format.frame_rate > 0 && bytes_per_frame(format) > 0) {
264 		duration = s_to_us((format.buffer_size / bytes_per_frame(format)) / format.frame_rate);
265 	}
266 	return duration;
267 }
268 
269 double
270 us_to_s(bigtime_t usecs)
271 {
272 	return (usecs / 1000000.0);
273 }
274 
275 bigtime_t
276 s_to_us(double secs)
277 {
278 	return (bigtime_t) (secs * 1000000.0);
279 }
280 
281 const char *StringForFormat(char *str, const media_format & format)
282 {
283 	char fmtstr[20];
284 	const char *fmt;
285 	switch (format.u.raw_audio.format) {
286 		case media_raw_audio_format::B_AUDIO_FLOAT:
287 			fmt = "float";
288 			break;
289 		case media_raw_audio_format::B_AUDIO_INT:
290 			if (format.u.raw_audio.valid_bits != 0) {
291 				sprintf(fmtstr, "%d bit", format.u.raw_audio.valid_bits);
292 				fmt = fmtstr;
293 			} else {
294 				fmt = "32 bit";
295 			}
296 			break;
297 		case media_raw_audio_format::B_AUDIO_SHORT:
298 			fmt = "16 bit";
299 			break;
300 		case media_raw_audio_format::B_AUDIO_CHAR:
301 			fmt = "8 bit";
302 			break;
303 		case media_raw_audio_format::B_AUDIO_UCHAR:
304 			fmt = "8 bit unsigned";
305 			break;
306 		default:
307 			fmt = "unknown";
308 			break;
309 	}
310 	int a,b;
311 	a = int(format.u.raw_audio.frame_rate + 0.05) / 1000;
312 	b = int(format.u.raw_audio.frame_rate + 0.05) % 1000;
313 	if (b)
314 		sprintf(str, "%d.%d kHz %s", a, b / 100, fmt);
315 	else
316 		sprintf(str, "%d kHz %s", a, fmt);
317 	return str;
318 }
319 
320 const char *
321 StringForFormat(char *buf, MixerOutput *output)
322 {
323 	return StringForFormat(buf, output->MediaOutput().format);
324 }
325 
326 const char *
327 StringForFormat(char *buf, MixerInput *input)
328 {
329 	return StringForFormat(buf, input->MediaInput().format);
330 }
331 
332 const char *
333 StringForChannelType(char *buf, int type)
334 {
335 	return StringForChannelMask(buf, 1 << type);
336 }
337