1 // **************************************************************************** 2 // 3 // CLayla.cpp 4 // 5 // Implementation file for the CLayla driver class; this is for 20-bit 6 // Layla. 7 // 8 // Set editor tabs to 3 for your viewing pleasure. 9 // 10 // ---------------------------------------------------------------------------- 11 // 12 // Copyright Echo Digital Audio Corporation (c) 1998 - 2004 13 // All rights reserved 14 // www.echoaudio.com 15 // 16 // This file is part of Echo Digital Audio's generic driver library. 17 // 18 // Echo Digital Audio's generic driver library is free software; 19 // you can redistribute it and/or modify it under the terms of 20 // the GNU General Public License as published by the Free Software Foundation. 21 // 22 // This program is distributed in the hope that it will be useful, 23 // but WITHOUT ANY WARRANTY; without even the implied warranty of 24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 // GNU General Public License for more details. 26 // 27 // You should have received a copy of the GNU General Public License 28 // along with this program; if not, write to the Free Software 29 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, 30 // MA 02111-1307, USA. 31 // 32 // **************************************************************************** 33 34 #include "CLayla.h" 35 36 #define LAYLA20_ANALOG_OUTPUT_LATENCY 57 37 #define LAYLA20_ANALOG_INPUT_LATENCY 64 38 #define LAYLA20_DIGITAL_OUTPUT_LATENCY 32 39 #define LAYLA20_DIGITAL_INPUT_LATENCY 32 40 41 42 /**************************************************************************** 43 44 Construction and destruction 45 46 ****************************************************************************/ 47 48 //=========================================================================== 49 // 50 // Overload new & delete so memory for this object is allocated 51 // from non-paged memory. 52 // 53 //=========================================================================== 54 55 PVOID CLayla::operator new( size_t Size ) 56 { 57 PVOID pMemory; 58 ECHOSTATUS Status; 59 60 Status = OsAllocateNonPaged(Size,&pMemory); 61 62 if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory )) 63 { 64 ECHO_DEBUGPRINTF(("CLayla::operator new - memory allocation failed\n")); 65 66 pMemory = NULL; 67 } 68 else 69 { 70 memset( pMemory, 0, Size ); 71 } 72 73 return pMemory; 74 75 } // PVOID CLayla::operator new( size_t Size ) 76 77 78 VOID CLayla::operator delete( PVOID pVoid ) 79 { 80 if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) ) 81 { 82 ECHO_DEBUGPRINTF( ("CLayla::operator delete memory free failed\n") ); 83 } 84 } // VOID CLayla::operator delete( PVOID pVoid ) 85 86 87 //=========================================================================== 88 // 89 // Constructor and destructor 90 // 91 //=========================================================================== 92 93 CLayla::CLayla( PCOsSupport pOsSupport ) 94 : CEchoGalsMTC( pOsSupport ) 95 { 96 ECHO_DEBUGPRINTF( ( "CLayla::CLayla() is born!\n" ) ); 97 98 m_wAnalogOutputLatency = LAYLA20_ANALOG_OUTPUT_LATENCY; 99 m_wAnalogInputLatency = LAYLA20_ANALOG_INPUT_LATENCY; 100 m_wDigitalOutputLatency = LAYLA20_DIGITAL_OUTPUT_LATENCY; 101 m_wDigitalInputLatency = LAYLA20_DIGITAL_INPUT_LATENCY; 102 103 } // CLayla::CLayla() 104 105 106 CLayla::~CLayla() 107 { 108 ECHO_DEBUGPRINTF( ( "CLayla::~CLayla() is toast!\n" ) ); 109 } // CLayla::~CLayla() 110 111 112 113 114 /**************************************************************************** 115 116 Setup and hardware initialization 117 118 ****************************************************************************/ 119 120 //=========================================================================== 121 // 122 // Every card has an InitHw method 123 // 124 //=========================================================================== 125 126 ECHOSTATUS CLayla::InitHw() 127 { 128 ECHOSTATUS Status; 129 WORD i; 130 131 // 132 // Call the base method 133 // 134 if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) ) 135 return Status; 136 137 // 138 // Create the DSP comm object 139 // 140 ASSERT( NULL == m_pDspCommObject ); 141 m_pDspCommObject = new CLaylaDspCommObject( (PDWORD) m_pvSharedMemory, 142 m_pOsSupport ); 143 if (NULL == m_pDspCommObject) 144 { 145 ECHO_DEBUGPRINTF(("CLayla::InitHw - could not create DSP comm object\n")); 146 return ECHOSTATUS_NO_MEM; 147 } 148 149 // 150 // Load the DSP and the external box ASIC 151 // 152 GetDspCommObject()->LoadFirmware(); 153 if ( GetDspCommObject()->IsBoardBad() ) 154 return ECHOSTATUS_DSP_DEAD; 155 156 // 157 // Clear the "bad board" flag; set the flag to indicate that 158 // Darla24 can handle super-interleave. 159 // 160 m_wFlags &= ~ECHOGALS_FLAG_BADBOARD; 161 m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK; 162 163 // 164 // Must call this here after DSP is init to 165 // init gains and mutes 166 // 167 Status = InitLineLevels(); 168 if ( ECHOSTATUS_OK != Status ) 169 return Status; 170 171 // 172 // Initialize the MIDI input 173 // 174 Status = m_MidiIn.Init( this ); 175 if ( ECHOSTATUS_OK != Status ) 176 return Status; 177 178 ECHO_DEBUGPRINTF(("\tMIDI input init done\n")); 179 180 // 181 // Set defaults for +4/-10 182 // 183 for (i = 0; i < GetFirstDigitalBusOut(); i++ ) 184 { 185 ECHO_DEBUGPRINTF(("\tSetting nominal output level %d\n",i)); 186 GetDspCommObject()->SetNominalLevel( i, TRUE ); // TRUE is -10 here 187 } 188 for ( i = 0; i < GetFirstDigitalBusIn(); i++ ) 189 { 190 ECHO_DEBUGPRINTF(("\tSetting nominal input level %d\n",i)); 191 GetDspCommObject()->SetNominalLevel( GetNumBussesOut() + i, TRUE ); 192 } 193 194 ECHO_DEBUGPRINTF(("\tNominal levels done\n")); 195 196 // 197 // Set the S/PDIF output format to "professional" 198 // 199 SetProfessionalSpdif( TRUE ); 200 ECHO_DEBUGPRINTF(("\tSet S/PDIF format OK\n")); 201 202 // 203 // Get default sample rate from DSP 204 // 205 m_dwSampleRate = GetDspCommObject()->GetSampleRate(); 206 ECHO_DEBUGPRINTF( ( "\tCLayla::InitHw() finished\n" ) ); 207 208 return Status; 209 210 } // ECHOSTATUS CLayla::InitHw() 211 212 213 214 215 /**************************************************************************** 216 217 Informational methods 218 219 ****************************************************************************/ 220 221 //=========================================================================== 222 // 223 // Override GetCapabilities to enumerate unique capabilties for Layla20 224 // 225 //=========================================================================== 226 227 ECHOSTATUS CLayla::GetCapabilities 228 ( 229 PECHOGALS_CAPS pCapabilities 230 ) 231 { 232 ECHOSTATUS Status; 233 WORD i; 234 235 Status = GetBaseCapabilities(pCapabilities); 236 237 // 238 // Add input gain and nominal level to input busses 239 // 240 for (i = 0; i < GetFirstDigitalBusIn(); i++) 241 { 242 pCapabilities->dwBusInCaps[i] |= ECHOCAPS_GAIN | 243 ECHOCAPS_MUTE | 244 ECHOCAPS_NOMINAL_LEVEL; 245 } 246 247 // 248 // Add nominal levels to output busses 249 // 250 for (i = 0; i < GetFirstDigitalBusOut(); i++) 251 { 252 pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL; 253 } 254 255 if ( ECHOSTATUS_OK != Status ) 256 return Status; 257 258 pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_WORD | 259 ECHO_CLOCK_BIT_SUPER | 260 ECHO_CLOCK_BIT_SPDIF | 261 ECHO_CLOCK_BIT_MTC; 262 263 pCapabilities->dwOutClockTypes |= ECHO_CLOCK_BIT_WORD | 264 ECHO_CLOCK_BIT_SUPER; 265 266 return Status; 267 268 } // ECHOSTATUS CLayla::GetCapabilities 269 270 271 //=========================================================================== 272 // 273 // QueryAudioSampleRate is used to find out if this card can handle a 274 // given sample rate. 275 // 276 //=========================================================================== 277 278 ECHOSTATUS CLayla::QueryAudioSampleRate 279 ( 280 DWORD dwSampleRate 281 ) 282 { 283 if ( dwSampleRate < 8000 || 284 dwSampleRate > 50000 ) 285 { 286 ECHO_DEBUGPRINTF( 287 ("CLayla::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) ); 288 return ECHOSTATUS_BAD_FORMAT; 289 } 290 ECHO_DEBUGPRINTF( ( "CLayla::QueryAudioSampleRate() %ld Hz OK\n", 291 dwSampleRate ) ); 292 return ECHOSTATUS_OK; 293 294 } // ECHOSTATUS CLayla::QueryAudioSampleRate 295 296 297 //=========================================================================== 298 // 299 // GetInputClockDetect returns a bitmask consisting of all the input 300 // clocks currently connected to the hardware; this changes as the user 301 // connects and disconnects clock inputs. 302 // 303 // You should use this information to determine which clocks the user is 304 // allowed to select. 305 // 306 // Layla20 supports S/PDIF clock, word clock, and super clock. 307 // 308 //=========================================================================== 309 310 ECHOSTATUS CLayla::GetInputClockDetect(DWORD &dwClockDetectBits) 311 { 312 if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() ) 313 { 314 ECHO_DEBUGPRINTF( ("CLayla::GetInputClockDetect: DSP Dead!\n") ); 315 return ECHOSTATUS_DSP_DEAD; 316 } 317 318 DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect(); 319 320 dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_MTC; 321 322 if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_SPDIF)) 323 dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF; 324 325 if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_WORD)) 326 { 327 if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_SUPER)) 328 dwClockDetectBits |= ECHO_CLOCK_BIT_SUPER; 329 else 330 dwClockDetectBits |= ECHO_CLOCK_BIT_WORD; 331 } 332 333 return ECHOSTATUS_OK; 334 335 } // GetInputClockDetect 336 337 338 // *** CLayla.cpp *** 339