1 // ****************************************************************************
5 // Class to control monitors
7 // ----------------------------------------------------------------------------
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
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.
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.
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
28 // ****************************************************************************
30 #include "CEchoGals.h"
31 #include "CMonitorCtrl.h"
33 //*****************************************************************************
35 // Destructor (this class uses the default constructor)
37 //*****************************************************************************
39 CMonitorCtrl::~CMonitorCtrl()
45 //*****************************************************************************
49 //*****************************************************************************
51 ECHOSTATUS
CMonitorCtrl::Init(CEchoGals
*pEG
)
65 m_wNumBussesIn
= pEG
->GetNumBussesIn();
66 m_wNumBussesOut
= pEG
->GetNumBussesOut();
69 // Indigo has no inputs; attempting to allocate 0 bytes
70 // causes a BSOD on Windows ME.
72 if ((0 == m_wNumBussesIn
) || (0 == m_wNumBussesOut
))
74 ECHO_DEBUGPRINTF(("CMonitorCtrl::Init - this card has no inputs!\n"));
78 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
80 // Allocate the arrays
82 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
84 dwArraySize
= m_wNumBussesIn
* (m_wNumBussesOut
>> 1);
86 dwBytes
= sizeof(INT8
) * dwArraySize
;
87 OsAllocateNonPaged(dwBytes
,(void **) &m_Gains
);
91 return ECHOSTATUS_NO_MEM
;
94 dwBytes
= sizeof(WORD
) * dwArraySize
;
95 OsAllocateNonPaged(dwBytes
,(void **) &m_Pans
);
99 return ECHOSTATUS_NO_MEM
;
102 dwBytes
= sizeof(BYTE
) * dwArraySize
;
103 OsAllocateNonPaged(dwBytes
,(void **) &m_Mutes
);
107 return ECHOSTATUS_NO_MEM
;
110 dwBytes
= sizeof(PAN_DB
) * dwArraySize
;
111 OsAllocateNonPaged(dwBytes
,(void **) &m_PanDbs
);
112 if (NULL
== m_PanDbs
)
115 return ECHOSTATUS_NO_MEM
;
118 //==============================================================
122 //==============================================================
124 WORD wBusIn
,wBusOut
,wIndex
;
126 for (wBusIn
= 0; wBusIn
< m_wNumBussesIn
; wBusIn
++)
127 for (wBusOut
= 0; wBusOut
< m_wNumBussesOut
; wBusOut
+= 2)
129 wIndex
= GetIndex(wBusIn
,wBusOut
);
132 // Pan hard left for even inputs, hard right for odd
134 if (0 == (wBusIn
& 1))
137 m_PanDbs
[wIndex
].iLeft
= 0;
138 m_PanDbs
[wIndex
].iRight
= (INT8
) GENERIC_TO_DSP( ECHOGAIN_MUTED
);
142 m_Pans
[wIndex
] = MAX_MIXER_PAN
;
143 m_PanDbs
[wIndex
].iLeft
= (INT8
) GENERIC_TO_DSP( ECHOGAIN_MUTED
);
144 m_PanDbs
[wIndex
].iRight
= 0;
148 // Mute unless this is not a digital input
149 // and the input is going to the same-numbered output
151 if ( (wBusIn
< m_pEG
->GetFirstDigitalBusIn()) &&
152 ( (wBusIn
& 0xfffe) == wBusOut
) )
154 m_Mutes
[wIndex
] = FALSE
;
158 m_Mutes
[wIndex
] = TRUE
;
162 // Put stuff in the comm page
164 SetGain(wBusIn
,wBusOut
,ECHOGAIN_UPDATE
,FALSE
);
168 // Now actually update the DSP
170 m_pEG
->GetDspCommObject()->UpdateAudioOutLineLevel();
173 return ECHOSTATUS_OK
;
178 //*****************************************************************************
180 // Cleanup - free allocated memory
182 //*****************************************************************************
184 void CMonitorCtrl::Cleanup()
187 OsFreeNonPaged(m_Gains
);
190 OsFreeNonPaged(m_Mutes
);
193 OsFreeNonPaged(m_Pans
);
196 OsFreeNonPaged(m_PanDbs
);
201 //*****************************************************************************
205 //*****************************************************************************
207 ECHOSTATUS
CMonitorCtrl::SetGain
218 return ECHOSTATUS_DSP_DEAD
;
220 if ( (NULL
== m_Gains
) ||
222 return ECHOSTATUS_NO_MEM
;
224 if ( (wBusIn
>= m_wNumBussesIn
) || (wBusOut
>= m_wNumBussesOut
) )
226 ECHO_DEBUGPRINTF(("CMonitorCtrl::SetGain - out of range in %d out %d\n",
228 return ECHOSTATUS_INVALID_PARAM
;
232 // Round down to the nearest even bus
237 // Figure out the index into the array
239 WORD wIndex
= GetIndex(wBusIn
,wBusOut
);
241 if (ECHOGAIN_UPDATE
== iGain
)
243 iGain
= DSP_TO_GENERIC( m_Gains
[ wIndex
] );
247 if (iGain
> ECHOGAIN_MAXOUT
)
248 iGain
= ECHOGAIN_MAXOUT
;
249 else if (iGain
< ECHOGAIN_MUTED
)
250 iGain
= ECHOGAIN_MUTED
;
252 m_Gains
[ wIndex
] = (INT8
) GENERIC_TO_DSP( iGain
);
255 // Gain has changed; store the notify
257 m_pEG
->MixerControlChanged(ECHO_MONITOR
,MXN_LEVEL
,wBusIn
,wBusOut
);
261 // Use the gain that was passed in, the pan setting,
262 // and the mute to calculate the left and right gains
264 INT32 iLeft
= iGain
+ DSP_TO_GENERIC( m_PanDbs
[wIndex
].iLeft
);
265 INT32 iRight
= iGain
+ DSP_TO_GENERIC( m_PanDbs
[wIndex
].iRight
);
268 // Adjust left and right by the output bus gain
270 iLeft
+= m_pEG
->m_BusOutLineLevels
[wBusOut
].GetGain();
271 iRight
+= m_pEG
->m_BusOutLineLevels
[wBusOut
+ 1].GetGain();
274 // Either mute or clamp
276 if (TRUE
== m_Mutes
[wIndex
])
278 iLeft
= ECHOGAIN_MUTED
;
279 iRight
= ECHOGAIN_MUTED
;
283 if ( m_pEG
->m_BusOutLineLevels
[wBusOut
].IsMuteOn() )
285 iLeft
= ECHOGAIN_MUTED
;
292 if (iLeft
> ECHOGAIN_MAXOUT
)
293 iLeft
= ECHOGAIN_MAXOUT
;
294 else if (iLeft
< ECHOGAIN_MUTED
)
295 iLeft
= ECHOGAIN_MUTED
;
298 if ( m_pEG
->m_BusOutLineLevels
[wBusOut
+ 1].IsMuteOn() )
300 iRight
= ECHOGAIN_MUTED
;
307 if (iRight
> ECHOGAIN_MAXOUT
)
308 iRight
= ECHOGAIN_MAXOUT
;
309 else if (iRight
< ECHOGAIN_MUTED
)
310 iRight
= ECHOGAIN_MUTED
;
317 // Set the left channel
319 if ( (NULL
== m_pEG
) ||
320 (NULL
== m_pEG
->GetDspCommObject() ) )
321 return ECHOSTATUS_DSP_DEAD
;
326 SetAudioMonitor( wBusOut
,
332 // Set the right channel
334 if (ECHOSTATUS_OK
== Status
)
338 SetAudioMonitor( wBusOut
+ 1,
348 ECHOSTATUS
CMonitorCtrl::GetGain(WORD wBusIn
, WORD wBusOut
, INT32
&iGain
)
350 WORD wIndex
= GetIndex(wBusIn
,wBusOut
);
353 return ECHOSTATUS_NO_MEM
;
355 if ( (wBusIn
>= m_wNumBussesIn
) || (wBusOut
>= m_wNumBussesOut
) )
357 ECHO_DEBUGPRINTF(("CMonitorCtrl::GetGain - out of range in %d out %d\n",
359 return ECHOSTATUS_INVALID_PARAM
;
362 iGain
= DSP_TO_GENERIC( m_Gains
[wIndex
] );
364 return ECHOSTATUS_OK
;
368 //*****************************************************************************
372 //*****************************************************************************
374 ECHOSTATUS
CMonitorCtrl::SetMute
383 return ECHOSTATUS_NO_MEM
;
385 if ( (wBusIn
>= m_wNumBussesIn
) || (wBusOut
>= m_wNumBussesOut
) )
387 ECHO_DEBUGPRINTF(("CMonitorCtrl::SetMute - out of range in %d out %d\n",
389 return ECHOSTATUS_INVALID_PARAM
;
394 WORD wIndex
= GetIndex(wBusIn
,wBusOut
);
399 m_Mutes
[ wIndex
] = (BYTE
) bMute
;
404 m_pEG
->MixerControlChanged(ECHO_MONITOR
,MXN_MUTE
,wBusIn
,wBusOut
);
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.
412 return SetGain(wBusIn
,wBusOut
,ECHOGAIN_UPDATE
,fImmediate
);
416 ECHOSTATUS
CMonitorCtrl::GetMute(WORD wBusIn
, WORD wBusOut
, BOOL
&bMute
)
420 if ( (wBusIn
>= m_wNumBussesIn
) || (wBusOut
>= m_wNumBussesOut
) )
422 ECHO_DEBUGPRINTF(("CMonitorCtrl::GetMute - out of range in %d out %d\n",
424 return ECHOSTATUS_INVALID_PARAM
;
428 WORD wIndex
= GetIndex(wBusIn
,wBusOut
);
431 return ECHOSTATUS_NO_MEM
;
433 bMute
= (BOOL
) m_Mutes
[ wIndex
];
435 return ECHOSTATUS_OK
;
439 //*****************************************************************************
443 //*****************************************************************************
445 ECHOSTATUS
CMonitorCtrl::SetPan(WORD wBusIn
, WORD wBusOut
, INT32 iPan
)
447 if ( (wBusIn
>= m_wNumBussesIn
) || (wBusOut
>= m_wNumBussesOut
) )
449 ECHO_DEBUGPRINTF(("CMonitorCtrl::SetPan - out of range in %d out %d\n",
451 return ECHOSTATUS_INVALID_PARAM
;
456 WORD wIndex
= GetIndex(wBusIn
,wBusOut
);
459 return ECHOSTATUS_NO_MEM
;
462 // Clamp it and stash it
466 else if (iPan
> MAX_MIXER_PAN
)
467 iPan
= MAX_MIXER_PAN
;
469 m_Pans
[wIndex
] = (WORD
) iPan
;
472 // Convert this pan setting into left and right dB values
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
) );
480 m_pEG
->MixerControlChanged(ECHO_MONITOR
,MXN_PAN
,wBusIn
,wBusOut
);
483 // Once again SetGain does all the hard work
485 return SetGain(wBusIn
,wBusOut
,ECHOGAIN_UPDATE
);
489 ECHOSTATUS
CMonitorCtrl::GetPan(WORD wBusIn
, WORD wBusOut
, INT32
&iPan
)
491 if ( (wBusIn
>= m_wNumBussesIn
) || (wBusOut
>= m_wNumBussesOut
) )
493 ECHO_DEBUGPRINTF(("CMonitorCtrl::GetPan - out of range in %d out %d\n",
495 return ECHOSTATUS_INVALID_PARAM
;
501 WORD wIndex
= GetIndex(wBusIn
,wBusOut
);
504 return ECHOSTATUS_NO_MEM
;
506 iPan
= m_Pans
[ wIndex
];
508 return ECHOSTATUS_OK
;