1 |
/*************************************************************************** |
/*************************************************************************** |
2 |
* * |
* * |
3 |
* libgig - C++ cross-platform Gigasampler format file loader library * |
* libgig - C++ cross-platform Gigasampler format file access library * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003-2006 by Christian Schoenebeck * |
* Copyright (C) 2003-2006 by Christian Schoenebeck * |
6 |
* <cuse@users.sourceforge.net> * |
* <cuse@users.sourceforge.net> * |
29 |
#if WORDS_BIGENDIAN |
#if WORDS_BIGENDIAN |
30 |
# define LIST_TYPE_3PRG 0x33707267 |
# define LIST_TYPE_3PRG 0x33707267 |
31 |
# define LIST_TYPE_3EWL 0x3365776C |
# define LIST_TYPE_3EWL 0x3365776C |
32 |
|
# define LIST_TYPE_3GRI 0x33677269 |
33 |
|
# define LIST_TYPE_3GNL 0x33676E6C |
34 |
# define CHUNK_ID_SMPL 0x736D706C |
# define CHUNK_ID_SMPL 0x736D706C |
35 |
# define CHUNK_ID_3GIX 0x33676978 |
# define CHUNK_ID_3GIX 0x33676978 |
36 |
# define CHUNK_ID_3EWA 0x33657761 |
# define CHUNK_ID_3EWA 0x33657761 |
37 |
# define CHUNK_ID_3LNK 0x336C6E6B |
# define CHUNK_ID_3LNK 0x336C6E6B |
38 |
# define CHUNK_ID_3EWG 0x33657767 |
# define CHUNK_ID_3EWG 0x33657767 |
39 |
# define CHUNK_ID_EWAV 0x65776176 |
# define CHUNK_ID_EWAV 0x65776176 |
40 |
|
# define CHUNK_ID_3GNM 0x33676E6D |
41 |
#else // little endian |
#else // little endian |
42 |
# define LIST_TYPE_3PRG 0x67727033 |
# define LIST_TYPE_3PRG 0x67727033 |
43 |
# define LIST_TYPE_3EWL 0x6C776533 |
# define LIST_TYPE_3EWL 0x6C776533 |
44 |
|
# define LIST_TYPE_3GRI 0x69726733 |
45 |
|
# define LIST_TYPE_3GNL 0x6C6E6733 |
46 |
# define CHUNK_ID_SMPL 0x6C706D73 |
# 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 |
50 |
# define CHUNK_ID_3EWG 0x67776533 |
# define CHUNK_ID_3EWG 0x67776533 |
51 |
# define CHUNK_ID_EWAV 0x76617765 |
# define CHUNK_ID_EWAV 0x76617765 |
52 |
|
# define CHUNK_ID_3GNM 0x6D6E6733 |
53 |
#endif // WORDS_BIGENDIAN |
#endif // WORDS_BIGENDIAN |
54 |
|
|
55 |
/** Gigasampler specific classes and definitions */ |
/** Gigasampler specific classes and definitions */ |
210 |
dimension_none = 0x00, ///< Dimension not in use. |
dimension_none = 0x00, ///< Dimension not in use. |
211 |
dimension_samplechannel = 0x80, ///< If used sample has more than one channel (thus is not mono). |
dimension_samplechannel = 0x80, ///< If used sample has more than one channel (thus is not mono). |
212 |
dimension_layer = 0x81, ///< For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers). |
dimension_layer = 0x81, ///< For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers). |
213 |
dimension_velocity = 0x82, ///< Key Velocity (this is the only dimension where the ranges can exactly be defined). |
dimension_velocity = 0x82, ///< Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined). |
214 |
dimension_channelaftertouch = 0x83, ///< Channel Key Pressure |
dimension_channelaftertouch = 0x83, ///< Channel Key Pressure |
215 |
dimension_releasetrigger = 0x84, ///< Special dimension for triggering samples on releasing a key. |
dimension_releasetrigger = 0x84, ///< Special dimension for triggering samples on releasing a key. |
216 |
dimension_keyboard = 0x85, ///< Dimension for keyswitching |
dimension_keyboard = 0x85, ///< Dimension for keyswitching |
217 |
dimension_roundrobin = 0x86, ///< Different samples triggered each time a note is played, dimension regions selected in sequence |
dimension_roundrobin = 0x86, ///< Different samples triggered each time a note is played, dimension regions selected in sequence |
218 |
dimension_random = 0x87, ///< Different samples triggered each time a note is played, random order |
dimension_random = 0x87, ///< Different samples triggered each time a note is played, random order |
219 |
|
dimension_smartmidi = 0x88, ///< For MIDI tools like legato and repetition mode |
220 |
|
dimension_roundrobinkeyboard = 0x89, ///< Different samples triggered each time a note is played, any key advances the counter |
221 |
dimension_modwheel = 0x01, ///< Modulation Wheel (MIDI Controller 1) |
dimension_modwheel = 0x01, ///< Modulation Wheel (MIDI Controller 1) |
222 |
dimension_breath = 0x02, ///< Breath Controller (Coarse, MIDI Controller 2) |
dimension_breath = 0x02, ///< Breath Controller (Coarse, MIDI Controller 2) |
223 |
dimension_foot = 0x04, ///< Foot Pedal (Coarse, MIDI Controller 4) |
dimension_foot = 0x04, ///< Foot Pedal (Coarse, MIDI Controller 4) |
324 |
class Instrument; |
class Instrument; |
325 |
class Sample; |
class Sample; |
326 |
class Region; |
class Region; |
327 |
|
class Group; |
328 |
|
|
329 |
/** Encapsulates articulation information of a dimension region. |
/** Encapsulates articulation information of a dimension region. |
330 |
* |
* |
340 |
*/ |
*/ |
341 |
class DimensionRegion : protected DLS::Sampler { |
class DimensionRegion : protected DLS::Sampler { |
342 |
public: |
public: |
343 |
uint8_t VelocityUpperLimit; ///< Defines the upper velocity value limit of a velocity split (only if an user defined limit was set, thus a value not equal to 128/NumberOfSplits, else this value is 0). |
uint8_t VelocityUpperLimit; ///< Defines the upper velocity value limit of a velocity split (only if an user defined limit was set, thus a value not equal to 128/NumberOfSplits, else this value is 0). Only for gig2, otherwise the DimensionUpperLimts are used instead. |
344 |
Sample* pSample; ///< Points to the Sample which is assigned to the dimension region. |
Sample* pSample; ///< Points to the Sample which is assigned to the dimension region. |
345 |
// Sample Amplitude EG/LFO |
// Sample Amplitude EG/LFO |
346 |
uint16_t EG1PreAttack; ///< Preattack value of the sample amplitude EG (0 - 1000 permille). |
uint16_t EG1PreAttack; ///< Preattack value of the sample amplitude EG (0 - 1000 permille). |
424 |
bool MSDecode; ///< Gigastudio flag: defines if Mid Side Recordings should be decoded. |
bool MSDecode; ///< Gigastudio flag: defines if Mid Side Recordings should be decoded. |
425 |
uint16_t SampleStartOffset; ///< Number of samples the sample start should be moved (0 - 2000). |
uint16_t SampleStartOffset; ///< Number of samples the sample start should be moved (0 - 2000). |
426 |
double SampleAttenuation; ///< Sample volume (calculated from DLS::Sampler::Gain) |
double SampleAttenuation; ///< Sample volume (calculated from DLS::Sampler::Gain) |
427 |
|
uint8_t DimensionUpperLimits[8]; ///< gig3: defines the upper limit of the dimension values for this dimension region |
428 |
|
|
429 |
// derived attributes from DLS::Sampler |
// derived attributes from DLS::Sampler |
430 |
DLS::Sampler::UnityNote; |
DLS::Sampler::UnityNote; |
499 |
*/ |
*/ |
500 |
class Sample : public DLS::Sample { |
class Sample : public DLS::Sample { |
501 |
public: |
public: |
|
uint16_t SampleGroup; |
|
502 |
uint32_t Manufacturer; ///< Specifies the MIDI Manufacturer's Association (MMA) Manufacturer code for the sampler intended to receive this file's waveform. If no particular manufacturer is to be specified, a value of 0 should be used. |
uint32_t Manufacturer; ///< Specifies the MIDI Manufacturer's Association (MMA) Manufacturer code for the sampler intended to receive this file's waveform. If no particular manufacturer is to be specified, a value of 0 should be used. |
503 |
uint32_t Product; ///< Specifies the MIDI model ID defined by the manufacturer corresponding to the Manufacturer field. If no particular manufacturer's product is to be specified, a value of 0 should be used. |
uint32_t Product; ///< Specifies the MIDI model ID defined by the manufacturer corresponding to the Manufacturer field. If no particular manufacturer's product is to be specified, a value of 0 should be used. |
504 |
uint32_t SamplePeriod; ///< Specifies the duration of time that passes during the playback of one sample in nanoseconds (normally equal to 1 / Samples Per Second, where Samples Per Second is the value found in the format chunk), don't bother to update this attribute, it won't be saved. |
uint32_t SamplePeriod; ///< Specifies the duration of time that passes during the playback of one sample in nanoseconds (normally equal to 1 / Samples Per Second, where Samples Per Second is the value found in the format chunk), don't bother to update this attribute, it won't be saved. |
535 |
unsigned long Read(void* pBuffer, unsigned long SampleCount, buffer_t* pExternalDecompressionBuffer = NULL); |
unsigned long Read(void* pBuffer, unsigned long SampleCount, buffer_t* pExternalDecompressionBuffer = NULL); |
536 |
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); |
537 |
unsigned long Write(void* pBuffer, unsigned long SampleCount); |
unsigned long Write(void* pBuffer, unsigned long SampleCount); |
538 |
|
Group* GetGroup() const; |
539 |
virtual void UpdateChunks(); |
virtual void UpdateChunks(); |
540 |
protected: |
protected: |
541 |
static unsigned int Instances; ///< Number of instances of class Sample. |
static unsigned int Instances; ///< Number of instances of class Sample. |
542 |
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. |
543 |
|
Group* pGroup; ///< pointer to the Group this sample belongs to (always not-NULL) |
544 |
unsigned long FrameOffset; ///< Current offset (sample points) in current sample frame (for decompression only). |
unsigned long FrameOffset; ///< Current offset (sample points) in current sample frame (for decompression only). |
545 |
unsigned long* FrameTable; ///< For positioning within compressed samples only: stores the offset values for each frame. |
unsigned long* FrameTable; ///< For positioning within compressed samples only: stores the offset values for each frame. |
546 |
unsigned long SamplePos; ///< For compressed samples only: stores the current position (in sample points). |
unsigned long SamplePos; ///< For compressed samples only: stores the current position (in sample points). |
580 |
void ScanCompressedSample(); |
void ScanCompressedSample(); |
581 |
friend class File; |
friend class File; |
582 |
friend class Region; |
friend class Region; |
583 |
|
friend class Group; // allow to modify protected member pGroup |
584 |
}; |
}; |
585 |
|
|
586 |
// TODO: <3dnl> list not used yet - not important though (just contains optional descriptions for the dimensions) |
// TODO: <3dnl> list not used yet - not important though (just contains optional descriptions for the dimensions) |
649 |
friend class File; |
friend class File; |
650 |
}; |
}; |
651 |
|
|
652 |
// TODO: <3gnm> chunk not added yet (just contains the names of the sample groups) |
/** @brief Group of Gigasampler objects |
653 |
|
* |
654 |
|
* Groups help to organize a huge collection of Gigasampler objects. |
655 |
|
* Groups are not concerned at all for the synthesis, but they help |
656 |
|
* sound library developers when working on complex instruments with an |
657 |
|
* instrument editor (as long as that instrument editor supports it ;-). |
658 |
|
* |
659 |
|
* At the moment, it seems as only samples can be grouped together in |
660 |
|
* the Gigasampler format yet. If this is false in the meantime, please |
661 |
|
* tell us ! |
662 |
|
* |
663 |
|
* A sample is always assigned to exactly one Group. This also means |
664 |
|
* there is always at least one Group in a .gig file, no matter if you |
665 |
|
* created one yet or not. |
666 |
|
*/ |
667 |
|
class Group { |
668 |
|
public: |
669 |
|
String Name; ///< Stores the name of this Group. |
670 |
|
|
671 |
|
Sample* GetFirstSample(); |
672 |
|
Sample* GetNextSample(); |
673 |
|
void AddSample(Sample* pSample); |
674 |
|
protected: |
675 |
|
Group(File* file, RIFF::Chunk* ck3gnm); |
676 |
|
virtual ~Group(); |
677 |
|
virtual void UpdateChunks(); |
678 |
|
void MoveAll(); |
679 |
|
friend class File; |
680 |
|
private: |
681 |
|
File* pFile; |
682 |
|
RIFF::Chunk* pNameChunk; |
683 |
|
}; |
684 |
|
|
685 |
/** Parses Gigasampler files and provides abstract access to the data. */ |
/** Parses Gigasampler files and provides abstract access to the data. */ |
686 |
class File : protected DLS::File { |
class File : protected DLS::File { |
687 |
public: |
public: |
701 |
File(RIFF::File* pRIFF); |
File(RIFF::File* pRIFF); |
702 |
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. |
703 |
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. |
|
Instrument* GetFirstInstrument(); ///< Returns a pointer to the first <i>Instrument</i> object of the file, <i>NULL</i> otherwise. |
|
704 |
Sample* AddSample(); |
Sample* AddSample(); |
705 |
void DeleteSample(Sample* pSample); |
void DeleteSample(Sample* pSample); |
706 |
|
Instrument* GetFirstInstrument(); ///< Returns a pointer to the first <i>Instrument</i> object of the file, <i>NULL</i> otherwise. |
707 |
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. |
708 |
Instrument* GetInstrument(uint index, progress_t* pProgress = NULL); |
Instrument* GetInstrument(uint index, progress_t* pProgress = NULL); |
709 |
Instrument* AddInstrument(); |
Instrument* AddInstrument(); |
710 |
void DeleteInstrument(Instrument* pInstrument); |
void DeleteInstrument(Instrument* pInstrument); |
711 |
|
Group* GetFirstGroup(); ///< Returns a pointer to the first <i>Group</i> object of the file, <i>NULL</i> otherwise. |
712 |
|
Group* GetNextGroup(); ///< Returns a pointer to the next <i>Group</i> object of the file, <i>NULL</i> otherwise. |
713 |
|
Group* GetGroup(uint index); |
714 |
|
Group* AddGroup(); |
715 |
|
void DeleteGroup(Group* pGroup); |
716 |
|
virtual ~File(); |
717 |
protected: |
protected: |
718 |
// overridden protected methods from DLS::File |
// overridden protected methods from DLS::File |
719 |
virtual void LoadSamples(); |
virtual void LoadSamples(); |
720 |
virtual void LoadInstruments(); |
virtual void LoadInstruments(); |
721 |
|
virtual void LoadGroups(); |
722 |
// own protected methods |
// own protected methods |
723 |
virtual void LoadSamples(progress_t* pProgress); |
virtual void LoadSamples(progress_t* pProgress); |
724 |
virtual void LoadInstruments(progress_t* pProgress); |
virtual void LoadInstruments(progress_t* pProgress); |
725 |
friend class Region; |
friend class Region; |
726 |
|
friend class Sample; |
727 |
|
friend class Group; // so Group can access protected member pRIFF |
728 |
|
private: |
729 |
|
std::list<Group*>* pGroups; |
730 |
|
std::list<Group*>::iterator GroupsIterator; |
731 |
}; |
}; |
732 |
|
|
733 |
/** Will be thrown whenever a gig specific error occurs while trying to access a Gigasampler File. */ |
/** Will be thrown whenever a gig specific error occurs while trying to access a Gigasampler File. */ |