    /*
     *
     * Copyright (C) 2003  Peter Hanappe and others.
     *
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Library General Public License
     * as published by the Free Software Foundation; either version 2 of
     * the License, or (at your option) any later version.
     *
     * This library is distributed in the hope that it will be useful, but
     * WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Library General Public License for more details.
     *
     * You should have received a copy of the GNU Library General Public
     * License along with this library; if not, write to the Free
     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     * 02111-1307, USA
     */

    #ifndef __FLUID_S_H__
    #define __FLUID_S_H__

    #include "synthesizer/synthesizer.h"
    #include "synthesizer/midipatch.h"

    namespace FluidS {

    using namespace Ms;

    class Voice;
    class SFont;
    class Preset;
    class Sample;
    class Channel;
    struct Mod;
    class Fluid;

    #define FLUID_NUM_PROGRAMS      129

    enum fluid_loop {
          FLUID_UNLOOPED            = 0,
          FLUID_LOOP_DURING_RELEASE = 1,
          FLUID_NOTUSED             = 2,
          FLUID_LOOP_UNTIL_RELEASE  = 3
          };

    enum fluid_synth_status {
          FLUID_SYNTH_CLEAN,
          FLUID_SYNTH_PLAYING,
          FLUID_SYNTH_QUIET,
          FLUID_SYNTH_STOPPED
          };

    //---------------------------------------------------------
    //   BankOffset
    //---------------------------------------------------------

    struct BankOffset {
          int sfont_id;
          int offset;
          };

    enum fluid_midi_control_change {
          BANK_SELECT_MSB = 0x00,
          MODULATION_MSB = 0x01,
          BREATH_MSB = 0x02,
          FOOT_MSB = 0x04,
          PORTAMENTO_TIME_MSB = 0x05,
          DATA_ENTRY_MSB = 0x06,
          VOLUME_MSB = 0x07,
          BALANCE_MSB = 0x08,
          PAN_MSB = 0x0A,
          EXPRESSION_MSB = 0x0B,
          EFFECTS1_MSB = 0x0C,
          EFFECTS2_MSB = 0x0D,
          GPC1_MSB = 0x10, /* general purpose controller */
          GPC2_MSB = 0x11,
          GPC3_MSB = 0x12,
          GPC4_MSB = 0x13,
          BANK_SELECT_LSB = 0x20,
          MODULATION_WHEEL_LSB = 0x21,
          BREATH_LSB = 0x22,
          FOOT_LSB = 0x24,
          PORTAMENTO_TIME_LSB = 0x25,
          DATA_ENTRY_LSB = 0x26,
          VOLUME_LSB = 0x27,
          BALANCE_LSB = 0x28,
          PAN_LSB = 0x2A,
          EXPRESSION_LSB = 0x2B,
          EFFECTS1_LSB = 0x2C,
          EFFECTS2_LSB = 0x2D,
          GPC1_LSB = 0x30,
          GPC2_LSB = 0x31,
          GPC3_LSB = 0x32,
          GPC4_LSB = 0x33,
          SUSTAIN_SWITCH = 0x40,
          PORTAMENTO_SWITCH = 0x41,
          SOSTENUTO_SWITCH = 0x42,
          SOFT_PEDAL_SWITCH = 0x43,
          LEGATO_SWITCH = 0x45,
          HOLD2_SWITCH = 0x45,
          SOUND_CTRL1 = 0x46,
          SOUND_CTRL2 = 0x47,
          SOUND_CTRL3 = 0x48,
          SOUND_CTRL4 = 0x49,
          SOUND_CTRL5 = 0x4A,
          SOUND_CTRL6 = 0x4B,
          SOUND_CTRL7 = 0x4C,
          SOUND_CTRL8 = 0x4D,
          SOUND_CTRL9 = 0x4E,
          SOUND_CTRL10 = 0x4F,
          GPC5 = 0x50,
          GPC6 = 0x51,
          GPC7 = 0x52,
          GPC8 = 0x53,
          PORTAMENTO_CTRL = 0x54,
          EFFECTS_DEPTH1 = 0x5B,
          EFFECTS_DEPTH2 = 0x5C,
          EFFECTS_DEPTH3 = 0x5D,
          EFFECTS_DEPTH4 = 0x5E,
          EFFECTS_DEPTH5 = 0x5F,
          DATA_ENTRY_INCR = 0x60,
          DATA_ENTRY_DECR = 0x61,
          NRPN_LSB = 0x62,
          NRPN_MSB = 0x63,
          RPN_LSB = 0x64,
          RPN_MSB = 0x65,
          ALL_SOUND_OFF = 0x78,
          ALL_CTRL_OFF = 0x79,
          LOCAL_CONTROL = 0x7A,
          ALL_NOTES_OFF = 0x7B,
          OMNI_OFF = 0x7C,
          OMNI_ON = 0x7D,
          POLY_OFF = 0x7E,
          POLY_ON = 0x7F
          };

    /**
     * Generator (effect) numbers (SoundFont 2.01 specifications section 8.1.3)
     */
    enum fluid_gen_type {
      GEN_STARTADDROFS,		/**< Sample start address offset (0-32767) */
      GEN_ENDADDROFS,		      /**< Sample end address offset (-32767-0) */
      GEN_STARTLOOPADDROFS,		/**< Sample loop start address offset (-32767-32767) */
      GEN_ENDLOOPADDROFS,		/**< Sample loop end address offset (-32767-32767) */
      GEN_STARTADDRCOARSEOFS,	/**< Sample start address coarse offset (X 32768) */
      GEN_MODLFOTOPITCH,		/**< Modulation LFO to pitch */
      GEN_VIBLFOTOPITCH,		/**< Vibrato LFO to pitch */
      GEN_MODENVTOPITCH,		/**< Modulation envelope to pitch */
      GEN_FILTERFC,			/**< Filter cutoff */
      GEN_FILTERQ,			/**< Filter Q */
      GEN_MODLFOTOFILTERFC,		/**< Modulation LFO to filter cutoff */
      GEN_MODENVTOFILTERFC,		/**< Modulation envelope to filter cutoff */
      GEN_ENDADDRCOARSEOFS,		/**< Sample end address coarse offset (X 32768) */
      GEN_MODLFOTOVOL,		/**< Modulation LFO to volume */
      GEN_UNUSED1,			/**< Unused */
      GEN_CHORUSSEND,		      /**< Chorus send amount */
      GEN_REVERBSEND,		      /**< Reverb send amount */
      GEN_PAN,			      /**< Stereo panning */
      GEN_UNUSED2,			/**< Unused */
      GEN_UNUSED3,			/**< Unused */
      GEN_UNUSED4,			/**< Unused */
      GEN_MODLFODELAY,		/**< Modulation LFO delay */
      GEN_MODLFOFREQ,		      /**< Modulation LFO frequency */
      GEN_VIBLFODELAY,		/**< Vibrato LFO delay */
      GEN_VIBLFOFREQ,		      /**< Vibrato LFO frequency */
      GEN_MODENVDELAY,		/**< Modulation envelope delay */
      GEN_MODENVATTACK,		/**< Modulation envelope attack */
      GEN_MODENVHOLD,		      /**< Modulation envelope hold */
      GEN_MODENVDECAY,		/**< Modulation envelope decay */
      GEN_MODENVSUSTAIN,		/**< Modulation envelope sustain */
      GEN_MODENVRELEASE,		/**< Modulation envelope release */
      GEN_KEYTOMODENVHOLD,		/**< Key to modulation envelope hold */
      GEN_KEYTOMODENVDECAY,		/**< Key to modulation envelope decay */
      GEN_VOLENVDELAY,		/**< Volume envelope delay */
      GEN_VOLENVATTACK,		/**< Volume envelope attack */
      GEN_VOLENVHOLD,		      /**< Volume envelope hold */
      GEN_VOLENVDECAY,		/**< Volume envelope decay */
      GEN_VOLENVSUSTAIN,		/**< Volume envelope sustain */
      GEN_VOLENVRELEASE,		/**< Volume envelope release */
      GEN_KEYTOVOLENVHOLD,		/**< Key to volume envelope hold */
      GEN_KEYTOVOLENVDECAY,		/**< Key to volume envelope decay */
      GEN_INSTRUMENT,		      /**< Instrument ID (shouldn't be set by user) */
      GEN_RESERVED1,		      /**< Reserved */
      GEN_KEYRANGE,			/**< MIDI note range */
      GEN_VELRANGE,			/**< MIDI velocity range */
      GEN_STARTLOOPADDRCOARSEOFS,	/**< Sample start loop address coarse offset (X 32768) */
      GEN_KEYNUM,			/**< Fixed MIDI note number */
      GEN_VELOCITY,			/**< Fixed MIDI velocity value */
      GEN_ATTENUATION,		/**< Initial volume attenuation */
      GEN_RESERVED2,		      /**< Reserved */
      GEN_ENDLOOPADDRCOARSEOFS,	/**< Sample end loop address coarse offset (X 32768) */
      GEN_COARSETUNE,		      /**< Coarse tuning */
      GEN_FINETUNE,			/**< Fine tuning */
      GEN_SAMPLEID,			/**< Sample ID (shouldn't be set by user) */
      GEN_SAMPLEMODE,		      /**< Sample mode flags */
      GEN_RESERVED3,		      /**< Reserved */
      GEN_SCALETUNE,		      /**< Scale tuning */
      GEN_EXCLUSIVECLASS,		/**< Exclusive class number */
      GEN_OVERRIDEROOTKEY,		/**< Sample root note override */

      /* the initial pitch is not a "standard" generator. It is not
       * mentioned in the list of generator in the SF2 specifications. It
       * is used, however, as the destination for the default pitch wheel
       * modulator. */
      GEN_PITCH,			/**< Pitch (NOTE: Not a real SoundFont generator) */
      GEN_LAST			      /**< Value defines the count of generators (#fluid_gen_type) */
          };

    //---------------------------------------------------------
    //   Channel
    //---------------------------------------------------------

    class Channel {
          Fluid* synth;

          unsigned int sfontnum;
          unsigned int banknum;
          unsigned int prognum;
          Preset* _preset;

       public:
          int channum;
          short key_pressure;
          short channel_pressure;
          short pitch_bend;
          short pitch_wheel_sensitivity;

          short cc[128];          // controller values

          /* cached values of last MSB values of MSB/LSB controllers */
          unsigned char bank_msb;
          int interp_method;

          /* NRPN system */
          short nrpn_select;

          /* The values of the generators, set by NRPN messages, or by
           * fluid_synth_set_gen(), are cached in the channel so they can be
           * applied to future notes. They are copied to a voice's generators
           * in fluid_voice_init(), wihich calls fluid_gen_init().  */

          float gen[GEN_LAST];

          /* By default, the NRPN values are relative to the values of the
           * generators set in the SoundFont. For example, if the NRPN
           * specifies an attack of 100 msec then 100 msec will be added to the
           * combined attack time of the sound font and the modulators.
           *
           * However, it is useful to be able to specify the generator value
           * absolutely, completely ignoring the generators of the sound font
           * and the values of modulators. The gen_abs field, is a boolean
           * flag indicating whether the NRPN value is absolute or not.
           */
          char gen_abs[GEN_LAST];

       public:
          Channel(Fluid* synth, int num);

          bool sustained() const              { return cc[SUSTAIN_SWITCH] >= 64; }
          void setGen(int n, float v, char a) { gen[n] = v; gen_abs[n] = a; }
          float getGen(int n) const           { return gen[n]; }
          char getGenAbs(int n) const         { return gen_abs[n]; }
          void init();
          void initCtrl();
          void setCC(int n, int val)          { cc[n] = val; }
          void reset();
          void setPreset(Preset* p);
          Preset* preset() const              { return _preset;  }
          unsigned int getSfontnum() const    { return sfontnum; }
          void setSfontnum(unsigned int s)    { sfontnum = s;    }
          unsigned int getBanknum() const     { return banknum;  }
          void setBanknum(unsigned int b)     { banknum = b;     }
          void setPrognum(int p)              { prognum = p;     }
          int getPrognum() const              { return prognum;  }
          void setcc(int ctrl, int val);
          void pitchBend(int val);
          int getPitchBend() const            { return pitch_bend; }
          void pitchWheelSens(int val);
          int getCC(int num);
          int getNum() const                  { return channum;    }
          void setInterpMethod(int m)         { interp_method = m; }
          int getInterpMethod() const         { return interp_method; }
          };

    // subsystems:
    enum {
          FLUID_GROUP  = 0,
          };

    //---------------------------------------------------------
    //   Fluid
    //---------------------------------------------------------

    class Fluid : public Synthesizer {
          QList<SFont*> sfonts;               // the loaded soundfonts
          QList<MidiPatch*> patches;

          QList<Voice*> freeVoices;           // unused synthesis processes
          QList<Voice*> activeVoices;         // active synthesis processes
          QString _error;                     // last error message

          static bool initialized;

          double sample_rate;                 // The sample rate
          float _masterTuning;                // usually 440.0
          double _tuning[128];                // the pitch of every key, in cents

          QMutex mutex;
          void updatePatchList();

       protected:
          int _state;                         // the synthesizer state

          unsigned int sfont_id;

          QList<Channel*> channel;            // the channels

          unsigned int noteid;                // the id is incremented for every new note. it's used for noteoff's

          SFont* get_sfont_by_name(const QString& name);
          SFont* get_sfont_by_id(int id);
          SFont* get_sfont(int idx) const     { return sfonts[idx];   }
          bool sfunload(int id);
          int sfload(const QString& filename);

       public:
          Fluid();
          ~Fluid();
          virtual void init(float sampleRate);

          virtual const char* name() const { return "Fluid"; }

          virtual void play(const PlayEvent&);
          virtual const QList<MidiPatch*>& getPatchInfo() const { return patches; }

          // get/set synthesizer state (parameter set)
          virtual SynthesizerGroup state() const;
          virtual bool setState(const SynthesizerGroup&);

          virtual void allSoundsOff(int);
          virtual void allNotesOff(int);

          Preset* get_preset(unsigned int sfontnum, unsigned int banknum, unsigned int prognum);
          Preset* find_preset(unsigned int banknum, unsigned int prognum);
          void modulate_voices(int chan, bool is_cc, int ctrl);
          void modulate_voices_all(int chan);
          void damp_voices(int chan);
          int kill_voice(Voice * voice);
          void print_voice();

          /** This function assures that every MIDI channels has a valid preset
           *  (NULL is okay). This function is called after a SoundFont is
           *  unloaded or reloaded. */
          void update_presets();

          int get_cc(int chan, int num) const { return channel[chan]->cc[num]; }

          void system_reset();
          void program_change(int chan, int prognum);

          void set_gen2(int chan, int param, float value, int absolute, int normalized);
          float get_gen(int chan, int param);
          void set_gen(int chan, int param, float value);
          void set_interp_method(int chan, int interp_method);

          Preset* get_channel_preset(int chan) const { return channel[chan]->preset(); }

          virtual bool loadSoundFonts(const QStringList& s);
          virtual bool addSoundFont(const QString& s);
          virtual bool removeSoundFont(const QString& s);
          virtual QStringList soundFonts() const;

          void start_voice(Voice* voice);
          Voice* alloc_voice(unsigned id, Sample* sample, int chan, int key, int vel, double vt);
          void free_voice_by_kill();

          virtual void process(unsigned len, float* out, float* effect1, float* effect2);

          bool program_select(int chan, unsigned sfont_id, unsigned bank_num, unsigned preset_num);
          void get_program(int chan, unsigned* sfont_id, unsigned* bank_num, unsigned* preset_num);
    //      void sfont_select(int chan, unsigned int sfont_id)    { channel[chan]->setSfontnum(sfont_id); }
    //      void bank_select(int chan, unsigned int bank)         { channel[chan]->setBanknum(bank); }

          void get_pitch_wheel_sens(int chan, int* pval);
          void pitch_wheel_sens(int chan, int val);
          void get_pitch_bend(int chan, int* ppitch_bend);

          void freeVoice(Voice* v);

          double getPitch(int k) const   { return _tuning[k]; }
          float ct2hz_real(float cents)  { return powf(2.0f, (cents - 6900.0f) / 1200.0f) * _masterTuning; }

          float act2hz(float c)          { return 8.176 * pow(2.0, (double) c / 1200.0); }
          float ct2hz(float cents)       { return act2hz(qBound(1500.0f, cents, 13500.0f)); }

          virtual double masterTuning() const     { return _masterTuning; }
          virtual void setMasterTuning(double f)  { _masterTuning = f;    }

          QString error() const { return _error; }

          virtual SynthesizerGui* gui();

          static QFileInfoList sfFiles();

          friend class Voice;
          friend class Preset;
          };

      /*
       *
       * Chorus
       *
       */

    enum fluid_chorus_mod {
          FLUID_CHORUS_MOD_SINE = 0,
          FLUID_CHORUS_MOD_TRIANGLE = 1
          };

    /* Those are the default settings for the chorus. */
    #define FLUID_CHORUS_DEFAULT_N      3
    #define FLUID_CHORUS_DEFAULT_LEVEL  2.0f
    #define FLUID_CHORUS_DEFAULT_SPEED  0.3f
    #define FLUID_CHORUS_DEFAULT_DEPTH  8.0f
    #define FLUID_CHORUS_DEFAULT_TYPE   FLUID_CHORUS_MOD_SINE

      /*
       *
       * Synthesis parameters
       *
       */

      /* Flags to choose the interpolation method */
    enum fluid_interp {
          /* no interpolation: Fastest, but questionable audio quality */
          FLUID_INTERP_NONE     = 0,
          /* Straight-line interpolation: A bit slower, reasonable audio quality */
          FLUID_INTERP_LINEAR   = 1,
          /* Fourth-order interpolation: Requires 50 % of the whole DSP processing time, good quality
           * Default. */
          FLUID_INTERP_DEFAULT  = 4,
          FLUID_INTERP_4THORDER = 4,
          FLUID_INTERP_7THORDER = 7,
          FLUID_INTERP_HIGHEST  = 7
          };

    #define fluid_sample_refcount(_sample) ((_sample)->refcount)

    /** Sample types */

    enum {
          FLUID_SAMPLETYPE_MONO =	      1,
          FLUID_SAMPLETYPE_RIGHT =	2,
          FLUID_SAMPLETYPE_LEFT =	      4,
          FLUID_SAMPLETYPE_LINKED =	8,
          FLUID_SAMPLETYPE_OGG_VORBIS = 0x10,
          FLUID_SAMPLETYPE_ROM =	      0x8000
          };

    /* Sets the sound data of the sample
     *     Warning : if copy_data is FALSE, data should have 8 unused frames at start
     *     and 8 unused frames at the end.
     */
    int fluid_sample_set_sound_data(Sample* sample, short *data,
    			       unsigned int nbframes, short copy_data, int rootkey);

    /*
     *
     *  Utility functions
     */

      /* Maximum number of modulators in a voice */
    #define FLUID_NUM_MOD           64

    /**
     * SoundFont generator structure.
     */
    class Generator {
       public:
          unsigned char flags; /**< Is the generator set or not (#fluid_gen_flags) */
          double val;          /**< The nominal value           */
          double mod;          /**< Change by modulators        */
          double nrpn;         /**< Change by NRPN messages     */

          void set_mod(double _val)  { mod  = _val; }
          void set_nrpn(double _val) { nrpn = _val; }
          };

    /**
     * Enum value for 'flags' field of #_Generator (not really flags).
     */
    enum fluid_gen_flags {
          GEN_UNUSED,		/**< Generator value is not set */
          GEN_SET,		/**< Generator value is set     */
          GEN_ABS_NRPN	/**< DOCME                      */
          };

    void fluid_gen_set_default_values(Generator* gen);
      /*
       *  The interface to the synthesizer's voices
       *  Examples on using them can be found in fluid_defsfont.c
       */

      /* for fluid_voice_add_mod */
    enum fluid_voice_add_mod {
          FLUID_VOICE_OVERWRITE,
          FLUID_VOICE_ADD,
          FLUID_VOICE_DEFAULT
          };

    /* Disable FPE exception check */
    #define fluid_check_fpe(expl)

    unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe);

    /*
     * interpolation data
     */
    struct fluid_interp_coeff_t {
          float a0, a1, a2, a3;
          };

    /* Flags telling the polarity of a modulator.  Compare with SF2.01
       section 8.2. Note: The numbers of the bits are different!  (for
       example: in the flags of a SF modulator, the polarity bit is bit
       nr. 9) */

    enum fluid_mod_flags {
          FLUID_MOD_POSITIVE = 0,
          FLUID_MOD_NEGATIVE = 1,
          FLUID_MOD_UNIPOLAR = 0,
          FLUID_MOD_BIPOLAR  = 2,
          FLUID_MOD_LINEAR   = 0,
          FLUID_MOD_CONCAVE  = 4,
          FLUID_MOD_CONVEX   = 8,
          FLUID_MOD_SWITCH   = 12,
          FLUID_MOD_GC       = 0,
          FLUID_MOD_CC       = 16
          };

    //---------------------------------------------------------
    //   Mod
    //---------------------------------------------------------

    struct Mod
          {
          unsigned char dest;
          unsigned char src1;
          unsigned char flags1;
          unsigned char src2;
          unsigned char flags2;
          double amount;

          void clone(Mod* mod) const;
          void dump() const;
          int has_source(bool cc, int ctrl) {
                return (((src1 == ctrl) && (flags1 & FLUID_MOD_CC)    && cc)
                    || (((src1 == ctrl) && (!(flags1 & FLUID_MOD_CC)) && !cc)))
                    || (((src2 == ctrl) && (flags2 & FLUID_MOD_CC)    && cc)
                    || (((src2 == ctrl) && (!(flags2 & FLUID_MOD_CC)) && !cc)));
                }
          void set_source1(int src, int flags);
          void set_source2(int src, int flags);
          void set_dest(int val)                    { dest = val;    }
          void set_amount(double val)               { amount = val;  }
          int get_source1() const                   { return src1;   }
          int get_flags1() const                    { return flags1; }
          int get_source2() const                   { return src2;   }
          int get_flags2() const                    { return flags2; }
          int get_dest() const                      { return dest;   }
          double get_amount() const                 { return amount; }
          float get_value(Channel* chan, Voice* voice);
          };

    /* Flags telling the source of a modulator.  This corresponds to
     * SF2.01 section 8.2.1 */

    enum fluid_mod_src {
          FLUID_MOD_NONE             = 0,
          FLUID_MOD_VELOCITY         = 2,
          FLUID_MOD_KEY              = 3,
          FLUID_MOD_KEYPRESSURE      = 10,
          FLUID_MOD_CHANNELPRESSURE  = 13,
          FLUID_MOD_PITCHWHEEL       = 14,
          FLUID_MOD_PITCHWHEELSENS   = 16
          };

    /* Determines, if two modulators are 'identical' (all parameters
       except the amount match) */
    bool test_identity(const Mod * mod1, const Mod * mod2);

    void fluid_dump_modulator(Mod * mod);

    #define fluid_mod_has_source(mod,cc,ctrl)  \
    ( ((((mod)->src1 == ctrl) && (((mod)->flags1 & FLUID_MOD_CC) != 0) && (cc != 0)) \
       || ((((mod)->src1 == ctrl) && (((mod)->flags1 & FLUID_MOD_CC) == 0) && (cc == 0)))) \
    || ((((mod)->src2 == ctrl) && (((mod)->flags2 & FLUID_MOD_CC) != 0) && (cc != 0)) \
        || ((((mod)->src2 == ctrl) && (((mod)->flags2 & FLUID_MOD_CC) == 0) && (cc == 0)))))

    #define fluid_mod_has_dest(mod,gen)  ((mod)->dest == gen)

    /*
     *  phase
     */

    #define FLUID_INTERP_BITS        8
    #define FLUID_INTERP_BITS_MASK   0xff000000
    #define FLUID_INTERP_BITS_SHIFT  24
    #define FLUID_INTERP_MAX         256

    #define FLUID_FRACT_MAX ((double)4294967296.0)

    //---------------------------------------------------------
    //   Phase
    /* Purpose:
    * Playing pointer for voice playback
    *
    * When a sample is played back at a different pitch, the playing pointer in the
    * source sample will not advance exactly one sample per output sample.
    * This playing pointer is implemented using Phase.
    * It is a 64 bit number. The higher 32 bits contain the 'index' (number of
    * the current sample), the lower 32 bits the fractional part.
    * Access is possible in two ways:
    * -through the 64 bit part 'b64', if the architecture supports 64 bit integers
    * -through 'index' and 'fract'
    * Note: b64 and index / fract share the same memory location!
    */

    struct Phase {
          qint64 data;

          void operator+=(const Phase& p) { data += p.data; }
          void setInt(qint32 b)           { data = qint64(b) << 32; }
          void setFloat(double b)          {
                 data = (((qint64)(b)) << 32) | (quint32) (((double)(b) - (int)(b)) * (double)FLUID_FRACT_MAX);
                }

          void operator-=(const Phase& b) { data -= b.data;  }
          void operator-=(int b)          { data -= (qint64(b) << 32);  }
          int index() const               { return data >> 32; }
          quint32 fract() const           { return quint32(data & 0xffffffff); }
          quint32 index_round() const     { return quint32((data+0x80000000) >> 32); }

          Phase() {}
          Phase(qint64 v) : data(v) {}
          };

    /* Purpose:
     * Takes the fractional part of the argument phase and
     * calculates the corresponding position in the interpolation table.
     * The fractional position of the playing pointer is calculated with a quite high
     * resolution (32 bits). It would be unpractical to keep a set of interpolation
     * coefficients for each possible fractional part...
     */
    #define fluid_phase_fract_to_tablerow(_x) \
      ((int)(((_x).fract() & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT))

    #define fluid_phase_double(_x) \
      ((double)((_x).index()) + ((double)((_x).fract()) / FLUID_FRACT_MAX))

    /* Purpose:
     * The playing pointer is _phase. How many output samples are produced, until the point _p1 in the sample is reached,
     * if _phase advances in steps of _incr?
     */
    #define fluid_phase_steps(_phase,_idx,_incr) \
      (int)(((double)(_idx) - fluid_phase_double(_phase)) / (double)_incr)

    /* Purpose:
     * Creates the expression a.index++.
    */
    #define fluid_phase_index_plusplus(a) (((a)._index)++)

    }  // namespace Fluid

    #endif  // __FLUID_S_H__

↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: data.