From alt.binaries.sounds.misc Wed Feb 19 18:07:33 1992
Path: cs.tu-berlin.de!fauern!ira.uka.de!sol.ctr.columbia.edu!zaphod.mps.ohio-state.edu!qt.cs.utexas.edu!cs.utexas.edu!rutgers!cmcl2!panix!entropy
From: entropy@panix.com (Daniel Gross)
Newsgroups: alt.binaries.sounds.misc
Subject: Re: SoundBlaster file format information
Keywords: VOC SND BLAST SOUND INFO FORMAT FILE PC ECHO TANGO FOXTROT
Message-ID: <1992Feb17.024108.5930@panix.com>
Date: 17 Feb 92 02:41:08 GMT
References: <14FEB199210031263@cl2.cl.uh.edu>
Organization: PANIX Public Access Unix, NYC
Lines: 129

In <14FEB199210031263@cl2.cl.uh.edu> csci1176@cl2.cl.uh.edu (Kirk Odle (getting less green in netmail)) writes:

>Is there any information available in the public domain regarding the format
>of commonly used PC Sound boards.  I am most interested in VOC files.  My

I've been e-mailing to many people individually with the same question, so
maybe it's time to upgrade the question to the blessed status of FAQ. Here is
my submission for the standard reply. I sure hope you like C....

:-) Daniel

-------------------- STUFF FOLLOWS ----------------------------

#define BYTE unsigned char
#define UWRD unsigned long
#define UINT unsigned int
.
#pragma pack( 1 )
.
.
typedef enum _PackType {
        unp8 = 0,                               /* 8 bits unpackaed */
        unp4,                           /* 4 bits packed (ADPCM) */
        unp25,                          /* 2.5 bits packed */
        unp2,                           /* 2 bits packed */
        multi1,                         /* 1-channel Multi-DAC */
        multi2,                         /* 2-channel ... */
        multi3,                         /* etc. */
        multi4,
        multi5,
        multi6,
        multi7
} PackType;
.
/* VOC file block types  -- note types in file are BYTES while the enum values may be 2 bytes */
.
typedef enum _BlockType {
        EndBlock = 0,                   /* end block -- last byte in any .VOC file */
        VocBlock = 1,                   /* voice block */
        SubVocBlock = 2,                /* subsequent voice block */
        SilenceBlock = 3,               /* silence block */
        MarkerBlock = 4,                /* marker */
        MessageBlock = 5,               /* embedded ASCII text block */
        RepeatBlock = 6,                /* start-repeat group marker */
        EndRepeatBlock = 7              /* end-repeat group marker */
} BlockType;
.
.
/*
        NOTE: we don't use the PackType enum in struct's below since we can't
        be sure it'll be one byte wide (MSC 6.0 sizeof(enum) == sizeof(int)).
*/
.
.
typedef struct _voc_hdr {
        char            filedesc[20];           /* Always "Creative Voice File" + 0x1A */
        int             dataoffset;             /* offset from file start to voice data (0x1A for now) */
        BYTE            lovers, hivers; /* minor & major version numbers */
        int             vfID;                   /* voice file ID, complement of version & 0x1234 */
} voc_hdr;
.
.
/* macro for stuffing three bytes into a long int (for blocklen fields below) */
.
#define ToLong(l,b)             *(((BYTE *)&l) + 0)     = b[0]; \
                                        *(((BYTE *)&l) + 1)     = b[1]; \
                                        *(((BYTE *)&l) + 2)     = b[2]; \
                                        *(((BYTE *)&l) + 3)     = 0
.
typedef struct  _voice_block {  /* BlockType == VocBlock */
        BYTE            blocklen[3];            /* 3 bytes of block length */
        BYTE            samprate;                       /* Actual rate is 256 - 1000000 / samprate */
        BYTE            packcode;                       /* one-byte packcode, see PackType enum for values */
} voice_block;
.
#define Sampling(s)                             ((UWRD) (1000000L / (UWRD) ((256 - s))))
#define Duration(bytes,samp)            ((UWRD) (((long)((bytes) * 1000L))/Sampling(samp)))
.
typedef struct _svoc_block {            /* BlockType == SubVocBlock */
        BYTE            blocklen[3];            /* 3 bytes of block length */
} svoc_block;
.
.
typedef struct _silnc_block {           /* BlockType == SilenceBlock */
        BYTE            blocklen[3];            /* 3 bytes of block length -- fixed at 3 for silence */
        UINT            period;                 /* duration of silence - 1 */
        BYTE            samprate;                       /* silence's sampling byte (same formula as for voc_block) */
} silence_block;
.
.
typedef struct _voc_marker {            /* BlockType == MarkerBlock */
        BYTE            blocklen[3];            /* 3 bytes of block length, always == 2 for marker */
        UINT            markvalue;              /* value of mark, range 1 to 0xfffe */
} voc_marker;
.
.
typedef struct _msg_block {             /* BlockType == MessageBlock */
        BYTE            blocklen[3];            /* 3 bytes of block length */
} msg_block;                                    /* block followed by blocklen bytes of null-term'd string */
.
.
typedef struct _rpt_block {             /* BlockType == RepeatBlock */
        BYTE            blocklen[3];            /* 3 bytes of block length, always == 2 for repeat */
        UINT            count;                  /* repeat count - 1 */
} rpt_block;
.
.
typedef struct _end_rpt_block { /* BlockType == EndRepeatBlock (7) */
        BYTE            blocklen[3];            /* 3 bytes of block length, always == 0 for end-repeat */
} end_rpt_block;
.
.
typedef union _vocblock {
        voice_block     v;
        svoc_block      sv;
        silence_block   s;
        voc_marker      m;
        msg_block               a;
        rpt_block               r;
        end_rpt_block   er;
} VOCBLOCK;
.
.
----------------------- STUFF ENDS -------------------------

-- 
  Daniel Gross              \  My opinions ALWAYS
  FLOW Research, Inc.       |  reflect those of my company.
  entropy@panix.com         |  If yours don't, consider quitting.

