/* ====================================================================
 *  AuCoreAHMhdr.h
 *  Version: 0.500
 * ==================================================================== */
#ifndef Au_AHM_HDR_H
 #define Au_AHM_HDR_H
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *   AuCoreAHMHDR is the AHM format header definition
 *
 *   The structs and enums defined in this file are used
 *     in the AuCoreAHM, AuCoreAHMF and AuCoreAHMIO classes.
 *   Structs and enums defined:
 *         struct aAHMF_th
 *         struct aAHMF_bh
 *         enum AHMwindowType
 *         enum AHMdisplayEQType
 *         struct ah_sequence_field
 *         struct aAHMF_ASCIIh
 *         struct ah_spec_bits
 *         struct AH14_HDR_FMT
 *         struct AH13_HDR_FMT
 *         struct AH12_HDR_FMT
 *
 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *  Copyright (C) 1998-2010 AuSIM, Inc.
 *
 *  This document contains UNPUBLISHED PROPRIETARY SOURCE CODE of
 *  AuSIM Engineering Solutions, Palo Alto, CA;
 *  the contents of this file may not be disclosed to third parties,
 *  copied or duplicated in any form, in whole or in part,
 *  without the prior written permission of AuSIM Engineering Solutions.
 *
 *  RESTRICTED RIGHTS LEGEND:
 *  Use, duplication or disclosure by the Government is subject to
 *  restrictions as set forth in subdivision (c)(1)(ii) of the Rights in
 *  Technical Data and Computer Software clause at DFARS 252.227-7013,
 *  and/or in similar or successor clauses in the FAR, DOD or NASA FAR
 *  Supplements.
 *  Unpublished  -
 *     rights reserved under the Copyright Laws of the United States.
 *
 *  Authors:
 *     William L. Chapin (WLC)
 *     Elizabeth J. Purswell (EJP)
 *     Agnieszka Roginska (ARO)
 * --------------------------------------------------------------------
 * Modification log:
 *  22Sep10 WLC  0.500   EQF 1.2, AHM 1.5, AFM 1.2
 *  24Sep08 WLC  0.440   EQF 1.1
 *  08Aug07 WLC  0.431   Reset of file version
 *  19Dec00 WLC  0.301   Completed redesign
 *  17Dec00 WLC  0.300   Redesigned for v1.410, made public
 *  05Dec00 ARO  0.200   Revamped for v1.4
 *  14Sep99 EJP  0.101   Some commenting added.
 *  04Jan98 WlC  0.100   Created.
 * --------------------------------------------------------------------
 * Keywords: Acoustic Head Map, file format, filter, HRTF
 * ==================================================================== */

 #define AHM_VERSION  1.50
 #define EQF_VERSION  1.20
 #define AFM_VERSION  1.20

/* Notes:
  EQF v1.1 supports absolute compensation, relative compensation,
  band-pass filters, and the combination of absolute comp and band-pass.
  This version also supports the inclusion of SINKVECT and SINKLABEL
  within EQF files.
  AHM v1.44 now supports SINKVECT and SINKLABEL within AHM files.
  */

/* --------------------------------------------------------------------
    The AHM format consists of 4 parts:
        * (1) an ASCII "title header" (required)
              this part is the only mandatory human readable section
              it does not normally contain detailed data,
              but does contain basic archiving information.
              The comment section may contain any data in ASCII format.
        * (2) a "binary header" (required)
              this part describes the dataset in an exhaustive detail
              if the dataset contains data that should be special
              interpretation not supported by the binary data structure,
              then the binary header directs the loader to alert the
              operator to read the comment within the title header.
        * (3) an ASCII "header extension" (optional)
              This section is normally used to provide an additional
              comment of any length.  The existence of this section is
              indicated by a non-zero entry in the "thisMap" offset
              field of the binary header.  "thisMap" defines the number
              of bytes between the last byte of the binary header and
              the first byte of the dataset.
              NOTE:
                Some contributors to the format specification requested
              that a completely human readable format option be
              supported.  If Ctrl-Z is missing from the title header AND
              this ASCII header extension provides the complete
              description for interpreting the dataset,
              then the binary header part may be omitted.
        * (4) the data (required)
              the data always immediately follows the last byte
              of the binary header plus the "thisMap" offset.
    The format supports the creation of libraries of datasets with a
    common identifier.  For such datasets, part (1), the title header,
    is present only at the beginning of the file; parts (2), (3), & (4)
    may be repeated as many times as needed.  In such multi-dataset
    instances, the "nextMap" and "prevMap" fields for all binary headers
    must specify the non-zero offset from the byte after the end of the
    current binary header.  All offsets are positive number of bytes.
    The usefulness of multi-datasets may include different filter types
    such as FIR, ARMA, and PCA; different samplerates, or different
    optimization lengths.
  --------------------------------------------------------------------- */
/* NOTE ---------------------------------------------------------------
 * All multi-byte datatypes are little-endian:
 *   Little-endian means that the least significant byte of a field
 *   comes first, followed up with more significant bytes until
 *   finally reaching the most significant byte.
 *   Thus if the unsigned long integer 0x9A78BC56 is in an AHM file,
 *   the bytes would be read-in in the following order:
 *     0x56, 0xBC, 0x78, 0x9A
 *   The little-endian rule is true for header and data.
 * -------------------------------------------------------------------- */

