abcde
abcde - create a simple demo RIFF file
abcde
This program creates a RIFF file with the following
structure. FRM1 is a form, CHKA is a single chunk, and LSTA is
a list containing chunks CHKB and CHKC.
FRMA --- CHKB
LSTC - CHKD
CHKE
We will use routines from the Standard C library, RIFFIO and STDCRIFF.
#include
#include "riffio.h"
#include "stdcriff.h"
extern void doerror(const char *strMessage);
int
main()
{
We need a Standard C FILE pointer to our new RIFF file.
FILE *pFILEOut; /* The new RIFF file */
We also need an associated RIFFIOFile for RIFFIO file operations.
RIFFIOFile *prf; /* Also the new RIFF file */
Chunk information is stored in RIFFIOChunk structures. There are
no RIFFIOChunkNew() or RIFFIOChunkDelete() routines; we can simply
define RIFFIOChunks.
We need three chunk variables because we have to keep
chunk information around until the chunk contents are finalized.
For example, LSTC cannot be finialized until CHKD and CHKE are written.
RIFFIOChunk chunkForm; /* FRMA */
RIFFIOChunk chunkList; /* LSTC */
RIFFIOChunk chunkChunk; /* CHKB, CHKD, CHKE */
Open the Standard C library RIFF file for writing and
associate it with RIFFIOFile.
Make sure the file is opened in binary mode.
pFILEOut = fopen("abcde.rif", "wb");
if (!pFILEOut)
doerror("Can't open abcde.rif for writing");
prf = RIFFIOFileNew();
if (! prf)
doerror("RIFFIOFileNew failed");
if (! RIFFIOFileInit(prf, pFILEOut,
STDCRIFFRead, STDCRIFFWrite,
STDCRIFFSeek, STDCRIFFTell))
doerror("RIFFIOFileInit Failed");
First we must create the form chunk. We do so by filling in the
form's chunk id (RIFF or RIFX),the form type (FRMA in our case),
and optionally the form's data size. Because this example is so
simple, we could conceivably predict the size of the entire
form. Ordinarily that would be too difficult so we will leave
chunkForm.sizeData alone and let
RIFFIOChunkFinalize()
calculate it
later. Once the chunkForm's members are initialized we call
RIFFIOChunkCreate()
to write the chunk's header.
chunkForm.fccId = RIFFIO_FOURCC_RIFF;
chunkForm.fccType = RIFFIOMAKEFOURCC('F','R','M','A');
if (! RIFFIOChunkCreate(prf, &chunkForm))
doerror("Couldn't create form chunk");
RIFFIOChunkCreate()
fills in other, private, fields of <chunkForm> that
are used later by
RIFFIOChunkFinalize()
.
RIFFIOChunkCreate()
leaves the RIFF file positioned at the start of
the new chunk's contents. In this case we are poised to write the
first chunk of the form, CHKB.
Because CHKB is neither a form or a list we can ignore the fccType
member of the chunk. CHKB will be empty, so we can immediately call
RIFFIOChunkFinalize()
to complete the chunk.
chunkChunk.fccId = RIFFIOMAKEFOURCC('C','H','K','B');
chunkChunk.sizeData = 0;
if (! RIFFIOChunkCreate(prf, &chunkChunk))
doerror("Couldn't create chunk CHKB");
if (! RIFFIOChunkFinalize(prf, &chunkChunk))
doerror("Couldn't finalize chunk CHKB");
RIFFIOChunkFinalize()
updates CHKB's size in the RIFF file if necessary.
It then writes an NUL pad byte of the chunk has an odd size and leaves
the RIFF file positioned at the end of the chunk.
We can now start LSTC.
chunkList.fccId = RIFFIO_FOURCC_LIST;
chunkList.fccType = RIFFIOMAKEFOURCC('L','S','T','C');
if (! RIFFIOChunkCreate(prf, &chunkList))
doerror("Couldn't create chunk LSTC");
We will reuse chunkChunk to write CHKD. CHKD will contain 18 bytes
of data so we will demonstrate filling in the sizeData member
(even though we really don't need to).
chunkChunk.fccId = RIFFIOMAKEFOURCC('C','H','K','D');
chunkChunk.sizeData = 18; /* predict the chunk size */
if (! RIFFIOChunkCreate(prf, &chunkChunk))
doerror("Couldn't create chunk ");
RIFFIOWrite(prf, "This is CHKD data.", 18);
if (! RIFFIOChunkFinalize(prf, &chunkChunk))
doerror("Couldn't finalize chunk ");
When we write CHKE we will let
RIFFIOChunkFinalize()
calculate the
correct size.
chunkChunk.fccId = RIFFIOMAKEFOURCC('C','H','K','E');
chunkChunk.sizeData = 999; /* Wrong but will be fixed automatically */
if (! RIFFIOChunkCreate(prf, &chunkChunk))
doerror("Couldn't create chunk ");
RIFFIOWrite(prf, "This is CHKE data.", 18);
if (! RIFFIOChunkFinalize(prf, &chunkChunk))
doerror("Couldn't finalize chunk ");
Here is the end of LSTC.
if (! RIFFIOChunkFinalize(prf, &chunkList))
doerror("Couldn't finalize list ");
Here is the end of FRMA.
if (! RIFFIOChunkFinalize(prf, &chunkForm))
doerror("Couldn't finalize form ");
We are done writing chunks. It is time to clean up.
RIFFIOFileDelete(prf);
Even though we have deleted the RIFFIOFile we still haven't officially
closed the Standard C Libarary representation.
fclose(pFILEOut);
return 0;
}
Report an error and exit.
void
doerror(const char *strMessage)
{
fprintf(stderr, "%s\n", strMessage);
exit(1);
}