This project has moved and is read-only. For the latest updates, please go here.

DataChunk header in wrong position

Jun 22, 2015 at 7:12 PM
I am quite new at using naudio and I am following an example provided I found on this site to trim wav files. I am using the example along with my own code to determine the lengths of wave files and trimming them to be at a length that I can use.

The program works great, it trims them perfectly everytime, exactly how I need them except for the datachunk. It is always 2 positions forward. Looking at my wav file in HxD, my original wav file datachunk is in position 37-40.

After I trim the file the datachunk is in position 39-42. This causes a problem in the other program I an using to look at the files. I have tried opening in Audacity and exporting and the datachunk position gets corrected, not sure why but it does. I have also altered the position in HxD and that works too but I would rather not have to go through all of the extra steps if I do not have to.
As I am new to naudio I am unsure if I am doing something wrong (Very possible) and I have looked for similar problems for a few days now and cannot find a single solution.

Here is the code I found through this site. The rest of my code just determines the amount that I need to trim based on the lot of files I am altering. I just read a wave file, trim and store in a different folder.

any help would be greatly appreciated, if you need any more information please let me know and I will provide what I am able to.
 public static void TrimWavFile(string inPath, string outPath, TimeSpan cutFromStart, TimeSpan cutFromEnd)
        {
            using (WaveFileReader reader = new WaveFileReader(inPath))
            {
                using (WaveFileWriter writer = new WaveFileWriter(outPath, reader.WaveFormat))
                {
                    int bytesPerMillisecond = reader.WaveFormat.AverageBytesPerSecond / 1000;

                    int startPos = (int)cutFromStart.TotalMilliseconds * bytesPerMillisecond;
                    startPos = startPos - startPos % reader.WaveFormat.BlockAlign;

                    int endBytes = (int)cutFromEnd.TotalMilliseconds * bytesPerMillisecond;
                    endBytes = endBytes - endBytes % reader.WaveFormat.BlockAlign;
                    int endPos = (int)reader.Length - endBytes;

                    TrimWavFile(reader, writer, startPos, endPos);
                }
            }
        }

        private static void TrimWavFile(WaveFileReader reader, WaveFileWriter writer, int startPos, int endPos)
        {
            reader.Position = startPos;
            byte[] buffer = new byte[1024];
            while (reader.Position < endPos)
            {
                int bytesRequired = (int)(endPos - reader.Position);
                if (bytesRequired > 0)
                {
                    int bytesToRead = Math.Min(bytesRequired, buffer.Length);
                    int bytesRead = reader.Read(buffer, 0, bytesToRead);
                    if (bytesRead > 0)
                    {
                        writer.WriteData(buffer, 0, bytesRead);
                    }
                }
            }
        }
Jun 22, 2015 at 7:21 PM
this will most likely by that NAudio writes a WAVEFORMATEX structure rather than a WAVEFORMAT structure. It has two more bytes. This really shouldn't be a problem with other software.
Jun 22, 2015 at 7:31 PM
The other program, that I did not write, is using the files for analysis, the files it reads for some reason does not like the 2 extra bytes. It just crashes. Is there a way to do a WAVEFORMAT through NAudio or a way to alter the file programmatically instead of the extra few steps? Not looking for a handout just if it is possible and possibly point me in the right direction?
Jun 22, 2015 at 7:53 PM
the problem is that it's fairly hard-coded into WaveFormat.Serialize. However, you could create your own custom WaveFormat class that derives from WaveFormat and overrides Serialize to not write the extraSize. Something like this (not tested)
        public override void Serialize(BinaryWriter writer)
        {
            writer.Write((int)(16 + extraSize)); // wave format length
            writer.Write((short)Encoding);
            writer.Write((short)Channels);
            writer.Write((int)SampleRate);
            writer.Write((int)AverageBytesPerSecond);
            writer.Write((short)BlockAlign);
            writer.Write((short)BitsPerSample);
        }
Jun 22, 2015 at 7:58 PM
oh boy this will be interesting lol. I really appreciate the help! Now to see if I can figure out how to do something like that :)
Jun 22, 2015 at 8:35 PM
Thank you so much! I believe this to have worked. I have not extensively tested the solution but it has not crashed my program when trying to run a file!

Much Appreciated
Feb 18, 2016 at 1:07 PM
Edited Feb 18, 2016 at 1:11 PM
markheath wrote:
this will most likely by that NAudio writes a WAVEFORMATEX structure rather than a WAVEFORMAT structure. It has two more bytes. This really shouldn't be a problem with other software.
FYI there are a few apps/libs that rely on WAVEFORMAT and error out on WAVEFORMATEX.
Personally I think it may be a good idea to add WAVEFORMAT support.

I realise the issue with Serialize() but perhaps there is a way to specify the preferred format before or during the call to Serialize?

The Aubio.org library is one example, I had to create my own Wav writer instead of simply using nAudio. Aubio would error out saying "Not a PCM format" since the 18 byte WAVEFORMATEX header was on the TODO list.
Took me hours to code it due to lack of consistent documentation, but at least I know the WAV format back to front now lol