MixerUtils.cpp revision 973f1214
1a9cf57cfSAxel Dörfler/*
2a9cf57cfSAxel Dörfler * Copyright 2003-2009 Haiku Inc. All rights reserved.
3a9cf57cfSAxel Dörfler * Distributed under the terms of the MIT License.
4a9cf57cfSAxel Dörfler *
5a9cf57cfSAxel Dörfler * Authors:
6a9cf57cfSAxel Dörfler *		Marcus Overhagen
7a9cf57cfSAxel Dörfler */
8a9cf57cfSAxel Dörfler
9a9cf57cfSAxel Dörfler
10e6c7c99fSbeveloper#include <MediaDefs.h>
11cf706dc7Sbeveloper#include <OS.h>
12e6c7c99fSbeveloper#include <stdio.h>
13e6c7c99fSbeveloper#include <string.h>
14299d70adSbeveloper#include <math.h>
15e6c7c99fSbeveloper
16e6c7c99fSbeveloper#include "MixerUtils.h"
179391f0a5Sbeveloper#include "MixerInput.h"
189391f0a5Sbeveloper#include "MixerOutput.h"
19ab276ac8Sbeveloper#include "MixerCore.h"
20f916862cSMarcus Overhagen#include "MixerDebug.h"
21e6c7c99fSbeveloper
220c63c7d0Sbeveloperconst char *StringForFormat(char *str, const media_format & format);
239391f0a5Sbeveloper
240c63c7d0Sbeveloperconst char *
250c63c7d0SbeveloperStringForChannelMask(char *str, uint32 mask)
26e6c7c99fSbeveloper{
27e6c7c99fSbeveloper	if (mask == 0) {
28e6c7c99fSbeveloper		strcpy(str, "<none>");
290c63c7d0Sbeveloper		return str;
30e6c7c99fSbeveloper	}
310c63c7d0Sbeveloper	str[0] = 0;
32e6c7c99fSbeveloper	#define DECODE(type, text)	if (mask & (type)) \
33e6c7c99fSbeveloper		 do { strcat(str, text); mask &= ~(type); if (mask != 0) strcat(str, ", "); } while (0)
34e6c7c99fSbeveloper	DECODE(B_CHANNEL_LEFT, "Left");
35e6c7c99fSbeveloper	DECODE(B_CHANNEL_RIGHT, "Right");
36e6c7c99fSbeveloper	DECODE(B_CHANNEL_CENTER, "Center");
37e6c7c99fSbeveloper	DECODE(B_CHANNEL_SUB, "Sub");
38e6c7c99fSbeveloper	DECODE(B_CHANNEL_REARLEFT, "Rear-Left");
39e6c7c99fSbeveloper	DECODE(B_CHANNEL_REARRIGHT, "Rear-Right");
40e6c7c99fSbeveloper	DECODE(B_CHANNEL_FRONT_LEFT_CENTER, "Front-Left-Center");
41e6c7c99fSbeveloper	DECODE(B_CHANNEL_FRONT_RIGHT_CENTER, "Front-Right-Center");
42e6c7c99fSbeveloper	DECODE(B_CHANNEL_BACK_CENTER, "Back-Center");
43e6c7c99fSbeveloper	DECODE(B_CHANNEL_SIDE_LEFT, "Side-Left");
44e6c7c99fSbeveloper	DECODE(B_CHANNEL_SIDE_RIGHT, "Side-Right");
45ab276ac8Sbeveloper// XXX disabled for mono workaround
46ab276ac8Sbeveloper//	DECODE(B_CHANNEL_TOP_CENTER, "Top-Center");
47e6c7c99fSbeveloper	DECODE(B_CHANNEL_TOP_FRONT_LEFT, "Top-Front-Left");
48e6c7c99fSbeveloper	DECODE(B_CHANNEL_TOP_FRONT_CENTER, "Top-Front-Center");
49e6c7c99fSbeveloper	DECODE(B_CHANNEL_TOP_FRONT_RIGHT, "Top-Front-Right");
50e6c7c99fSbeveloper	DECODE(B_CHANNEL_TOP_BACK_LEFT, "Top-Back-Left");
51e6c7c99fSbeveloper	DECODE(B_CHANNEL_TOP_BACK_CENTER, "Top-Back-Center");
52e6c7c99fSbeveloper	DECODE(B_CHANNEL_TOP_BACK_RIGHT, "Top-Back-Right");
53ab276ac8Sbeveloper	DECODE(B_CHANNEL_MONO, "Mono");
54e6c7c99fSbeveloper	#undef DECODE
55e6c7c99fSbeveloper	if (mask)
56973f1214SJérôme Duval		sprintf(str + strlen(str), "0x%08" B_PRIx32, mask);
570c63c7d0Sbeveloper	return str;
58e6c7c99fSbeveloper}
59e6c7c99fSbeveloper
602e9d6607Sbeveloperint
612e9d6607Sbevelopercount_nonzero_bits(uint32 value)
62e6c7c99fSbeveloper{
63e6c7c99fSbeveloper	int count = 0;
64e6c7c99fSbeveloper	for (int i = 0; i < 32; i++)
65e6c7c99fSbeveloper		if (value & (1 << i))
66e6c7c99fSbeveloper			count++;
67e6c7c99fSbeveloper	return count;
68e6c7c99fSbeveloper}
69e6c7c99fSbeveloper
702e9d6607Sbevelopervoid
712e9d6607Sbeveloperfix_multiaudio_format(media_multi_audio_format *format)
72e6c7c99fSbeveloper{
73e6c7c99fSbeveloper	if (format->format == media_raw_audio_format::B_AUDIO_INT) {
74e6c7c99fSbeveloper		if (format->valid_bits != 0 && (format->valid_bits < 16 || format->valid_bits >= 32))
75e6c7c99fSbeveloper			format->valid_bits = 0;
76e6c7c99fSbeveloper	}
77e6c7c99fSbeveloper	switch (format->channel_count) {
78e6c7c99fSbeveloper		case 0:
79e6c7c99fSbeveloper			format->channel_mask = 0;
80e6c7c99fSbeveloper			format->matrix_mask = 0;
81e6c7c99fSbeveloper			break;
82e6c7c99fSbeveloper		case 1:
83e6c7c99fSbeveloper			if (count_nonzero_bits(format->channel_mask) != 1) {
84e6c7c99fSbeveloper				format->channel_mask = B_CHANNEL_LEFT;
85e6c7c99fSbeveloper				format->matrix_mask = 0;
86e6c7c99fSbeveloper			}
87e6c7c99fSbeveloper			break;
88e6c7c99fSbeveloper		case 2:
89e6c7c99fSbeveloper			if (count_nonzero_bits(format->channel_mask) != 2) {
90e6c7c99fSbeveloper				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT;
91e6c7c99fSbeveloper				format->matrix_mask = 0;
92e6c7c99fSbeveloper			}
93e6c7c99fSbeveloper			break;
942e9d6607Sbeveloper		case 3:
952e9d6607Sbeveloper			if (count_nonzero_bits(format->channel_mask) != 3) {
962e9d6607Sbeveloper				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_CENTER;
972e9d6607Sbeveloper				format->matrix_mask = 0;
982e9d6607Sbeveloper			}
992e9d6607Sbeveloper			break;
100e6c7c99fSbeveloper		case 4:
101e6c7c99fSbeveloper			if (count_nonzero_bits(format->channel_mask) != 4) {
102e6c7c99fSbeveloper				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT;
103e6c7c99fSbeveloper				format->matrix_mask = 0;
104e6c7c99fSbeveloper			}
105e6c7c99fSbeveloper			break;
106e6c7c99fSbeveloper		case 5:
107e6c7c99fSbeveloper			if (count_nonzero_bits(format->channel_mask) != 5) {
108e6c7c99fSbeveloper				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT | B_CHANNEL_CENTER;
109e6c7c99fSbeveloper				format->matrix_mask = 0;
110e6c7c99fSbeveloper			}
111e6c7c99fSbeveloper			break;
112e6c7c99fSbeveloper		case 6:
113e6c7c99fSbeveloper			if (count_nonzero_bits(format->channel_mask) != 6) {
114e6c7c99fSbeveloper				format->channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT | B_CHANNEL_CENTER | B_CHANNEL_SUB;
115e6c7c99fSbeveloper				format->matrix_mask = 0;
116e6c7c99fSbeveloper			}
117e6c7c99fSbeveloper			break;
118e6c7c99fSbeveloper		case 7:
119e6c7c99fSbeveloper			if (count_nonzero_bits(format->channel_mask) != 7) {
120e6c7c99fSbeveloper				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;
121e6c7c99fSbeveloper				format->matrix_mask = 0;
122e6c7c99fSbeveloper			}
123e6c7c99fSbeveloper			break;
124cf706dc7Sbeveloper		case 8:
125cf706dc7Sbeveloper			if (count_nonzero_bits(format->channel_mask) != 8) {
126cf706dc7Sbeveloper				// XXX not sure if 7.1 is like that:
127cf706dc7Sbeveloper				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;
128cf706dc7Sbeveloper				format->matrix_mask = 0;
129cf706dc7Sbeveloper			}
130cf706dc7Sbeveloper			break;
131a9cf57cfSAxel Dörfler
1322e9d6607Sbeveloper		default:
133cf706dc7Sbeveloper			if (count_nonzero_bits(format->channel_mask) != (int)format->channel_count) {
134cf706dc7Sbeveloper				format->channel_mask = 0xffffffff;
135cf706dc7Sbeveloper				format->matrix_mask = 0;
136cf706dc7Sbeveloper			}
1372e9d6607Sbeveloper			break;
1382e9d6607Sbeveloper	}
139dfe7be41Sbeveloper
140dfe7be41Sbeveloper	// XXX Workaround for broken BeOS R5 quicktime extractor media node
141dfe7be41Sbeveloper	if (format->channel_count == 1
142dfe7be41Sbeveloper			&& format->format == media_multi_audio_format::B_AUDIO_UCHAR
143dfe7be41Sbeveloper			&& int(format->frame_rate + 0.5) == 11025
144dfe7be41Sbeveloper			&& format->byte_order == B_MEDIA_BIG_ENDIAN
145dfe7be41Sbeveloper			&& format->buffer_size == 548) {
146af8d0a4dSbeveloper		ERROR("Mixer: quicktime extractor bug workaround activated, changing buffer size from 548 into 4096\n");
147dfe7be41Sbeveloper		format->buffer_size = 4096;
148dfe7be41Sbeveloper	}
1492e9d6607Sbeveloper}
1502e9d6607Sbeveloper
1512e9d6607Sbeveloperuint32
1522e9d6607SbeveloperGetChannelMask(int channel, uint32 all_channel_masks)
1532e9d6607Sbeveloper{
154cf706dc7Sbeveloper	if (all_channel_masks == 0) {
155cf706dc7Sbeveloper		debugger("Mixer: GetChannelMask: all_channel_masks == 0\n");
156cf706dc7Sbeveloper		return 0;
157cf706dc7Sbeveloper	}
158cf706dc7Sbeveloper	if (channel > count_nonzero_bits(all_channel_masks)) {
159cf706dc7Sbeveloper		debugger("Mixer: GetChannelMask: channel > count_nonzero_bits(all_channel_masks)\n");
160cf706dc7Sbeveloper		return 0;
161cf706dc7Sbeveloper	}
1622e9d6607Sbeveloper
1632e9d6607Sbeveloper	uint32 mask = 1;
1642e9d6607Sbeveloper	int pos = 0;
1652e9d6607Sbeveloper	for (;;) {
1662e9d6607Sbeveloper		while ((all_channel_masks & mask) == 0)
1672e9d6607Sbeveloper			mask <<= 1;
1682e9d6607Sbeveloper		if (pos == channel)
1692e9d6607Sbeveloper			return mask;
1702e9d6607Sbeveloper		pos++;
1712e9d6607Sbeveloper		mask <<= 1;
1722e9d6607Sbeveloper		if (mask == 0)
1732e9d6607Sbeveloper			return 0;
1742e9d6607Sbeveloper	}
1752e9d6607Sbeveloper}
1762e9d6607Sbeveloper
177a4b8db85Sbeveloperint ChannelMaskToChannelType(uint32 mask)
178a4b8db85Sbeveloper{
179a4b8db85Sbeveloper	for (int i = 0; i < 32; i++)
180a4b8db85Sbeveloper		if (mask & (1 << i))
181a4b8db85Sbeveloper			return i;
182a4b8db85Sbeveloper	return -1;
183a4b8db85Sbeveloper}
184a4b8db85Sbeveloper
185a4b8db85Sbeveloperuint32 ChannelTypeToChannelMask(int type)
186a4b8db85Sbeveloper{
187a4b8db85Sbeveloper	if (type < 0 || type > 31)
188a4b8db85Sbeveloper		return 0;
189a4b8db85Sbeveloper	return 1 << type;
190a4b8db85Sbeveloper}
191a4b8db85Sbeveloper
192b6270d60Sbeveloperint
193b6270d60SbeveloperGetChannelType(int channel, uint32 all_channel_masks)
194b6270d60Sbeveloper{
195b6270d60Sbeveloper	return ChannelMaskToChannelType(GetChannelMask(channel, all_channel_masks));
196b6270d60Sbeveloper}
197b6270d60Sbeveloper
198a2ca4723Sbeveloperbool
199a2ca4723SbeveloperHasKawamba()
2002e9d6607Sbeveloper{
201a2ca4723Sbeveloper	team_info i;
202a2ca4723Sbeveloper	int32 c = 0;
203a2ca4723Sbeveloper	while (!get_next_team_info(&c, &i))
204a2ca4723Sbeveloper		if (i.argc && strstr(i.args, "\x42\x65\x54\x75\x6e\x65\x73"))
205a2ca4723Sbeveloper			return true;
206a2ca4723Sbeveloper	return false;
207e6c7c99fSbeveloper}
208299d70adSbeveloper
20960e2e68cSbevelopervoid
21060e2e68cSbeveloperZeroFill(float *_dst, int32 _dst_sample_offset, int32 _sample_count)
21160e2e68cSbeveloper{
21260e2e68cSbeveloper	register char * dst = (char *) _dst;
21360e2e68cSbeveloper	register int32 sample_count = _sample_count;
21460e2e68cSbeveloper	register int32 dst_sample_offset = _dst_sample_offset;
21560e2e68cSbeveloper	while (sample_count--) {
21660e2e68cSbeveloper		*(float *)dst = 0.0f;
21760e2e68cSbeveloper		dst += dst_sample_offset;
21860e2e68cSbeveloper	}
21960e2e68cSbeveloper}
22060e2e68cSbeveloper
221299d70adSbeveloperint64
222299d70adSbeveloperframes_for_duration(double framerate, bigtime_t duration)
223299d70adSbeveloper{
22490f98241Sbeveloper	if (duration <= 0 || framerate <= 0.0)
22590f98241Sbeveloper		return 0;
226299d70adSbeveloper	return (int64) ceil(framerate * double(duration) / 1000000.0);
227299d70adSbeveloper}
228299d70adSbeveloper
229299d70adSbeveloperbigtime_t
230299d70adSbeveloperduration_for_frames(double framerate, int64 frames)
231299d70adSbeveloper{
23290f98241Sbeveloper	if (frames <= 0 || framerate <= 0.0)
23390f98241Sbeveloper		return 0;
234299d70adSbeveloper	return (bigtime_t)((1000000.0 * frames) / framerate);
235299d70adSbeveloper}
236299d70adSbeveloper
23778563dcaSbeveloperint
23878563dcaSbeveloperbytes_per_sample(const media_multi_audio_format & format)
23978563dcaSbeveloper{
24078563dcaSbeveloper	return format.format & 0xf;
24178563dcaSbeveloper}
24278563dcaSbeveloper
243299d70adSbeveloperint
244299d70adSbeveloperbytes_per_frame(const media_multi_audio_format & format)
245299d70adSbeveloper{
246299d70adSbeveloper	return format.channel_count * (format.format & 0xf);
247299d70adSbeveloper}
248299d70adSbeveloper
249299d70adSbeveloperint
250299d70adSbeveloperframes_per_buffer(const media_multi_audio_format & format)
251299d70adSbeveloper{
252299d70adSbeveloper	int frames = 0;
253299d70adSbeveloper	if (bytes_per_frame(format) > 0) {
254299d70adSbeveloper		frames = format.buffer_size / bytes_per_frame(format);
255299d70adSbeveloper	}
256299d70adSbeveloper	return frames;
257299d70adSbeveloper}
2582560202bSbeveloper
2592560202bSbeveloperbigtime_t
2602560202bSbeveloperbuffer_duration(const media_multi_audio_format & format)
2612560202bSbeveloper{
2622560202bSbeveloper	bigtime_t duration = 0;
2632560202bSbeveloper	if (format.buffer_size > 0 && format.frame_rate > 0 && bytes_per_frame(format) > 0) {
2642560202bSbeveloper		duration = s_to_us((format.buffer_size / bytes_per_frame(format)) / format.frame_rate);
2652560202bSbeveloper	}
2662560202bSbeveloper	return duration;
2672560202bSbeveloper}
2682560202bSbeveloper
2692560202bSbeveloperdouble
2702560202bSbeveloperus_to_s(bigtime_t usecs)
2712560202bSbeveloper{
2722560202bSbeveloper	return (usecs / 1000000.0);
2732560202bSbeveloper}
2742560202bSbeveloper
2752560202bSbeveloperbigtime_t
2762560202bSbevelopers_to_us(double secs)
2772560202bSbeveloper{
2782560202bSbeveloper	return (bigtime_t) (secs * 1000000.0);
2792560202bSbeveloper}
2809391f0a5Sbeveloper
2810c63c7d0Sbeveloperconst char *StringForFormat(char *str, const media_format & format)
2829391f0a5Sbeveloper{
2830c63c7d0Sbeveloper	char fmtstr[20];
2849391f0a5Sbeveloper	const char *fmt;
2859391f0a5Sbeveloper	switch (format.u.raw_audio.format) {
2869391f0a5Sbeveloper		case media_raw_audio_format::B_AUDIO_FLOAT:
2879391f0a5Sbeveloper			fmt = "float";
2889391f0a5Sbeveloper			break;
2899391f0a5Sbeveloper		case media_raw_audio_format::B_AUDIO_INT:
2909391f0a5Sbeveloper			if (format.u.raw_audio.valid_bits != 0) {
2910c63c7d0Sbeveloper				sprintf(fmtstr, "%d bit", format.u.raw_audio.valid_bits);
2920c63c7d0Sbeveloper				fmt = fmtstr;
2939391f0a5Sbeveloper			} else {
2949391f0a5Sbeveloper				fmt = "32 bit";
2959391f0a5Sbeveloper			}
2969391f0a5Sbeveloper			break;
2979391f0a5Sbeveloper		case media_raw_audio_format::B_AUDIO_SHORT:
2989391f0a5Sbeveloper			fmt = "16 bit";
2999391f0a5Sbeveloper			break;
3009391f0a5Sbeveloper		case media_raw_audio_format::B_AUDIO_CHAR:
3019391f0a5Sbeveloper			fmt = "8 bit";
3029391f0a5Sbeveloper			break;
3039391f0a5Sbeveloper		case media_raw_audio_format::B_AUDIO_UCHAR:
3049391f0a5Sbeveloper			fmt = "8 bit unsigned";
3059391f0a5Sbeveloper			break;
3069391f0a5Sbeveloper		default:
3079391f0a5Sbeveloper			fmt = "unknown";
3089391f0a5Sbeveloper			break;
3099391f0a5Sbeveloper	}
3109391f0a5Sbeveloper	int a,b;
3119391f0a5Sbeveloper	a = int(format.u.raw_audio.frame_rate + 0.05) / 1000;
3129391f0a5Sbeveloper	b = int(format.u.raw_audio.frame_rate + 0.05) % 1000;
3139391f0a5Sbeveloper	if (b)
3140c63c7d0Sbeveloper		sprintf(str, "%d.%d kHz %s", a, b / 100, fmt);
3159391f0a5Sbeveloper	else
3160c63c7d0Sbeveloper		sprintf(str, "%d kHz %s", a, fmt);
3170c63c7d0Sbeveloper	return str;
3180c63c7d0Sbeveloper}
3190c63c7d0Sbeveloper
3200c63c7d0Sbeveloperconst char *
3210c63c7d0SbeveloperStringForFormat(char *buf, MixerOutput *output)
3220c63c7d0Sbeveloper{
3230c63c7d0Sbeveloper	return StringForFormat(buf, output->MediaOutput().format);
3249391f0a5Sbeveloper}
3259391f0a5Sbeveloper
3260c63c7d0Sbeveloperconst char *
3270c63c7d0SbeveloperStringForFormat(char *buf, MixerInput *input)
3289391f0a5Sbeveloper{
3290c63c7d0Sbeveloper	return StringForFormat(buf, input->MediaInput().format);
3309391f0a5Sbeveloper}
3319391f0a5Sbeveloper
3320c63c7d0Sbeveloperconst char *
3330c63c7d0SbeveloperStringForChannelType(char *buf, int type)
3349391f0a5Sbeveloper{
3350c63c7d0Sbeveloper	return StringForChannelMask(buf, 1 << type);
3369391f0a5Sbeveloper}
337