c# - How can I get the data of 8bit wav file -


i'm making demo sound in windowsform, created 3 classes taking data of wave file. code below:

riffblock

public class riffblock     {         private byte[] riffid;         private uint riffsize;         private byte[] riffformat;         public byte[] riffid         {             { return riffid; }         }          public uint riffsize         {             { return (riffsize); }         }          public byte[] riffformat         {             { return riffformat; }         }         public riffblock()         {             riffid = new byte[4];             riffformat = new byte[4];         }         public void readriff(filestream infs)         {             infs.read(riffid, 0, 4);             binaryreader binread = new binaryreader(infs);             riffsize = binread.readuint32();             infs.read(riffformat, 0, 4);         }     } 

formatblock

public class formatblock         {             private byte[] fmtid;             private uint fmtsize;             private ushort fmttag;             private ushort fmtchannels;             private uint fmtsamplespersec;             private uint fmtaveragebytespersec;             private ushort fmtblockalign;             private ushort fmtbitspersample;             public byte[] fmtid             {                 { return fmtid; }             }              public uint fmtsize             {                 { return fmtsize; }             }              public ushort fmttag             {                 { return fmttag; }             }              public ushort channels             {                 { return fmtchannels; }             }              public uint samplespersec             {                 { return fmtsamplespersec; }             }              public uint averagebytespersec             {                 { return fmtaveragebytespersec; }             }              public ushort blockalign             {                 { return fmtblockalign; }             }              public ushort bitspersample             {                 { return fmtbitspersample; }             }             public formatblock()             {                 fmtid = new byte[4];             }             public void readfmt(filestream infs)             {                 infs.read(fmtid, 0, 4);                  binaryreader binread = new binaryreader(infs);                  fmtsize = binread.readuint32();                 fmttag = binread.readuint16();                 fmtchannels = binread.readuint16();                 fmtsamplespersec = binread.readuint32();                 fmtaveragebytespersec = binread.readuint32();                 fmtblockalign = binread.readuint16();                 fmtbitspersample = binread.readuint16();                  // accounts variable format header size                  // 12 bytes of riff header, 4 bytes formatid, 4 bytes formatsize & actual size of format header                  infs.seek(fmtsize + 20, system.io.seekorigin.begin);             }         } 

datablock

public class datablock         {             private byte[] dataid;             private uint datasize;             private int16[] data;             private int datanumsamples;              public byte[] dataid             {                 { return dataid; }             }              public uint datasize             {                 { return datasize; }             }              public int16 this[int pos]             {                 { return data[pos]; }             }              public int numsamples             {                 { return datanumsamples; }             }             public datablock()             {                 dataid = new byte[4];             }              public void readdata(filestream infs)             {                 infs.read(dataid, 0, 4);                  binaryreader binread = new binaryreader(infs);                  datasize = binread.readuint32();                  data = new int16[datasize];                  infs.seek(40, seekorigin.begin);                  datanumsamples = (int)(datasize / 2);                  (int = 0; < datanumsamples; i++)                 {                     data[i] = binread.readint16();                 }             }         } 

it works ok 16bit wave file, when choose 8 bit wav file or another, result of command datasize = binread.readuint32();is 4 although file size big.

how can data of 8bit, 24bit... wav file? solutions appreciated, thank much.

your reading methodology flawed. length correct 8 bits per sample file should reading bytes not words; stands data incorrect , value returned numsamples property wrong.

in case, sub chunk size 1160, number of channels 1 (mono) , bits per sample 8 (byte). need decode bits per sample , adjust reading accordingly. wav file used, program allocated data array correct length 16 bit, divided data length 2 , called number of samples (wrong, should 1160) , proceeded read 580 word values stream.


edit: ancient code not cut in modern age (i seem recall having modify years ago cope @ least 1 additional chunk type details escape me).

this get; more , question should read "could write me program load wav files", is, way beyond original question , time knuckle down , make work how need :-)

references:

all useful.

///<summary> ///reads 16 bit wav files ///</summary> ///<remarks> things have changed in last 15 years</remarks> public class riffloader {     public enum riffstatus { unknown = 0, ok, fileerror, formaterror, unsupportedformat };      linkedlist<chunk> chunks = new linkedlist<chunk>();      riffstatus status = riffstatus.unknown;     list<string> errormessages = new list<string>();     string source;      public string sourcename { { return source; } }     public riffstatus status { { return status; } }     public string[] messages { { return errormessages.toarray(); } }      enum chunktype { unknown = 0, nomore, riff, fmt, fact, data, error = -1 };      static int32 scan32bits(byte[] source, int offset = 0)     {         return source[offset] | source[offset + 1] << 8 | source[offset + 2] << 16 | source[offset + 3] << 24;     }     static int32 scan16bits(byte[] source, int offset = 0)     {         return source[offset] | source[offset + 1] << 8;     }      static int32 scan8bits(byte[] source, int offset = 0)     {         return source[offset];     }      abstract class chunk     {         public chunktype ident = chunktype.unknown;         public int bytecount = 0;     }      class riffchunk : chunk     {         public riffchunk(int count)         {             this.ident = chunktype.riff;             this.bytecount = count;         }     }      class fmtchunk : chunk     {         int formatcode = 0;         int channels = 0;         int samplespersec = 0;         int avgbytespersec = 0;         int blockalign = 0;         int bitspersample = 0;         int significantbits = 0;          public int format { { return formatcode; } }         public int channels { { return channels; } }         public int blockalign { { return blockalign; } }         public int bytespersample { { return bitspersample / 8 + ((bitspersample % 8) > 0 ? 1 : 0); } }         public int bitspersample         {                         {                 if (significantbits > 0)                     return significantbits;                 return bitspersample;             }         }          public fmtchunk(byte[] buffer) : base()         {             int size = buffer.length;              // if length 18 buffer 16,17 should 00 00 (i don't bother checking)             if (size != 16 && size != 18 && size != 40)                 return;             formatcode = scan16bits(buffer, 0);             channels = scan16bits(buffer, 2);             samplespersec = scan32bits(buffer, 4);             avgbytespersec = scan32bits(buffer, 8);             blockalign = scan16bits(buffer, 12);             bitspersample = scan16bits(buffer, 14);              if (formatcode == 0xfffe) // extensible             {                 if (size != 40)                     return;                     significantbits = scan16bits(buffer, 18);                     // skiping speaker map                     formatcode = scan16bits(buffer, 24); // first 2 bytes of guid                     // rest of guid fixed, decode , check if wish             }              this.ident = chunktype.fmt;             this.bytecount = size;         }      }     class datachunk : chunk     {         byte[] samples = null;         ///<summary>         ///create data chunk         ///<para>         ///the supplied buffer must correctly sized 0 offset , must purely class         ///</para>         ///<summary>         ///<param name="buffer">source array</param>         public datachunk(byte[] buffer)         {             this.ident = chunktype.data;             this.bytecount = buffer.length;             samples = buffer;         }          public enum samplestatus { ok, duff }         public class samples         {             public samplestatus status = samplestatus.duff;             public list<int[]> channels = new list<int[]>(); #if false // debugger helper method             /*             ** change #if false #if true include             ** break @ end of getsamples on "return retval"             ** open immediate window , type retval.dumplast(16)             ** in output window dump of last 16 entries             */             public int dumplast(int count)             {                 (int = channels[0].length - count; < channels[0].length; i++)                     console.writeline(string.format("{0:x4} {1:x4},{2:x4}", i, channels[0][i], channels[1][i]));                 return 0;             } #endif         }         /*         ** return decoded samples         */         public samples getsamples(fmtchunk format)         {             samples retval = new samples();             int samplesperchannel = this.bytecount / (format.bytespersample *  format.channels);             int mask = 0;             int [][] samples = new int [format.channels][];              (int c = 0; c < format.channels; c++)                 samples[c] = new int[samplesperchannel];              if (format.bitspersample >= 8 && format.bitspersample <= 16) // 24+ left excercise             {                 mask = (int)math.floor(math.pow(2, format.bitspersample) - 1);                  int offset = 0, index = 0;                 while (index < samplesperchannel)                 {                     (int c = 0; c < format.channels; c++)                     {                         switch (format.bytespersample)                         {                         case 1:                             samples[c][index] = scan8bits(this.samples, offset) & mask;                             break;                         case 2:                             samples[c][index] = scan16bits(this.samples, offset) & mask;                             break;                         }                         offset += format.bytespersample;                      }                     ++index;                 }                 retval.channels = new list<int[]>(samples);                 retval.status = samplestatus.ok;             }             return retval;         }     }      class factchunk : chunk     {         int samplesperchannel;          public int samplesperchannel { { return samplesperchannel; } }         public factchunk(byte[] buffer)         {             this.ident = chunktype.fact;             this.bytecount = buffer.length;              if (buffer.length >= 4)                 samplesperchannel = scan32bits(buffer);         }     }     class dummychunk : chunk     {         public dummychunk(int size, chunktype type = chunktype.unknown)         {             this.ident = type;             this.bytecount = size;         }     }      public riffloader(string filename)     {         source = filename;         try         {             using (filestream fs = new filestream(filename, filemode.open, fileaccess.read))             using (binaryreader reader = new binaryreader(fs))             {                 chunk c = getchunk(fs, reader);                 if (c.ident != chunktype.riff)                 {                     status = riffstatus.fileerror;                     errormessages.add(string.format("error loading \"{0}\": no valid header"));                 }                 chunks.addlast(c);                 c = getchunk(fs, reader);                 if (c.ident != chunktype.fmt)                 {                     status = riffstatus.fileerror;                     errormessages.add(string.format("error loading \"{0}\": no format chunk"));                 }                 chunks.addlast(c);                 /*                 ** on keep scanning end of file                 */                 while (fs.position < fs.length)                 {                     c = getchunk(fs, reader);                     switch (c.ident)                     {                     case chunktype.fact:                     case chunktype.data:                         chunks.addlast(c);                         break;                     case chunktype.unknown:                         break; // skip - don't care                     }                 }                 fmtchunk format = null;                  foreach (var chunk in chunks)                 {                      switch(chunk.ident)                     {                     case chunktype.fmt:                         format = chunk fmtchunk;                         break;                     case chunktype.data:                         if (format != null)                         {                             datachunk dc = chunk datachunk;                             var x = dc.getsamples(format);                         }                         break;                     }                 }             }          }         catch (exception e)         {             status = riffstatus.fileerror;             errormessages.add(string.format("error loading \"{0}\": {1}", e.message));         }     }       /*     ** chunk of data file - knows nothing of internal format of chunk.     */     chunk getchunk(filestream stream, binaryreader reader)     {         byte[] buffer;         int size;          buffer = reader.readbytes(8);         if (buffer.length == 8)         {             string prefix = new string(encoding.ascii.getchars(buffer, 0, 4));             size = scan32bits(buffer, 4);              if (size + stream.position <= stream.length) // skip if there isn't enough data             {                 if (string.compare(prefix, "riff") == 0)                 {                     /*                      ** "wave" type acceptable                     **                     ** don't read size bytes or entire file end in riff chunk                     */                     if (size >= 4)                     {                         buffer = reader.readbytes(4);                         string ident = new string(encoding.ascii.getchars(buffer, 0, 4));                         if (string.compareordinal(ident, "wave") == 0)                             return new riffchunk(size - 4);                     }                 }                 else if (string.compare(prefix, "fmt ") == 0)                 {                     if (size >= 16)                     {                         buffer = reader.readbytes(size);                         if (buffer.length == size)                             return new fmtchunk(buffer);                     }                 }                 else if (string.compare(prefix, "fact") == 0)                 {                     if (size >= 4)                     {                         buffer = reader.readbytes(4);                         if (buffer.length == size)                             return new factchunk(buffer);                     }                 }                 else if (string.compare(prefix, "data") == 0)                 {                     // assume there has data                     if (size > 0)                     {                         buffer = reader.readbytes(size);                         if ((size & 1) != 0) // odd length?                         {                             if (stream.position < stream.length)                                 reader.readbyte();                             else                                 size = -1; // force error - there should pad byte                         }                         if (buffer.length == size)                             return new datachunk(buffer);                     }                 }                 else                 {                     /*                     ** there number of weird , wonderful block types - assume there has data                     */                     if (size > 0)                     {                         buffer = reader.readbytes(size);                         if ((size & 1) != 0) // odd length?                         {                             if (stream.position < stream.length)                                 reader.readbyte();                             else                                 size = -1; // force error - there should pad byte                         }                         if (buffer.length == size)                         {                             dummychunk skip = new dummychunk(size);                             return skip;                         }                     }                 }             }         }         return new dummychunk(0, chunktype.error);     } } 

you need add properties required , code navigate returned linked list. particular properties may need sample rates in format block, assuming going process data in way.

adding 24 32 bits simple, if need go beyond 32 bits have switch int64's.

i have tested samples http://www-mmsp.ece.mcgill.ca/documents/audioformats/wave/samples.html, 8 bit file, , decodes ok , seems have correct data.

you should more capable of making work now, luck.


Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -