--- libgig/trunk/src/gig.h 2018/12/22 18:59:29 3442 +++ libgig/trunk/src/gig.h 2021/06/19 08:09:58 3948 @@ -2,7 +2,7 @@ * * * libgig - C++ cross-platform Gigasampler format file access library * * * - * Copyright (C) 2003-2018 by Christian Schoenebeck * + * Copyright (C) 2003-2021 by Christian Schoenebeck * * * * * * This library is free software; you can redistribute it and/or modify * @@ -26,6 +26,7 @@ #include "DLS.h" #include +#include // since C++11 #ifndef __has_feature # define __has_feature(x) 0 @@ -50,6 +51,7 @@ # define LIST_TYPE_3GNL 0x33676E6C # define LIST_TYPE_3LS 0x334c5320 // own gig format extension # define LIST_TYPE_RTIS 0x52544953 // own gig format extension +# define LIST_TYPE_3DNM 0x33646e6d # define CHUNK_ID_3GIX 0x33676978 # define CHUNK_ID_3EWA 0x33657761 # define CHUNK_ID_3LNK 0x336C6E6B @@ -61,7 +63,9 @@ # define CHUNK_ID_SCRI 0x53637269 // own gig format extension # define CHUNK_ID_LSNM 0x4c534e4d // own gig format extension # define CHUNK_ID_SCSL 0x5343534c // own gig format extension +# define CHUNK_ID_SCPV 0x53435056 // own gig format extension # define CHUNK_ID_LSDE 0x4c534445 // own gig format extension +# define CHUNK_ID_3DDP 0x33646470 #else // little endian # define LIST_TYPE_3PRG 0x67727033 # define LIST_TYPE_3EWL 0x6C776533 @@ -69,6 +73,7 @@ # define LIST_TYPE_3GNL 0x6C6E6733 # define LIST_TYPE_3LS 0x20534c33 // own gig format extension # define LIST_TYPE_RTIS 0x53495452 // own gig format extension +# define LIST_TYPE_3DNM 0x6d6e6433 # define CHUNK_ID_3GIX 0x78696733 # define CHUNK_ID_3EWA 0x61776533 # define CHUNK_ID_3LNK 0x6B6E6C33 @@ -80,7 +85,9 @@ # define CHUNK_ID_SCRI 0x69726353 // own gig format extension # define CHUNK_ID_LSNM 0x4d4e534c // own gig format extension # define CHUNK_ID_SCSL 0x4c534353 // own gig format extension +# define CHUNK_ID_SCPV 0x56504353 // own gig format extension # define CHUNK_ID_LSDE 0x4544534c // own gig format extension +# define CHUNK_ID_3DDP 0x70646433 #endif // WORDS_BIGENDIAN #ifndef GIG_DECLARE_ENUM @@ -148,6 +155,23 @@ curve_type_unknown = 0xffffffff /**< Unknown curve type. */ ); + /** Defines the wave form type used by an LFO (gig format extension). + * + * This is a gig format extension. The original Gigasampler/GigaStudio + * software always used a sine (sinus) wave form for all its 3 LFOs, so this + * was not configurable in the original gig format. Accordingly setting any + * other wave form than sine (sinus) will be ignored by the original + * Gigasampler/GigaStudio software. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(lfo_wave_t, + lfo_wave_sine = 0, /**< Sine (sinus) wave form (this is the default wave form). */ + lfo_wave_triangle = 1, /**< Triangle wave form. */ + lfo_wave_saw = 2, /**< Saw (up) wave form (saw down wave form can be achieved by flipping the phase). */ + lfo_wave_square = 3, /**< Square wave form. */ + ); + /** Dimensions allow to bypass one of the following controllers. * * @see enumCount(), enumKey(), enumKeys(), enumValue() @@ -338,16 +362,37 @@ float zone_size; ///< Intended for internal usage: reflects the size of each zone (128/zones) for normal split types only, 0 otherwise. }; - /** Defines which frequencies are filtered by the VCF. + /** Audio filter types. + * + * The first 5 filter types are the ones which exist in GigaStudio, and + * which are very accurately modeled on LinuxSampler side such that they + * would sound with LinuxSampler exactly as with GigaStudio. + * + * The other filter types listed here are extensions to the gig format and + * are LinuxSampler specific filter type implementations. Note that none of + * these are duplicates of the GigaStudio filter types. For instance + * @c vcf_type_lowpass (GigaStudio) and @c vcf_type_lowpass_2p + * (LinuxSampler) are both lowpass filters with 2 poles, however they do + * sound differently. * * @see enumCount(), enumKey(), enumKeys(), enumValue() */ GIG_DECLARE_ENUM(vcf_type_t, - vcf_type_lowpass = 0x00, /**< Standard lowpass filter type. */ - vcf_type_lowpassturbo = 0xff, /**< More poles than normal lowpass. */ - vcf_type_bandpass = 0x01, /**< Bandpass filter type. */ - vcf_type_highpass = 0x02, /**< Highpass filter type. */ - vcf_type_bandreject = 0x03 /**< Band reject filter type. */ + vcf_type_lowpass = 0x00, /**< Standard lowpass filter type (GigaStudio). */ + vcf_type_lowpassturbo = 0xff, /**< More poles than normal lowpass (GigaStudio). */ + vcf_type_bandpass = 0x01, /**< Bandpass filter type (GigaStudio). */ + vcf_type_highpass = 0x02, /**< Highpass filter type (GigaStudio). */ + vcf_type_bandreject = 0x03, /**< Band reject filter type (GigaStudio). */ + vcf_type_lowpass_1p = 0x11, /**< [gig extension]: 1-pole lowpass filter type (LinuxSampler). */ + vcf_type_lowpass_2p = 0x12, /**< [gig extension]: 2-pole lowpass filter type (LinuxSampler). */ + vcf_type_lowpass_4p = 0x14, /**< [gig extension]: 4-pole lowpass filter type (LinuxSampler). */ + vcf_type_lowpass_6p = 0x16, /**< [gig extension]: 6-pole lowpass filter type (LinuxSampler). */ + vcf_type_highpass_1p = 0x21, /**< [gig extension]: 1-pole highpass filter type (LinuxSampler). */ + vcf_type_highpass_2p = 0x22, /**< [gig extension]: 2-pole highpass filter type (LinuxSampler). */ + vcf_type_highpass_4p = 0x24, /**< [gig extension]: 4-pole highpass filter type (LinuxSampler). */ + vcf_type_highpass_6p = 0x26, /**< [gig extension]: 6-pole highpass filter type (LinuxSampler). */ + vcf_type_bandpass_2p = 0x32, /**< [gig extension]: 2-pole bandpass filter type (LinuxSampler). */ + vcf_type_bandreject_2p = 0x42 /**< [gig extension]: 2-pole bandreject filter type (LinuxSampler). */ ); /** @@ -433,7 +478,7 @@ GIG_DECLARE_ENUM(sust_rel_trg_t, sust_rel_trg_none = 0x00, /**< No release triggered sample(s) are played on sustain pedal up (default). */ sust_rel_trg_maxvelocity = 0x01, /**< Play release trigger sample(s) on sustain pedal up, and simply use 127 as MIDI velocity for playback. */ - sust_rel_trg_keyvelocity = 0x02, /**< Play release trigger sample(s) on sustain pedal up, and use the key's last MIDI note-on velocity for playback. */ + sust_rel_trg_keyvelocity = 0x02 /**< Play release trigger sample(s) on sustain pedal up, and use the key`s last MIDI note-on velocity for playback. */ ); // just symbol prototyping @@ -505,11 +550,13 @@ uint8_t EG1ControllerAttackInfluence; ///< Amount EG1 Controller has influence on the EG1 Attack time (0 - 3, where 0 means off). uint8_t EG1ControllerDecayInfluence; ///< Amount EG1 Controller has influence on the EG1 Decay time (0 - 3, where 0 means off). uint8_t EG1ControllerReleaseInfluence; ///< Amount EG1 Controller has influence on the EG1 Release time (0 - 3, where 0 means off). + lfo_wave_t LFO1WaveForm; ///< [gig extension]: The fundamental wave form to be used by the amplitude LFO, e.g. sine, triangle, saw, square (default: sine). double LFO1Frequency; ///< Frequency of the sample amplitude LFO (0.10 - 10.00 Hz). + double LFO1Phase; ///< [gig extension]: Phase displacement of the amplitude LFO's wave form (0.0° - 360.0°). uint16_t LFO1InternalDepth; ///< Firm pitch of the sample amplitude LFO (0 - 1200 cents). uint16_t LFO1ControlDepth; ///< Controller depth influencing sample amplitude LFO pitch (0 - 1200 cents). lfo1_ctrl_t LFO1Controller; ///< MIDI Controller which controls sample amplitude LFO. - bool LFO1FlipPhase; ///< Inverts phase of the sample amplitude LFO wave. + bool LFO1FlipPhase; ///< Inverts the polarity of the sample amplitude LFO wave, so it flips the wave form vertically. bool LFO1Sync; ///< If set to true only one LFO should be used for all voices. // Filter Cutoff Frequency EG/LFO uint16_t EG2PreAttack; ///< Preattack value of the filter cutoff EG (0 - 1000 permille). @@ -524,19 +571,24 @@ uint8_t EG2ControllerAttackInfluence; ///< Amount EG2 Controller has influence on the EG2 Attack time (0 - 3, where 0 means off). uint8_t EG2ControllerDecayInfluence; ///< Amount EG2 Controller has influence on the EG2 Decay time (0 - 3, where 0 means off). uint8_t EG2ControllerReleaseInfluence; ///< Amount EG2 Controller has influence on the EG2 Release time (0 - 3, where 0 means off). + lfo_wave_t LFO2WaveForm; ///< [gig extension]: The fundamental wave form to be used by the filter cutoff LFO, e.g. sine, triangle, saw, square (default: sine). double LFO2Frequency; ///< Frequency of the filter cutoff LFO (0.10 - 10.00 Hz). + double LFO2Phase; ///< [gig extension]: Phase displacement of the filter cutoff LFO's wave form (0.0° - 360.0°). uint16_t LFO2InternalDepth; ///< Firm pitch of the filter cutoff LFO (0 - 1200 cents). uint16_t LFO2ControlDepth; ///< Controller depth influencing filter cutoff LFO pitch (0 - 1200). lfo2_ctrl_t LFO2Controller; ///< MIDI Controlle which controls the filter cutoff LFO. - bool LFO2FlipPhase; ///< Inverts phase of the filter cutoff LFO wave. + bool LFO2FlipPhase; ///< Inverts the polarity of the filter cutoff LFO wave, so it flips the wave form vertically. bool LFO2Sync; ///< If set to true only one LFO should be used for all voices. // Sample Pitch EG/LFO double EG3Attack; ///< Attack time of the sample pitch EG (0.000 - 10.000s). int16_t EG3Depth; ///< Depth of the sample pitch EG (-1200 - +1200). + lfo_wave_t LFO3WaveForm; ///< [gig extension]: The fundamental wave form to be used by the pitch LFO, e.g. sine, triangle, saw, square (default: sine). double LFO3Frequency; ///< Frequency of the sample pitch LFO (0.10 - 10.00 Hz). + double LFO3Phase; ///< [gig extension]: Phase displacement of the pitch LFO's wave form (0.0° - 360.0°). int16_t LFO3InternalDepth; ///< Firm depth of the sample pitch LFO (-1200 - +1200 cents). int16_t LFO3ControlDepth; ///< Controller depth of the sample pitch LFO (-1200 - +1200 cents). lfo3_ctrl_t LFO3Controller; ///< MIDI Controller which controls the sample pitch LFO. + bool LFO3FlipPhase; ///< [gig extension]: Inverts the polarity of the pitch LFO wave, so it flips the wave form vertically (@b NOTE: this setting for LFO3 is a gig format extension; flipping the polarity was only available for LFO1 and LFO2 in the original Gigasampler/GigaStudio software). bool LFO3Sync; ///< If set to true only one LFO should be used for all voices. // Filter bool VCFEnabled; ///< If filter should be used. @@ -577,6 +629,7 @@ eg_opt_t EG1Options; ///< [gig extension]: Behavior options which should be used for envelope generator 1 (volume amplitude EG). eg_opt_t EG2Options; ///< [gig extension]: Behavior options which should be used for envelope generator 2 (filter cutoff EG). sust_rel_trg_t SustainReleaseTrigger; ///< [gig extension]: Whether a sustain pedal up event shall play release trigger sample. + bool NoNoteOffReleaseTrigger; ///< [gig extension]: If @c true then don't play a release trigger sample on MIDI note-off events. // derived attributes from DLS::Sampler using DLS::Sampler::UnityNote; @@ -603,8 +656,8 @@ using DLS::Sampler::AddSampleLoop; using DLS::Sampler::DeleteSampleLoop; // overridden methods - virtual void SetGain(int32_t gain); - virtual void UpdateChunks(progress_t* pProgress); + virtual void SetGain(int32_t gain) OVERRIDE; + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; 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. @@ -730,6 +783,7 @@ double* GetCutoffVelocityTable(curve_type_t vcfVelocityCurve, uint8_t vcfVelocityDynamicRange, uint8_t vcfVelocityScale, vcf_cutoff_ctrl_t vcfCutoffController); double* GetVelocityTable(curve_type_t curveType, uint8_t depth, uint8_t scaling); double* CreateVelocityTable(curve_type_t curveType, uint8_t depth, uint8_t scaling); + bool UsesAnyGigFormatExtension() const; }; /** @brief Encapsulates sample waves of Gigasampler/GigaStudio files used for playback. @@ -796,14 +850,14 @@ file_offset_t ReadAndLoop(void* pBuffer, file_offset_t SampleCount, playback_state_t* pPlaybackState, DimensionRegion* pDimRgn, buffer_t* pExternalDecompressionBuffer = NULL); file_offset_t Write(void* pBuffer, file_offset_t SampleCount); Group* GetGroup() const; - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; void CopyAssignMeta(const Sample* orig); void CopyAssignWave(const Sample* orig); uint32_t GetWaveDataCRC32Checksum(); bool VerifyWaveData(uint32_t* pActually = NULL); protected: static size_t 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. + static buffer_t InternalDecompressionBuffer; ///< Buffer used for decompression of samples, and only if no external decompression buffer was supplied. Group* pGroup; ///< pointer to the Group this sample belongs to (always not-NULL) file_offset_t FrameOffset; ///< Current offset (sample points) in current sample frame (for decompression only). file_offset_t* FrameTable; ///< For positioning within compressed samples only: stores the offset values for each frame. @@ -890,8 +944,8 @@ void SplitDimensionZone(dimension_t type, int zone); void SetDimensionType(dimension_t oldType, dimension_t newType); // overridden methods - virtual void SetKeyRange(uint16_t Low, uint16_t High); - virtual void UpdateChunks(progress_t* pProgress); + virtual void SetKeyRange(uint16_t Low, uint16_t High) OVERRIDE; + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; virtual void CopyAssign(const Region* orig); protected: Region(Instrument* pInstrument, RIFF::List* rgnList); @@ -902,6 +956,8 @@ DimensionRegion* GetDimensionRegionByBit(const std::map& DimCase); ~Region(); friend class Instrument; + private: + bool UsesAnyGigFormatExtension() const; }; /** @brief Abstract base class for all MIDI rules. @@ -984,7 +1040,7 @@ protected: MidiRuleCtrlTrigger(RIFF::Chunk* _3ewg); MidiRuleCtrlTrigger(); - void UpdateChunks(uint8_t* pData) const; + void UpdateChunks(uint8_t* pData) const OVERRIDE; friend class Instrument; }; @@ -1024,7 +1080,7 @@ protected: MidiRuleLegato(RIFF::Chunk* _3ewg); MidiRuleLegato(); - void UpdateChunks(uint8_t* pData) const; + void UpdateChunks(uint8_t* pData) const OVERRIDE; friend class Instrument; }; @@ -1076,7 +1132,7 @@ protected: MidiRuleAlternator(RIFF::Chunk* _3ewg); MidiRuleAlternator(); - void UpdateChunks(uint8_t* pData) const; + void UpdateChunks(uint8_t* pData) const OVERRIDE; friend class Instrument; }; @@ -1096,7 +1152,7 @@ class MidiRuleUnknown : public MidiRule { protected: MidiRuleUnknown() { } - void UpdateChunks(uint8_t* pData) const { } + void UpdateChunks(uint8_t* pData) const OVERRIDE { } friend class Instrument; }; @@ -1120,7 +1176,7 @@ * - NKSP Reference Manual * - Using Instrument Scripts with Gigedit */ - class Script { + class Script : protected DLS::Storage { public: enum Encoding_t { ENCODING_ASCII = 0 ///< Standard 8 bit US ASCII character encoding (default). @@ -1137,6 +1193,7 @@ Encoding_t Encoding; ///< Format the script's source code text is encoded with. Language_t Language; ///< Programming language and dialect the script is written in. bool Bypass; ///< Global bypass: if enabled, this script shall not be executed by the sampler for any instrument. + uint8_t Uuid[16]; ///< Persistent Universally Unique Identifier of this script, which remains identical after any changes to this script. String GetScriptAsText(); void SetScriptAsText(const String& text); @@ -1146,8 +1203,10 @@ protected: Script(ScriptGroup* group, RIFF::Chunk* ckScri); virtual ~Script(); - void UpdateChunks(progress_t* pProgress); + void UpdateChunks(progress_t* pProgress) OVERRIDE; + void DeleteChunks() OVERRIDE; void RemoveAllScriptReferences(); + void GenerateUuid(); friend class ScriptGroup; friend class Instrument; private: @@ -1168,7 +1227,7 @@ * not available in the GigaStudio 4 software. It is currently only * supported by LinuxSampler and gigedit. */ - class ScriptGroup { + class ScriptGroup : protected DLS::Storage { public: String Name; ///< Name of this script group. For example to be displayed in an instrument editor. @@ -1179,13 +1238,14 @@ ScriptGroup(File* file, RIFF::List* lstRTIS); virtual ~ScriptGroup(); void LoadScripts(); - void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; + virtual void DeleteChunks() OVERRIDE; friend class Script; friend class File; private: File* pFile; RIFF::List* pList; ///< 'RTIS' list chunk - std::list* pScripts; + std::vector* pScripts; }; /** @brief Provides access to a Gigasampler/GigaStudio instrument. @@ -1227,12 +1287,13 @@ // derived methods from DLS::Resource using DLS::Resource::GetParent; // overridden methods - Region* GetFirstRegion(); - Region* GetNextRegion(); + Region* GetRegionAt(size_t pos); + Region* GetFirstRegion() LIBGIG_DEPRECATED_API("Use GetRegionAt() instead."); + Region* GetNextRegion() LIBGIG_DEPRECATED_API("Use GetRegionAt() instead."); Region* AddRegion(); void DeleteRegion(Region* pRegion); void MoveTo(Instrument* dst); - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; virtual void CopyAssign(const Instrument* orig); // own methods Region* GetRegion(unsigned int Key); @@ -1250,6 +1311,11 @@ uint ScriptSlotCount() const; bool IsScriptSlotBypassed(uint index); void SetScriptSlotBypassed(uint index, bool bBypass); + bool IsScriptPatchVariableSet(int slot, String variable); + std::map GetScriptPatchVariables(int slot); + String GetScriptPatchVariable(int slot, String variable); + void SetScriptPatchVariable(int slot, String variable, String value); + void UnsetScriptPatchVariable(int slot = -1, String variable = ""); protected: Region* RegionKeyTable[128]; ///< fast lookup for the corresponding Region of a MIDI key @@ -1270,9 +1336,18 @@ Script* script; bool bypass; }; + typedef std::array _UUID; + typedef std::map _PatchVars; + typedef std::map _VarsBySlot; + typedef std::map<_UUID,_VarsBySlot> _VarsByScript; MidiRule** pMidiRules; std::vector<_ScriptPooolEntry> scriptPoolFileOffsets; std::vector<_ScriptPooolRef>* pScriptRefs; + _VarsByScript scriptVars; + + _VarsByScript stripScriptVars(); + bool ReferencesScriptWithUuid(const _UUID& uuid); + bool UsesAnyGigFormatExtension() const; }; /** @brief Group of Gigasampler samples @@ -1286,22 +1361,25 @@ * there is always at least one Group in a .gig file, no matter if you * created one yet or not. */ - class Group { + class Group : public DLS::Storage { public: String Name; ///< Stores the name of this Group. - Sample* GetFirstSample(); - Sample* GetNextSample(); + Sample* GetSample(size_t index); + Sample* GetFirstSample() LIBGIG_DEPRECATED_API("Use GetSample() instead."); + Sample* GetNextSample() LIBGIG_DEPRECATED_API("Use GetSample() instead."); void AddSample(Sample* pSample); protected: Group(File* file, RIFF::Chunk* ck3gnm); virtual ~Group(); - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; + virtual void DeleteChunks() OVERRIDE; void MoveAll(); friend class File; private: File* pFile; RIFF::Chunk* pNameChunk; ///< '3gnm' chunk + size_t SamplesIterator; ///< Used by GetFirstSample(), GetNextSample() only. }; /** @brief Provides convenient access to Gigasampler/GigaStudio .gig files. @@ -1359,25 +1437,26 @@ using DLS::File::Save; using DLS::File::GetFileName; using DLS::File::SetFileName; + using DLS::File::GetRiffFile; // 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* GetFirstSample(progress_t* pProgress = NULL) LIBGIG_DEPRECATED_API("Use GetSample() instead."); + Sample* GetNextSample() LIBGIG_DEPRECATED_API("Use GetSample() instead."); + Sample* GetSample(size_t index, progress_t* pProgress = NULL); Sample* AddSample(); size_t CountSamples(); 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* GetFirstInstrument() LIBGIG_DEPRECATED_API("Use GetInstrument() instead."); + Instrument* GetNextInstrument() LIBGIG_DEPRECATED_API("Use GetInstrument() instead."); + Instrument* GetInstrument(size_t index, progress_t* pProgress = NULL); Instrument* AddInstrument(); Instrument* AddDuplicateInstrument(const Instrument* orig); size_t CountInstruments(); 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. - Group* GetGroup(uint index); + Group* GetFirstGroup() LIBGIG_DEPRECATED_API("Use GetGroup() instead."); + Group* GetNextGroup() LIBGIG_DEPRECATED_API("Use GetGroup() instead."); + Group* GetGroup(size_t index); Group* GetGroup(String name); Group* AddGroup(); void DeleteGroup(Group* pGroup); @@ -1390,13 +1469,13 @@ ScriptGroup* AddScriptGroup(); void DeleteScriptGroup(ScriptGroup* pGroup); virtual ~File(); - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; protected: // overridden protected methods from DLS::File - virtual void LoadSamples(); - virtual void LoadInstruments(); + virtual void LoadSamples() OVERRIDE; + virtual void LoadInstruments() OVERRIDE; virtual void LoadGroups(); - virtual void UpdateFileOffsets(); + virtual void UpdateFileOffsets() OVERRIDE; // own protected methods virtual void LoadSamples(progress_t* pProgress); virtual void LoadInstruments(progress_t* pProgress); @@ -1413,10 +1492,12 @@ friend class Group; // so Group can access protected member pRIFF friend class ScriptGroup; // so ScriptGroup can access protected member pRIFF private: - std::list* pGroups; - std::list::iterator GroupsIterator; + std::vector* pGroups; + std::vector::iterator GroupsIterator; bool bAutoLoad; std::list* pScriptGroups; + + bool UsesAnyGigFormatExtension() const; }; /**