// utility macros
#define ver_num2str(numver) "v" #numver
#define ver_mac2str(macver) ver_num2str(macver)

 #define AHM_VER_STR  "AH" ver_mac2str(AHM_VERSION)
 #define EQF_VER_STR  "EQ" ver_mac2str(EQF_VERSION)
 #define AFM_VER_STR  "AF" ver_mac2str(AFM_VERSION)




/* --------------------------------------------------------------------
 *  Current AHM Structures --------------------------------------------
 * -------------------------------------------------------------------- */

/* Acoustic Head Map Format Header-Title structure --------------------
 *   is common between both BINARY and ASCII forms
 *   If "ctrlZtm"==^Z, then header is BINARY.
 */
 #define AHMFHT_SIZ  192      /* header title section size */
 #define VERSTR_SIZ    8
 #define HIDSTR_SIZ   32
 #define CMTSTR_SIZ  140      /* two lines of text */
 #define TRESRV_OFS  (VERSTR_SIZ+HIDSTR_SIZ+CMTSTR_SIZ+1)
 #define TRESRV_SIZ  (AHMFHT_SIZ-TRESRV_OFS)  /* 12 bytes of padding */

 #define AFMF_SINKLABELSTR_SIZ  32

 #define _CTRL_Z     0x1A

/* ASCII header
   All AHM/EQF/AFM formats use this ASCII header structure, except v1.3
   See AH13_HDR_FMT below.  The fixed-sized v1.3 header is entirely ASCII.
   The interpretation of the first 40 bytes is exactly the same for all AHMs.
   */
struct aAHMF_th {
    char version[VERSTR_SIZ], head_id[HIDSTR_SIZ];
    char comment[CMTSTR_SIZ], ctrlZtm, rsrvCh1[TRESRV_SIZ];
  };
typedef struct aAHMF_th aAHMF_ht;  // legacy name, do not use

/* Acoustic Head Map Format BINARY Header structure -------------------
 *   aliased to the current version of the format
 */
typedef struct AH14_HDR_FMT aAHMF_bh;


/*  Sequence fields structure -----------------------------------------
 *     define the order for sections, subsections, & components
 *     the structure consists of an array of enumerated values
 *     each relating to a field to be ordered
 *     followed by a format flag, which modifies the ordering.
 */
#define AHMF_MAX_SEQFIELD  7
struct ah_sequence_field {
    unsigned char fld[AHMF_MAX_SEQFIELD];
    unsigned char flg;
  };

/* AHMF v1.4xx & v1.5xx use identical structures
   contain 208 bytes and elimates the bit-field (see AH12_HDR_FMT at bottom) */
struct AH14_HDR_FMT {
    unsigned long                    // 12 fields of 4 bytes each  (48 bytes)
        // offsets are relative to first byte after header,
        // which is where the file pointer is pointing after sucking header.
        bhdrSiz,  // size in bytes of this binary header structure (208 bytes)
        thisMap,  // offset for this map (0 default), indicates comment
        nextMap,  // offset next map     (0 default)
        prevMap,  // offset previous map (0 default)
        lotmDat,  // low-dword of UTC time/date code, must be 64-bit boundary
        hitmDat,  // high-dword contains epoch of lotmDat seconds count
        totlSiz,  // total bytes in file, including header for verification
        totlRsp,  // total responses stored (including caps)
        respTps,  // response taps (for pure FIR) or total number of sections, see note
        rsrvLng[3];
    float                            // 8 fields of 4 bytes each  (32 bytes)
        smplRat,  // sample rate in Hertz
        headSiz,  // interaural distance in range units
        fixpCvt,  // fixed point coefficient conversion value.
        bassFrq,  // bass extension low-pass cut-off frequency
        spdoSnd,  // speed of sound at which measurements were taken, 0.0 = 343 m/sec
        trebFrq,  // treble extension high-pass cut-off frequency
        cutoSlp,  // slope of frequency cut-offs; 0 = 12 dB/Octave
        rsrvFlt[1];
    unsigned short                   // 12 fields of 2 bytes each  (24 bytes)
        azimRsp,  // grid azimuth responses
        elevRsp,  // grid elevation responses
        rangRsp,  // grid range responses
        rtapZrs,  // response tap zero coefficients (zeros per tap)
        rtapPls,  // response tap pole coefficients (poles per tap)
        respCmp,  // response components (number of weights if PCA)
        optmTps,  // compression optimization size (or weighting function length)
        sinkCnt,  // number of sinks per transfer function (legacy 0==2)
        virtNod,  // number of virtual nodes in vector
        triaCnt,  // triangle count for triangulation of sinks and virtual nodes
        rsrvSht[2];
    unsigned char                    // 32 fields of 1 bytes each  (32 bytes)
        coefDat,  // coefficient type (integer/float),      see AHMdataType enum
        iatdDat,  // time delay type (integer/float),       see AHMdataType enum
        wghtDat,  // component weight type (integer/float), see AHMdataType enum
        nlvlDat,  // normalization level type (integer/float)

        coefSiz,  // bits per coefficient
        iatdSiz,  // bits per delay
        wghtSiz,  // bits per weight
        nlvlSiz,  // bits per normalization level

        distFmt,  // dist units (inches/feet/cm/meters), see AHMscaleUnits enum
        anglFmt,  // angular units (rads/degs/grads),    see AHMscaleUnits enum
        timeFmt,  // time units (sample/secs/millisecs), see AHMscaleUnits enum
        nlvlFmt,  // level units (linear/decibel),       see AHMscaleUnits enum

