xref: /haiku/src/add-ons/media/media-add-ons/multi_audio/MultiAudioDevice.cpp (revision 51978af14a173e7fae0563b562be5603bc652aeb)
1 /*
2  * multiaudio replacement media addon for BeOS
3  *
4  * Copyright (c) 2002, 2003, Jerome Duval (jerome.duval@free.fr)
5  *
6  * All rights reserved.
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted provided that the following conditions are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright notice,
13  *   this list of conditions and the following disclaimer in the documentation
14  *   and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 #include "MultiAudioDevice.h"
29 #include "debug.h"
30 #include "driver_io.h"
31 #include <MediaDefs.h>
32 #include <string.h>
33 
34 float SAMPLE_RATES[] = {
35 			8000.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, 44100.0,
36 			48000.0, 64000.0, 88200.0, 96000.0, 176400.0, 192000.0, 384000.0, 1536000.0
37 			};
38 
39 
40 float MultiAudioDevice::convert_multiaudio_rate_to_media_rate(uint32 rate)
41 {
42 	uint8 count = 0;
43 	uint8 size = sizeof(SAMPLE_RATES)/sizeof(SAMPLE_RATES[0]);
44 	while(count < size) {
45 		if(rate & 1)
46 			return SAMPLE_RATES[count];
47 		count++;
48 		rate >>= 1;
49 	}
50 	return 0.0;
51 }
52 
53 uint32 MultiAudioDevice::convert_media_rate_to_multiaudio_rate(float rate)
54 {
55 	uint8 count = 0;
56 	uint size = sizeof(SAMPLE_RATES)/sizeof(SAMPLE_RATES[0]);
57 	while(count < size) {
58 		if(rate <= SAMPLE_RATES[count])
59 			return (0x1 << count);
60 		count++;
61 	}
62 	return 0;
63 }
64 
65 uint32 MultiAudioDevice::convert_multiaudio_format_to_media_format(uint32 fmt)
66 {
67 	switch(fmt) {
68 		case B_FMT_FLOAT:
69 			return media_raw_audio_format::B_AUDIO_FLOAT;
70 		case B_FMT_18BIT:
71 		case B_FMT_20BIT:
72 		case B_FMT_24BIT:
73 		case B_FMT_32BIT:
74 			return media_raw_audio_format::B_AUDIO_INT;
75 		case B_FMT_16BIT:
76 			return media_raw_audio_format::B_AUDIO_SHORT;
77 		case B_FMT_8BIT_S:
78 			return media_raw_audio_format::B_AUDIO_CHAR;
79 		case B_FMT_8BIT_U:
80 			return media_raw_audio_format::B_AUDIO_UCHAR;
81 		default:
82 			return 0;
83 	}
84 }
85 
86 uint32 MultiAudioDevice::convert_media_format_to_multiaudio_format(uint32 fmt)
87 {
88 	switch(fmt) {
89 		case media_raw_audio_format::B_AUDIO_FLOAT:
90 			return B_FMT_FLOAT;
91 		case media_raw_audio_format::B_AUDIO_INT:
92 			return B_FMT_32BIT;
93 		case media_raw_audio_format::B_AUDIO_SHORT:
94 			return B_FMT_16BIT;
95 		case media_raw_audio_format::B_AUDIO_CHAR:
96 			return B_FMT_8BIT_S;
97 		case media_raw_audio_format::B_AUDIO_UCHAR:
98 			return B_FMT_8BIT_U;
99 		default:
100 			return 0;
101 	}
102 }
103 
104 uint32 MultiAudioDevice::select_multiaudio_rate(uint32 rate)
105 {
106 	//highest rate
107 	uint32 crate = B_SR_1536000;
108 	while(crate != 0) {
109 		if(rate & crate)
110 			return crate;
111 		crate >>= 1;
112 	}
113 	return 0;
114 }
115 
116 uint32 MultiAudioDevice::select_multiaudio_format(uint32 fmt)
117 {
118 	//highest format
119 	if(fmt & B_FMT_FLOAT) {
120 		return B_FMT_FLOAT;
121 	} else if(fmt & B_FMT_32BIT) {
122 		return B_FMT_32BIT;
123 	} else if(fmt & B_FMT_24BIT) {
124 		return B_FMT_24BIT;
125 	} else if(fmt & B_FMT_20BIT) {
126 		return B_FMT_20BIT;
127 	} else if(fmt & B_FMT_18BIT) {
128 		return B_FMT_18BIT;
129 	} else if(fmt & B_FMT_16BIT) {
130 		return B_FMT_16BIT;
131 	} else if(fmt & B_FMT_8BIT_S) {
132 		return B_FMT_8BIT_S;
133 	} else if(fmt & B_FMT_8BIT_U) {
134 		return B_FMT_8BIT_U;
135 	} else
136 		return 0;
137 }
138 
139 
140 
141 MultiAudioDevice::~MultiAudioDevice()
142 {
143 	CALLED();
144 	if ( fd != 0 ) {
145 		close( fd );
146 	}
147 }
148 
149 MultiAudioDevice::MultiAudioDevice(const char* name, const char* path)
150 {
151 	CALLED();
152 	fInitCheckStatus = B_NO_INIT;
153 
154 	strcpy(fDevice_name, name);
155 	strcpy(fDevice_path, path);
156 
157 	PRINT(("name : %s, path : %s\n", fDevice_name, fDevice_path));
158 
159 	if(InitDriver()!=B_OK)
160 		return;
161 
162 	fInitCheckStatus = B_OK;
163 }
164 
165 
166 status_t MultiAudioDevice::InitCheck(void) const
167 {
168 	CALLED();
169 	return fInitCheckStatus;
170 }
171 
172 
173 status_t MultiAudioDevice::InitDriver()
174 {
175 	multi_channel_enable 	MCE;
176 	uint32					mce_enable_bits;
177 	int rval, i, num_outputs, num_inputs, num_channels;
178 
179 	CALLED();
180 
181 	//open the device driver for output
182 	fd = open( fDevice_path, O_WRONLY );
183 
184 	if ( fd == 0 ) {
185 		return B_ERROR;
186 	}
187 
188 	//
189 	// Get description
190 	//
191 	MD.info_size = sizeof(MD);
192 	MD.request_channel_count = MAX_CHANNELS;
193 	MD.channels = MCI;
194 	rval = DRIVER_GET_DESCRIPTION(&MD,0);
195 	if (B_OK != rval)
196 	{
197 		fprintf(stderr, "Failed on B_MULTI_GET_DESCRIPTION\n");
198 		return B_ERROR;
199 	}
200 
201 	PRINT(("Friendly name:\t%s\nVendor:\t\t%s\n",
202 				MD.friendly_name,MD.vendor_info));
203 	PRINT(("%ld outputs\t%ld inputs\n%ld out busses\t%ld in busses\n",
204 				MD.output_channel_count,MD.input_channel_count,
205 				MD.output_bus_channel_count,MD.input_bus_channel_count));
206 	PRINT(("\nChannels\n"
207 			 "ID\tKind\tDesig\tConnectors\n"));
208 
209 	for (i = 0 ; i < (MD.output_channel_count + MD.input_channel_count); i++)
210 	{
211 		PRINT(("%ld\t%d\t0x%lx\t0x%lx\n",MD.channels[i].channel_id,
212 											MD.channels[i].kind,
213 											MD.channels[i].designations,
214 											MD.channels[i].connectors));
215 	}
216 	PRINT(("\n"));
217 
218 	PRINT(("Output rates\t\t0x%lx\n",MD.output_rates));
219 	PRINT(("Input rates\t\t0x%lx\n",MD.input_rates));
220 	PRINT(("Max CVSR\t\t%.0f\n",MD.max_cvsr_rate));
221 	PRINT(("Min CVSR\t\t%.0f\n",MD.min_cvsr_rate));
222 	PRINT(("Output formats\t\t0x%lx\n",MD.output_formats));
223 	PRINT(("Input formats\t\t0x%lx\n",MD.input_formats));
224 	PRINT(("Lock sources\t\t0x%lx\n",MD.lock_sources));
225 	PRINT(("Timecode sources\t0x%lx\n",MD.timecode_sources));
226 	PRINT(("Interface flags\t\t0x%lx\n",MD.interface_flags));
227 	PRINT(("Control panel string:\t\t%s\n",MD.control_panel));
228 	PRINT(("\n"));
229 
230 	num_outputs = MD.output_channel_count;
231 	num_inputs = MD.input_channel_count;
232 	num_channels = num_outputs + num_inputs;
233 
234 	// Get and set enabled channels
235 	MCE.info_size = sizeof(MCE);
236 	MCE.enable_bits = (uchar *) &mce_enable_bits;
237 	rval = DRIVER_GET_ENABLED_CHANNELS(&MCE, sizeof(MCE));
238 	if (B_OK != rval)
239 	{
240 		fprintf(stderr, "Failed on B_MULTI_GET_ENABLED_CHANNELS len is 0x%lx\n",sizeof(MCE));
241 		return B_ERROR;
242 	}
243 
244 	mce_enable_bits = (1 << num_channels) - 1;
245 	MCE.lock_source = B_MULTI_LOCK_INTERNAL;
246 	rval = DRIVER_SET_ENABLED_CHANNELS(&MCE, 0);
247 	if (B_OK != rval)
248 	{
249 		fprintf(stderr, "Failed on B_MULTI_SET_ENABLED_CHANNELS 0x%p 0x%x\n", MCE.enable_bits, *(MCE.enable_bits));
250 		return B_ERROR;
251 	}
252 
253 	//
254 	// Set the sample rate
255 	//
256 	MFI.info_size = sizeof(MFI);
257 	MFI.output.rate = select_multiaudio_rate(MD.output_rates);
258 	MFI.output.cvsr = 0;
259 	MFI.output.format = select_multiaudio_format(MD.output_formats);
260 	MFI.input.rate = MFI.output.rate;
261 	MFI.input.cvsr = MFI.output.cvsr;
262 	MFI.input.format = MFI.output.format;
263 	rval = DRIVER_SET_GLOBAL_FORMAT(&MFI, 0);
264 	if (B_OK != rval)
265 	{
266 		fprintf(stderr, "Failed on B_MULTI_SET_GLOBAL_FORMAT\n");
267 		return B_ERROR;
268 	}
269 
270 	//
271 	// Get the buffers
272 	//
273 	for (i = 0; i < NB_BUFFERS; i++) {
274 		play_buffer_desc[i] = &play_buffer_list[i * MAX_CHANNELS];
275 		record_buffer_desc[i] = &record_buffer_list[i * MAX_CHANNELS];
276 	}
277 	MBL.info_size = sizeof(MBL);
278 	MBL.request_playback_buffer_size = 0;           //use the default......
279 	MBL.request_playback_buffers = NB_BUFFERS;
280 	MBL.request_playback_channels = num_outputs;
281 	MBL.playback_buffers = (buffer_desc **) play_buffer_desc;
282 	MBL.request_record_buffer_size = 0;           //use the default......
283 	MBL.request_record_buffers = NB_BUFFERS;
284 	MBL.request_record_channels = num_inputs;
285 	MBL.record_buffers = (buffer_desc **) record_buffer_desc;
286 
287 	rval = DRIVER_GET_BUFFERS(&MBL, 0);
288 
289 	if (B_OK != rval)
290 	{
291 		fprintf(stderr, "Failed on B_MULTI_GET_BUFFERS\n");
292 		return B_ERROR;
293 	}
294 
295 	for (i = 0; i < MBL.return_playback_buffers; i++)
296 		for (int j=0; j < MBL.return_playback_channels; j++) {
297 			PRINT(("MBL.playback_buffers[%d][%d].base: %p\n",
298 				i,j,MBL.playback_buffers[i][j].base));
299 			PRINT(("MBL.playback_buffers[%d][%d].stride: %i\n",
300 				i,j,MBL.playback_buffers[i][j].stride));
301 		}
302 
303 	for (i = 0; i < MBL.return_record_buffers; i++)
304 		for (int j=0; j < MBL.return_record_channels; j++) {
305 			PRINT(("MBL.record_buffers[%d][%d].base: %p\n",
306 				i,j,MBL.record_buffers[i][j].base));
307 			PRINT(("MBL.record_buffers[%d][%d].stride: %i\n",
308 				i,j,MBL.record_buffers[i][j].stride));
309 		}
310 
311 	MMCI.info_size = sizeof(MMCI);
312 	MMCI.control_count = MAX_CONTROLS;
313 	MMCI.controls = MMC;
314 
315 	rval = DRIVER_LIST_MIX_CONTROLS(&MMCI, 0);
316 
317 	if (B_OK != rval)
318 	{
319 		fprintf(stderr, "Failed on DRIVER_LIST_MIX_CONTROLS\n");
320 		return B_ERROR;
321 	}
322 
323 	return B_OK;
324 }
325 
326 int
327 MultiAudioDevice::DoBufferExchange(multi_buffer_info *MBI)
328 {
329 	return DRIVER_BUFFER_EXCHANGE(MBI, 0);
330 }
331 
332 int
333 MultiAudioDevice::DoSetMix(multi_mix_value_info *MMVI)
334 {
335 	return DRIVER_SET_MIX(MMVI, 0);
336 }
337 
338 int
339 MultiAudioDevice::DoGetMix(multi_mix_value_info *MMVI)
340 {
341 	return DRIVER_GET_MIX(MMVI, 0);
342 }
343