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
22const char *StringForFormat(char *str, const media_format & format);
23
24const char *
25StringForChannelMask(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
60int
61count_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
70void
71fix_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
151uint32
152GetChannelMask(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
177int 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
185uint32 ChannelTypeToChannelMask(int type)
186{
187	if (type < 0 || type > 31)
188		return 0;
189	return 1 << type;
190}
191
192int
193GetChannelType(int channel, uint32 all_channel_masks)
194{
195	return ChannelMaskToChannelType(GetChannelMask(channel, all_channel_masks));
196}
197
198bool
199HasKawamba()
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
209void
210ZeroFill(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
221int64
222frames_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
229bigtime_t
230duration_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
237int
238bytes_per_sample(const media_multi_audio_format & format)
239{
240	return format.format & 0xf;
241}
242
243int
244bytes_per_frame(const media_multi_audio_format & format)
245{
246	return format.channel_count * (format.format & 0xf);
247}
248
249int
250frames_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
259bigtime_t
260buffer_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
269double
270us_to_s(bigtime_t usecs)
271{
272	return (usecs / 1000000.0);
273}
274
275bigtime_t
276s_to_us(double secs)
277{
278	return (bigtime_t) (secs * 1000000.0);
279}
280
281const 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
320const char *
321StringForFormat(char *buf, MixerOutput *output)
322{
323	return StringForFormat(buf, output->MediaOutput().format);
324}
325
326const char *
327StringForFormat(char *buf, MixerInput *input)
328{
329	return StringForFormat(buf, input->MediaInput().format);
330}
331
332const char *
333StringForChannelType(char *buf, int type)
334{
335	return StringForChannelMask(buf, 1 << type);
336}
337