/*

This software module was originally developed by 

Mike Guzewicz (E-mu Systems)


in the course of development of the MPEG-4 Audio (ISO/IEC 14496-3) standard. 
This software module is an implementation of a part of one or more 
MPEG-4 Audio (ISO/IEC 14496-3) tools as specified by the MPEG-4 Audio 
(ISO/IEC 14496-3). ISO/IEC gives users of the MPEG-4 Audio (ISO/IEC 14496-3) 
free license to this software module or modifications thereof for use 
in hardware or software products claiming conformance to the MPEG-4 Audio 
(ISO/IEC 14496-3). Those intending to use this software module in hardware 
or software products are advised that its use may infringe existing patents. 
The original developer of this software module and his/her company, the 
subsequent editors and their companies, and ISO/IEC have no liability for 
use of this software module or modifications thereof in an implementation. 
Copyright is not released for non MPEG-4 Audio (ISO/IEC 14496-3) conforming 
products. E-mu Systems retains full right to use the code for his/her own 
purpose, assign or donate the code to a third party and to inhibit third 
parties from using the code for non MPEG-4 Audio (ISO/IEC 14496-3) 
conforming products. This copyright notice must be included in all copies 
or derivative works. 

Copyright (C) 1997 E-mu Systems, Inc.

*/     /*********************************************************************
     
     sfe_hydra.h
     
     
     *********************************************************************/

#ifndef __HYDRA_H_
#define __HYDRA_H_

#include <stddef.h>
#include "sfe_datatype.h"
#include "sfe_sfdata.h"
#include "sfe_sfenum.h"
#include "sfe_emuerrs.h"
//*****************************************************************************
// @(#)hydra.h	1.2 09:40:05 3/21/95 09:40:06
// Description: 
//
//     This file defines the datatype HydraClass. 
// HydraClass is the base level in memory datatype used to describe
// a single SoundFont bank. It also contains the Global default parameters for
// a SoundFontObject. 
// 
//*****************************************************************************

#define SF_DATASTRUCTS  9       // The # of SF data structs
#define INSTNAMESIZE    20

#define SAMPLEBUFFER    32

enum SoundFontDS {
  prstHdr = 0,
  prstBagNdx,
  prstGenList,
  prstModList,
  inst,
  instBagNdx,
  instGenList,
  instModList,
  sampHdr

};


/////////////////////////////
//SoundFont Data Structures//
/////////////////////////////

typedef struct sfVersionTag
{
  WORD wMajor;               // Reads the major ver (if present) -was uiHi
  WORD wMinor;               // Reads the minor ver              -was uiLo
} sfVersion;


typedef struct sfINFOTag
{
  sfVersion sfSFVer;
  CHAR*     pchSoundEngine;
  CHAR*     pchROMName;
  sfVersion sfROMVer;
  CHAR*     pchBankName;
  CHAR*     pchProduct;
  CHAR*     pchCopyright;
  CHAR*     pchDate;
  CHAR*     pchEngineer;
} sfINFO;

// The stRanges data structure is applicable in the Generator List only.
// They are used as values for key ranges and velocity ranges.
// Typically, a Generator value is a 16 bit signed entity, whose bytes must be
// swapped on Big Endian (Byte Incoherent) machines. In other words,
// the byte ordering for _typical_ generators is NOT the same 
// between Big Endian and Little Endian systems.

// However the byte ordering for _ranges_ IS the same regardless of the
// Endian nature of the system. 

// So instead of having the sfReader detect the relatively few key ranges 
// and NOT swapping those, it swaps bytes for ALL generator values 
// and these data structures are re-designed to compensate for that.

#ifdef __BYTE_COHERENT
struct stRanges            // This is for both key and velocity ranges
{
  BYTE byLo;    
  BYTE byHi;   
};

#elif defined (__BYTE_INCOHERENT)
struct stRanges
{
  BYTE byHi;  
  BYTE byLo;
};

#endif


typedef union unGenAmtTag
{
  struct stRanges stRange;    // Sometimes the generator is an stRange
  SHORT             shAmount; //   and sometimes it is a short
} unGenAmt;


//// Standard list used in Phdr (Preset lists) ////
// in SFDATA.H


//// Standard list used in Pbag, Ibag (Layer, split lists) ////
typedef struct sfBagNdxTag

{
  WORD wGenNdx;          // Index to generator list
  WORD wModNdx;          // Index to modulator list

} sfBagNdx;


