예제 #1
0
static status WriteCues (AFfilehandle file)
{
	int		i, *markids, markCount;
	uint32_t	numCues, cueChunkSize, listChunkSize;
	_WAVEInfo	*wave;

	assert(file);

	markCount = afGetMarkIDs(file, AF_DEFAULT_TRACK, NULL);
	if (markCount == 0)
		return AF_SUCCEED;

	wave = file->formatSpecific;

	if (wave->markOffset == 0)
		wave->markOffset = af_ftell(file->fh);
	else
		af_fseek(file->fh, wave->markOffset, SEEK_SET);

	af_fwrite("cue ", 4, 1, file->fh);

	/*
		The cue chunk consists of 4 bytes for the number of cue points
		followed by 24 bytes for each cue point record.
	*/
	cueChunkSize = 4 + markCount * 24;
	af_write_uint32_le(&cueChunkSize, file->fh);
	numCues = markCount;
	af_write_uint32_le(&numCues, file->fh);

	markids = _af_calloc(markCount, sizeof (int));
	assert(markids != NULL);
	afGetMarkIDs(file, AF_DEFAULT_TRACK, markids);

	/* Write each marker to the file. */
	for (i=0; i < markCount; i++)
	{
		uint32_t	identifier, position, chunkStart, blockStart;
		uint32_t	sampleOffset;
		AFframecount	markposition;

		identifier = markids[i];
		af_write_uint32_le(&identifier, file->fh);

		position = i;
		af_write_uint32_le(&position, file->fh);

		/* For now the RIFF id is always the first data chunk. */
		af_fwrite("data", 4, 1, file->fh);

		/*
			For an uncompressed WAVE file which contains
			only one data chunk, chunkStart and blockStart
			are zero.
		*/
		chunkStart = 0;
		af_fwrite(&chunkStart, sizeof (uint32_t), 1, file->fh);

		blockStart = 0;
		af_fwrite(&blockStart, sizeof (uint32_t), 1, file->fh);

		markposition = afGetMarkPosition(file, AF_DEFAULT_TRACK, markids[i]);

		/* Sample offsets are stored in the WAVE file as frames. */
		sampleOffset = markposition;
		af_write_uint32_le(&sampleOffset, file->fh);
	}

	/*
		Now write the cue names which is in a master list chunk
		with a subchunk for each cue's name.
	*/

	listChunkSize = 4;
	for (i=0; i<markCount; i++)
	{
		const char *name;

		name = afGetMarkName(file, AF_DEFAULT_TRACK, markids[i]);

		/*
			Each label chunk consists of 4 bytes for the
			"labl" chunk ID, 4 bytes for the chunk data
			size, 4 bytes for the cue point ID, and then
			the length of the label as a Pascal-style string.

			In all, this is 12 bytes plus the length of the
			string, its size byte, and a trailing pad byte
			if the length of the chunk is otherwise odd.
		*/
		listChunkSize += 12 + (strlen(name) + 1) +
			((strlen(name) + 1) % 2);
	}

	af_fwrite("LIST", 4, 1, file->fh);
	af_write_uint32_le(&listChunkSize, file->fh);
	af_fwrite("adtl", 4, 1, file->fh);

	for (i=0; i<markCount; i++)
	{
		const char	*name;
		uint32_t	labelSize, cuePointID;

		name = afGetMarkName(file, AF_DEFAULT_TRACK, markids[i]);

		/* Make labelSize even if it is not already. */
		labelSize = 4+(strlen(name)+1) + ((strlen(name) + 1) % 2);
		cuePointID = markids[i];

		af_fwrite("labl", 4, 1, file->fh);
		af_write_uint32_le(&labelSize, file->fh);
		af_write_uint32_le(&cuePointID, file->fh);
		af_fwrite(name, strlen(name) + 1, 1, file->fh);
		/*
			If the name plus the size byte comprises an odd
			length, add another byte to make the string an
			even length.
		*/
		if (((strlen(name) + 1) % 2) != 0)
		{
			uint8_t	zero=0;
			af_write_uint8(&zero, file->fh);
		}
	}

	free(markids);

	return AF_SUCCEED;
}
예제 #2
0
status WAVEFile::writeCues()
{
	int *markids, markCount;
	uint32_t numCues, cueChunkSize, listChunkSize;

	markCount = afGetMarkIDs(this, AF_DEFAULT_TRACK, NULL);
	if (markCount == 0)
		return AF_SUCCEED;

	if (markOffset == 0)
		markOffset = fh->tell();
	else
		fh->seek(markOffset, File::SeekFromBeginning);

	fh->write("cue ", 4);

	/*
		The cue chunk consists of 4 bytes for the number of cue points
		followed by 24 bytes for each cue point record.
	*/
	cueChunkSize = 4 + markCount * 24;
	writeU32(&cueChunkSize);
	numCues = markCount;
	writeU32(&numCues);

	markids = (int *) _af_calloc(markCount, sizeof (int));
	assert(markids != NULL);
	afGetMarkIDs(this, AF_DEFAULT_TRACK, markids);

	/* Write each marker to the file. */
	for (int i=0; i < markCount; i++)
	{
		uint32_t	identifier, position, chunkStart, blockStart;
		uint32_t	sampleOffset;
		AFframecount	markposition;

		identifier = markids[i];
		writeU32(&identifier);

		position = i;
		writeU32(&position);

		/* For now the RIFF id is always the first data chunk. */
		fh->write("data", 4);

		/*
			For an uncompressed WAVE file which contains
			only one data chunk, chunkStart and blockStart
			are zero.
		*/
		chunkStart = 0;
		fh->write(&chunkStart, sizeof (uint32_t));

		blockStart = 0;
		fh->write(&blockStart, sizeof (uint32_t));

		markposition = afGetMarkPosition(this, AF_DEFAULT_TRACK, markids[i]);

		/* Sample offsets are stored in the WAVE file as frames. */
		sampleOffset = markposition;
		writeU32(&sampleOffset);
	}

	/*
		Now write the cue names which is in a master list chunk
		with a subchunk for each cue's name.
	*/

	listChunkSize = 4;
	for (int i=0; i<markCount; i++)
	{
		const char *name;

		name = afGetMarkName(this, AF_DEFAULT_TRACK, markids[i]);

		/*
			Each label chunk consists of 4 bytes for the
			"labl" chunk ID, 4 bytes for the chunk data
			size, 4 bytes for the cue point ID, and then
			the length of the label as a Pascal-style string.

			In all, this is 12 bytes plus the length of the
			string, its size byte, and a trailing pad byte
			if the length of the chunk is otherwise odd.
		*/
		listChunkSize += 12 + (strlen(name) + 1) +
			((strlen(name) + 1) % 2);
	}

	fh->write("LIST", 4);
	writeU32(&listChunkSize);
	fh->write("adtl", 4);

	for (int i=0; i<markCount; i++)
	{
		const char	*name;
		uint32_t	labelSize, cuePointID;

		name = afGetMarkName(this, AF_DEFAULT_TRACK, markids[i]);

		/* Make labelSize even if it is not already. */
		labelSize = 4+(strlen(name)+1) + ((strlen(name) + 1) % 2);
		cuePointID = markids[i];

		fh->write("labl", 4);
		writeU32(&labelSize);
		writeU32(&cuePointID);
		fh->write(name, strlen(name) + 1);
		/*
			If the name plus the size byte comprises an odd
			length, add another byte to make the string an
			even length.
		*/
		if (((strlen(name) + 1) % 2) != 0)
		{
			uint8_t	zero=0;
			writeU8(&zero);
		}
	}

	free(markids);

	return AF_SUCCEED;
}
예제 #3
0
int testmarkers (int fileformat)
{
	AFfilehandle	file;
	AFfilesetup	setup;
	int		markids[] = {1, 2, 3, 4};
	AFframecount	markpositions[] = {14, 54, 23, 101};
	const char	*marknames[] = {"one", "two", "three", "four"};
	short		frames[FRAME_COUNT * 2] = {0};
	int		readmarkcount;
	int		readmarkids[4];
	AFframecount	frameswritten;

	setup = afNewFileSetup();
	ensure(setup != AF_NULL_FILESETUP, "Could not create file setup");

	afInitFileFormat(setup, fileformat);
	afInitChannels(setup, AF_DEFAULT_TRACK, 2);

	afInitMarkIDs(setup, AF_DEFAULT_TRACK, markids, 4);

	afInitMarkName(setup, AF_DEFAULT_TRACK, markids[0], marknames[0]);
	afInitMarkName(setup, AF_DEFAULT_TRACK, markids[1], marknames[1]);
	afInitMarkName(setup, AF_DEFAULT_TRACK, markids[2], marknames[2]);
	afInitMarkName(setup, AF_DEFAULT_TRACK, markids[3], marknames[3]);

	file = afOpenFile(sTestFileName, "w", setup);
	ensure(file != AF_NULL_FILEHANDLE, "Could not open file for writing");

	afFreeFileSetup(setup);

	frameswritten = afWriteFrames(file, AF_DEFAULT_TRACK, frames, FRAME_COUNT);
	ensure(frameswritten == FRAME_COUNT, "Error writing audio data");

	afSetMarkPosition(file, AF_DEFAULT_TRACK, markids[0], markpositions[0]);
	afSetMarkPosition(file, AF_DEFAULT_TRACK, markids[1], markpositions[1]);
	afSetMarkPosition(file, AF_DEFAULT_TRACK, markids[2], markpositions[2]);
	afSetMarkPosition(file, AF_DEFAULT_TRACK, markids[3], markpositions[3]);

	afCloseFile(file);

	file = afOpenFile(sTestFileName, "r", NULL);
	ensure(file != AF_NULL_FILEHANDLE, "Could not open file for reading");

	readmarkcount = afGetMarkIDs(file, AF_DEFAULT_TRACK, NULL);
	ensure(readmarkcount == 4, "Number of markers is not correct");

	afGetMarkIDs(file, AF_DEFAULT_TRACK, readmarkids);

	for (int i=0; i<readmarkcount; i++)
		ensure(readmarkids[i] = markids[i],
			"Marker identification numbers do not match");

	for (int i=0; i<readmarkcount; i++)
	{
		AFframecount	readmarkposition;
		const char	*readmarkname;

		readmarkposition = afGetMarkPosition(file, AF_DEFAULT_TRACK, readmarkids[i]);

		readmarkname = afGetMarkName(file, AF_DEFAULT_TRACK, readmarkids[i]);

		ensure(readmarkposition == markpositions[i],
			"Marker positions do not match");
		ensure(strcmp(readmarkname, marknames[i]) == 0,
			"Marker names do not match");
	}

	afCloseFile(file);

	return EXIT_SUCCESS;
}