4 |
* * |
* * |
5 |
* Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005-2008 Christian Schoenebeck * |
* Copyright (C) 2005-2008 Christian Schoenebeck * |
7 |
* Copyright (C) 2009-2011 Christian Schoenebeck and Grigor Iliev * |
* Copyright (C) 2009-2013 Christian Schoenebeck and Grigor Iliev * |
8 |
* * |
* * |
9 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
10 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
312 |
// lower minimum release time |
// lower minimum release time |
313 |
const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate; |
const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate; |
314 |
for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) { |
for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) { |
315 |
iterVoice->pEG1->CalculateFadeOutCoeff(minReleaseTime, SampleRate); |
iterVoice->CalculateFadeOutCoeff(minReleaseTime, SampleRate); |
316 |
} |
} |
317 |
pVoicePool->clear(); |
pVoicePool->clear(); |
318 |
} |
} |
345 |
pDiskThread->StartThread(); |
pDiskThread->StartThread(); |
346 |
dmsg(1,("OK\n")); |
dmsg(1,("OK\n")); |
347 |
|
|
348 |
|
bool printEqInfo = true; |
349 |
for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) { |
for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) { |
350 |
if (!iterVoice->pDiskThread) { |
if (!iterVoice->pDiskThread) { |
351 |
dmsg(0,("Engine -> voice::trigger: !pDiskThread\n")); |
dmsg(0,("Engine -> voice::trigger: !pDiskThread\n")); |
352 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
353 |
} |
} |
354 |
|
|
355 |
|
iterVoice->CreateEq(); |
356 |
|
|
357 |
|
if(printEqInfo) { |
358 |
|
iterVoice->PrintEqInfo(); |
359 |
|
printEqInfo = false; |
360 |
|
} |
361 |
} |
} |
362 |
pVoicePool->clear(); |
pVoicePool->clear(); |
363 |
|
|
368 |
pDedicatedVoiceChannelLeft = new AudioChannel(0, MaxSamplesPerCycle); |
pDedicatedVoiceChannelLeft = new AudioChannel(0, MaxSamplesPerCycle); |
369 |
pDedicatedVoiceChannelRight = new AudioChannel(1, MaxSamplesPerCycle); |
pDedicatedVoiceChannelRight = new AudioChannel(1, MaxSamplesPerCycle); |
370 |
} |
} |
371 |
|
|
372 |
|
// Implementattion for abstract method derived from Engine. |
373 |
|
virtual void ReconnectAudioOutputDevice() { |
374 |
|
SuspendAll(); |
375 |
|
if (pAudioOutputDevice) Connect(pAudioOutputDevice); |
376 |
|
ResumeAll(); |
377 |
|
} |
378 |
|
|
379 |
/** |
/** |
380 |
* Similar to @c Disable() but this method additionally kills all voices |
* Similar to @c Disable() but this method additionally kills all voices |
429 |
*/ |
*/ |
430 |
virtual void Suspend(RR* pRegion) { |
virtual void Suspend(RR* pRegion) { |
431 |
dmsg(2,("EngineBase: Suspending Region %x ...\n",pRegion)); |
dmsg(2,("EngineBase: Suspending Region %x ...\n",pRegion)); |
432 |
SuspendedRegionsMutex.Lock(); |
{ |
433 |
SuspensionChangeOngoing.Set(true); |
LockGuard lock(SuspendedRegionsMutex); |
434 |
pPendingRegionSuspension = pRegion; |
SuspensionChangeOngoing.Set(true); |
435 |
SuspensionChangeOngoing.WaitAndUnlockIf(true); |
pPendingRegionSuspension = pRegion; |
436 |
SuspendedRegionsMutex.Unlock(); |
SuspensionChangeOngoing.WaitAndUnlockIf(true); |
437 |
|
} |
438 |
dmsg(2,("EngineBase: Region %x suspended.",pRegion)); |
dmsg(2,("EngineBase: Region %x suspended.",pRegion)); |
439 |
} |
} |
440 |
|
|
446 |
*/ |
*/ |
447 |
virtual void Resume(RR* pRegion) { |
virtual void Resume(RR* pRegion) { |
448 |
dmsg(2,("EngineBase: Resuming Region %x ...\n",pRegion)); |
dmsg(2,("EngineBase: Resuming Region %x ...\n",pRegion)); |
449 |
SuspendedRegionsMutex.Lock(); |
{ |
450 |
SuspensionChangeOngoing.Set(true); |
LockGuard lock(SuspendedRegionsMutex); |
451 |
pPendingRegionResumption = pRegion; |
SuspensionChangeOngoing.Set(true); |
452 |
SuspensionChangeOngoing.WaitAndUnlockIf(true); |
pPendingRegionResumption = pRegion; |
453 |
SuspendedRegionsMutex.Unlock(); |
SuspensionChangeOngoing.WaitAndUnlockIf(true); |
454 |
|
} |
455 |
dmsg(2,("EngineBase: Region %x resumed.\n",pRegion)); |
dmsg(2,("EngineBase: Region %x resumed.\n",pRegion)); |
456 |
} |
} |
457 |
|
|
977 |
} |
} |
978 |
case 10: { // panpot |
case 10: { // panpot |
979 |
//TODO: not sample accurate yet |
//TODO: not sample accurate yet |
|
pChannel->GlobalPanLeft = PanCurve[128 - itControlChangeEvent->Param.CC.Value]; |
|
|
pChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value]; |
|
980 |
pChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value; |
pChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value; |
981 |
break; |
break; |
982 |
} |
} |
1327 |
* control and status variables. This method is protected by a mutex. |
* control and status variables. This method is protected by a mutex. |
1328 |
*/ |
*/ |
1329 |
virtual void ResetInternal() { |
virtual void ResetInternal() { |
1330 |
ResetInternalMutex.Lock(); |
LockGuard lock(ResetInternalMutex); |
1331 |
|
|
1332 |
// make sure that the engine does not get any sysex messages |
// make sure that the engine does not get any sysex messages |
1333 |
// while it's reseting |
// while it's reseting |
1356 |
pEventQueue->init(); |
pEventQueue->init(); |
1357 |
pSysexBuffer->init(); |
pSysexBuffer->init(); |
1358 |
if (sysexDisabled) MidiInputPort::AddSysexListener(this); |
if (sysexDisabled) MidiInputPort::AddSysexListener(this); |
|
ResetInternalMutex.Unlock(); |
|
1359 |
} |
} |
1360 |
|
|
1361 |
/** |
/** |