--- libgig/trunk/src/gig.h 2016/05/17 14:30:10 2912 +++ libgig/trunk/src/gig.h 2017/05/21 12:46:05 3198 @@ -2,7 +2,7 @@ * * * libgig - C++ cross-platform Gigasampler format file access library * * * - * Copyright (C) 2003-2016 by Christian Schoenebeck * + * Copyright (C) 2003-2017 by Christian Schoenebeck * * * * * * This library is free software; you can redistribute it and/or modify * @@ -27,6 +27,22 @@ #include "DLS.h" #include +#ifndef __has_feature +# define __has_feature(x) 0 +#endif +#ifndef HAVE_RTTI +# if __GXX_RTTI || __has_feature(cxx_rtti) || _CPPRTTI +# define HAVE_RTTI 1 +# else +# define HAVE_RTTI 0 +# endif +#endif +#if HAVE_RTTI +# include +#else +# warning No RTTI available! +#endif + #if WORDS_BIGENDIAN # define LIST_TYPE_3PRG 0x33707267 # define LIST_TYPE_3EWL 0x3365776C @@ -45,7 +61,6 @@ # 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_FFMT 0x46466D74 // own gig format extension #else // little endian # define LIST_TYPE_3PRG 0x67727033 # define LIST_TYPE_3EWL 0x6C776533 @@ -64,9 +79,15 @@ # 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_FFMT 0x746D4646 // own gig format extension #endif // WORDS_BIGENDIAN +#ifndef GIG_DECLARE_ENUM +# define GIG_DECLARE_ENUM(type, ...) enum type { __VA_ARGS__ } +#endif + +// just symbol prototyping (since Serialization.h not included by default here) +namespace Serialization { class Archive; } + /** Gigasampler/GigaStudio specific classes and definitions */ namespace gig { @@ -92,66 +113,90 @@ } }; - /** Standard types of sample loops. */ - typedef enum { + /** Standard types of sample loops. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(loop_type_t, loop_type_normal = 0x00000000, ///< Loop forward (normal) loop_type_bidirectional = 0x00000001, ///< Alternating loop (forward/backward, also known as Ping Pong) loop_type_backward = 0x00000002 ///< Loop backward (reverse) - } loop_type_t; + ); - /** Society of Motion Pictures and Television E time format. */ - typedef enum { + /** Society of Motion Pictures and Television E time format. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(smpte_format_t, smpte_format_no_offset = 0x00000000, ///< no SMPTE offset smpte_format_24_frames = 0x00000018, ///< 24 frames per second smpte_format_25_frames = 0x00000019, ///< 25 frames per second smpte_format_30_frames_dropping = 0x0000001D, ///< 30 frames per second with frame dropping (30 drop) smpte_format_30_frames = 0x0000001E ///< 30 frames per second - } smpte_format_t; + ); - /** Defines the shape of a function graph. */ - typedef enum { + /** Defines the shape of a function graph. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(curve_type_t, curve_type_nonlinear = 0, curve_type_linear = 1, curve_type_special = 2, curve_type_unknown = 0xffffffff - } curve_type_t; + ); - /** Dimensions allow to bypass one of the following controllers. */ - typedef enum { + /** Dimensions allow to bypass one of the following controllers. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(dim_bypass_ctrl_t, dim_bypass_ctrl_none, dim_bypass_ctrl_94, ///< Effect 4 Depth (MIDI Controller 94) dim_bypass_ctrl_95 ///< Effect 5 Depth (MIDI Controller 95) - } dim_bypass_ctrl_t; + ); - /** Defines how LFO3 is controlled by. */ - typedef enum { + /** Defines how LFO3 is controlled by. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(lfo3_ctrl_t, lfo3_ctrl_internal = 0x00, ///< Only internally controlled. lfo3_ctrl_modwheel = 0x01, ///< Only controlled by external modulation wheel. lfo3_ctrl_aftertouch = 0x02, ///< Only controlled by aftertouch controller. lfo3_ctrl_internal_modwheel = 0x03, ///< Controlled internally and by external modulation wheel. lfo3_ctrl_internal_aftertouch = 0x04 ///< Controlled internally and by aftertouch controller. - } lfo3_ctrl_t; + ); - /** Defines how LFO2 is controlled by. */ - typedef enum { + /** Defines how LFO2 is controlled by. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(lfo2_ctrl_t, lfo2_ctrl_internal = 0x00, ///< Only internally controlled. lfo2_ctrl_modwheel = 0x01, ///< Only controlled by external modulation wheel. lfo2_ctrl_foot = 0x02, ///< Only controlled by external foot controller. lfo2_ctrl_internal_modwheel = 0x03, ///< Controlled internally and by external modulation wheel. lfo2_ctrl_internal_foot = 0x04 ///< Controlled internally and by external foot controller. - } lfo2_ctrl_t; + ); - /** Defines how LFO1 is controlled by. */ - typedef enum { + /** Defines how LFO1 is controlled by. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(lfo1_ctrl_t, lfo1_ctrl_internal = 0x00, ///< Only internally controlled. lfo1_ctrl_modwheel = 0x01, ///< Only controlled by external modulation wheel. lfo1_ctrl_breath = 0x02, ///< Only controlled by external breath controller. lfo1_ctrl_internal_modwheel = 0x03, ///< Controlled internally and by external modulation wheel. lfo1_ctrl_internal_breath = 0x04 ///< Controlled internally and by external breath controller. - } lfo1_ctrl_t; + ); - /** Defines how the filter cutoff frequency is controlled by. */ - typedef enum { + /** Defines how the filter cutoff frequency is controlled by. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(vcf_cutoff_ctrl_t, vcf_cutoff_ctrl_none = 0x00, vcf_cutoff_ctrl_none2 = 0x01, ///< The difference between none and none2 is unknown vcf_cutoff_ctrl_modwheel = 0x81, ///< Modulation Wheel (MIDI Controller 1) @@ -164,16 +209,19 @@ vcf_cutoff_ctrl_genpurpose7 = 0xd2, ///< General Purpose Controller 7 (Button, MIDI Controller 82) vcf_cutoff_ctrl_genpurpose8 = 0xd3, ///< General Purpose Controller 8 (Button, MIDI Controller 83) vcf_cutoff_ctrl_aftertouch = 0x80 ///< Key Pressure - } vcf_cutoff_ctrl_t; + ); - /** Defines how the filter resonance is controlled by. */ - typedef enum { + /** Defines how the filter resonance is controlled by. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(vcf_res_ctrl_t, vcf_res_ctrl_none = 0xffffffff, vcf_res_ctrl_genpurpose3 = 0, ///< General Purpose Controller 3 (Slider, MIDI Controller 18) vcf_res_ctrl_genpurpose4 = 1, ///< General Purpose Controller 4 (Slider, MIDI Controller 19) vcf_res_ctrl_genpurpose5 = 2, ///< General Purpose Controller 5 (Button, MIDI Controller 80) vcf_res_ctrl_genpurpose6 = 3 ///< General Purpose Controller 6 (Button, MIDI Controller 81) - } vcf_res_ctrl_t; + ); /** * Defines a controller that has a certain contrained influence on a @@ -184,15 +232,21 @@ * attenuation_ctrl_t, eg1_ctrl_t or eg2_ctrl_t) in your code! */ struct leverage_ctrl_t { - typedef enum { + /** Defines possible controllers. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(type_t, type_none = 0x00, ///< No controller defined type_channelaftertouch = 0x2f, ///< Channel Key Pressure type_velocity = 0xff, ///< Key Velocity type_controlchange = 0xfe ///< Ordinary MIDI control change controller, see field 'controller_number' - } type_t; + ); type_t type; ///< Controller type uint controller_number; ///< MIDI controller number if this controller is a control change controller, 0 otherwise + + void serialize(Serialization::Archive* archive); }; /** @@ -222,8 +276,10 @@ * dimension zones is always a power of two. All dimensions can have up * to 32 zones (except the layer dimension with only up to 8 zones and * the samplechannel dimension which currently allows only 2 zones). + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() */ - typedef enum { + GIG_DECLARE_ENUM(dimension_t, dimension_none = 0x00, ///< Dimension not in use. dimension_samplechannel = 0x80, ///< If used sample has more than one channel (thus is not mono). dimension_layer = 0x81, ///< For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers). @@ -258,16 +314,18 @@ dimension_effect3depth = 0x5d, ///< Effect 3 Depth (MIDI Controller 93) dimension_effect4depth = 0x5e, ///< Effect 4 Depth (MIDI Controller 94) dimension_effect5depth = 0x5f ///< Effect 5 Depth (MIDI Controller 95) - } dimension_t; + ); /** * Intended for internal usage: will be used to convert a dimension value * into the corresponding dimension bit number. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() */ - typedef enum { + GIG_DECLARE_ENUM(split_type_t, split_type_normal, ///< dimension value between 0-127 split_type_bit ///< dimension values are already the sought bit number - } split_type_t; + ); /** General dimension definition. */ struct dimension_def_t { @@ -278,14 +336,17 @@ 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. */ - typedef enum { + /** Defines which frequencies are filtered by the VCF. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(vcf_type_t, vcf_type_lowpass = 0x00, vcf_type_lowpassturbo = 0xff, ///< More poles than normal lowpass vcf_type_bandpass = 0x01, vcf_type_highpass = 0x02, vcf_type_bandreject = 0x03 - } vcf_type_t; + ); /** * Defines the envelope of a crossfade. @@ -306,6 +367,8 @@ uint8_t out_start; ///< Start position of fade out. uint8_t out_end; ///< End postition of fade out. #endif // WORDS_BIGENDIAN + + void serialize(Serialization::Archive* archive); }; /** Reflects the current playback state for a sample. */ @@ -488,7 +551,9 @@ DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src); ~DimensionRegion(); void CopyAssign(const DimensionRegion* orig, const std::map* mSamples); + void serialize(Serialization::Archive* archive); friend class Region; + friend class Serialization::Archive; private: typedef enum { ///< Used to decode attenuation, EG1 and EG2 controller // official leverage controllers as they were defined in the original Gigasampler/GigaStudio format: @@ -591,7 +656,7 @@ } _lev_ctrl_t; typedef std::map VelocityTableMap; - static uint Instances; ///< Number of DimensionRegion instances. + static size_t Instances; ///< Number of DimensionRegion instances. static VelocityTableMap* pVelocityTables; ///< Contains the tables corresponding to the various velocity parameters (VelocityResponseCurve and VelocityResponseDepth). double* pVelocityAttenuationTable; ///< Points to the velocity table corresponding to the velocity parameters of this DimensionRegion. double* pVelocityReleaseTable; ///< Points to the velocity table corresponding to the release velocity parameters of this DimensionRegion @@ -663,7 +728,7 @@ static void DestroyDecompressionBuffer(buffer_t& DecompressionBuffer); // overridden methods void ReleaseSampleData(); - void Resize(int iNewSize); + void Resize(file_offset_t NewSize); file_offset_t SetPos(file_offset_t SampleCount, RIFF::stream_whence_t Whence = RIFF::stream_start); file_offset_t GetPos() const; file_offset_t Read(void* pBuffer, file_offset_t SampleCount, buffer_t* pExternalDecompressionBuffer = NULL); @@ -673,8 +738,10 @@ virtual void UpdateChunks(progress_t* pProgress); void CopyAssignMeta(const Sample* orig); void CopyAssignWave(const Sample* orig); + uint32_t GetWaveDataCRC32Checksum(); + bool VerifyWaveData(uint32_t* pActually = NULL); protected: - static unsigned int Instances; ///< Number of instances of class Sample. + 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. 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). @@ -687,10 +754,11 @@ unsigned long FileNo; ///< File number (> 0 when sample is stored in an extension file, 0 when it's in the gig) RIFF::Chunk* pCk3gix; RIFF::Chunk* pCkSmpl; - uint32_t crc; ///< CRC-32 checksum of the raw sample data + uint32_t crc; ///< Reflects CRC-32 checksum of the raw sample data at the last time when the sample's raw wave form data has been modified consciously by the user by calling Write(). - Sample(File* pFile, RIFF::List* waveList, file_offset_t WavePoolOffset, unsigned long fileNo = 0); + Sample(File* pFile, RIFF::List* waveList, file_offset_t WavePoolOffset, unsigned long fileNo = 0, int index = -1); ~Sample(); + uint32_t CalculateWaveDataChecksum(); // Guess size (in bytes) of a compressed sample inline file_offset_t GuessSize(file_offset_t samples) { @@ -1013,6 +1081,7 @@ void SetScriptAsText(const String& text); void SetGroup(ScriptGroup* pGroup); ScriptGroup* GetGroup() const; + void CopyAssign(const Script* orig); protected: Script(ScriptGroup* group, RIFF::Chunk* ckScri); virtual ~Script(); @@ -1269,8 +1338,11 @@ virtual void LoadInstruments(progress_t* pProgress); virtual void LoadScriptGroups(); void SetSampleChecksum(Sample* pSample, uint32_t crc); - uint GetFormatExtensionVersion() const; - bool HasMonolithicLargeFilePolicy() const; + uint32_t GetSampleChecksum(Sample* pSample); + uint32_t GetSampleChecksumByIndex(int index); + bool VerifySampleChecksumTable(); + bool RebuildSampleChecksumTable(); + int GetWaveTableIndexOf(gig::Sample* pSample); friend class Region; friend class Sample; friend class Instrument; @@ -1293,10 +1365,25 @@ */ class Exception : public DLS::Exception { public: - Exception(String Message); + Exception(String format, ...); + Exception(String format, va_list arg); void PrintMessage(); + protected: + Exception(); }; +#if HAVE_RTTI + size_t enumCount(const std::type_info& type); + const char* enumKey(const std::type_info& type, size_t value); + bool enumKey(const std::type_info& type, String key); + const char** enumKeys(const std::type_info& type); +#endif // HAVE_RTTI + size_t enumCount(String typeName); + const char* enumKey(String typeName, size_t value); + bool enumKey(String typeName, String key); + const char** enumKeys(String typeName); + size_t enumValue(String key); + String libraryName(); String libraryVersion();