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.
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 :-)
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?!?
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