--- linuxsampler/trunk/src/engines/gig/Engine.h 2005/02/19 02:40:24 392 +++ linuxsampler/trunk/src/engines/gig/Engine.h 2006/11/27 21:34:55 947 @@ -3,6 +3,7 @@ * LinuxSampler - modular, streaming capable sampler * * * * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * + * Copyright (C) 2005, 2006 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 * @@ -25,71 +26,47 @@ #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 "InstrumentResourceManager.h" #include "../../network/lscp.h" +#include "EngineChannel.h" -#define PITCHBEND_SEMITONES 12 -#define MAX_AUDIO_VOICES 128 -#define SYSEX_BUFFER_SIZE 2048 // 2kB -#define VOICE_STEAL_ALGORITHM voice_steal_algo_oldestkey ///< @see voice_steal_algo_t for available voice stealing algorithms +// identifier of this sampler engine +#define LS_GIG_ENGINE_NAME "GIG" namespace LinuxSampler { namespace gig { - using std::map; - // just symbol prototyping class Voice; class DiskThread; class InstrumentResourceManager; + class midi_key_info_t; + class EngineChannel; /** * Sampler engine for the Gigasampler format. */ - class Engine : public LinuxSampler::Engine, public InstrumentConsumer { + class Engine : public LinuxSampler::Engine { public: - // types - enum voice_steal_algo_t { - voice_steal_algo_none, - voice_steal_algo_keymask, - voice_steal_algo_oldestkey - }; - // methods Engine(); - ~Engine(); + virtual ~Engine(); + void Connect(AudioOutputDevice* pAudioOut); - // abstract methods derived from class 'LinuxSampler::Engine' - virtual void PrepareLoadInstrument(const char* FileName, uint Instrument); - virtual void LoadInstrument(); + // implementation of abstract methods derived from class 'LinuxSampler::Engine' + virtual int RenderAudio(uint Samples); + virtual void SendSysex(void* pData, uint Size); virtual void Reset(); virtual void Enable(); virtual void Disable(); - virtual void SendNoteOn(uint8_t Key, uint8_t Velocity); - virtual void SendNoteOff(uint8_t Key, uint8_t Velocity); - virtual void SendPitchbend(int Pitch); - virtual void SendControlChange(uint8_t Controller, uint8_t Value); - virtual void SendSysex(void* pData, uint Size); - virtual float Volume(); - virtual void Volume(float f); - virtual uint Channels(); - virtual void Connect(AudioOutputDevice* pAudioOut); - virtual void DisconnectAudioOutputDevice(); - virtual void SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel); - virtual int OutputChannel(uint EngineAudioChannel); - virtual int RenderAudio(uint Samples); virtual uint VoiceCount(); virtual uint VoiceCountMax(); virtual bool DiskStreamSupported(); @@ -100,93 +77,85 @@ virtual String Description(); virtual String Version(); virtual String EngineName(); - virtual String InstrumentFileName(); - virtual String InstrumentName(); - virtual int InstrumentIndex(); - virtual int InstrumentStatus(); - - // abstract methods derived from interface class 'InstrumentConsumer' - virtual void ResourceToBeUpdated(::gig::Instrument* pResource, void*& pUpdateArg); - virtual void ResourceUpdated(::gig::Instrument* pOldResource, ::gig::Instrument* pNewResource, void* pUpdateArg); - //protected: - struct midi_key_info_t { - RTList* pActiveVoices; ///< Contains the active voices associated with the MIDI key. - bool KeyPressed; ///< Is true if the respective MIDI key is currently pressed. - bool Active; ///< If the key contains active voices. - bool ReleaseTrigger; ///< If we have to launch release triggered voice(s) when the key is released - Pool::Iterator itSelf; ///< hack to allow fast deallocation of the key from the list of active keys - RTList* pEvents; ///< Key specific events (only Note-on, Note-off and sustain pedal currently) - }; + 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. - static InstrumentResourceManager Instruments; + //protected: + static InstrumentResourceManager instruments; AudioOutputDevice* pAudioOutputDevice; - float* pOutputLeft; ///< Audio output channel buffer (left) - float* pOutputRight; ///< Audio output channel buffer (right) - int AudioDeviceChannelLeft; ///< audio device channel number to which the left channel is connected to - int AudioDeviceChannelRight; ///< audio device channel number to which the right channel is connected to uint SampleRate; ///< Sample rate of the engines output audio signal (in Hz) uint MaxSamplesPerCycle; ///< Size of each audio output buffer DiskThread* pDiskThread; - uint8_t ControllerTable[128]; ///< Reflects the current values (0-127) of all MIDI controllers for this engine / sampler channel. - RingBuffer* pEventQueue; ///< Input event queue. - RingBuffer* pSysexBuffer; ///< Input buffer for MIDI system exclusive messages. - midi_key_info_t pMIDIKeyInfo[128]; ///< Contains all active voices sorted by MIDI key number and other informations to the respective MIDI key + RingBuffer* pEventQueue; ///< Input event queue for engine global events (e.g. SysEx messages). Pool* pVoicePool; ///< Contains all voices that can be activated. - Pool* pActiveKeys; ///< Holds all keys in it's allocation list with active voices. - Pool* pEventPool; ///< Contains all Event objects that can be used. EventGenerator* pEventGenerator; RTList* pVoiceStealingQueue; ///< All voice-launching events which had to be postponed due to free voice shortage. - RTList* pEvents; ///< All events for the current audio fragment. - RTList* pCCEvents; ///< All control change events for the current audio fragment. - RTList* pSynthesisEvents[Event::destination_count]; ///< Events directly affecting synthesis parameter (like pitch, volume and filter). - 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). - map ActiveKeyGroups; ///< Contains active keys (in case they belong to a key group) ordered by key group ID. - RIFF::File* pRIFF; - ::gig::File* pGig; - ::gig::Instrument* pInstrument; - bool SustainPedal; ///< true if sustain pedal is down - double GlobalVolume; ///< overall volume (a value < 1.0 means attenuation, a value > 1.0 means amplification) - int Pitch; ///< Current (absolute) MIDI pitch value. - int CurrentKeyDimension; ///< Current value (0-127) for the keyboard dimension, altered by pressing a keyswitching key. - int ActiveVoiceCount; ///< number of currently active voices + 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. + 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 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; - String InstrumentFile; - int InstrumentIdx; - String InstrumentIdxName; - int InstrumentStat; int8_t ScaleTuning[12]; ///< contains optional detune factors (-64..+63 cents) for all 12 semitones of an octave - 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. - int MaxFadeOutPos; ///< The last position in an audio fragment to allow a instant fade out (e.g. for voice stealing) without leading to clicks. - - void ProcessNoteOn(Pool::Iterator& itNoteOnEvent); - void ProcessNoteOff(Pool::Iterator& itNoteOffEvent); - void ProcessPitchbend(Pool::Iterator& itPitchbendEvent); - void ProcessControlChange(Pool::Iterator& itControlChangeEvent); + 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 PostProcess(EngineChannel* pEngineChannel); + void ClearEventLists(); + void ImportEvents(uint Samples); + void ProcessNoteOn(EngineChannel* pEngineChannel, Pool::Iterator& itNoteOnEvent); + void ProcessNoteOff(EngineChannel* pEngineChannel, Pool::Iterator& itNoteOffEvent); + void ProcessPitchbend(EngineChannel* pEngineChannel, Pool::Iterator& itPitchbendEvent); + void ProcessControlChange(EngineChannel* pEngineChannel, Pool::Iterator& itControlChangeEvent); void ProcessSysex(Pool::Iterator& itSysexEvent); - Pool::Iterator LaunchVoice(Pool::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing); - void StealVoice(Pool::Iterator& itNoteOnEvent); - void FreeVoice(Pool::Iterator& itVoice); - void FreeKey(midi_key_info_t* pKey); - void ResetSynthesisParameters(Event::destination_t dst, float val); + 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 ResetInternal(); + void ResetScaleTuning(); + + static Engine* AcquireEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice); + static void FreeEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice); + + 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; - friend class InstrumentResourceManager; private: - void DisableAndLock(); + ArrayList engineChannels; ///< All engine channels of a gig::Engine instance. + + static std::map engines; ///< All instances of gig::Engine. + + 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); + 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