1 // **************************************************************************** 2 // 3 // CMonitorCtrl.cpp 4 // 5 // Class to control monitors 6 // 7 // ---------------------------------------------------------------------------- 8 // 9 // This file is part of Echo Digital Audio's generic driver library. 10 // Copyright Echo Digital Audio Corporation (c) 1998 - 2005 11 // All rights reserved 12 // www.echoaudio.com 13 // 14 // This library is free software; you can redistribute it and/or 15 // modify it under the terms of the GNU Lesser General Public 16 // License as published by the Free Software Foundation; either 17 // version 2.1 of the License, or (at your option) any later version. 18 // 19 // This library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 // Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public 25 // License along with this library; if not, write to the Free Software 26 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 // 28 // **************************************************************************** 29 30 #include "CEchoGals.h" 31 #include "CMonitorCtrl.h" 32 33 //***************************************************************************** 34 // 35 // Destructor (this class uses the default constructor) 36 // 37 //***************************************************************************** 38 39 CMonitorCtrl::~CMonitorCtrl() 40 { 41 Cleanup(); 42 } 43 44 45 //***************************************************************************** 46 // 47 // Init 48 // 49 //***************************************************************************** 50 51 ECHOSTATUS CMonitorCtrl::Init(CEchoGals *pEG) 52 { 53 DWORD dwBytes; 54 DWORD dwArraySize; 55 56 m_Gains = NULL; 57 m_Mutes = NULL; 58 m_Pans = NULL; 59 m_PanDbs = NULL; 60 61 // 62 // Cache stuff 63 // 64 m_pEG = pEG; 65 m_wNumBussesIn = pEG->GetNumBussesIn(); 66 m_wNumBussesOut = pEG->GetNumBussesOut(); 67 68 // 69 // Indigo has no inputs; attempting to allocate 0 bytes 70 // causes a BSOD on Windows ME. 71 // 72 if ((0 == m_wNumBussesIn) || (0 == m_wNumBussesOut)) 73 { 74 ECHO_DEBUGPRINTF(("CMonitorCtrl::Init - this card has no inputs!\n")); 75 return ECHOSTATUS_OK; 76 } 77 78 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 79 // 80 // Allocate the arrays 81 // 82 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 83 84 dwArraySize = m_wNumBussesIn * (m_wNumBussesOut >> 1); 85 86 dwBytes = sizeof(INT8) * dwArraySize; 87 OsAllocateNonPaged(dwBytes,(void **) &m_Gains); 88 if (NULL == m_Gains) 89 { 90 Cleanup(); 91 return ECHOSTATUS_NO_MEM; 92 } 93 94 dwBytes = sizeof(WORD) * dwArraySize; 95 OsAllocateNonPaged(dwBytes,(void **) &m_Pans); 96 if (NULL == m_Pans) 97 { 98 Cleanup(); 99 return ECHOSTATUS_NO_MEM; 100 } 101 102 dwBytes = sizeof(BYTE) * dwArraySize; 103 OsAllocateNonPaged(dwBytes,(void **) &m_Mutes); 104 if (NULL == m_Mutes) 105 { 106 Cleanup(); 107 return ECHOSTATUS_NO_MEM; 108 } 109 110 dwBytes = sizeof(PAN_DB) * dwArraySize; 111 OsAllocateNonPaged(dwBytes,(void **) &m_PanDbs ); 112 if (NULL == m_PanDbs) 113 { 114 Cleanup(); 115 return ECHOSTATUS_NO_MEM; 116 } 117 118 //============================================================== 119 // 120 // Init the arrays 121 // 122 //============================================================== 123 124 WORD wBusIn,wBusOut,wIndex; 125 126 for (wBusIn = 0; wBusIn < m_wNumBussesIn; wBusIn++) 127 for (wBusOut = 0; wBusOut < m_wNumBussesOut; wBusOut += 2) 128 { 129 wIndex = GetIndex(wBusIn,wBusOut); 130 131 // 132 // Pan hard left for even inputs, hard right for odd 133 // 134 if (0 == (wBusIn & 1)) 135 { 136 m_Pans[wIndex] = 0; 137 m_PanDbs[wIndex].iLeft = 0; 138 m_PanDbs[wIndex].iRight = (INT8) GENERIC_TO_DSP( ECHOGAIN_MUTED ); 139 } 140 else 141 { 142 m_Pans[wIndex] = MAX_MIXER_PAN; 143 m_PanDbs[wIndex].iLeft = (INT8) GENERIC_TO_DSP( ECHOGAIN_MUTED ); 144 m_PanDbs[wIndex].iRight = 0; 145 } 146 147 // 148 // Mute unless this is not a digital input 149 // and the input is going to the same-numbered output 150 // 151 if ( (wBusIn < m_pEG->GetFirstDigitalBusIn()) && 152 ( (wBusIn & 0xfffe) == wBusOut ) ) 153 { 154 m_Mutes[wIndex] = FALSE; 155 } 156 else 157 { 158 m_Mutes[wIndex] = TRUE; 159 } 160 161 // 162 // Put stuff in the comm page 163 // 164 SetGain(wBusIn,wBusOut,ECHOGAIN_UPDATE,FALSE); 165 } 166 167 // 168 // Now actually update the DSP 169 // 170 m_pEG->GetDspCommObject()->UpdateAudioOutLineLevel(); 171 172 173 return ECHOSTATUS_OK; 174 175 } // Init 176 177 178 //***************************************************************************** 179 // 180 // Cleanup - free allocated memory 181 // 182 //***************************************************************************** 183 184 void CMonitorCtrl::Cleanup() 185 { 186 if (m_Gains) 187 OsFreeNonPaged(m_Gains); 188 189 if (m_Mutes) 190 OsFreeNonPaged(m_Mutes); 191 192 if (m_Pans) 193 OsFreeNonPaged(m_Pans); 194 195 if (m_PanDbs) 196 OsFreeNonPaged(m_PanDbs); 197 198 } // Cleanup 199 200 201 //***************************************************************************** 202 // 203 // Set and get gain 204 // 205 //***************************************************************************** 206 207 ECHOSTATUS CMonitorCtrl::SetGain 208 ( 209 WORD wBusIn, 210 WORD wBusOut, 211 INT32 iGain, 212 BOOL fImmediate 213 ) 214 { 215 ECHOSTATUS Status; 216 217 if (NULL == m_pEG) 218 return ECHOSTATUS_DSP_DEAD; 219 220 if ( (NULL == m_Gains) || 221 (NULL == m_PanDbs) ) 222 return ECHOSTATUS_NO_MEM; 223 224 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) ) 225 { 226 ECHO_DEBUGPRINTF(("CMonitorCtrl::SetGain - out of range in %d out %d\n", 227 wBusIn,wBusOut)); 228 return ECHOSTATUS_INVALID_PARAM; 229 } 230 231 // 232 // Round down to the nearest even bus 233 // 234 wBusOut &= 0xfffe; 235 236 // 237 // Figure out the index into the array 238 // 239 WORD wIndex = GetIndex(wBusIn,wBusOut); 240 241 if (ECHOGAIN_UPDATE == iGain) 242 { 243 iGain = DSP_TO_GENERIC( m_Gains[ wIndex ] ); 244 } 245 else 246 { 247 if (iGain > ECHOGAIN_MAXOUT) 248 iGain = ECHOGAIN_MAXOUT; 249 else if (iGain < ECHOGAIN_MUTED) 250 iGain = ECHOGAIN_MUTED; 251 252 m_Gains[ wIndex ] = (INT8) GENERIC_TO_DSP( iGain ); 253 254 // 255 // Gain has changed; store the notify 256 // 257 m_pEG->MixerControlChanged(ECHO_MONITOR,MXN_LEVEL,wBusIn,wBusOut); 258 } 259 260 // 261 // Use the gain that was passed in, the pan setting, 262 // and the mute to calculate the left and right gains 263 // 264 INT32 iLeft = iGain + DSP_TO_GENERIC( m_PanDbs[wIndex].iLeft ); 265 INT32 iRight = iGain + DSP_TO_GENERIC( m_PanDbs[wIndex].iRight ); 266 267 // 268 // Adjust left and right by the output bus gain 269 // 270 iLeft += m_pEG->m_BusOutLineLevels[wBusOut].GetGain(); 271 iRight += m_pEG->m_BusOutLineLevels[wBusOut + 1].GetGain(); 272 273 // 274 // Either mute or clamp 275 // 276 if (TRUE == m_Mutes[wIndex]) 277 { 278 iLeft = ECHOGAIN_MUTED; 279 iRight = ECHOGAIN_MUTED; 280 } 281 else 282 { 283 if ( m_pEG->m_BusOutLineLevels[wBusOut].IsMuteOn() ) 284 { 285 iLeft = ECHOGAIN_MUTED; 286 } 287 else 288 { 289 // 290 // Clamp left 291 // 292 if (iLeft > ECHOGAIN_MAXOUT) 293 iLeft = ECHOGAIN_MAXOUT; 294 else if (iLeft < ECHOGAIN_MUTED) 295 iLeft = ECHOGAIN_MUTED; 296 } 297 298 if ( m_pEG->m_BusOutLineLevels[wBusOut + 1].IsMuteOn() ) 299 { 300 iRight = ECHOGAIN_MUTED; 301 } 302 else 303 { 304 // 305 // Clamp right 306 // 307 if (iRight > ECHOGAIN_MAXOUT) 308 iRight = ECHOGAIN_MAXOUT; 309 else if (iRight < ECHOGAIN_MUTED) 310 iRight = ECHOGAIN_MUTED; 311 312 } 313 } 314 315 316 // 317 // Set the left channel 318 // 319 if ( (NULL == m_pEG) || 320 (NULL == m_pEG->GetDspCommObject() ) ) 321 return ECHOSTATUS_DSP_DEAD; 322 323 324 Status = m_pEG-> 325 GetDspCommObject()-> 326 SetAudioMonitor( wBusOut, 327 wBusIn, 328 iLeft, 329 FALSE); 330 331 // 332 // Set the right channel 333 // 334 if (ECHOSTATUS_OK == Status) 335 { 336 Status = m_pEG-> 337 GetDspCommObject()-> 338 SetAudioMonitor( wBusOut + 1, 339 wBusIn, 340 iRight, 341 fImmediate); 342 } 343 344 return Status; 345 } 346 347 348 ECHOSTATUS CMonitorCtrl::GetGain(WORD wBusIn, WORD wBusOut, INT32 &iGain) 349 { 350 WORD wIndex = GetIndex(wBusIn,wBusOut); 351 352 if (NULL == m_Gains) 353 return ECHOSTATUS_NO_MEM; 354 355 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) ) 356 { 357 ECHO_DEBUGPRINTF(("CMonitorCtrl::GetGain - out of range in %d out %d\n", 358 wBusIn,wBusOut)); 359 return ECHOSTATUS_INVALID_PARAM; 360 } 361 362 iGain = DSP_TO_GENERIC( m_Gains[wIndex] ); 363 364 return ECHOSTATUS_OK; 365 } 366 367 368 //***************************************************************************** 369 // 370 // Set and get mute 371 // 372 //***************************************************************************** 373 374 ECHOSTATUS CMonitorCtrl::SetMute 375 ( 376 WORD wBusIn, 377 WORD wBusOut, 378 BOOL bMute, 379 BOOL fImmediate 380 ) 381 { 382 if (NULL == m_Mutes) 383 return ECHOSTATUS_NO_MEM; 384 385 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) ) 386 { 387 ECHO_DEBUGPRINTF(("CMonitorCtrl::SetMute - out of range in %d out %d\n", 388 wBusIn,wBusOut)); 389 return ECHOSTATUS_INVALID_PARAM; 390 } 391 392 wBusOut &= 0xfffe; 393 394 WORD wIndex = GetIndex(wBusIn,wBusOut); 395 396 // 397 // Store the mute 398 // 399 m_Mutes[ wIndex ] = (BYTE) bMute; 400 401 // 402 // Store the notify 403 // 404 m_pEG->MixerControlChanged(ECHO_MONITOR,MXN_MUTE,wBusIn,wBusOut); 405 406 407 // 408 // Call the SetGain function to do all the heavy lifting 409 // Use the ECHOGAIN_UPDATE value to tell the function to 410 // recalculate the gain setting using the currently stored value. 411 // 412 return SetGain(wBusIn,wBusOut,ECHOGAIN_UPDATE,fImmediate); 413 } 414 415 416 ECHOSTATUS CMonitorCtrl::GetMute(WORD wBusIn, WORD wBusOut, BOOL &bMute) 417 { 418 wBusOut &= 0xfffe; 419 420 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) ) 421 { 422 ECHO_DEBUGPRINTF(("CMonitorCtrl::GetMute - out of range in %d out %d\n", 423 wBusIn,wBusOut)); 424 return ECHOSTATUS_INVALID_PARAM; 425 } 426 427 428 WORD wIndex = GetIndex(wBusIn,wBusOut); 429 430 if (NULL == m_Mutes) 431 return ECHOSTATUS_NO_MEM; 432 433 bMute = (BOOL) m_Mutes[ wIndex ]; 434 435 return ECHOSTATUS_OK; 436 } 437 438 439 //***************************************************************************** 440 // 441 // Set and get pan 442 // 443 //***************************************************************************** 444 445 ECHOSTATUS CMonitorCtrl::SetPan(WORD wBusIn, WORD wBusOut, INT32 iPan) 446 { 447 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) ) 448 { 449 ECHO_DEBUGPRINTF(("CMonitorCtrl::SetPan - out of range in %d out %d\n", 450 wBusIn,wBusOut)); 451 return ECHOSTATUS_INVALID_PARAM; 452 } 453 454 wBusOut &= 0xfffe; 455 456 WORD wIndex = GetIndex(wBusIn,wBusOut); 457 458 if (NULL == m_Pans) 459 return ECHOSTATUS_NO_MEM; 460 461 // 462 // Clamp it and stash it 463 // 464 if (iPan < 0) 465 iPan = 0; 466 else if (iPan > MAX_MIXER_PAN) 467 iPan = MAX_MIXER_PAN; 468 469 m_Pans[wIndex] = (WORD) iPan; 470 471 // 472 // Convert this pan setting into left and right dB values 473 // 474 m_PanDbs[wIndex].iLeft = (INT8) GENERIC_TO_DSP( PanToDb(MAX_MIXER_PAN - iPan) ); 475 m_PanDbs[wIndex].iRight = (INT8) GENERIC_TO_DSP( PanToDb(iPan) ); 476 477 // 478 // Store the notify 479 // 480 m_pEG->MixerControlChanged(ECHO_MONITOR,MXN_PAN,wBusIn,wBusOut); 481 482 // 483 // Once again SetGain does all the hard work 484 // 485 return SetGain(wBusIn,wBusOut,ECHOGAIN_UPDATE); 486 } 487 488 489 ECHOSTATUS CMonitorCtrl::GetPan(WORD wBusIn, WORD wBusOut, INT32 &iPan) 490 { 491 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) ) 492 { 493 ECHO_DEBUGPRINTF(("CMonitorCtrl::GetPan - out of range in %d out %d\n", 494 wBusIn,wBusOut)); 495 return ECHOSTATUS_INVALID_PARAM; 496 } 497 498 499 wBusOut &= 0xfffe; 500 501 WORD wIndex = GetIndex(wBusIn,wBusOut); 502 503 if (NULL == m_Pans) 504 return ECHOSTATUS_NO_MEM; 505 506 iPan = m_Pans[ wIndex ]; 507 508 return ECHOSTATUS_OK; 509 } 510