--- libgig/trunk/src/gig.h 2016/05/18 18:04:49 2922 +++ libgig/trunk/src/gig.h 2019/12/14 17:10:57 3657 @@ -2,7 +2,7 @@ * * * libgig - C++ cross-platform Gigasampler format file access library * * * - * Copyright (C) 2003-2016 by Christian Schoenebeck * + * Copyright (C) 2003-2019 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 @@ -34,6 +50,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 @@ -45,6 +62,8 @@ # 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_LSDE 0x4c534445 // own gig format extension +# define CHUNK_ID_3DDP 0x33646470 #else // little endian # define LIST_TYPE_3PRG 0x67727033 # define LIST_TYPE_3EWL 0x6C776533 @@ -52,6 +71,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 @@ -63,8 +83,17 @@ # 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_LSDE 0x4544534c // own gig format extension +# define CHUNK_ID_3DDP 0x70646433 #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 { @@ -90,88 +119,132 @@ } }; - /** Standard types of sample loops. */ - typedef enum { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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) - vcf_cutoff_ctrl_effect1 = 0x8c, ///< Effect Controller 1 (Coarse, MIDI Controller 12) - vcf_cutoff_ctrl_effect2 = 0x8d, ///< Effect Controller 2 (Coarse, MIDI Controller 13) - vcf_cutoff_ctrl_breath = 0x82, ///< Breath Controller (Coarse, MIDI Controller 2) - vcf_cutoff_ctrl_foot = 0x84, ///< Foot Pedal (Coarse, MIDI Controller 4) - vcf_cutoff_ctrl_sustainpedal = 0xc0, ///< Sustain Pedal (MIDI Controller 64) - vcf_cutoff_ctrl_softpedal = 0xc3, ///< Soft Pedal (MIDI Controller 67) - 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 { - 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; + /** 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) */ + ); + + /** 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 */ + ); + + /** Defines the shape of a function graph. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + GIG_DECLARE_ENUM(curve_type_t, + curve_type_nonlinear = 0, /**< Non-linear curve type. */ + curve_type_linear = 1, /**< Linear curve type. */ + curve_type_special = 2, /**< Special curve type. */ + 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() + */ + GIG_DECLARE_ENUM(dim_bypass_ctrl_t, + dim_bypass_ctrl_none, /**< No controller bypass. */ + dim_bypass_ctrl_94, /**< Effect 4 Depth (MIDI Controller 94) */ + dim_bypass_ctrl_95 /**< Effect 5 Depth (MIDI Controller 95) */ + ); + + /** 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. */ + ); + + /** 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. */ + ); + + /** 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. */ + ); + + /** 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, /**< No MIDI controller assigned for filter cutoff frequency. */ + vcf_cutoff_ctrl_none2 = 0x01, /**< The difference between none and none2 is unknown */ + vcf_cutoff_ctrl_modwheel = 0x81, /**< Modulation Wheel (MIDI Controller 1) */ + vcf_cutoff_ctrl_effect1 = 0x8c, /**< Effect Controller 1 (Coarse, MIDI Controller 12) */ + vcf_cutoff_ctrl_effect2 = 0x8d, /**< Effect Controller 2 (Coarse, MIDI Controller 13) */ + vcf_cutoff_ctrl_breath = 0x82, /**< Breath Controller (Coarse, MIDI Controller 2) */ + vcf_cutoff_ctrl_foot = 0x84, /**< Foot Pedal (Coarse, MIDI Controller 4) */ + vcf_cutoff_ctrl_sustainpedal = 0xc0, /**< Sustain Pedal (MIDI Controller 64) */ + vcf_cutoff_ctrl_softpedal = 0xc3, /**< Soft Pedal (MIDI Controller 67) */ + 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 */ + ); + + /** 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, /**< No MIDI controller assigned for filter resonance. */ + 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) */ + ); /** * Defines a controller that has a certain contrained influence on a @@ -182,15 +255,21 @@ * attenuation_ctrl_t, eg1_ctrl_t or eg2_ctrl_t) in your code! */ struct leverage_ctrl_t { - typedef enum { - 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; + /** 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; ///< Controller type uint controller_number; ///< MIDI controller number if this controller is a control change controller, 0 otherwise + + void serialize(Serialization::Archive* archive); }; /** @@ -220,52 +299,56 @@ * 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 { - 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). - dimension_velocity = 0x82, ///< Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined). - dimension_channelaftertouch = 0x83, ///< Channel Key Pressure - dimension_releasetrigger = 0x84, ///< Special dimension for triggering samples on releasing a key. - dimension_keyboard = 0x85, ///< Dimension for keyswitching - dimension_roundrobin = 0x86, ///< Different samples triggered each time a note is played, dimension regions selected in sequence - dimension_random = 0x87, ///< Different samples triggered each time a note is played, random order - dimension_smartmidi = 0x88, ///< For MIDI tools like legato and repetition mode - dimension_roundrobinkeyboard = 0x89, ///< Different samples triggered each time a note is played, any key advances the counter - dimension_modwheel = 0x01, ///< Modulation Wheel (MIDI Controller 1) - dimension_breath = 0x02, ///< Breath Controller (Coarse, MIDI Controller 2) - dimension_foot = 0x04, ///< Foot Pedal (Coarse, MIDI Controller 4) - dimension_portamentotime = 0x05, ///< Portamento Time (Coarse, MIDI Controller 5) - dimension_effect1 = 0x0c, ///< Effect Controller 1 (Coarse, MIDI Controller 12) - dimension_effect2 = 0x0d, ///< Effect Controller 2 (Coarse, MIDI Controller 13) - dimension_genpurpose1 = 0x10, ///< General Purpose Controller 1 (Slider, MIDI Controller 16) - dimension_genpurpose2 = 0x11, ///< General Purpose Controller 2 (Slider, MIDI Controller 17) - dimension_genpurpose3 = 0x12, ///< General Purpose Controller 3 (Slider, MIDI Controller 18) - dimension_genpurpose4 = 0x13, ///< General Purpose Controller 4 (Slider, MIDI Controller 19) - dimension_sustainpedal = 0x40, ///< Sustain Pedal (MIDI Controller 64) - dimension_portamento = 0x41, ///< Portamento (MIDI Controller 65) - dimension_sostenutopedal = 0x42, ///< Sostenuto Pedal (MIDI Controller 66) - dimension_softpedal = 0x43, ///< Soft Pedal (MIDI Controller 67) - dimension_genpurpose5 = 0x30, ///< General Purpose Controller 5 (Button, MIDI Controller 80) - dimension_genpurpose6 = 0x31, ///< General Purpose Controller 6 (Button, MIDI Controller 81) - dimension_genpurpose7 = 0x32, ///< General Purpose Controller 7 (Button, MIDI Controller 82) - dimension_genpurpose8 = 0x33, ///< General Purpose Controller 8 (Button, MIDI Controller 83) - dimension_effect1depth = 0x5b, ///< Effect 1 Depth (MIDI Controller 91) - dimension_effect2depth = 0x5c, ///< Effect 2 Depth (MIDI Controller 92) - 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; + 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). */ + dimension_velocity = 0x82, /**< Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined). */ + dimension_channelaftertouch = 0x83, /**< Channel Key Pressure */ + dimension_releasetrigger = 0x84, /**< Special dimension for triggering samples on releasing a key. */ + dimension_keyboard = 0x85, /**< Dimension for keyswitching */ + dimension_roundrobin = 0x86, /**< Different samples triggered each time a note is played, dimension regions selected in sequence */ + dimension_random = 0x87, /**< Different samples triggered each time a note is played, random order */ + dimension_smartmidi = 0x88, /**< For MIDI tools like legato and repetition mode */ + dimension_roundrobinkeyboard = 0x89, /**< Different samples triggered each time a note is played, any key advances the counter */ + dimension_modwheel = 0x01, /**< Modulation Wheel (MIDI Controller 1) */ + dimension_breath = 0x02, /**< Breath Controller (Coarse, MIDI Controller 2) */ + dimension_foot = 0x04, /**< Foot Pedal (Coarse, MIDI Controller 4) */ + dimension_portamentotime = 0x05, /**< Portamento Time (Coarse, MIDI Controller 5) */ + dimension_effect1 = 0x0c, /**< Effect Controller 1 (Coarse, MIDI Controller 12) */ + dimension_effect2 = 0x0d, /**< Effect Controller 2 (Coarse, MIDI Controller 13) */ + dimension_genpurpose1 = 0x10, /**< General Purpose Controller 1 (Slider, MIDI Controller 16) */ + dimension_genpurpose2 = 0x11, /**< General Purpose Controller 2 (Slider, MIDI Controller 17) */ + dimension_genpurpose3 = 0x12, /**< General Purpose Controller 3 (Slider, MIDI Controller 18) */ + dimension_genpurpose4 = 0x13, /**< General Purpose Controller 4 (Slider, MIDI Controller 19) */ + dimension_sustainpedal = 0x40, /**< Sustain Pedal (MIDI Controller 64) */ + dimension_portamento = 0x41, /**< Portamento (MIDI Controller 65) */ + dimension_sostenutopedal = 0x42, /**< Sostenuto Pedal (MIDI Controller 66) */ + dimension_softpedal = 0x43, /**< Soft Pedal (MIDI Controller 67) */ + dimension_genpurpose5 = 0x30, /**< General Purpose Controller 5 (Button, MIDI Controller 80) */ + dimension_genpurpose6 = 0x31, /**< General Purpose Controller 6 (Button, MIDI Controller 81) */ + dimension_genpurpose7 = 0x32, /**< General Purpose Controller 7 (Button, MIDI Controller 82) */ + dimension_genpurpose8 = 0x33, /**< General Purpose Controller 8 (Button, MIDI Controller 83) */ + dimension_effect1depth = 0x5b, /**< Effect 1 Depth (MIDI Controller 91) */ + dimension_effect2depth = 0x5c, /**< Effect 2 Depth (MIDI Controller 92) */ + 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) */ + ); /** * 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 { - split_type_normal, ///< dimension value between 0-127 - split_type_bit ///< dimension values are already the sought bit number - } split_type_t; + 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 */ + ); /** General dimension definition. */ struct dimension_def_t { @@ -276,14 +359,38 @@ 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 { - 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; + /** 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 (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). */ + ); /** * Defines the envelope of a crossfade. @@ -304,6 +411,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. */ @@ -313,6 +422,62 @@ file_offset_t loop_cycles_left; ///< How many times the loop has still to be passed, this value will be decremented with each loop cycle. }; + /** + * Defines behavior options for envelope generators (gig format extension). + * + * These options allow to override the precise default behavior of the + * envelope generators' state machines. + * + * @b Note: These EG options are an extension to the original gig file + * format, so these options are not available with the original + * Gigasampler/GigaStudio software! Currently only LinuxSampler and gigedit + * support these EG options! + * + * Adding these options to the original gig file format was necessary, + * because the precise state machine behavior of envelope generators of the + * gig format (and thus the default EG behavior if not explicitly overridden + * here) deviates from common, expected behavior of envelope generators in + * general, if i.e. compared with EGs of hardware synthesizers. For example + * with the gig format, the attack and decay stages will be aborted as soon + * as a note-off is received. Most other EG implementations in the industry + * however always run the attack and decay stages to their full duration, + * even if an early note-off arrives. The latter behavior is intentionally + * implemented in most other products, because it is required to resemble + * percussive sounds in a realistic manner. + */ + struct eg_opt_t { + bool AttackCancel; ///< Whether the "attack" stage is cancelled when receiving a note-off (default: @c true). + bool AttackHoldCancel; ///< Whether the "attack hold" stage is cancelled when receiving a note-off (default: @c true). + bool Decay1Cancel; ///< Whether the "decay 1" stage is cancelled when receiving a note-off (default: @c true). + bool Decay2Cancel; ///< Whether the "decay 2" stage is cancelled when receiving a note-off (default: @c true). + bool ReleaseCancel; ///< Whether the "release" stage is cancelled when receiving a note-on (default: @c true). + + eg_opt_t(); + void serialize(Serialization::Archive* archive); + }; + + /** @brief Defines behaviour of release triggered sample(s) on sustain pedal up event. + * + * This option defines whether a sustain pedal up event (CC#64) would cause + * release triggered samples to be played (if any). + * + * @b Note: This option is an extension to the original gig file format, + * so this option is not available with the original Gigasampler/GigaStudio + * software! Currently only LinuxSampler and gigedit support this option! + * + * By default (which equals the original Gigasampler/GigaStudio behaviour) + * no release triggered samples are played if the sustain pedal is released. + * So usually in the gig format release triggered samples are only played + * on MIDI note-off events. + * + * @see enumCount(), enumKey(), enumKeys(), enumValue() + */ + 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. */ + ); + // just symbol prototyping class File; class Instrument; @@ -382,11 +547,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). @@ -401,19 +568,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. @@ -451,6 +623,10 @@ uint16_t SampleStartOffset; ///< Number of samples the sample start should be moved (0 - 2000). double SampleAttenuation; ///< Sample volume (calculated from DLS::Sampler::Gain) uint8_t DimensionUpperLimits[8]; ///< gig3: defines the upper limit of the dimension values for this dimension region. In case you wondered why this is defined on DimensionRegion level and not on Region level: the zone sizes (upper limits) of the velocity dimension can indeed differ in the individual dimension regions, depending on which zones of the other dimension types are currently selected. So this is exceptional for the velocity dimension only. All other dimension types have the same dimension zone sizes for every single DimensionRegion (of the sample Region). + 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; @@ -477,8 +653,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. @@ -486,7 +662,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: @@ -602,6 +780,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. @@ -668,9 +847,11 @@ 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. @@ -685,10 +866,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) { @@ -759,8 +941,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); @@ -853,7 +1035,7 @@ protected: MidiRuleCtrlTrigger(RIFF::Chunk* _3ewg); MidiRuleCtrlTrigger(); - void UpdateChunks(uint8_t* pData) const; + void UpdateChunks(uint8_t* pData) const OVERRIDE; friend class Instrument; }; @@ -893,7 +1075,7 @@ protected: MidiRuleLegato(RIFF::Chunk* _3ewg); MidiRuleLegato(); - void UpdateChunks(uint8_t* pData) const; + void UpdateChunks(uint8_t* pData) const OVERRIDE; friend class Instrument; }; @@ -945,7 +1127,7 @@ protected: MidiRuleAlternator(RIFF::Chunk* _3ewg); MidiRuleAlternator(); - void UpdateChunks(uint8_t* pData) const; + void UpdateChunks(uint8_t* pData) const OVERRIDE; friend class Instrument; }; @@ -965,7 +1147,7 @@ class MidiRuleUnknown : public MidiRule { protected: MidiRuleUnknown() { } - void UpdateChunks(uint8_t* pData) const { } + void UpdateChunks(uint8_t* pData) const OVERRIDE { } friend class Instrument; }; @@ -989,7 +1171,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). @@ -1011,10 +1193,12 @@ 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(); - void UpdateChunks(progress_t* pProgress); + void UpdateChunks(progress_t* pProgress) OVERRIDE; + void DeleteChunks() OVERRIDE; void RemoveAllScriptReferences(); friend class ScriptGroup; friend class Instrument; @@ -1036,7 +1220,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. @@ -1047,7 +1231,8 @@ 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: @@ -1100,7 +1285,7 @@ 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); @@ -1154,7 +1339,7 @@ * 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. @@ -1164,7 +1349,8 @@ 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: @@ -1212,6 +1398,7 @@ public: static const DLS::version_t VERSION_2; static const DLS::version_t VERSION_3; + static const DLS::version_t VERSION_4; // derived attributes from DLS::Resource using DLS::Resource::pInfo; @@ -1226,6 +1413,7 @@ using DLS::File::Save; using DLS::File::GetFileName; using DLS::File::SetFileName; + using DLS::File::GetRiffFile; // overridden methods File(); File(RIFF::File* pRIFF); @@ -1233,12 +1421,14 @@ Sample* GetNextSample(); ///< Returns a pointer to the next Sample object of the file, NULL otherwise. Sample* GetSample(uint index); 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* 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. @@ -1255,18 +1445,23 @@ 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); virtual void LoadScriptGroups(); void SetSampleChecksum(Sample* pSample, uint32_t crc); + 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; @@ -1289,10 +1484,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();