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