        azimInc,  // azim increment (add/multiply/log), see AHMincrOperation enum
        elevInc,  // elev increment (add/multiply/log), see AHMincrOperation enum
        rangInc,  // rang increment (add/multiply/log), see AHMincrOperation enum
        rsrvInc[1],  // spare

        axisCfg,  // axis order and type (cart/cyl/sphr),  see AHMaxesConfig
        wndoTyp,  // filter window type,               see AHMwindowType enum
        dseqTyp,  // display equalization type,        see AHMdisplayEQType enum
        fdeqTyp,  // field equalization method,        see AHMfieldEQType enum
        crptTyp,  // encryption type,                  see AHMencryptType enum
        enhcMtd,  // enhancement method (bass-extension), see AHMenhanceMethod OR bits
        trakDev,  // Head Tracking device              see AHMtrackingDevice enum
        nrmlTyp,  // normalization type (peak/RMS),    see AHMnormalizationType enum

        leftSrc,  // left  response (none/sampled/mirrored), see AHMrespSource enum
        rghtSrc,  // right response (none/sampled/mirrored), see AHMrespSource enum
        NcapSrc,  // north polarcap (none/sampled/infered), see AHMrespSource enum
        ScapSrc,  // south polarcap (none/sampled/infered), see AHMrespSource enum
        readCmt,  // specialized map boolean
        fileTyp,  // AHM, EQF, AFM, see AFMfileType enum
        lveqTyp,  // level equalization method,        see AHMlevelEQType enum
        rsrvChr[1];
    ah_sequence_field                // 6 fields of 8 bytes each  (48 bytes)
        coefSeq,  // order of  coefs/sections/section groups:  zero, pole, cascade, parallel
        vectSeq,  // order of vector:  azim, elev, rang
        respSeq,  // order of  resps:  resp, time, level
        regnSeq,  // order of regions: mapgrid, northcap, southcap
        bnsdSeq,  // order of bonusdata: weighting, sinkvect, sinklabel, sinktriangles
        rsrvSeq[1];
    float                            // 6 fields of 4 bytes each  (24 bytes)
        azimOrg,  // primary axis, see AHMaxisConfig
        elevOrg,  // secondary axis
        rangOrg,  // tertiary axis
        azimInt,
        elevInt,
        rangInt;
  };

/* NOTE ---------------------------------------------------------------
 * Explanation of respTps, rtapZrs, rtapPls:
 *   respTps, rtapZrs, rtapPls can easily be confused.
 *   The file format always refers to number of coefficients, not poly order.
 *   Unity coefficients must be explicitly stated.
 *   Coefficients may be zero-padded and it is up to the loader to optimize the filters.
 *   The total number of coefficients per function is IN ALL CASES
 *       respTps * ( rtapZrs + rtapPls )
 *   Condition: respTps == Response Taps
 *     Only valid for FIR filters.
 *     Only valid for when rtapPls == 0, and rtapZrs == 1.
 *     Older formats may have rtapZrs == 0, but this is promoted to 1.
 *     coefSeq is ignored.
 *     This condition is supported for 1) legacy, and 2) very long FIR filters.
 *   Condition: respTps == Number of Sections
 *     Valid for any filter.
 *     Only valid for when either rtapPls > 0 or rtapZrs > 1.
 *     If coefSeq.flg == 0, then all sections are in one cascade,
 *        zero coefs precede zero coefs within a section,
 *        and all coefSeq.fld are ignored.
 *     If coefSeq.flg > 0, then coefSeq dictates how multiple sections are configured.
 * -------------------------------------------------------------------- */
/* NOTE ---------------------------------------------------------------
 * Explanation of Epoch storage in hitmDat:
 *   high word contains the year AD of epoch
 *   low word contains the number of hours into the epoch year
 *   at which time the lotmDat would register zero seconds
 * -------------------------------------------------------------------- */
/* NOTE ---------------------------------------------------------------
 * Explanation of PCA or Palette representation:
 *   For PCA, respCmp is non-zero and the left and right regions
 *   represent weight vectors.  A non-zero respCmp defines
 *   both the number of Singular-Value-Decomposition components
 *   as well as the number of weights in each PCA vector.
 *   rspsTps, rtapZrs, rtapPls then describe the component filters.
 *   The component filters, otherwise known as BASIS FUNCTIONS
 *   are defined as independent regions.
 *   The component filters will never be encrypted.
 * -------------------------------------------------------------------- */



/* --------------------------------------------------------------------
 *  Type Enumerations -------------------------------------------------
 * -------------------------------------------------------------------- */
