How do I write RIFF chunk data to the end of a WAV file? Yes, that's right, to the end of a WAV file. Why? Because that's the way the old program I'm replacing did it and the integrating programs are prepared for it that way and they cannot be modified.
-
possible duplicate of [NTFS Alternate Data Streams - .NET](http://stackoverflow.com/questions/604960/ntfs-alternate-data-streams-net) – p.s.w.g Apr 04 '13 at 19:31
-
will this help in regards to at least reading from it http://msdn.microsoft.com/en-us/library/system.diagnostics.fileversioninfo.comments.aspx – MethodMan Apr 04 '13 at 19:44
-
@DJKRAZE, in hind sight, I think that reads the comments from the `AssemblyInfo` class. Though it does state that it's for any file on disk. But I can't write with it. Man, this is crazy! – Mike Perrenoud Apr 04 '13 at 19:48
-
You could try this >[link](http://stackoverflow.com/questions/220097/read-write-extended-file-properties-c)< - as I remember, that gets closest and the 'least' involved when dealing with this - see if the requirements match. – NSGaga-mostly-inactive Apr 04 '13 at 19:54
-
And since you mentioned .wav files - this involves something similar for mp3-s - http://www.codeproject.com/Articles/5036/ID3-Tag-Reader-Using-Shell-Functions – NSGaga-mostly-inactive Apr 04 '13 at 19:55
-
@NSGaga, both of those link to the same CodeProject article, and it just reads the properties. My code above reads them. I need to be able to write them unfortunately. – Mike Perrenoud Apr 04 '13 at 19:58
-
I think that it's a bug actually..because I can read the `FileName` property, If I add something to the Comments of the File, it still returns empty.String – MethodMan Apr 04 '13 at 20:22
-
@MichaelPerrenoud yes - actually I thought they're wrappers around the streams and what you need - but you're right. This is what I had in mind, just took me a bit to dig that out - you need the `Hidden / Alternate Data Stream C#` (native but 'search string') - it is low-level - but you can get some help - let me know if this seems more like it - and I can elaborate, just to find a few mins – NSGaga-mostly-inactive Apr 04 '13 at 20:32
-
"Comments" is not a standard part of typical WAV file. It would either have to be stored in an additional RIFF chunk (ICMT would be best) as suggested below, or maybe Windows uses alternate data streams to store this kind of metadata. – Mark Heath Apr 05 '13 at 10:18
-
@MarkHeath, I've edited my question to be more accurate for what I **now realize** I'm really seeking. From your comment it feels like NAudio doesn't support this - is that correct? Also, after reviewing the answer by Aybe, it doesn't look like I can leverage that either because I'm building and compressing the file with NAudio. Do you know how to do this by chance? Or does NAudio support it and I just misunderstood? – Mike Perrenoud Apr 05 '13 at 12:45
-
@MichaelPerrenoud NAudio does not have a general purpose solution to this, but have a look at the source for CueWaveFileWriter, and you will see how you can fairly easily make a derived wave file writer that adds a custom chunk on save. – Mark Heath Apr 05 '13 at 12:56
-
@MarkHeath, do you think I could leverage the `Cue` and `CueList` class to build the RIFF chunks? I ask that because the data at the bottom will be something like this `ICOP` then some random control characters then `01/10/2013 13:44:43` for the copyright chunk. – Mike Perrenoud Apr 05 '13 at 13:06
-
@MichaelPerrenoud you'd need to find official documentation for the format of those chunks, but I'd imagine it is fairly straightforward – Mark Heath Apr 05 '13 at 13:30
-
@MarkHeath, thanks a lot for your help! Have a look at my answer - it was crazy! I'm pretty sure that's not a standard RIFF chunk format. I wanted to be able to add it to NAudio, but I'm just not sure that's something ***anybody else*** would ever need to use! – Mike Perrenoud Apr 05 '13 at 15:16
2 Answers
Personally I would use BASS.NET, it does handle the RIFF ICMT tag.
The EncoderWAV class provides an WAV_AddRiffInfo property that permits it.
// re-encodes a file and adds a comment to it.
var init = Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
if (init)
{
int channel = Bass.BASS_StreamCreateFile("filename", 0, 0, BASSFlag.BASS_STREAM_DECODE);
var tagInfo = new TAG_INFO { comment = "your comment" };
var encoderWav = new EncoderWAV(channel);
encoderWav.WAV_AddRiffInfo = true;
encoderWav.TAGs = tagInfo;
encoderWav.OutputFile = "output.wav";
var start = encoderWav.Start(null, IntPtr.Zero, false);
Bass.Free();
}
Note : do not forget to put bass.dll where your .EXE is
(at first BASS is a C library, BASS.NET provides a wrapper for it but also many cool stuff not present in the original library such as encoders, visualisers etc ...)
IMO BASS.NET is the best audio library for .NET, especially low-level stuff, actually that's the only one :-)

- 15,516
- 9
- 57
- 105
-
Ok, you and Mark really lead me down the right path. However, it doesn't appear that I can use BASS because I'm recording, building, and compressing the file with NAudio and I can't switch over to BASS now. Is there a way I could write to the wave file **after** it's been built by NAudio? Also, will this still work even though my file was compressed to the GSM format? – Mike Perrenoud Apr 05 '13 at 12:46
-
The code sample I shown to you processes an already created WAV file. I've just checked and the WAVEFormatTag has a GSM610 member (GSM 6.10, Microsoft Corporation) so I guess it's supported by BASS. Pretty much all operations you would apply during playback can be applied to recording as well in BASS so you should find what you need in it. What you can do is, download/install it and browse the CHM help file to see what features it has to offer to you. The other way for you would be to implement a WAV reader/writer but that is certainly a lot of work. – aybe Apr 05 '13 at 13:54
Ok, so in the end it wasn't really a standard format. We found that out by leveraging the CueWaveFileWriter
like Mark Heath stated. The format was actually something very custom and looked more like this:
LIST - this is a one-time blurb of text.
Tag Name (e.g. ICOP for copyright)
4 bytes indicating the length of the following value + 1. The 1 was a (byte)0 terminator.
Value
so an example might look like this:
ICOP<bh:15><bh:00><bh:00><bh:00>4/5/2013 10:48:40 AM<bh:00>
so, to get this done, we just created a BinaryWriter
and wrote them out directly like this:
using (BinaryWriter bw = new BinaryWriter(writer))
{
foreach (var item in RIFFChunks)
{
if (!(bw.BaseStream.Position % 2 == 0))
{
bw.Write((byte)0);
}
bw.Write(Encoding.Default.GetBytes(item.Key));
bw.Write(item.Value.Length + 1);
bw.Write(Encoding.Default.GetBytes(item.Value));
bw.Write((byte)0);
}
}
and you may want to take note to this line if (!(bw.BaseStream.Position % 2 == 0))
, that needed to exist because each tag name needed to start on an even offset. I honestly don't know why, I just know it did.
I have to say though, there's a good chance I can now reverse engineer just about any file format. But really, what good is that?!?

- 66,820
- 29
- 157
- 232