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