1 // **************************************************************************** 2 // 3 // CMiaDspCommObject.cpp 4 // 5 // Implementation file for EchoGals generic driver Darla 24 DSP 6 // interface class. 7 // 8 // Copyright Echo Digital Audio Corporation (c) 1998 - 2002 9 // All rights reserved 10 // www.echoaudio.com 11 // 12 // Permission is hereby granted, free of charge, to any person obtaining a 13 // copy of this software and associated documentation files (the 14 // "Software"), to deal with the Software without restriction, including 15 // without limitation the rights to use, copy, modify, merge, publish, 16 // distribute, sublicense, and/or sell copies of the Software, and to 17 // permit persons to whom the Software is furnished to do so, subject to 18 // the following conditions: 19 // 20 // - Redistributions of source code must retain the above copyright 21 // notice, this list of conditions and the following disclaimers. 22 // 23 // - Redistributions in binary form must reproduce the above copyright 24 // notice, this list of conditions and the following disclaimers in the 25 // documentation and/or other materials provided with the distribution. 26 // 27 // - Neither the name of Echo Digital Audio, nor the names of its 28 // contributors may be used to endorse or promote products derived from 29 // this Software without specific prior written permission. 30 // 31 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 32 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 33 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 34 // IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR 35 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 36 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 37 // SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. 38 // 39 // **************************************************************************** 40 41 #include "CEchoGals.h" 42 #include "CMiaDspCommObject.h" 43 44 #include "MiaDSP.c" 45 46 47 /**************************************************************************** 48 49 Construction and destruction 50 51 ****************************************************************************/ 52 53 //=========================================================================== 54 // 55 // Constructor 56 // 57 //=========================================================================== 58 59 CMiaDspCommObject::CMiaDspCommObject 60 ( 61 PDWORD pdwRegBase, // Virtual ptr to DSP registers 62 PCOsSupport pOsSupport 63 ) : CDspCommObject( pdwRegBase, pOsSupport ) 64 { 65 strcpy( m_szCardName, "Mia" ); 66 m_pdwDspRegBase = pdwRegBase; // Virtual addr DSP's register base 67 68 m_wNumPipesOut = 8; 69 m_wNumPipesIn = 4; 70 m_wNumBussesOut = 4; 71 m_wNumBussesIn = 4; 72 m_wFirstDigitalBusOut = 2; 73 m_wFirstDigitalBusIn = 2; 74 75 m_fHasVmixer = TRUE; 76 77 m_wNumMidiOut = 0; // # MIDI out channels 78 m_wNumMidiIn = 0; // # MIDI in channels 79 80 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 44100 ); 81 82 m_bHasASIC = FALSE; 83 84 m_pwDspCodeToLoad = pwMiaDSP; 85 86 m_byDigitalMode = DIGITAL_MODE_NONE; 87 88 // 89 // Since this card has no ASIC, mark it as loaded so everything works OK 90 // 91 m_bASICLoaded = TRUE; 92 93 } // CMiaDspCommObject::CMiaDspCommObject( DWORD dwPhysRegBase ) 94 95 96 //=========================================================================== 97 // 98 // Destructor 99 // 100 //=========================================================================== 101 102 CMiaDspCommObject::~CMiaDspCommObject() 103 { 104 } // CMiaDspCommObject::~CMiaDspCommObject() 105 106 107 108 109 /**************************************************************************** 110 111 Hardware setup and config 112 113 ****************************************************************************/ 114 115 //=========================================================================== 116 // 117 // Set the input clock 118 // 119 //=========================================================================== 120 121 ECHOSTATUS CMiaDspCommObject::SetInputClock(WORD wClock) 122 { 123 DWORD dwSampleRate = GetSampleRate(); 124 125 ECHO_DEBUGPRINTF( ("CMiaDspCommObject::SetInputClock:\n") ); 126 127 switch ( wClock ) 128 { 129 case ECHO_CLOCK_INTERNAL : 130 { 131 ECHO_DEBUGPRINTF( ( "\tSet Mia clock to INTERNAL\n" ) ); 132 133 // If the sample rate is out of range for some reason, set it 134 // to a reasonable value. mattg 135 if ( ( dwSampleRate < 8000 ) || 136 ( dwSampleRate > 96000 ) ) 137 { 138 dwSampleRate = 48000; 139 } 140 141 break; 142 } // CLK_CLOCKININTERNAL 143 144 case ECHO_CLOCK_SPDIF : 145 { 146 ECHO_DEBUGPRINTF( ( "\tSet Mia clock to SPDIF\n" ) ); 147 break; 148 } // CLK_CLOCKINSPDIF 149 150 default : 151 ECHO_DEBUGPRINTF(("Input clock 0x%x not supported for Mia\n",wClock)); 152 ECHO_DEBUGBREAK(); 153 return ECHOSTATUS_CLOCK_NOT_SUPPORTED; 154 } // switch (wInputClock) 155 156 m_wInputClock = wClock; 157 158 SetSampleRate( dwSampleRate ); 159 160 return ECHOSTATUS_OK; 161 } // ECHOSTATUS CMiaDspCommObject::SetInputClock 162 163 164 //=========================================================================== 165 // 166 // SetSampleRate 167 // 168 // Set the audio sample rate for Mia 169 // 170 //=========================================================================== 171 172 DWORD CMiaDspCommObject::SetSampleRate( DWORD dwNewSampleRate ) 173 { 174 // 175 // Set the sample rate 176 // 177 DWORD dwControlReg = MIA_48000; 178 179 switch ( dwNewSampleRate ) 180 { 181 case 96000 : 182 dwControlReg = MIA_96000; 183 break; 184 185 case 88200 : 186 dwControlReg = MIA_88200; 187 break; 188 189 case 44100 : 190 dwControlReg = MIA_44100; 191 break; 192 193 case 32000 : 194 dwControlReg = MIA_32000; 195 break; 196 197 case 24000 : 198 dwControlReg = MIA_24000; 199 break; 200 201 case 22050 : 202 dwControlReg = MIA_22050; 203 break; 204 205 case 16000 : 206 dwControlReg = MIA_16000; 207 break; 208 209 case 12000 : 210 dwControlReg = MIA_12000; 211 break; 212 213 case 11025 : 214 dwControlReg = MIA_11025; 215 break; 216 217 case 8000 : 218 dwControlReg = MIA_8000; 219 break; 220 } 221 222 // 223 // Override the clock setting if this Mia is set to S/PDIF clock 224 // 225 if ( ECHO_CLOCK_SPDIF == GetInputClock() ) 226 { 227 dwControlReg &= MIA_SRC_MASK; 228 dwControlReg |= MIA_SPDIF; 229 } 230 231 // 232 // Set the control register if it has changed 233 // 234 if (dwControlReg != GetControlRegister()) 235 { 236 if ( !WaitForHandshake() ) 237 return 0xffffffff; 238 239 // 240 // Set the values in the comm page; the dwSampleRate 241 // field isn't used by the DSP, but is read by the call 242 // to GetSampleRate below 243 // 244 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate ); 245 SetControlRegister( dwControlReg ); 246 247 // 248 // Poke the DSP 249 // 250 ClearHandshake(); 251 SendVector( DSP_VC_UPDATE_CLOCKS ); 252 } 253 254 return GetSampleRate(); 255 256 } // DWORD CMiaDspCommObject::SetSampleRate( DWORD dwNewSampleRate ) 257 258 259 260 //=========================================================================== 261 // 262 // GetAudioMeters 263 // 264 // Meters are written to the comm page by the DSP as follows: 265 // 266 // Output busses 267 // Input busses 268 // Output pipes (vmixer cards only) 269 // 270 // This function is overridden for vmixer cards 271 // 272 //=========================================================================== 273 274 ECHOSTATUS CMiaDspCommObject::GetAudioMeters 275 ( 276 PECHOGALS_METERS pMeters 277 ) 278 { 279 WORD i; 280 281 pMeters->iNumPipesIn = 0; 282 283 // 284 // Output 285 // 286 DWORD dwCh = 0; 287 288 pMeters->iNumBussesOut = (int) m_wNumBussesOut; 289 for (i = 0; i < m_wNumBussesOut; i++) 290 { 291 pMeters->iBusOutVU[i] = 292 DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->VULevel[ dwCh ]) ); 293 294 pMeters->iBusOutPeak[i] = 295 DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->PeakMeter[ dwCh ]) ); 296 297 dwCh++; 298 } 299 300 pMeters->iNumBussesIn = (int) m_wNumBussesIn; 301 for (i = 0; i < m_wNumPipesIn; i++) 302 { 303 pMeters->iBusInVU[i] = 304 DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->VULevel[ dwCh ]) ); 305 pMeters->iBusInPeak[i] = 306 DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->PeakMeter[ dwCh ]) ); 307 308 dwCh++; 309 } 310 311 pMeters->iNumPipesOut = (int) m_wNumPipesOut; 312 for (i = 0; i < m_wNumPipesOut; i++) 313 { 314 pMeters->iPipeOutVU[i] = 315 DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->VULevel[ dwCh ]) ); 316 pMeters->iPipeOutPeak[i] = 317 DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->PeakMeter[ dwCh ]) ); 318 319 dwCh++; 320 } 321 322 return ECHOSTATUS_OK; 323 324 } // GetAudioMeters 325 326 327 //=========================================================================== 328 // 329 // GetPipeOutGain and SetPipeOutGain 330 // 331 // On Mia, this doesn't set the line out volume; instead, it sets the 332 // vmixer volume. 333 // 334 //=========================================================================== 335 336 ECHOSTATUS CMiaDspCommObject::SetPipeOutGain 337 ( 338 WORD wPipeOut, 339 WORD wBusOut, 340 int iGain, 341 BOOL fImmediate 342 ) 343 { 344 if (wPipeOut >= m_wNumPipesOut) 345 { 346 ECHO_DEBUGPRINTF( ("CDspCommObject::SetPipeOutGain: Invalid out pipe " 347 "%d\n", 348 wPipeOut) ); 349 350 return ECHOSTATUS_INVALID_CHANNEL; 351 } 352 353 iGain = GENERIC_TO_DSP(iGain); 354 355 if ( wBusOut < m_wNumBussesOut ) 356 { 357 if ( !WaitForHandshake() ) 358 return ECHOSTATUS_DSP_DEAD; 359 360 DWORD dwIndex = wBusOut * m_wNumPipesOut + wPipeOut; 361 m_pDspCommPage->byVmixerLevel[ dwIndex ] = (BYTE) iGain; 362 363 ECHO_DEBUGPRINTF( ("CMiaDspCommObject::SetPipeOutGain: Out pipe %d, " 364 "out bus %d = %u\n", 365 wPipeOut, 366 wBusOut, 367 iGain) ); 368 369 if (fImmediate) 370 { 371 return UpdateVmixerLevel(); 372 } 373 374 return ECHOSTATUS_OK; 375 } 376 377 ECHO_DEBUGPRINTF( ("CMiaDspCommObject::SetPipeOutGain: Invalid out bus " 378 "%d\n", 379 wBusOut) ); 380 381 return ECHOSTATUS_INVALID_CHANNEL; 382 383 } // SetPipeOutGain 384 385 386 ECHOSTATUS CMiaDspCommObject::GetPipeOutGain 387 ( 388 WORD wPipeOut, 389 WORD wBusOut, 390 int &iGain 391 ) 392 { 393 if (wPipeOut >= m_wNumPipesOut) 394 { 395 ECHO_DEBUGPRINTF( ("CMiaDspCommObject::GetPipeOutGain: Invalid out pipe " 396 "%d\n", 397 wPipeOut) ); 398 399 return ECHOSTATUS_INVALID_CHANNEL; 400 } 401 402 if (wBusOut < m_wNumBussesOut) 403 { 404 iGain = m_pDspCommPage->byVmixerLevel[ wBusOut * m_wNumPipesOut + wPipeOut ]; 405 iGain = DSP_TO_GENERIC(iGain); 406 return ECHOSTATUS_OK; 407 } 408 409 ECHO_DEBUGPRINTF( ("CMiaDspCommObject::GetPipeOutGain: Invalid out bus " 410 "%d\n", 411 wBusOut) ); 412 413 return ECHOSTATUS_INVALID_CHANNEL; 414 415 } // GetPipeOutGain 416 417 //=========================================================================== 418 // 419 // SetBusOutGain 420 // 421 //=========================================================================== 422 423 ECHOSTATUS CMiaDspCommObject::SetBusOutGain(WORD wBusOut,int iGain) 424 { 425 if ( wBusOut < m_wNumBussesOut ) 426 { 427 if ( !WaitForHandshake() ) 428 return ECHOSTATUS_DSP_DEAD; 429 430 iGain = GENERIC_TO_DSP(iGain); 431 m_pDspCommPage->OutLineLevel[ wBusOut ] = (BYTE) iGain; 432 433 ECHO_DEBUGPRINTF( ("CMiaDspCommObject::SetBusOutGain: Out bus %d " 434 "= %u\n", 435 wBusOut, 436 iGain) ); 437 438 return UpdateAudioOutLineLevel(); 439 440 } 441 442 ECHO_DEBUGPRINTF( ("CMiaDspCommObject::SetBusOutGain: Invalid out bus " 443 "%d\n", 444 wBusOut) ); 445 446 return ECHOSTATUS_INVALID_CHANNEL; 447 } 448 449 450 //=========================================================================== 451 // 452 // Tell the DSP to read and update vmixer levels 453 // from the comm page. 454 // 455 //=========================================================================== 456 457 ECHOSTATUS CMiaDspCommObject::UpdateVmixerLevel() 458 { 459 ECHO_DEBUGPRINTF( ( "CMiaDspCommObject::UpdateVmixerLevel:\n" ) ); 460 461 ClearHandshake(); 462 return( SendVector( DSP_VC_SET_VMIXER_GAIN ) ); 463 } 464 465 466 // **** CMiaDspCommObject.cpp **** 467