--- libgig/trunk/src/gig.h 2007/11/25 17:29:37 1524 +++ libgig/trunk/src/gig.h 2013/05/08 17:53:07 2450 @@ -2,7 +2,7 @@ * * * libgig - C++ cross-platform Gigasampler format file access library * * * - * Copyright (C) 2003-2007 by Christian Schoenebeck * + * Copyright (C) 2003-2013 by Christian Schoenebeck * * * * * * This library is free software; you can redistribute it and/or modify * @@ -31,7 +31,6 @@ # define LIST_TYPE_3EWL 0x3365776C # define LIST_TYPE_3GRI 0x33677269 # define LIST_TYPE_3GNL 0x33676E6C -# define CHUNK_ID_SMPL 0x736D706C # define CHUNK_ID_3GIX 0x33676978 # define CHUNK_ID_3EWA 0x33657761 # define CHUNK_ID_3LNK 0x336C6E6B @@ -45,7 +44,6 @@ # define LIST_TYPE_3EWL 0x6C776533 # define LIST_TYPE_3GRI 0x69726733 # define LIST_TYPE_3GNL 0x6C6E6733 -# define CHUNK_ID_SMPL 0x6C706D73 # define CHUNK_ID_3GIX 0x78696733 # define CHUNK_ID_3EWA 0x61776533 # define CHUNK_ID_3LNK 0x6B6E6C33 @@ -431,11 +429,11 @@ uint8_t DimensionUpperLimits[8]; ///< gig3: defines the upper limit of the dimension values for this dimension region // derived attributes from DLS::Sampler - DLS::Sampler::UnityNote; - DLS::Sampler::FineTune; - DLS::Sampler::Gain; - DLS::Sampler::SampleLoops; - DLS::Sampler::pSampleLoops; + using DLS::Sampler::UnityNote; + using DLS::Sampler::FineTune; + using DLS::Sampler::Gain; + using DLS::Sampler::SampleLoops; + using DLS::Sampler::pSampleLoops; // own methods double GetVelocityAttenuation(uint8_t MIDIKeyVelocity); @@ -452,11 +450,12 @@ void SetVCFVelocityScale(uint8_t scaling); Region* GetParent() const; // derived methods - DLS::Sampler::AddSampleLoop; - DLS::Sampler::DeleteSampleLoop; + using DLS::Sampler::AddSampleLoop; + using DLS::Sampler::DeleteSampleLoop; // overridden methods virtual void SetGain(int32_t gain); virtual void UpdateChunks(); + virtual void CopyAssign(const DimensionRegion* orig); protected: uint8_t* VelocityTable; ///< For velocity dimensions with custom defined zone ranges only: used for fast converting from velocity MIDI value to dimension bit number. DimensionRegion(Region* pParent, RIFF::List* _3ewl); @@ -630,6 +629,7 @@ // overridden methods virtual void SetKeyRange(uint16_t Low, uint16_t High); virtual void UpdateChunks(); + virtual void CopyAssign(const Region* orig); protected: Region(Instrument* pInstrument, RIFF::List* rgnList); void LoadDimensionRegions(RIFF::List* rgn); @@ -639,19 +639,120 @@ friend class Instrument; }; + /** Abstract base class for all MIDI rules. */ + class MidiRule { + public: + virtual ~MidiRule() { } + protected: + virtual void UpdateChunks(uint8_t* pData) const = 0; + friend class Instrument; + }; + + /** MIDI rule for triggering notes by control change events. */ + class MidiRuleCtrlTrigger : public MidiRule { + public: + uint8_t ControllerNumber; ///< MIDI controller number. + uint8_t Triggers; ///< Number of triggers. + struct trigger_t { + uint8_t TriggerPoint; ///< The CC value to pass for the note to be triggered. + bool Descending; ///< If the change in CC value should be downwards. + uint8_t VelSensitivity; ///< How sensitive the velocity should be to the speed of the controller change. + uint8_t Key; ///< Key to trigger. + bool NoteOff; ///< If a note off should be triggered instead of a note on. + uint8_t Velocity; ///< Velocity of the note to trigger. 255 means that velocity should depend on the speed of the controller change. + bool OverridePedal; ///< If a note off should be triggered even if the sustain pedal is down. + } pTriggers[32]; + + protected: + MidiRuleCtrlTrigger(RIFF::Chunk* _3ewg); + MidiRuleCtrlTrigger(); + void UpdateChunks(uint8_t* pData) const; + friend class Instrument; + }; + + /** MIDI rule for instruments with legato samples. */ + class MidiRuleLegato : public MidiRule { + public: + uint8_t LegatoSamples; ///< Number of legato samples per key in each direction (always 12) + bool BypassUseController; ///< If a controller should be used to bypass the sustain note + uint8_t BypassKey; ///< Key to be used to bypass the sustain note + uint8_t BypassController; ///< Controller to be used to bypass the sustain note + uint16_t ThresholdTime; ///< Maximum time (ms) between two notes that should be played legato + uint16_t ReleaseTime; ///< Release time + range_t KeyRange; ///< Key range for legato notes + uint8_t ReleaseTriggerKey; ///< Key triggering release samples + uint8_t AltSustain1Key; ///< Key triggering alternate sustain samples + uint8_t AltSustain2Key; ///< Key triggering a second set of alternate sustain samples + + protected: + MidiRuleLegato(RIFF::Chunk* _3ewg); + MidiRuleLegato(); + void UpdateChunks(uint8_t* pData) const; + friend class Instrument; + }; + + /** MIDI rule to automatically cycle through specified sequences of different articulations. The instrument must be using the smartmidi dimension. */ + class MidiRuleAlternator : public MidiRule { + public: + uint8_t Articulations; ///< Number of articulations in the instrument + String pArticulations[32]; ///< Names of the articulations + + range_t PlayRange; ///< Key range of the playable keys in the instrument + + uint8_t Patterns; ///< Number of alternator patterns + struct pattern_t { + String Name; ///< Name of the pattern + int Size; ///< Number of steps in the pattern + const uint8_t& operator[](int i) const { /// Articulation to play + return data[i]; + } + uint8_t& operator[](int i) { + return data[i]; + } + private: + uint8_t data[32]; + } pPatterns[32]; ///< A pattern is a sequence of articulation numbers + + typedef enum { + selector_none, + selector_key_switch, + selector_controller + } selector_t; + selector_t Selector; ///< Method by which pattern is chosen + range_t KeySwitchRange; ///< Key range for key switch selector + uint8_t Controller; ///< CC number for controller selector + + bool Polyphonic; ///< If alternator should step forward only when all notes are off + bool Chained; ///< If all patterns should be chained together + + protected: + MidiRuleAlternator(RIFF::Chunk* _3ewg); + MidiRuleAlternator(); + void UpdateChunks(uint8_t* pData) const; + friend class Instrument; + }; + + /** A MIDI rule not yet implemented by libgig. */ + class MidiRuleUnknown : public MidiRule { + protected: + MidiRuleUnknown() { } + void UpdateChunks(uint8_t* pData) const { } + friend class Instrument; + }; + /** Provides all neccessary information for the synthesis of an Instrument. */ class Instrument : protected DLS::Instrument { public: // derived attributes from DLS::Resource - DLS::Resource::pInfo; - DLS::Resource::pDLSID; + using DLS::Resource::pInfo; + using DLS::Resource::pDLSID; // derived attributes from DLS::Instrument - DLS::Instrument::IsDrum; - DLS::Instrument::MIDIBank; - DLS::Instrument::MIDIBankCoarse; - DLS::Instrument::MIDIBankFine; - DLS::Instrument::MIDIProgram; - DLS::Instrument::Regions; + using DLS::Instrument::IsDrum; + using DLS::Instrument::MIDIBank; + using DLS::Instrument::MIDIBankCoarse; + using DLS::Instrument::MIDIBankFine; + using DLS::Instrument::MIDIProgram; + using DLS::Instrument::Regions; // own attributes int32_t Attenuation; ///< in dB uint16_t EffectSend; @@ -662,15 +763,21 @@ // derived methods from DLS::Resource - DLS::Resource::GetParent; + using DLS::Resource::GetParent; // overridden methods Region* GetFirstRegion(); Region* GetNextRegion(); Region* AddRegion(); void DeleteRegion(Region* pRegion); virtual void UpdateChunks(); + virtual void CopyAssign(const Instrument* orig); // own methods Region* GetRegion(unsigned int Key); + MidiRule* GetMidiRule(int i); + MidiRuleCtrlTrigger* AddMidiRuleCtrlTrigger(); + MidiRuleLegato* AddMidiRuleLegato(); + MidiRuleAlternator* AddMidiRuleAlternator(); + void DeleteMidiRule(int i); protected: Region* RegionKeyTable[128]; ///< fast lookup for the corresponding Region of a MIDI key @@ -679,6 +786,8 @@ void UpdateRegionKeyTable(); friend class File; friend class Region; // so Region can call UpdateRegionKeyTable() + private: + MidiRule** pMidiRules; }; /** @brief Group of Gigasampler objects @@ -721,16 +830,17 @@ static const DLS::version_t VERSION_3; // derived attributes from DLS::Resource - DLS::Resource::pInfo; - DLS::Resource::pDLSID; + using DLS::Resource::pInfo; + using DLS::Resource::pDLSID; // derived attributes from DLS::File - DLS::File::pVersion; - DLS::File::Instruments; + using DLS::File::pVersion; + using DLS::File::Instruments; // derived methods from DLS::Resource - DLS::Resource::GetParent; + using DLS::Resource::GetParent; // derived methods from DLS::File - DLS::File::Save; + using DLS::File::Save; + using DLS::File::GetFileName; // overridden methods File(); File(RIFF::File* pRIFF); @@ -742,6 +852,7 @@ Instrument* GetNextInstrument(); ///< Returns a pointer to the next Instrument object of the file, NULL otherwise. Instrument* GetInstrument(uint index, progress_t* pProgress = NULL); Instrument* AddInstrument(); + Instrument* AddDuplicateInstrument(const Instrument* orig); void DeleteInstrument(Instrument* pInstrument); Group* GetFirstGroup(); ///< Returns a pointer to the first Group object of the file, NULL otherwise. Group* GetNextGroup(); ///< Returns a pointer to the next Group object of the file, NULL otherwise.