c# - Why does SoundEffect.FromStream() throw InvalidOperationException when reading "valid" WAV files? -


i'm trying load sound effects game (c#/xna 4.0, visual studio 2013 on win8.1). game "clone" of existing mmorpg client , should compatible existing directory structure - meaning sound effects stored in directory named 'sfx' in game's working directory.

i came across soundeffect.fromstream when attempting accomplish this. works great of files have, files throw invalidoperationexception. stack trace reveals error located in internal wav file constructor within xna dll.

i'm aware of restrictions on wav files soundeffect.fromstream method: 8 or 16 bit, mono or stereo, pcm, sample rate between 8khz , 48khz. problem having best of knowledge, specific wav files failing load meet of these requirements.

here how loading wav files:

//soundinfo wrapper around soundeffect //  implementation details not relevant question private readonly list<soundinfo> m_guitarsounds; private readonly list<soundinfo> m_harpsounds; private readonly list<soundinfo> m_sounds;  //... additional initialization  foreach (string sfx in soundfiles) {     using (filestream fs = new filestream(sfx, filemode.open,             fileaccess.read, fileshare.read))     {         int samples = getsamplespersecond(sfx);          soundeffect nexteffect;         try         {             nexteffect = soundeffect.fromstream(fs);         }         catch (invalidoperationexception)         {             //i got idea stackoverflow answer             nexteffect = new soundeffect(file.readallbytes(sfx), samples,                                           audiochannels.mono);         }          if (sfx.tolower().contains("gui"))             m_guitarsounds.add(new soundinfo(nexteffect));         else if (sfx.tolower().contains("har"))             m_harpsounds.add(new soundinfo(nexteffect));         else             m_sounds.add(new soundinfo(nexteffect));     } } 

on failure, effect constructed byte array of data read file , forced mono. seems work errors arise due invalidoperationexception. sound quite distorted in these cases.

below code getsamplespersecond (referenced in above code):

private int getsamplespersecond(string filename) {     //this method in place debugging purposes used     //  samplespersec audio files can't     //  loaded using fromstream     byte[] wav = file.readallbytes(filename);      // past other sub chunks data subchunk:     int pos = 12;   // first subchunk id 12 16      //get fmt chunk     while (!((char)wav[pos] == 'f' && (char)wav[pos + 1] == 'm' &&              (char)wav[pos + 2] == 't' && (char)wav[pos + 3] == ' '))     {         pos += 4;         int chunksize = wav[pos] + wav[pos + 1] * 256 +                          wav[pos + 2] * 65536 + wav[pos + 3] * 16777216;         pos += 4 + chunksize;     }     pos += 8;      int format = wav[pos] + wav[pos + 1]*256;     pos += 2;     int channels = wav[pos] + wav[pos + 1]*256;     pos += 2;     int samplespersec = wav[pos] + wav[pos + 1]*256 + wav[pos + 2]*65536                         + wav[pos + 3]*16777216;     pos += 4;     int avgbytespersec = wav[pos] + wav[pos + 1]*256 + wav[pos + 2]*65536                         + wav[pos + 3] * 16777216;     pos += 4;     int blockalign = wav[pos] + wav[pos + 1]*256;     pos += 2;      int bitspersample = 0;     if (format == 1)     {         bitspersample = wav[pos] + wav[pos + 1]*256;         //pos += 2; //necessary if want @ other chunks     }      return samplespersec; } 

with debug logging statements thrown in, got these file contents. section failures, , there 9 failures in total (scroll right!):

sfx\sfx001.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16   sfx\sfx002.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16    [ failed ] sfx\sfx003.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16    [ failed ] sfx\sfx004.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=22050, blockalign=1, bitspersample=8   sfx\sfx005.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16    [ failed ] sfx\sfx006.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16    [ failed ] sfx\sfx007.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16   sfx\sfx008.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=22050, blockalign=1, bitspersample=8   sfx\sfx009.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16   sfx\sfx010.wav: format=1, channels=2, samplespersec=22050, avgbytespersec=88200, blockalign=4, bitspersample=16    [ failed ] sfx\sfx011.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16   sfx\sfx012.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16    [ failed ] sfx\sfx013.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16   sfx\sfx014.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=22050, blockalign=1, bitspersample=8   sfx\sfx015.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16   sfx\sfx016.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16    [ failed ] sfx\sfx017.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16    [ failed ] sfx\sfx018.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16    [ failed ] sfx\sfx019.wav: format=1, channels=1, samplespersec=22050, avgbytespersec=44100, blockalign=2, bitspersample=16   

the values printed above log printed directly getsamplespersecond method after reading wav file header ('fmt ' chunk). used http://www.neurophys.wisc.edu/auditory/riff-format.txt reference determining meaning of data in wav file.

according log, each of files pcm, 8- or 16-bit, 22050hz sample rate, , either mono or stereo (based on channel count). files open fine in original game client , work in audacity windows media player, can rule out problem files themselves.

what missing here? , if incompatibility source audio files, there way can load them , play them work, without using content pipeline?

the files failed load each throwing invalidoperationexception due malformed files, not because of wav format restrictions.

the error occurred in files length reported in bytes 4, 5, 6, , 7 of files different actual length of data riff.

windows media player , audacity compensating error, soundeffect.fromstream() detecting , throwing exceptions.

here working method used solve problem:

private void _correctthefilelength(string filename) {     byte[] wav = file.readallbytes(filename);      string riff = encoding.ascii.getstring(wav.subarray(0, 4));     if (riff != "riff" || wav.length < 8) //check riff tag , length         return;      int reportedlength = wav[4] + wav[5]*256 + wav[6]*65536 + wav[7]*16777216;     int actuallength = wav.length - 8;     if (reportedlength != actuallength)     {         wav[4] = (byte) (actuallength & 0xff);         wav[5] = (byte) ((actuallength >> 8) & 0xff);         wav[6] = (byte) ((actuallength >> 16) & 0xff);         wav[7] = (byte) ((actuallength >> 24) & 0xff);         file.writeallbytes(filename, wav);     } } 

Popular posts from this blog