2 |
* * |
* * |
3 |
* libgig - C++ cross-platform Gigasampler format file access library * |
* libgig - C++ cross-platform Gigasampler format file access library * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003-2009 by Christian Schoenebeck * |
* Copyright (C) 2003-2013 by Christian Schoenebeck * |
6 |
* <cuse@users.sourceforge.net> * |
* <cuse@users.sourceforge.net> * |
7 |
* * |
* * |
8 |
* This library is free software; you can redistribute it and/or modify * |
* This library is free software; you can redistribute it and/or modify * |
31 |
# define LIST_TYPE_3EWL 0x3365776C |
# define LIST_TYPE_3EWL 0x3365776C |
32 |
# define LIST_TYPE_3GRI 0x33677269 |
# define LIST_TYPE_3GRI 0x33677269 |
33 |
# define LIST_TYPE_3GNL 0x33676E6C |
# define LIST_TYPE_3GNL 0x33676E6C |
|
# define CHUNK_ID_SMPL 0x736D706C |
|
34 |
# define CHUNK_ID_3GIX 0x33676978 |
# define CHUNK_ID_3GIX 0x33676978 |
35 |
# define CHUNK_ID_3EWA 0x33657761 |
# define CHUNK_ID_3EWA 0x33657761 |
36 |
# define CHUNK_ID_3LNK 0x336C6E6B |
# define CHUNK_ID_3LNK 0x336C6E6B |
44 |
# define LIST_TYPE_3EWL 0x6C776533 |
# define LIST_TYPE_3EWL 0x6C776533 |
45 |
# define LIST_TYPE_3GRI 0x69726733 |
# define LIST_TYPE_3GRI 0x69726733 |
46 |
# define LIST_TYPE_3GNL 0x6C6E6733 |
# define LIST_TYPE_3GNL 0x6C6E6733 |
|
# define CHUNK_ID_SMPL 0x6C706D73 |
|
47 |
# define CHUNK_ID_3GIX 0x78696733 |
# define CHUNK_ID_3GIX 0x78696733 |
48 |
# define CHUNK_ID_3EWA 0x61776533 |
# define CHUNK_ID_3EWA 0x61776533 |
49 |
# define CHUNK_ID_3LNK 0x6B6E6C33 |
# define CHUNK_ID_3LNK 0x6B6E6C33 |
429 |
uint8_t DimensionUpperLimits[8]; ///< gig3: defines the upper limit of the dimension values for this dimension region |
uint8_t DimensionUpperLimits[8]; ///< gig3: defines the upper limit of the dimension values for this dimension region |
430 |
|
|
431 |
// derived attributes from DLS::Sampler |
// derived attributes from DLS::Sampler |
432 |
DLS::Sampler::UnityNote; |
using DLS::Sampler::UnityNote; |
433 |
DLS::Sampler::FineTune; |
using DLS::Sampler::FineTune; |
434 |
DLS::Sampler::Gain; |
using DLS::Sampler::Gain; |
435 |
DLS::Sampler::SampleLoops; |
using DLS::Sampler::SampleLoops; |
436 |
DLS::Sampler::pSampleLoops; |
using DLS::Sampler::pSampleLoops; |
437 |
|
|
438 |
// own methods |
// own methods |
439 |
double GetVelocityAttenuation(uint8_t MIDIKeyVelocity); |
double GetVelocityAttenuation(uint8_t MIDIKeyVelocity); |
450 |
void SetVCFVelocityScale(uint8_t scaling); |
void SetVCFVelocityScale(uint8_t scaling); |
451 |
Region* GetParent() const; |
Region* GetParent() const; |
452 |
// derived methods |
// derived methods |
453 |
DLS::Sampler::AddSampleLoop; |
using DLS::Sampler::AddSampleLoop; |
454 |
DLS::Sampler::DeleteSampleLoop; |
using DLS::Sampler::DeleteSampleLoop; |
455 |
// overridden methods |
// overridden methods |
456 |
virtual void SetGain(int32_t gain); |
virtual void SetGain(int32_t gain); |
457 |
virtual void UpdateChunks(); |
virtual void UpdateChunks(); |
458 |
|
virtual void CopyAssign(const DimensionRegion* orig); |
459 |
protected: |
protected: |
460 |
uint8_t* VelocityTable; ///< For velocity dimensions with custom defined zone ranges only: used for fast converting from velocity MIDI value to dimension bit number. |
uint8_t* VelocityTable; ///< For velocity dimensions with custom defined zone ranges only: used for fast converting from velocity MIDI value to dimension bit number. |
461 |
DimensionRegion(Region* pParent, RIFF::List* _3ewl); |
DimensionRegion(Region* pParent, RIFF::List* _3ewl); |
462 |
DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src); |
DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src); |
463 |
~DimensionRegion(); |
~DimensionRegion(); |
464 |
|
void CopyAssign(const DimensionRegion* orig, const std::map<Sample*,Sample*>* mSamples); |
465 |
friend class Region; |
friend class Region; |
466 |
private: |
private: |
467 |
typedef enum { ///< Used to decode attenuation, EG1 and EG2 controller |
typedef enum { ///< Used to decode attenuation, EG1 and EG2 controller |
558 |
void ReleaseSampleData(); |
void ReleaseSampleData(); |
559 |
void Resize(int iNewSize); |
void Resize(int iNewSize); |
560 |
unsigned long SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence = RIFF::stream_start); |
unsigned long SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence = RIFF::stream_start); |
561 |
unsigned long GetPos(); |
unsigned long GetPos() const; |
562 |
unsigned long Read(void* pBuffer, unsigned long SampleCount, buffer_t* pExternalDecompressionBuffer = NULL); |
unsigned long Read(void* pBuffer, unsigned long SampleCount, buffer_t* pExternalDecompressionBuffer = NULL); |
563 |
unsigned long ReadAndLoop(void* pBuffer, unsigned long SampleCount, playback_state_t* pPlaybackState, DimensionRegion* pDimRgn, buffer_t* pExternalDecompressionBuffer = NULL); |
unsigned long ReadAndLoop(void* pBuffer, unsigned long SampleCount, playback_state_t* pPlaybackState, DimensionRegion* pDimRgn, buffer_t* pExternalDecompressionBuffer = NULL); |
564 |
unsigned long Write(void* pBuffer, unsigned long SampleCount); |
unsigned long Write(void* pBuffer, unsigned long SampleCount); |
565 |
Group* GetGroup() const; |
Group* GetGroup() const; |
566 |
virtual void UpdateChunks(); |
virtual void UpdateChunks(); |
567 |
|
void CopyAssignMeta(const Sample* orig); |
568 |
|
void CopyAssignWave(const Sample* orig); |
569 |
protected: |
protected: |
570 |
static unsigned int Instances; ///< Number of instances of class Sample. |
static unsigned int Instances; ///< Number of instances of class Sample. |
571 |
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 as well as for truncation of 24 Bit -> 16 Bit samples. |
632 |
// overridden methods |
// overridden methods |
633 |
virtual void SetKeyRange(uint16_t Low, uint16_t High); |
virtual void SetKeyRange(uint16_t Low, uint16_t High); |
634 |
virtual void UpdateChunks(); |
virtual void UpdateChunks(); |
635 |
|
virtual void CopyAssign(const Region* orig); |
636 |
protected: |
protected: |
637 |
Region(Instrument* pInstrument, RIFF::List* rgnList); |
Region(Instrument* pInstrument, RIFF::List* rgnList); |
638 |
void LoadDimensionRegions(RIFF::List* rgn); |
void LoadDimensionRegions(RIFF::List* rgn); |
639 |
void UpdateVelocityTable(); |
void UpdateVelocityTable(); |
640 |
Sample* GetSampleFromWavePool(unsigned int WavePoolTableIndex, progress_t* pProgress = NULL); |
Sample* GetSampleFromWavePool(unsigned int WavePoolTableIndex, progress_t* pProgress = NULL); |
641 |
|
void CopyAssign(const Region* orig, const std::map<Sample*,Sample*>* mSamples); |
642 |
~Region(); |
~Region(); |
643 |
friend class Instrument; |
friend class Instrument; |
644 |
}; |
}; |
647 |
class MidiRule { |
class MidiRule { |
648 |
public: |
public: |
649 |
virtual ~MidiRule() { } |
virtual ~MidiRule() { } |
650 |
|
protected: |
651 |
|
virtual void UpdateChunks(uint8_t* pData) const = 0; |
652 |
|
friend class Instrument; |
653 |
}; |
}; |
654 |
|
|
655 |
/** MIDI rule for triggering notes by control change events. */ |
/** MIDI rule for triggering notes by control change events. */ |
669 |
|
|
670 |
protected: |
protected: |
671 |
MidiRuleCtrlTrigger(RIFF::Chunk* _3ewg); |
MidiRuleCtrlTrigger(RIFF::Chunk* _3ewg); |
672 |
|
MidiRuleCtrlTrigger(); |
673 |
|
void UpdateChunks(uint8_t* pData) const; |
674 |
|
friend class Instrument; |
675 |
|
}; |
676 |
|
|
677 |
|
/** MIDI rule for instruments with legato samples. */ |
678 |
|
class MidiRuleLegato : public MidiRule { |
679 |
|
public: |
680 |
|
uint8_t LegatoSamples; ///< Number of legato samples per key in each direction (always 12) |
681 |
|
bool BypassUseController; ///< If a controller should be used to bypass the sustain note |
682 |
|
uint8_t BypassKey; ///< Key to be used to bypass the sustain note |
683 |
|
uint8_t BypassController; ///< Controller to be used to bypass the sustain note |
684 |
|
uint16_t ThresholdTime; ///< Maximum time (ms) between two notes that should be played legato |
685 |
|
uint16_t ReleaseTime; ///< Release time |
686 |
|
range_t KeyRange; ///< Key range for legato notes |
687 |
|
uint8_t ReleaseTriggerKey; ///< Key triggering release samples |
688 |
|
uint8_t AltSustain1Key; ///< Key triggering alternate sustain samples |
689 |
|
uint8_t AltSustain2Key; ///< Key triggering a second set of alternate sustain samples |
690 |
|
|
691 |
|
protected: |
692 |
|
MidiRuleLegato(RIFF::Chunk* _3ewg); |
693 |
|
MidiRuleLegato(); |
694 |
|
void UpdateChunks(uint8_t* pData) const; |
695 |
|
friend class Instrument; |
696 |
|
}; |
697 |
|
|
698 |
|
/** MIDI rule to automatically cycle through specified sequences of different articulations. The instrument must be using the smartmidi dimension. */ |
699 |
|
class MidiRuleAlternator : public MidiRule { |
700 |
|
public: |
701 |
|
uint8_t Articulations; ///< Number of articulations in the instrument |
702 |
|
String pArticulations[32]; ///< Names of the articulations |
703 |
|
|
704 |
|
range_t PlayRange; ///< Key range of the playable keys in the instrument |
705 |
|
|
706 |
|
uint8_t Patterns; ///< Number of alternator patterns |
707 |
|
struct pattern_t { |
708 |
|
String Name; ///< Name of the pattern |
709 |
|
int Size; ///< Number of steps in the pattern |
710 |
|
const uint8_t& operator[](int i) const { /// Articulation to play |
711 |
|
return data[i]; |
712 |
|
} |
713 |
|
uint8_t& operator[](int i) { |
714 |
|
return data[i]; |
715 |
|
} |
716 |
|
private: |
717 |
|
uint8_t data[32]; |
718 |
|
} pPatterns[32]; ///< A pattern is a sequence of articulation numbers |
719 |
|
|
720 |
|
typedef enum { |
721 |
|
selector_none, |
722 |
|
selector_key_switch, |
723 |
|
selector_controller |
724 |
|
} selector_t; |
725 |
|
selector_t Selector; ///< Method by which pattern is chosen |
726 |
|
range_t KeySwitchRange; ///< Key range for key switch selector |
727 |
|
uint8_t Controller; ///< CC number for controller selector |
728 |
|
|
729 |
|
bool Polyphonic; ///< If alternator should step forward only when all notes are off |
730 |
|
bool Chained; ///< If all patterns should be chained together |
731 |
|
|
732 |
|
protected: |
733 |
|
MidiRuleAlternator(RIFF::Chunk* _3ewg); |
734 |
|
MidiRuleAlternator(); |
735 |
|
void UpdateChunks(uint8_t* pData) const; |
736 |
|
friend class Instrument; |
737 |
|
}; |
738 |
|
|
739 |
|
/** A MIDI rule not yet implemented by libgig. */ |
740 |
|
class MidiRuleUnknown : public MidiRule { |
741 |
|
protected: |
742 |
|
MidiRuleUnknown() { } |
743 |
|
void UpdateChunks(uint8_t* pData) const { } |
744 |
friend class Instrument; |
friend class Instrument; |
745 |
}; |
}; |
746 |
|
|
748 |
class Instrument : protected DLS::Instrument { |
class Instrument : protected DLS::Instrument { |
749 |
public: |
public: |
750 |
// derived attributes from DLS::Resource |
// derived attributes from DLS::Resource |
751 |
DLS::Resource::pInfo; |
using DLS::Resource::pInfo; |
752 |
DLS::Resource::pDLSID; |
using DLS::Resource::pDLSID; |
753 |
// derived attributes from DLS::Instrument |
// derived attributes from DLS::Instrument |
754 |
DLS::Instrument::IsDrum; |
using DLS::Instrument::IsDrum; |
755 |
DLS::Instrument::MIDIBank; |
using DLS::Instrument::MIDIBank; |
756 |
DLS::Instrument::MIDIBankCoarse; |
using DLS::Instrument::MIDIBankCoarse; |
757 |
DLS::Instrument::MIDIBankFine; |
using DLS::Instrument::MIDIBankFine; |
758 |
DLS::Instrument::MIDIProgram; |
using DLS::Instrument::MIDIProgram; |
759 |
DLS::Instrument::Regions; |
using DLS::Instrument::Regions; |
760 |
// own attributes |
// own attributes |
761 |
int32_t Attenuation; ///< in dB |
int32_t Attenuation; ///< in dB |
762 |
uint16_t EffectSend; |
uint16_t EffectSend; |
767 |
|
|
768 |
|
|
769 |
// derived methods from DLS::Resource |
// derived methods from DLS::Resource |
770 |
DLS::Resource::GetParent; |
using DLS::Resource::GetParent; |
771 |
// overridden methods |
// overridden methods |
772 |
Region* GetFirstRegion(); |
Region* GetFirstRegion(); |
773 |
Region* GetNextRegion(); |
Region* GetNextRegion(); |
774 |
Region* AddRegion(); |
Region* AddRegion(); |
775 |
void DeleteRegion(Region* pRegion); |
void DeleteRegion(Region* pRegion); |
776 |
virtual void UpdateChunks(); |
virtual void UpdateChunks(); |
777 |
|
virtual void CopyAssign(const Instrument* orig); |
778 |
// own methods |
// own methods |
779 |
Region* GetRegion(unsigned int Key); |
Region* GetRegion(unsigned int Key); |
780 |
MidiRule* GetMidiRule(int i); |
MidiRule* GetMidiRule(int i); |
781 |
|
MidiRuleCtrlTrigger* AddMidiRuleCtrlTrigger(); |
782 |
|
MidiRuleLegato* AddMidiRuleLegato(); |
783 |
|
MidiRuleAlternator* AddMidiRuleAlternator(); |
784 |
|
void DeleteMidiRule(int i); |
785 |
protected: |
protected: |
786 |
Region* RegionKeyTable[128]; ///< fast lookup for the corresponding Region of a MIDI key |
Region* RegionKeyTable[128]; ///< fast lookup for the corresponding Region of a MIDI key |
787 |
|
|
788 |
Instrument(File* pFile, RIFF::List* insList, progress_t* pProgress = NULL); |
Instrument(File* pFile, RIFF::List* insList, progress_t* pProgress = NULL); |
789 |
~Instrument(); |
~Instrument(); |
790 |
|
void CopyAssign(const Instrument* orig, const std::map<Sample*,Sample*>* mSamples); |
791 |
void UpdateRegionKeyTable(); |
void UpdateRegionKeyTable(); |
792 |
friend class File; |
friend class File; |
793 |
friend class Region; // so Region can call UpdateRegionKeyTable() |
friend class Region; // so Region can call UpdateRegionKeyTable() |
825 |
friend class File; |
friend class File; |
826 |
private: |
private: |
827 |
File* pFile; |
File* pFile; |
828 |
RIFF::Chunk* pNameChunk; |
RIFF::Chunk* pNameChunk; ///< '3gnm' chunk |
829 |
}; |
}; |
830 |
|
|
831 |
/** Parses Gigasampler files and provides abstract access to the data. */ |
/** Parses Gigasampler files and provides abstract access to the data. */ |
835 |
static const DLS::version_t VERSION_3; |
static const DLS::version_t VERSION_3; |
836 |
|
|
837 |
// derived attributes from DLS::Resource |
// derived attributes from DLS::Resource |
838 |
DLS::Resource::pInfo; |
using DLS::Resource::pInfo; |
839 |
DLS::Resource::pDLSID; |
using DLS::Resource::pDLSID; |
840 |
// derived attributes from DLS::File |
// derived attributes from DLS::File |
841 |
DLS::File::pVersion; |
using DLS::File::pVersion; |
842 |
DLS::File::Instruments; |
using DLS::File::Instruments; |
843 |
|
|
844 |
// derived methods from DLS::Resource |
// derived methods from DLS::Resource |
845 |
DLS::Resource::GetParent; |
using DLS::Resource::GetParent; |
846 |
// derived methods from DLS::File |
// derived methods from DLS::File |
847 |
DLS::File::Save; |
using DLS::File::Save; |
848 |
|
using DLS::File::GetFileName; |
849 |
|
using DLS::File::SetFileName; |
850 |
// overridden methods |
// overridden methods |
851 |
File(); |
File(); |
852 |
File(RIFF::File* pRIFF); |
File(RIFF::File* pRIFF); |
853 |
Sample* GetFirstSample(progress_t* pProgress = NULL); ///< Returns a pointer to the first <i>Sample</i> object of the file, <i>NULL</i> otherwise. |
Sample* GetFirstSample(progress_t* pProgress = NULL); ///< Returns a pointer to the first <i>Sample</i> object of the file, <i>NULL</i> otherwise. |
854 |
Sample* GetNextSample(); ///< Returns a pointer to the next <i>Sample</i> object of the file, <i>NULL</i> otherwise. |
Sample* GetNextSample(); ///< Returns a pointer to the next <i>Sample</i> object of the file, <i>NULL</i> otherwise. |
855 |
|
Sample* GetSample(uint index); |
856 |
Sample* AddSample(); |
Sample* AddSample(); |
857 |
void DeleteSample(Sample* pSample); |
void DeleteSample(Sample* pSample); |
858 |
Instrument* GetFirstInstrument(); ///< Returns a pointer to the first <i>Instrument</i> object of the file, <i>NULL</i> otherwise. |
Instrument* GetFirstInstrument(); ///< Returns a pointer to the first <i>Instrument</i> object of the file, <i>NULL</i> otherwise. |
859 |
Instrument* GetNextInstrument(); ///< Returns a pointer to the next <i>Instrument</i> object of the file, <i>NULL</i> otherwise. |
Instrument* GetNextInstrument(); ///< Returns a pointer to the next <i>Instrument</i> object of the file, <i>NULL</i> otherwise. |
860 |
Instrument* GetInstrument(uint index, progress_t* pProgress = NULL); |
Instrument* GetInstrument(uint index, progress_t* pProgress = NULL); |
861 |
Instrument* AddInstrument(); |
Instrument* AddInstrument(); |
862 |
|
Instrument* AddDuplicateInstrument(const Instrument* orig); |
863 |
void DeleteInstrument(Instrument* pInstrument); |
void DeleteInstrument(Instrument* pInstrument); |
864 |
Group* GetFirstGroup(); ///< Returns a pointer to the first <i>Group</i> object of the file, <i>NULL</i> otherwise. |
Group* GetFirstGroup(); ///< Returns a pointer to the first <i>Group</i> object of the file, <i>NULL</i> otherwise. |
865 |
Group* GetNextGroup(); ///< Returns a pointer to the next <i>Group</i> object of the file, <i>NULL</i> otherwise. |
Group* GetNextGroup(); ///< Returns a pointer to the next <i>Group</i> object of the file, <i>NULL</i> otherwise. |
869 |
void DeleteGroupOnly(Group* pGroup); |
void DeleteGroupOnly(Group* pGroup); |
870 |
void SetAutoLoad(bool b); |
void SetAutoLoad(bool b); |
871 |
bool GetAutoLoad(); |
bool GetAutoLoad(); |
872 |
|
void AddContentOf(File* pFile); |
873 |
virtual ~File(); |
virtual ~File(); |
874 |
virtual void UpdateChunks(); |
virtual void UpdateChunks(); |
875 |
protected: |
protected: |