--- libgig/trunk/src/gig.h 2006/10/24 22:24:45 929 +++ libgig/trunk/src/gig.h 2007/03/18 07:13:06 1102 @@ -1,8 +1,8 @@ /*************************************************************************** * * - * libgig - C++ cross-platform Gigasampler format file loader library * + * libgig - C++ cross-platform Gigasampler format file access library * * * - * Copyright (C) 2003-2006 by Christian Schoenebeck * + * Copyright (C) 2003-2007 by Christian Schoenebeck * * * * * * This library is free software; you can redistribute it and/or modify * @@ -210,12 +210,14 @@ 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 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). 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) @@ -324,7 +326,7 @@ class Region; class Group; - /** Encapsulates articulation information of a dimension region. + /** @brief Encapsulates articulation information of a dimension region. * * Every Gigasampler Instrument has at least one dimension region * (exactly then when it has no dimension defined). @@ -338,7 +340,7 @@ */ class DimensionRegion : protected DLS::Sampler { public: - 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. Sample* pSample; ///< Points to the Sample which is assigned to the dimension region. // Sample Amplitude EG/LFO uint16_t EG1PreAttack; ///< Preattack value of the sample amplitude EG (0 - 1000 permille). @@ -422,6 +424,7 @@ bool MSDecode; ///< Gigastudio flag: defines if Mid Side Recordings should be decoded. 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 // derived attributes from DLS::Sampler DLS::Sampler::UnityNote; @@ -496,7 +499,6 @@ */ class Sample : public DLS::Sample { public: - Group* pGroup; ///< pointer to the Group this sample belongs to, NULL otherwise 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 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 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. @@ -533,10 +535,12 @@ unsigned long Read(void* pBuffer, unsigned long SampleCount, buffer_t* pExternalDecompressionBuffer = NULL); unsigned long ReadAndLoop(void* pBuffer, unsigned long SampleCount, playback_state_t* pPlaybackState, DimensionRegion* pDimRgn, buffer_t* pExternalDecompressionBuffer = NULL); unsigned long Write(void* pBuffer, unsigned long SampleCount); + Group* GetGroup() const; virtual void UpdateChunks(); protected: static unsigned int 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) unsigned long FrameOffset; ///< Current offset (sample points) in current sample frame (for decompression only). unsigned long* FrameTable; ///< For positioning within compressed samples only: stores the offset values for each frame. unsigned long SamplePos; ///< For compressed samples only: stores the current position (in sample points). @@ -576,6 +580,7 @@ void ScanCompressedSample(); friend class File; friend class Region; + friend class Group; // allow to modify protected member pGroup }; // TODO: <3dnl> list not used yet - not important though (just contains optional descriptions for the dimensions) @@ -627,6 +632,8 @@ // derived methods from DLS::Resource DLS::Resource::GetParent; + // derived methods from DLS::Instrument + DLS::Instrument::MoveRegion; // overridden methods Region* GetFirstRegion(); Region* GetNextRegion(); @@ -654,17 +661,26 @@ * At the moment, it seems as only samples can be grouped together in * the Gigasampler format yet. If this is false in the meantime, please * tell us ! + * + * A sample is always assigned to exactly one Group. This also means + * there is always at least one Group in a .gig file, no matter if you + * created one yet or not. */ class Group { public: String Name; ///< Stores the name of this Group. + + Sample* GetFirstSample(); + Sample* GetNextSample(); + void AddSample(Sample* pSample); protected: - Group(RIFF::File* file, RIFF::Chunk* ck3gnm); + Group(File* file, RIFF::Chunk* ck3gnm); virtual ~Group(); virtual void UpdateChunks(); + void MoveAll(); friend class File; private: - RIFF::File* pFile; + File* pFile; RIFF::Chunk* pNameChunk; }; @@ -699,7 +715,9 @@ Group* GetGroup(uint index); Group* AddGroup(); void DeleteGroup(Group* pGroup); + void DeleteGroupOnly(Group* pGroup); virtual ~File(); + virtual void UpdateChunks(); protected: // overridden protected methods from DLS::File virtual void LoadSamples(); @@ -710,12 +728,20 @@ virtual void LoadInstruments(progress_t* pProgress); friend class Region; friend class Sample; + friend class Group; // so Group can access protected member pRIFF private: std::list* pGroups; std::list::iterator GroupsIterator; }; - /** 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. Note: In your application you should + * better catch for RIFF::Exception rather than this one, except you + * explicitly want to catch and handle gig::Exception, DLS::Exception + * and RIFF::Exception independently, which usually shouldn't be + * necessary though. + */ class Exception : public DLS::Exception { public: Exception(String Message);