/* AFMfileType enumeration - defines type of filters within file ------ */
enum AFMfileType {
    AFMfileAHM,  // map of HRTF or SRTF filters
    AFMfileEQF,  // v1.0 EQF file, interpreted as AFMfileEQFREL
    AFMfileAFM,  // generic filter map
    AFMfileEQFREL,  // v1.1 EQF file with relative compensation filter
    AFMfileEQFABS,  // v1.1 EQF file with absolute compensation filter
    AFMfileEQFBPS,  // v1.1 EQF file with band-pass filter
    AFMfileEQFCXO,  // v1.1 EQF file with compensation and X-over band-pass filter
    AFMfileLast  // end of enumeration
};
/* AFMfileType notes:
    For all EQF v1.1 types, Response Sequence must be correct!
    AFMfileEQFREL - equivalent in use to original EQF file
                    specifies compensation for relative position from each sink
                    smooth compensation filter is in the first filter position
                    raw compensation filter is in the second filter position
                    raw data is in subsequent filter positions
                    requires rangOrg to designate calibration position
    AFMfileEQFABS - loudspeaker compensation to absolute point
                    specifies compensation at one absolute position from each sink
                    smooth compensation filter is in the first filter position
                    raw compensation filter is in the second filter position
                    raw data is in subsequent filter positions
                    requires <azimOrg,elevOrg,rangOrg> to designate calibration position
                    AFMfileEQFABS should include SINKVECT region for absolute sink positions
    AFMfileEQFBPS - band-pass filter typically used for loudspeaker cross-overs
                    one sink may be a low-pass filter for a woofer
                    another sink may be a high-pass filter for a tweeter
                    band-pass filter is in first filter position
                    design criteria is specified as first four coefficients
                    in the second position <low-cutoff,low-slope,high-cutoff,high-slope>
    AFMfileEQFCXO - loudspeaker compensation convolved with cross-over band-pass filterset
                    smooth compensation filter is in the first filter position
                    raw compensation filter is in the second filter position
                    design criteria is specified as first four coefficients
                    in the third position <low-cutoff,low-slope,high-cutoff,high-slope>
                    AFMfileEQFCXO should include SINKVECT region for absolute sink positions
*/

/* AHMdistUnits enumeration - defines geometric configuration -------- */
/*   please note that these are identical to the ATRON.H enum
 */
enum AHMscaleUnits {
    AHMdistDefault = 0x00,
    AHMdistInches = AHMdistDefault,
    AHMdistFeet,
    AHMdistMMeters,
    AHMdistCMeters,
    AHMdistMeters,
    AHMdistUnitsLast,
    AHMdistSpecUnits,
    AHManglDefault = 0x10,
    AHManglRadians = AHManglDefault,
    AHManglDegrees,
    AHManglGradians,
    AHManglUnitsLast,
    AHManglSpecUnits,
    AHMtimeDefault = 0x20,
    AHMtimeSamples = AHMtimeDefault,
    AHMtimeSeconds,
    AHMtimeMSecs,
    AHMtimeUSecs,
    AHMtimeUnitsLast,
    AHMtimeSpecUnits,
    AHMlevelDefault = 0x30,
    AHMlevelLinear = AHMlevelDefault,
    AHMlevelDecibels,
    AHMlevelUnitsLast,
    AHMscaleUnitsLast = AHMlevelUnitsLast,
    AHMlevelSpecUnits
  };

/* AHMdataType enumeration - defines geometric configuration -------- */
enum AHMdataType {
    AHMdataTypeNone,
    AHMdataInteger,  // all integers are signed, must be at least 8-bits
    AHMdataFloat,    // all floats must be 32 or 64 bits
    AHMdataTypeLast
  };

/* AHMincrOperation enumeration - defines geometric configuration -------- */
/*   typically used to describe non-linear densities
 */
enum AHMincrOperation {
    AHMincrNone,
    AHMincrAdd,
    AHMincrMult,
    AHMincrTangent,  // converts angular to linear coordinates
    AHMincrLogN,
    AHMincrLog2,
    AHMincrLog10,
    AHMincrNoGrid,  // must have RESPVECT region to specify locations
    AHMincrOpLast
  };

/* AHMaxesConfig enumeration - defines geometric configuration -------- */
enum AHMaxesConfig {
    AHMaxesConfigNone,
    AHMaxesDefault=4,    // corrects for an early default error, equates to Spherical_ZYR
    // for spherical: first axis = azim, second axis = elev
    AHMaxesSpherical_ZYR=1,    // CRE/UWMadison default
    AHMaxesSpherical_YXR=2,    // UCDavis default (this should be YZR)
    AHMaxesSpherical_YZR=2,    // UCDavis default (same rotations as type 9)
    AHMaxesSpherical_XZR=3,
    // for cylindrical: first axis = azim, height = elev
    AHMaxesCylindrical_ZHR=8,
    AHMaxesCylindrical_YHR=5,
    AHMaxesCylindrical_XHR=6,
    // for cartesian: azim = Y, elev = Z, rang = X
    AHMaxesCartesian_YZX=7,
    AHMaxesSpherical_RYZ=9,  // special format with range first, elevation second, azimuth last
    AHMaxesNextConfig=10,    // placeholder
    AHMaxesConfigLast = AHMaxesNextConfig
  };

/* AHMwindowType enumeration - defines filter derivation -------------- */
enum AHMwindowType {
    AHMwndoNone,
    AHMwndoBoxCar,
    AHMwndoBartlett,
    AHMwndoHamming,
    AHMwndoHanning,
    AHMwndoKaiser,
    AHMwndoGausian,
    AHMwndoLast
  };

/* AHMdisplayEQType enumeration - defines embedded display EQ --------- */
enum AHMdisplayEQType {
    AHMdseqNone,
    AHMdseqHeadPhones,
    AHMdseqNearPhones,
    AHMdseqFrontPhones,
    AHMdseqRearPhones,
    AHMdseqSennheiserHD250,
    AHMdseqSennheiserHD540,
    AHMdseqSennheiserHD560,
    AHMdseqSennheiserHD580,
    AHMdseqSennheiserHD570,
    AHMdseqSennheiserHD500,
    AHMdseqSennheiserEH2200,
    AHMdseqCustom,
    AHMdseqLast
  };

/* AHMfieldEQType enumeration - defines any full-field EQ ------------- */
enum AHMfieldEQType {
    AHMfdeqNone,
    AHMfdeqDiffuse,
    AHMfdeqFree,
    AHMfdeqLast
  };

/* AHMlevelEQType enumeration - defines method detecting levels for equalization ------------- */
enum AHMlevelEQType {
    AHMlveqNone,
    AHMlveqGolay,
    AHMlveqSine1K,
    AHMlveqMultiTone,
    AHMlveqWhite,
    AHMlveqPink,
    AHMlveqSwept,           /* sine-sweep, assumed full-spectrum */
    AHMlveqLast,
    AHMlveqContinuous = 32,   /* longer than a burst; OR with other types */
    AHMlveqWeighted = 64,     /* OR with other types, look for weighting filter */
    AHMlveqDistributed = 128  /* OR with other types  */
  };

/* AHMencryptType enumeration - defines encryption method ------------- */
enum AHMencryptType {
    AHMcryptNone,
    AHMcryptCRE,
    AHMcryptAuSIM1,
    AHMcryptLast
  };

/* AHMnormalizationType enumeration - defines normalization method ------------- */
enum AHMnormalizationType {
    AHMnlvlNone,
    AHMnlvlPeak,
    AHMnlvlRMS,
    AHMnlvlLast
  };

/* AHMrespSource enumeration - defines source of polar-cap data --- */
enum AHMrespSource {
    AHMrespNone,
    AHMrespSampled,
    AHMrespTimeInterpol,
    AHMrespFreqInterpol,
    AHMrespModeled,
    AHMrespMirrored,  // valid for one of left or right
    AHMrespGeoCorrected,  // corrected for geometric errors
    AHMrespSourceLast
  };

/* AHMtrackingDevice enumeration - defines head tracking device --- */
enum AHMtrackingDevice {
    AHMtrakNone,
    AHMtrakFastrak,
    AHMtrakIsotrak,
    AHMtrakIC2,
    AHMtrakICube,      // any ISense IC, IC2, IC3, IC2+
    AHMtrakLiberty,    // any Liberty or Liberty LATUS
    AHMtrakPatriot,    // Patriot or Minuteman
    AHMtrakFreespace,  // any Freespace 3DOF
    AHMtrakUSDigital,  // any encoder
    AHMtrakLast
  };


/* AHMenhanceMethod OR bits - define filter enhancement methods ------- */
#define AHM_ENH_None         0x00
#define AHM_ENH_BassExt      0x01   // see bassFrq for cut-off frequency
#define AHM_ENH_CritBand     0x02
#define AHM_ENH_LowModel     0x04   // low-freq model
#define AHM_ENH_LowPass      0x08
#define AHM_ENH_HighPass     0x10
#define AHM_ENH_BandPass     0x18   // low and high pass together

 /* these are constants for the format struct fields (ah_sequence_field)
  * each has seven ordered sequence fields and a flag field
  * Response format constants:
  */
 /* Coef/Section format constants:  */
 #define AHMF_ZEROPOLE       0x00  // flag: zero coefficients precede pole coefs
 #define AHMF_POLEZERO       0x80  // flag: pole coefficients precede zero coefs
 #define AHMF_CASCADE_FIRST  0x00  // flag: cascade N sections
 #define AHMF_PARALLEL_FIRST 0x40  // flag: parallel N sections first
 /* coefSeq - definition
    If flag is zero, then it can be interpretted as prior to v1.50 format.
    However, all filters prior to v1.50 contained only zero coefficients.
    The low-nibble of the flag is a multiplier for N sections of each type.
    The high-nibble determines
       1) the order of zeros vs. poles within a section.
       2) the order of cascades vs. parallels in the sequencing of sections.
   The values of the fields are the number of sections in parallel or being cascaded.
   The total number of sections (respTps) must equal
     PRODUCT( [low-nibble of coefSeq.flg], [each non-zero coefSeq.fld] )
  */

 /* Note: all coefSeq fields and flags defined prior to AHM v1.5 (May 2010) are deprecated */
 #define AHMF_ZERO_dep       0x1  // deprecated zero coefficient
 #define AHMF_POLE_dep       0x2  // deprecated pole coefficient
 #define AHMF_GAIN_dep       0x3  // deprecated gain coefficient
 #define AHMF_FINITE_dep     0x0  // deprecated flag: coefs are FIR
 #define AHMF_INFINITE_dep   0x2  // deprecated flag: coefs are IIR (poles and zeros)
 #define AHMF_CASCADE_dep    0x4  // deprecated flag: sections are in cascade format
 #define AHMF_BIQUAD_dep     0x8  // deprecated flag: coefs are biquads

 /* Vector format constants:  */
 #define AHMF_AZIM           0x1  // azimuth or primary axis
 #define AHMF_ELEV           0x2  // elevation or secondary axis
 #define AHMF_RANG           0x3  // range or tertiary axis
 /* vector sequence specifies the outer-most to inner-most loop */

 /* response sequence constants: */
 #define AHMF_NULL           0x0  // placeholder
 #define AHMF_LEFT           0x1  // left response
 #define AHMF_RGHT           0x2  // right response
 #define AHMF_LATD           0x3  // left aural time delay
 #define AHMF_RATD           0x4  // right aural time delay
 #define AHMF_LALO           0x5  // left aural level offset
 #define AHMF_RALO           0x6  // right aural level offset
 #define AHMF_IATD           0x8  // interaural time difference
 #define AHMF_IALD           0x9  // interaural level difference
 #define AHMF_RESP           0xA  // response (multisink)
 #define AHMF_TIME           0xB  // time delay (multisink)
 #define AHMF_LEVL           0xC  // level offset (multisink)
 #define EQRS_SCMP           0x10  // EQ smooth compensation
 #define EQRS_RCMP           0x11  // EQ raw compensation
 #define EQRS_BPSF           0x12  // EQ band-pass filter
 #define EQRS_BPSD           0x13  // EQ band-pass design
 #define EQRS_RAWD           0x14  // EQ raw data used to derive filter

 #define AHMF_SECTIONED      0x0  // flag: LEFT, RIGHT, IATD, IALD separate sinks groups
 #define AHMF_INTERLEAV      0x1  // flag: LEFT, RIGHT, IATD, IALD interleaved
 #define AHMF_RSPINTRLV      0x2  // flag: responses (LEFT,RIGHT) interleaved, time&level separate table, only applies to interaural tables
 #define AHMF_INTERSECT      0x3  // flag: RESP, TIME, LEVL (interleaved sections)

 /* Region format constants:  */
 #define AHMF_MAPG           0x1  // Rectangular map grid
 #define AHMF_NCAP           0x2  // North cap
 #define AHMF_SCAP           0x3  // South cap
 #define AHMF_POLARCAPS      0x4  // North/South caps, see NcapSrc/ScapSrc if exist
 #define AHMF_BASIS          0x8  // Neutral basis functions
 #define AHMF_BASISLEFT      0x9  // Left basis functions
 #define AHMF_BASISRGHT      0xA  // Right basis functions
 #define AHMF_BASISSINK      0xB  // Basis functions per sink
 #define AHMF_TRAKDATA       0x10 // Actual 6DOF tracked location error vectors
 #define AHMF_TRAKDERR       0x11 // 3DOF tracked location error vectors <delta_azim,delta_elev,delta_rang>
 #define AHMF_RESPVECT       0x20 // Actual response location vectors <azim,elev,rang>
 #define AHMF_noCAPS         0x0  // flag: No caps in file
 #define AHMF_CAPSwMAP       0x1  // flag: Caps are with section
 #define AHMF_CAPSxTRA       0x2  // flag: Caps are in own section
 /* track data are assumed to be 32-bit float sextuple of <X,Y,Z,Yw,Pt,Rl> of difference */
 /* Order of Basis Functions must mirror the responses */
 /*   Responses group all components for each sink together */
 /*   Thus all components for each sink shall be grouped.  */

 /* BonusData sequence constants:  */
 #define AHMF_WEIGHTING      0x0C // Weighting function, if exist, num taps = optmTaps, num pole/zeros same as resp
 #define AHMF_SINKVECT       0x21 // Actual sink Cartesian positions and deflection from the centerdirection, vectors <X,Y,Z,Yw,Pt,Rl>.
 #define AHMF_SINKVECTBRG    0x22 // Actual sink Spherical bearings and deflection from the centerdirection, vectors <Az,El,Rg>.
 #define AHMF_SINKBANDFREQ   0x23 // sink band-pass/cross-over frequency pairs <b,t> in hertz.  Must be of type AFMfileEQFBPS or AFMfileEQFCXO
 #define AHMF_SINKCHNLMAP    0x30 // Sink channel map, allows for sparse sinks, by default 1,2,3...
 #define AHMF_SINKLABEL      0x31 // Sink labels, fixed-length text fields of AFMF_SINKLABEL_LEN size
 #define AHMF_SINKTRIANGLES  0x41 // List of 32-bit integer idx triples, each idx represents a sink/virtnode position
 #define AHMF_CALMICVECT     0x51 // Calibration microphone Cartesian positions and deflection from the centerdirection, vectors <X,Y,Z,Yw,Pt,Rl>.
 #define AHMF_CALMICWEIGHT   0x52 // Calibration microphone weights.
 /* Sink positions are assumed to be 32-bit float */
 /* All angle and length data must be in header units */
 /* Sink Position/Labels: must be (sinkCnt + virtNod) entries */
 /* Triangle list length given by triaCnt */

 /* Preset preferred sequences and formats */
 #define AHMF_NORMAL_SECFMT   (AHMF_ZEROPOLE|0x01)
 #define AHMF_NORMAL_SCTSEQ  { { 1, 0, 0, 0, 0, 0, 0 }, AHMF_NORMAL_SECFMT }
 #define AHMF_NORMAL_COEFMT_dep   (AHMF_ZEROPOLE|0x01)
 #define AHMF_NORMAL_COESEQ_dep  { { 1, 0, 0, 0, 0, 0, 0 }, AHMF_NORMAL_COEFMT }
 #define AHMF_NORMAL_VCTFMT   0
 #define AHMF_NORMAL_VCTSEQ  { { AHMF_RANG, AHMF_AZIM, AHMF_ELEV, 0, 0, 0, 0 }, AHMF_NORMAL_VCTFMT }

 /* in preparation for PCA rep and Multiple Sink AHM:s, we have redefined the default to: */
 #define AHMF_NORMAL_RSPFMT   AHMF_INTERSECT
 #define AHMF_NORMAL_RSPSEQ  { { AHMF_RESP, AHMF_TIME, AHMF_LEVL, 0, 0, 0, 0 }, AHMF_NORMAL_RSPFMT }

// #define AHMF_NORMAL_RSPFMT   AHMF_INTERLEAV
// #define AHMF_NORMAL_RSPSEQ  { { AHMF_LEFT, AHMF_LALO, AHMF_LATD, AHMF_RGHT, AHMF_RALO, AHMF_RATD, 0 }, AHMF_NORMAL_RSPFMT }
// #define AHMF_NORMAL_RSPFMT   AHMF_INTERLEAV
// #define AHMF_NORMAL_RSPSEQ  { { AHMF_LEFT, AHMF_RGHT, AHMF_LALO, AHMF_RALO, \
//                                 AHMF_LATD, AHMF_RATD, 0 }, AHMF_NORMAL_RSPFMT }
// #define AHMF_NORMAL_RSPFMT   AHMF_RSPINTRLV
// #define AHMF_NORMAL_RSPSEQ  { { AHMF_LEFT, AHMF_RGHT, AHMF_LATD, \
//                                 AHMF_RATD, AHMF_LALO, AHMF_RALO, 0 }, AHMF_NORMAL_RSPFMT }

// If TRAKDATA, TRAKDERR, RESPVECT are found in RGNSEQ, then they must exist in data.
 #define AHMF_NORMAL_RGNFMT   AHMF_noCAPS
 #define AHMF_NORMAL_RGNSEQ  { { AHMF_MAPG, AHMF_POLARCAPS, AHMF_BASISSINK, 0, 0, 0, 0 }, AHMF_NORMAL_RGNFMT }
// If WEIGHTING, SINKVECT, SINKCHNLMAP, SINKLABEL, SINKTRIANGLES are found in BSDSEQ, then they must exist in data.
 #define AHMF_NORMAL_BSDFMT   0
 #define AHMF_NORMAL_BSDSEQ  { { 0, 0, 0, 0, 0, 0, 0 }, AHMF_NORMAL_BSDFMT }



/* !!!! ---- The ASCII header is not up to date! ----                 */
/* The following string differentiates the ASCII header from data.    */
/*   It must appear as the first string on a line.                    */
/*   All text on the line after it is ignored.                        */
/*   All text following it is interpretted as data,                   */
/*   unless the symbol "!" appears in the first character of a line.  */

#define AHMF_ASCII_DATA  "AHMDATA"
#define AHMF_ASCII_BANG  '!'   // non-interpreted comment
#define AHMF_ASCII_CMNT  '*'   // concatenated comment

/* Acoustic Head Map Format ASCII Header structure  (upto 20 lines) */
struct aAHMF_ASCIIh {
    char *lng4flds,  // smplRat, nextMap, prevMap, rsrvLg1
         *int4rsps,  // totlRsp, azimRsp, elevRsp, rangRsp,
         *int2taps,  // respTps, rtapCfs
         *flt2flds,  // headSiz, fixpCvt, rsrvRl1;

         *fmt4coef,  // coefSeq;
         *fmt4vctr,  // vctrSeq;
         *fmt4resp,  // respSeq;
         *fmt4regn,  // regnSeq;

         *siz2flds,  // coefSiz, iatdSiz;
         *spc4fld1,  // distFmt, anglFmt, realRsp, readCmt
         *spc4fld2,  // NcapSrc, ScapSrc
         *spc4fld3,  // azimInc, elevInc, rangInc
         *spc4fld4,  // wndoTyp

         *flt3orgs,  // azimOrg, elevOrg, rangOrg
         *flt3ints,  // azimInt, elevInt, rangInt
         *comment ;  // concatenates all lines marked by AHMF_ASCII_CMNT
  };

 /* ASCII header print formats  */
 #define pfmtLng4Flds   "SR:%-14ld NM:%-14ld PM:%-14ld \r\n"
 #define pfmtInt4Rsps   "RESP T:%-8d A:%-8d E:%-8d R:%-8d\r\n"
 #define pfmtInt2Taps   "TAPS N:%-8d C:%-8d\r\n"
 #define pfmtSiz2Flds   "SIZE C:%-8d I:%-8d\r\n"
 #define pfmtSeq4Flds   "FMT-%4s: %7s %7s %7s %7s\r\n"
 #define pfmtSpc4Flds   "SPEC: %11s %11s %11s %11s\r\n"
 #define pfmtFlt2Flds   "HS:%-8.4f FC:%-8.4f\r\n"
 #define pfmtFlt3Orgs   "ORIGIN A:%-8.4f E:%-8.4f R:%-8.4f\r\n"
 #define pfmtFlt3Ints   "INTERV A:%-8.4f E:%-8.4f R:%-8.4f\r\n"

 /* ASCII header scan formats  */
 #define sfmtLng4Flds   "SR:%ld NM:%ld PM:%ld \r\n"
 #define sfmtInt4Rsps   "RESP T:%d A:%d E:%d R:%d\r\n"
 #define sfmtInt2Taps   "TAPS N:%d C:%d\r\n"
 #define sfmtSiz2Flds   "SIZE C:%d I:%d\r\n"
 #define sfmtSeq4Flds   "FMT-%s: %s %s %s %s\r\n"
 #define sfmtSpc4Flds   "SPEC: %s %s %s %s\r\n"
 #define sfmtFlt2Flds   "HS:%f FC:%f\r\n"
 #define sfmtFlt3Orgs   "ORIGIN A:%f E:%f R:%f\r\n"
 #define sfmtFlt3Ints   "INTERV A:%f E:%f R:%f\r\n"


/* This is the special Snapshot ENCRYPTED format header
 *   the version MUST BE: AHv1.3                        */
struct AH13_HDR_FMT {
    char magic_number[2];      /* Always 'AH' */
    char version[6];           /* Always in the form "v%4.2f" */
    char subject[62];          /* Subject's name or initials */
    char crlf_1[2];
    char copyright[78];
    char crlf_2[2];
    char date[12];
    char time[12];
    char sample_rate[12];
    char tap_count[12];        /* Number of taps */
    char response_count[12];   /* Number of responses */
    char crlf_3[12];
    char notes[254];
    char terminator[2];        /* CTRL-Z followed by a NULL */
};

/* ======================================================================== *
 * this bit-field structure was used in AHM v1.0, v1.1, and v1.2
 * it was created as a highly dense packing for boolean data
 * in v1.4 the binary header was extended from 128 to 256 bytes
 * and thus this data was converted to unsigned chars --------------------- */
/*  BINARY specification bit fields                         */
/*    these should be necessary for interpreting the data.  */
/*    Since bit-fields are not portable across CPUs,        */
/*    the alignment lo-bit is always set, the hi-bit unset.  */
struct ah_spec_bits {
    unsigned   algnLow:2;        // alignment low bit ALWAYS SET
    unsigned   distFmt:2;        //        meters/inches
    unsigned   anglFmt:2;        //        rads/degs/grads
    unsigned   coefFlt:1;        //  integer/float coefficients
    unsigned   readCmt:1;        //  specialized map

    unsigned   NcapSrc:2;        // none/sampled/infered
    unsigned   ScapSrc:2;        // none/sampled/infered
    unsigned   wghtFlt:1;        // integer/float component weights
    unsigned   iatdFlt:1;        // integer/float time delays
    unsigned   timeFmt:2;        // sample/secs/millisecs time delay

    unsigned   azimInc:2;        // add/multiply/log
    unsigned   elevInc:2;        // add/multiply/log
    unsigned   rangInc:2;        // add/multiply/log
    unsigned   crptMap:1;        // encryption off/on

    unsigned   bassBst:1;        // Bass-boosting
    unsigned   rsrvBt1:6;        // reserved bits -- future use
    unsigned   algnHig:1;        // alignment hi bit ALWAYS UNSET
  };



/* Acoustic Head Map Format v1.2 BINARY Header structure (128 bytes) */
struct AH12_HDR_FMT {
    unsigned long                             // 4 bytes each  (32 bytes)
        // offsets are relative to first byte after header,
        // which is where the file pointer is pointing after sucking header.
        nextMap,  // offset next map     (0 default)
        prevMap,  // offset previous map (0 default)
        thisMap,  // offset for this map (0 default), indicates comment
        totlSiz,  // total bytes in file, including header for verification
        totlRsp,  // total responses stored (including caps)
        rsrvLng[1],
        lotmDat,  // low-dword of UTC time/date code, must be 64-bit boundary
        hitmDat;  // high-dword of UTC time/date code
    float                                     // 4 bytes each  (16 bytes)
        smplRat,  // sample rate in Hertz
        headSiz,  // interaural distance in range units
        fixpCvt,  // fixed point coefficient conversion value.
        rsrvFlt[1];
    unsigned short                            // 2 bytes each  (16 bytes)
        azimRsp,  // grid azimuth responses
        elevRsp,  // grid elevation responses
        rangRsp,  // grid range responses
        respTps,  // response taps (poly order)
        rtapZrs,  // response tap zero coefficients (zeros per tap)
        rtapPls,  // response tap pole coefficients (poles per tap)
        respCmp,  // response components (number of weights if PCA)
        cmprTps,  // compression optimization size
        rsrvSht[1];
    unsigned char                             // 1 bytes each  (16 bytes)
        coefSiz,  // bits per coefficient
        iatdSiz,  // bits per delay
        wghtSiz,  // bits per weight
        wndoTyp,  // see WindowType enum
        dseqTyp,  // display equalization type, see AHMdisplayEQType enum
        fdeqTyp,  // field equalization method, see AHMfieldEQType enum
        sphrAxs,  // spherical axis order, see AHMsphrAxis
        rsrvChr[9];
    ah_sequence_field                         // 4 bytes each  (16 bytes)
        coefSeq,  // order of  coefs:  zero, pole, gain
        vectSeq,  // order of vector:  azim, elev, rang
        respSeq,  // order of  resps:  left, right, iatd
        regnSeq;  // order of regions: mapgrid, northcap, southcap
    union {                                   // 4 bytes each  ( 8 bytes)
      ah_spec_bits   b;
      unsigned long  codeSpc, rsrvBts;
    };
    float                                     // 4 bytes each  (24 bytes)
        azimOrg,
        elevOrg,
        rangOrg,
        azimInt,
        elevInt,
        rangInt;
  };


#endif   // Au_AHM_HDR_H

