1/*
2 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
3 * Copyright (c) 2002-2007, Jerome Duval (jerome.duval@free.fr)
4 *
5 * Distributed under the terms of the MIT License.
6 */
7
8
9#include "MultiAudioUtility.h"
10
11#include <errno.h>
12
13#include <MediaDefs.h>
14
15
16const float kSampleRates[] = {
17	8000.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, 44100.0,
18	48000.0, 64000.0, 88200.0, 96000.0, 176400.0, 192000.0, 384000.0, 1536000.0
19};
20const uint32 kSampleRateCount = sizeof(kSampleRates) / sizeof(kSampleRates[0]);
21
22
23template<typename T> static status_t
24call_driver(int device, int32 op, T* data)
25{
26	if (ioctl(device, op, data, sizeof(T)) != 0)
27		return errno;
28
29	return B_OK;
30}
31
32
33namespace MultiAudio {
34
35
36float
37convert_to_sample_rate(uint32 rate)
38{
39	for (uint32 i = 0; i < kSampleRateCount; i++) {
40		if (rate & 1)
41			return kSampleRates[i];
42
43		rate >>= 1;
44	}
45
46	return 0.0;
47}
48
49
50uint32
51convert_from_sample_rate(float rate)
52{
53	for (uint32 i = 0; i < kSampleRateCount; i++) {
54		if (rate <= kSampleRates[i])
55			return 1 << i;
56	}
57
58	return 0;
59}
60
61
62uint32
63convert_to_media_format(uint32 format)
64{
65	switch (format) {
66		case B_FMT_FLOAT:
67			return media_raw_audio_format::B_AUDIO_FLOAT;
68		case B_FMT_18BIT:
69		case B_FMT_20BIT:
70		case B_FMT_24BIT:
71		case B_FMT_32BIT:
72			return media_raw_audio_format::B_AUDIO_INT;
73		case B_FMT_16BIT:
74			return media_raw_audio_format::B_AUDIO_SHORT;
75		case B_FMT_8BIT_S:
76			return media_raw_audio_format::B_AUDIO_CHAR;
77		case B_FMT_8BIT_U:
78			return media_raw_audio_format::B_AUDIO_UCHAR;
79
80		default:
81			return 0;
82	}
83}
84
85
86int16
87convert_to_valid_bits(uint32 format)
88{
89	switch (format) {
90		case B_FMT_18BIT:
91			return 18;
92		case B_FMT_20BIT:
93			return 20;
94		case B_FMT_24BIT:
95			return 24;
96		case B_FMT_32BIT:
97			return 32;
98
99		default:
100			return 0;
101	}
102}
103
104
105uint32
106convert_from_media_format(uint32 format)
107{
108	switch (format) {
109		case media_raw_audio_format::B_AUDIO_FLOAT:
110			return B_FMT_FLOAT;
111		case media_raw_audio_format::B_AUDIO_INT:
112			return B_FMT_32BIT;
113		case media_raw_audio_format::B_AUDIO_SHORT:
114			return B_FMT_16BIT;
115		case media_raw_audio_format::B_AUDIO_CHAR:
116			return B_FMT_8BIT_S;
117		case media_raw_audio_format::B_AUDIO_UCHAR:
118			return B_FMT_8BIT_U;
119
120		default:
121			return 0;
122	}
123}
124
125
126uint32
127select_sample_rate(uint32 rate)
128{
129	// highest rate
130	uint32 crate = B_SR_1536000;
131	while (crate != 0) {
132		if (rate & crate)
133			return crate;
134		crate >>= 1;
135	}
136	return 0;
137}
138
139
140uint32
141select_format(uint32 format)
142{
143	// best format
144	// TODO ensure we support this format
145	/*if (format & B_FMT_FLOAT)
146		return B_FMT_FLOAT;*/
147	if (format & B_FMT_32BIT)
148		return B_FMT_32BIT;
149	if (format & B_FMT_24BIT)
150		return B_FMT_24BIT;
151	if (format & B_FMT_20BIT)
152		return B_FMT_20BIT;
153	if (format & B_FMT_18BIT)
154		return B_FMT_18BIT;
155	if (format & B_FMT_16BIT)
156		return B_FMT_16BIT;
157	if (format & B_FMT_8BIT_S)
158		return B_FMT_8BIT_S;
159	if (format & B_FMT_8BIT_U)
160		return B_FMT_8BIT_U;
161
162	return 0;
163}
164
165
166status_t
167get_description(int device, multi_description* description)
168{
169	return call_driver(device, B_MULTI_GET_DESCRIPTION, description);
170}
171
172
173status_t
174get_enabled_channels(int device, multi_channel_enable* enable)
175{
176	return call_driver(device, B_MULTI_GET_ENABLED_CHANNELS, enable);
177}
178
179
180status_t
181set_enabled_channels(int device, multi_channel_enable* enable)
182{
183	return call_driver(device, B_MULTI_SET_ENABLED_CHANNELS, enable);
184}
185
186
187status_t
188get_global_format(int device, multi_format_info* info)
189{
190	return call_driver(device, B_MULTI_GET_GLOBAL_FORMAT, info);
191}
192
193
194status_t
195set_global_format(int device, multi_format_info* info)
196{
197	return call_driver(device, B_MULTI_SET_GLOBAL_FORMAT, info);
198}
199
200
201status_t
202get_buffers(int device, multi_buffer_list* list)
203{
204	return call_driver(device, B_MULTI_GET_BUFFERS, list);
205}
206
207
208status_t
209buffer_exchange(int device, multi_buffer_info* info)
210{
211	return call_driver(device, B_MULTI_BUFFER_EXCHANGE, info);
212}
213
214
215status_t
216list_mix_controls(int device, multi_mix_control_info* info)
217{
218	return call_driver(device, B_MULTI_LIST_MIX_CONTROLS, info);
219}
220
221
222status_t
223get_mix(int device, multi_mix_value_info* info)
224{
225	return call_driver(device, B_MULTI_GET_MIX, info);
226}
227
228
229status_t
230set_mix(int device, multi_mix_value_info* info)
231{
232	return call_driver(device, B_MULTI_SET_MIX, info);
233}
234
235
236}	// namespace MultiAudio
237