--- libgig/trunk/src/gig.h 2010/01/10 12:58:51 2044 +++ libgig/trunk/src/gig.h 2014/04/23 16:39:43 2540 @@ -2,7 +2,7 @@ * * * libgig - C++ cross-platform Gigasampler format file access library * * * - * Copyright (C) 2003-2010 by Christian Schoenebeck * + * Copyright (C) 2003-2014 by Christian Schoenebeck * * * * * * This library is free software; you can redistribute it and/or modify * @@ -429,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); @@ -450,19 +450,22 @@ 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); DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src); ~DimensionRegion(); + void CopyAssign(const DimensionRegion* orig, const std::map* mSamples); friend class Region; private: typedef enum { ///< Used to decode attenuation, EG1 and EG2 controller + // official leverage controllers as they were defined in the original Gigasampler/GigaStudio format: _lev_ctrl_none = 0x00, _lev_ctrl_modwheel = 0x03, ///< Modulation Wheel (MIDI Controller 1) _lev_ctrl_breath = 0x05, ///< Breath Controller (Coarse, MIDI Controller 2) @@ -488,7 +491,77 @@ _lev_ctrl_effect4depth = 0x2b, ///< Effect 4 Depth (MIDI Controller 94) _lev_ctrl_effect5depth = 0x2d, ///< Effect 5 Depth (MIDI Controller 95) _lev_ctrl_channelaftertouch = 0x2f, ///< Channel Key Pressure - _lev_ctrl_velocity = 0xff ///< Key Velocity + _lev_ctrl_velocity = 0xff, ///< Key Velocity + + // format extension (these controllers are so far only supported by LinuxSampler & gigedit) they will *NOT* work with Gigasampler/GigaStudio ! + // (the assigned values here are their official MIDI CC number plus the highest bit set): + _lev_ctrl_CC3_EXT = 0x83, ///< MIDI Controller 3 [gig format extension] + + _lev_ctrl_CC6_EXT = 0x86, ///< Data Entry MSB (MIDI Controller 6) [gig format extension] + _lev_ctrl_CC7_EXT = 0x87, ///< Channel Volume (MIDI Controller 7) [gig format extension] + _lev_ctrl_CC8_EXT = 0x88, ///< Balance (MIDI Controller 8) [gig format extension] + _lev_ctrl_CC9_EXT = 0x89, ///< MIDI Controller 9 [gig format extension] + _lev_ctrl_CC10_EXT = 0x8a, ///< Pan (MIDI Controller 10) [gig format extension] + _lev_ctrl_CC11_EXT = 0x8b, ///< Expression Controller (MIDI Controller 11) [gig format extension] + + _lev_ctrl_CC14_EXT = 0x8e, ///< MIDI Controller 14 [gig format extension] + _lev_ctrl_CC15_EXT = 0x8f, ///< MIDI Controller 15 [gig format extension] + + _lev_ctrl_CC20_EXT = 0x94, ///< MIDI Controller 20 [gig format extension] + _lev_ctrl_CC21_EXT = 0x95, ///< MIDI Controller 21 [gig format extension] + _lev_ctrl_CC22_EXT = 0x96, ///< MIDI Controller 22 [gig format extension] + _lev_ctrl_CC23_EXT = 0x97, ///< MIDI Controller 23 [gig format extension] + _lev_ctrl_CC24_EXT = 0x98, ///< MIDI Controller 24 [gig format extension] + _lev_ctrl_CC25_EXT = 0x99, ///< MIDI Controller 25 [gig format extension] + _lev_ctrl_CC26_EXT = 0x9a, ///< MIDI Controller 26 [gig format extension] + _lev_ctrl_CC27_EXT = 0x9b, ///< MIDI Controller 27 [gig format extension] + _lev_ctrl_CC28_EXT = 0x9c, ///< MIDI Controller 28 [gig format extension] + _lev_ctrl_CC29_EXT = 0x9d, ///< MIDI Controller 29 [gig format extension] + _lev_ctrl_CC30_EXT = 0x9e, ///< MIDI Controller 30 [gig format extension] + _lev_ctrl_CC31_EXT = 0x9f, ///< MIDI Controller 31 [gig format extension] + + _lev_ctrl_CC68_EXT = 0xc4, ///< Legato Footswitch (MIDI Controller 68) [gig format extension] + _lev_ctrl_CC69_EXT = 0xc5, ///< Hold 2 (MIDI Controller 69) [gig format extension] + _lev_ctrl_CC70_EXT = 0xc6, ///< Sound Ctrl. 1 - Sound Variation (MIDI Controller 70) [gig format extension] + _lev_ctrl_CC71_EXT = 0xc7, ///< Sound Ctrl. 2 - Timbre (MIDI Controller 71) [gig format extension] + _lev_ctrl_CC72_EXT = 0xc8, ///< Sound Ctrl. 3 - Release Time (MIDI Controller 72) [gig format extension] + _lev_ctrl_CC73_EXT = 0xc9, ///< Sound Ctrl. 4 - Attack Time (MIDI Controller 73) [gig format extension] + _lev_ctrl_CC74_EXT = 0xca, ///< Sound Ctrl. 5 - Brightness (MIDI Controller 74) [gig format extension] + _lev_ctrl_CC75_EXT = 0xcb, ///< Sound Ctrl. 6 - Decay Time (MIDI Controller 75) [gig format extension] + _lev_ctrl_CC76_EXT = 0xcc, ///< Sound Ctrl. 7 - Vibrato Rate (MIDI Controller 76) [gig format extension] + _lev_ctrl_CC77_EXT = 0xcd, ///< Sound Ctrl. 8 - Vibrato Depth (MIDI Controller 77) [gig format extension] + _lev_ctrl_CC78_EXT = 0xce, ///< Sound Ctrl. 9 - Vibrato Delay (MIDI Controller 78) [gig format extension] + _lev_ctrl_CC79_EXT = 0xcf, ///< Sound Ctrl. 10 (MIDI Controller 79) [gig format extension] + + _lev_ctrl_CC84_EXT = 0xd4, ///< Portamento Control (MIDI Controller 84) [gig format extension] + _lev_ctrl_CC85_EXT = 0xd5, ///< MIDI Controller 85 [gig format extension] + _lev_ctrl_CC86_EXT = 0xd6, ///< MIDI Controller 86 [gig format extension] + _lev_ctrl_CC87_EXT = 0xd7, ///< MIDI Controller 87 [gig format extension] + + _lev_ctrl_CC89_EXT = 0xd9, ///< MIDI Controller 89 [gig format extension] + _lev_ctrl_CC90_EXT = 0xda, ///< MIDI Controller 90 [gig format extension] + + _lev_ctrl_CC96_EXT = 0xe0, ///< Data Increment (MIDI Controller 96) [gig format extension] + _lev_ctrl_CC97_EXT = 0xe1, ///< Data Decrement (MIDI Controller 97) [gig format extension] + + _lev_ctrl_CC102_EXT = 0xe6, ///< MIDI Controller 102 [gig format extension] + _lev_ctrl_CC103_EXT = 0xe7, ///< MIDI Controller 103 [gig format extension] + _lev_ctrl_CC104_EXT = 0xe8, ///< MIDI Controller 104 [gig format extension] + _lev_ctrl_CC105_EXT = 0xe9, ///< MIDI Controller 105 [gig format extension] + _lev_ctrl_CC106_EXT = 0xea, ///< MIDI Controller 106 [gig format extension] + _lev_ctrl_CC107_EXT = 0xeb, ///< MIDI Controller 107 [gig format extension] + _lev_ctrl_CC108_EXT = 0xec, ///< MIDI Controller 108 [gig format extension] + _lev_ctrl_CC109_EXT = 0xed, ///< MIDI Controller 109 [gig format extension] + _lev_ctrl_CC110_EXT = 0xee, ///< MIDI Controller 110 [gig format extension] + _lev_ctrl_CC111_EXT = 0xef, ///< MIDI Controller 111 [gig format extension] + _lev_ctrl_CC112_EXT = 0xf0, ///< MIDI Controller 112 [gig format extension] + _lev_ctrl_CC113_EXT = 0xf1, ///< MIDI Controller 113 [gig format extension] + _lev_ctrl_CC114_EXT = 0xf2, ///< MIDI Controller 114 [gig format extension] + _lev_ctrl_CC115_EXT = 0xf3, ///< MIDI Controller 115 [gig format extension] + _lev_ctrl_CC116_EXT = 0xf4, ///< MIDI Controller 116 [gig format extension] + _lev_ctrl_CC117_EXT = 0xf5, ///< MIDI Controller 117 [gig format extension] + _lev_ctrl_CC118_EXT = 0xf6, ///< MIDI Controller 118 [gig format extension] + _lev_ctrl_CC119_EXT = 0xf7 ///< MIDI Controller 119 [gig format extension] } _lev_ctrl_t; typedef std::map VelocityTableMap; @@ -556,12 +629,14 @@ void ReleaseSampleData(); void Resize(int iNewSize); unsigned long SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence = RIFF::stream_start); - unsigned long GetPos(); + unsigned long GetPos() const; unsigned long Read(void* pBuffer, unsigned long SampleCount, buffer_t* pExternalDecompressionBuffer = NULL); unsigned long ReadAndLoop(void* pBuffer, unsigned long SampleCount, playback_state_t* pPlaybackState, DimensionRegion* pDimRgn, buffer_t* pExternalDecompressionBuffer = NULL); unsigned long Write(void* pBuffer, unsigned long SampleCount); Group* GetGroup() const; virtual void UpdateChunks(); + void CopyAssignMeta(const Sample* orig); + void CopyAssignWave(const Sample* orig); protected: static unsigned int Instances; ///< Number of instances of class Sample. static buffer_t InternalDecompressionBuffer; ///< Buffer used for decompression as well as for truncation of 24 Bit -> 16 Bit samples. @@ -628,11 +703,13 @@ // 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); void UpdateVelocityTable(); Sample* GetSampleFromWavePool(unsigned int WavePoolTableIndex, progress_t* pProgress = NULL); + void CopyAssign(const Region* orig, const std::map* mSamples); ~Region(); friend class Instrument; }; @@ -641,6 +718,9 @@ 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. */ @@ -660,6 +740,78 @@ 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; }; @@ -667,15 +819,15 @@ 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; @@ -686,21 +838,27 @@ // 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 Instrument(File* pFile, RIFF::List* insList, progress_t* pProgress = NULL); ~Instrument(); + void CopyAssign(const Instrument* orig, const std::map* mSamples); void UpdateRegionKeyTable(); friend class File; friend class Region; // so Region can call UpdateRegionKeyTable() @@ -738,7 +896,7 @@ friend class File; private: File* pFile; - RIFF::Chunk* pNameChunk; + RIFF::Chunk* pNameChunk; ///< '3gnm' chunk }; /** Parses Gigasampler files and provides abstract access to the data. */ @@ -748,27 +906,31 @@ 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; + using DLS::File::SetFileName; // overridden methods File(); File(RIFF::File* pRIFF); Sample* GetFirstSample(progress_t* pProgress = NULL); ///< Returns a pointer to the first Sample object of the file, NULL otherwise. Sample* GetNextSample(); ///< Returns a pointer to the next Sample object of the file, NULL otherwise. + Sample* GetSample(uint index); Sample* AddSample(); void DeleteSample(Sample* pSample); Instrument* GetFirstInstrument(); ///< Returns a pointer to the first Instrument object of the file, NULL otherwise. 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. @@ -778,6 +940,7 @@ void DeleteGroupOnly(Group* pGroup); void SetAutoLoad(bool b); bool GetAutoLoad(); + void AddContentOf(File* pFile); virtual ~File(); virtual void UpdateChunks(); protected: