--- linuxsampler/trunk/src/engines/gig/Engine.h 2005/03/17 23:56:56 475 +++ linuxsampler/trunk/src/engines/gig/Engine.h 2007/09/04 01:12:49 1321 @@ -2,8 +2,8 @@ * * * LinuxSampler - modular, streaming capable sampler * * * - * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * - * Copyright (C) 2005 Christian Schoenebeck * + * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck * + * Copyright (C) 2005-2007 Christian Schoenebeck * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -26,26 +26,21 @@ #include "../../common/global.h" -#if DEBUG_HEADERS -# warning Engine.h included -#endif // DEBUG_HEADERS - #include +#include #include "EngineGlobals.h" #include "../../common/RingBuffer.h" #include "../../common/Pool.h" #include "../../common/ArrayList.h" #include "../../common/ConditionServer.h" -#include "../common/Engine.h" +#include "../Engine.h" #include "../common/Event.h" -#include "../common/BiquadFilter.h" -#include "../../lib/fileloader/libgig/gig.h" #include "../../network/lscp.h" #include "EngineChannel.h" // identifier of this sampler engine -#define LS_GIG_ENGINE_NAME "GigEngine" +#define LS_GIG_ENGINE_NAME "GIG" namespace LinuxSampler { namespace gig { @@ -63,8 +58,13 @@ public: // methods Engine(); - ~Engine(); + virtual ~Engine(); void Connect(AudioOutputDevice* pAudioOut); + ::gig::DimensionRegion** ChangeInstrument(EngineChannel* pEngineChannel, ::gig::Instrument* pInstrument); + void SuspendAll(); + void ResumeAll(); + void Suspend(::gig::Region* pRegion); + void Resume(::gig::Region* pRegion); // implementation of abstract methods derived from class 'LinuxSampler::Engine' virtual int RenderAudio(uint Samples); @@ -82,6 +82,11 @@ virtual String Description(); virtual String Version(); virtual String EngineName(); + virtual InstrumentManager* GetInstrumentManager(); + + static const float* VolumeCurve; ///< Table that maps volume control change values 0..127 to amplitude. Unity gain is at 90. + static const float* PanCurve; ///< Table that maps pan control change values 0..128 to right channel amplitude. Unity gain is at 64 (center). + static const float* CrossfadeCurve; ///< Table that maps crossfade control change values 0..127 to amplitude. Unity gain is at 127. //protected: static InstrumentResourceManager instruments; @@ -90,32 +95,33 @@ uint SampleRate; ///< Sample rate of the engines output audio signal (in Hz) uint MaxSamplesPerCycle; ///< Size of each audio output buffer DiskThread* pDiskThread; - RingBuffer* pEventQueue; ///< Input event queue for engine global events (e.g. SysEx messages). + RingBuffer* pEventQueue; ///< Input event queue for engine global events (e.g. SysEx messages). Pool* pVoicePool; ///< Contains all voices that can be activated. EventGenerator* pEventGenerator; RTList* pVoiceStealingQueue; ///< All voice-launching events which had to be postponed due to free voice shortage. RTList* pGlobalEvents; ///< All engine global events for the current audio fragment (usually only SysEx messages). Pool* pEventPool; ///< Contains all Event objects that can be used. - RingBuffer* pSysexBuffer; ///< Input buffer for MIDI system exclusive messages. - float* pSynthesisParameters[Event::destination_count]; ///< Matrix with final synthesis parameters for the current audio fragment which will be used in the main synthesis loop. - biquad_param_t* pBasicFilterParameters; ///< Biquad parameters of the basic bandpass filter. - biquad_param_t* pMainFilterParameters; ///< Main biquad parameters of the individual filter (lowpass / bandpass / highpass). + RingBuffer* pSysexBuffer; ///< Input buffer for MIDI system exclusive messages. int ActiveVoiceCount; ///< number of currently active voices (this value will be returned for public calls) int ActiveVoiceCountTemp; ///< number of currently active voices (for internal usage, will be used for incrementation) int ActiveVoiceCountMax; ///< the maximum voice usage since application start - int VoiceTheftsLeft; ///< We only allow MAX_AUDIO_VOICES voices to be stolen per audio fragment, we use this variable to ensure this limit. + int VoiceSpawnsLeft; ///< We only allow CONFIG_MAX_VOICES voices to be spawned per audio fragment, we use this variable to ensure this limit. RTList::Iterator itLastStolenVoice; ///< Only for voice stealing: points to the last voice which was theft in current audio fragment, NULL otherwise. RTList::Iterator iuiLastStolenKey; ///< Only for voice stealing: key number of last key on which the last voice was theft in current audio fragment, NULL otherwise. EngineChannel* pLastStolenChannel; ///< Only for voice stealing: points to the engine channel on which the previous voice was stolen in this audio fragment. + RTList::Iterator itLastStolenVoiceGlobally; ///< Same as itLastStolenVoice, but engine globally + RTList::Iterator iuiLastStolenKeyGlobally; ///< Same as iuiLastStolenKey, but engine globally bool SuspensionRequested; ConditionServer EngineDisabled; int8_t ScaleTuning[12]; ///< contains optional detune factors (-64..+63 cents) for all 12 semitones of an octave int MaxFadeOutPos; ///< The last position in an audio fragment to allow an instant fade out (e.g. for voice stealing) without leading to clicks. uint32_t RandomSeed; ///< State of the random number generator used by the random dimension. + Mutex ResetInternalMutex; ///< Mutex to protect the ResetInternal function for concurrent usage (e.g. by the lscp and instrument loader threads). void ProcessEvents(EngineChannel* pEngineChannel, uint Samples); void RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples); void RenderStolenVoices(uint Samples); + void RouteAudio(EngineChannel* pEngineChannel, uint Samples); void PostProcess(EngineChannel* pEngineChannel); void ClearEventLists(); void ImportEvents(uint Samples); @@ -124,12 +130,15 @@ void ProcessPitchbend(EngineChannel* pEngineChannel, Pool::Iterator& itPitchbendEvent); void ProcessControlChange(EngineChannel* pEngineChannel, Pool::Iterator& itControlChangeEvent); void ProcessSysex(Pool::Iterator& itSysexEvent); - Pool::Iterator LaunchVoice(EngineChannel* pEngineChannel, Pool::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing); + void ProcessSuspensionsChanges(); + void ProcessPendingStreamDeletions(); + Pool::Iterator LaunchVoice(EngineChannel* pEngineChannel, Pool::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing, bool HandleKeyGroupConflicts); int StealVoice(EngineChannel* pEngineChannel, Pool::Iterator& itNoteOnEvent); void FreeVoice(EngineChannel* pEngineChannel, Pool::Iterator& itVoice); void FreeKey(EngineChannel* pEngineChannel, midi_key_info_t* pKey); - void ResetSynthesisParameters(Event::destination_t dst, float val); void ResetInternal(); + void ResetScaleTuning(); + void ResetSuspendedRegions(); static Engine* AcquireEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice); static void FreeEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice); @@ -137,20 +146,47 @@ void DisableAndLock(); // FIXME: should at least be protected friend class Voice; - friend class EGADSR; - friend class EGDecay; - friend class VCAManipulator; - friend class VCFCManipulator; - friend class VCOManipulator; private: + + /// Command used by the instrument loader thread to + /// request an instrument change on a channel. + struct instrument_change_command_t { + EngineChannel* pEngineChannel; + ::gig::Instrument* pInstrument; + }; + struct instrument_change_reply_t { + int dummy; + }; + RingBuffer* InstrumentChangeQueue; ///< Contains the instrument change command + RingBuffer* InstrumentChangeReplyQueue; ///< Contains the acknowledge of an instrument change + ::gig::DimensionRegion** pDimRegionsInUse; ///< After an instrument change, this contains a list of dimension regions that are still in use by playing voices + + Pool< ::gig::Region*> SuspendedRegions; + Mutex SuspendedRegionsMutex; + Condition SuspensionChangeOngoing; + ::gig::Region* pPendingRegionSuspension; + ::gig::Region* pPendingRegionResumption; + int iPendingStreamDeletions; + ArrayList engineChannels; ///< All engine channels of a gig::Engine instance. static std::map engines; ///< All instances of gig::Engine. - uint8_t GSCheckSum(const RingBuffer::NonVolatileReader AddrReader, uint DataSize); + int SostenutoKeys[128]; + int SostenutoKeyCount; + + uint8_t GSCheckSum(const RingBuffer::NonVolatileReader AddrReader, uint DataSize); void AdjustScale(int8_t ScaleTunes[12]); void ReleaseAllVoices(EngineChannel* pEngineChannel, Pool::Iterator& itReleaseEvent); void KillAllVoices(EngineChannel* pEngineChannel, Pool::Iterator& itKillEvent); + bool ShouldReleaseVoice(EngineChannel* pEngineChannel, int Key); + bool RegionSuspended(::gig::Region* pRegion); + static float* InitVolumeCurve(); + static float* InitPanCurve(); + static float* InitCrossfadeCurve(); + static float* InitCurve(const float* segments, int size = 128); + + unsigned long FrameTime; ///< Time in frames of the start of the current audio fragment }; }} // namespace LinuxSampler::gig