//// Standard list used in Pgen, Igen (Generator lists) ////
typedef struct sfGenListTag
{
  WORD         sfGenOper; // Single generator 
  unGenAmt     unAmt;     // Amount applied to that generator
} sfGenList;


//// Standard list used in Pmod, Imod (Modulator lists) ////
typedef struct sfModListTag
{
  WORD    wModSrcOper;     // Source modulation operator
  WORD    wModDestOper;    // Destination modulation operator
  SHORT   shAmount;        // Source modulates destination by this amount
  WORD    wModAmtSrcOper;  // If used, source modulates destination by 
                           // THIS source's current value instead.
  WORD    wModTransOper;   // Send source through defined transform first
} sfModList;


//// Standard list used in Inst (Instrument lists) ////
typedef struct sfInstTag
{
  CHAR  achInstName[INSTNAMESIZE];     // Name of the instrument
  WORD  wBagNdx;                      // Index to sfInstrumentBag
  WORD  wRefCount; // This field is used in EDIT ENGINE for reference counts

  //// For Windows 3.1 and Borland's huge pointers //// 
  #ifdef EMU_WINDOWS
  DWORD dwPad0;
  DWORD dwPad1;
  #endif
} sfInst;


////////////////////////////////////////////////////
// Typedefs for working with segmented architecture
////////////////////////////////////////////////////

#if defined (EMU_WINDOWS) || defined (DOS_MEMORY)

//SFPRESETHDRPTR in sfe_sfdata.h
//SFSAMPLEHDRPTR in sfe_sfdata.h
typedef sfInst huge*      SFINSTPTR;
typedef sfBagNdx huge*    SFBAGNDXPTR;
typedef sfGenList huge*   SFGENLISTPTR;
typedef sfModList huge*   SFMODLISTPTR;

///////////////////////////////////////////////////////
// Typedefs for working with non segmented architecture
///////////////////////////////////////////////////////

#else

//SFPRESETHDRPTR in sfe_sfdata.h
//SFSAMPLEHDRPTR in sfe_sfdata.h
typedef sfInst*      SFINSTPTR;
typedef sfBagNdx*    SFBAGNDXPTR;
typedef sfGenList*   SFGENLISTPTR;
typedef sfModList*   SFMODLISTPTR;

#endif // Memory typedef dependencies


/////////////////////////////////
// DS for holding Sample Name  //
/////////////////////////////////

class HydraClass 
{
  public:
    //// Methods ////
    HydraClass(void);
    ~HydraClass(void);

    void ConstructHydra(void);
    void DestructHydra(void);

    void  ZapHydra(void);
    void  ResetDefault(void);

    const sfData* getDefault(void) { return &sfDefault; }

    void  SetVersion(WORD majorVersion, WORD minorVersion) 
        {HydraVersion.wMajor = majorVersion; 
         HydraVersion.wMinor = minorVersion;}
    void  GetVersion(WORD *majorVersion, WORD *minorVersion) 
        {*majorVersion = HydraVersion.wMajor;
         *minorVersion = HydraVersion.wMinor;}

    const CHAR *GetBankName(void) {return (const CHAR *)achBankName;}
    EMUSTAT     SetBankName(CHAR *theNewName);

    //// The public data ////
    
    // These 9 pointers point to the in-memory image of the SoundFont file data.
    // The only differences between this image of the SoundFont data 
    // and the data as it exists in the file itself are 
    // (1) The existence of 'reference count' fields in pInst and pSHdr
    // (2) The existence of 'sample loaded' boolean field in pSHdr
    // (3) SFBanks loaded on BYTE_INCOHERENT drivers have appropriate bytes 
    //     pre-swapped.

    SFPRESETHDRPTR pPHdr;
    SFBAGNDXPTR    pPBag;
    SFGENLISTPTR   pPGen;
    SFMODLISTPTR   pPMod;
    SFINSTPTR      pInst;
    SFBAGNDXPTR    pIBag;
    SFGENLISTPTR   pIGen;
    SFMODLISTPTR   pIMod;
    SFSAMPLEHDRPTR pSHdr;

    // This is an array used by the enabler and the edit engine to provide
    // convenient way to detect and prevent over-indexing the various arrays.
    WORD           awStructSize[SF_DATASTRUCTS]; // The count of each struct

    // This contains the default SoundFont generator vector, IE what each 
    // generator value should be if NO generator of a particular type exists 
    // within all of the appropriate key/velocity SPLITS of given INSTRUMENT.
    sfData sfDefault;

    CHAR      *achBankName; 
    sfVersion HydraVersion;
};

#endif // __HYDRA_H
