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