Beispiel #1
0
static status WriteFrameCount (AFfilehandle file)
{
	_Track		*track = NULL;
	_WAVEInfo	*waveinfo = NULL;
	u_int32_t	factSize = 4;
	u_int32_t	totalFrameCount;

	assert(file != NULL);

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);
	waveinfo = (_WAVEInfo *) file->formatSpecific;

	/* We only write the fact chunk for compressed audio. */
	if (track->f.compressionType == AF_COMPRESSION_NONE)
		return AF_SUCCEED;

	/*
		If the offset for the fact chunk hasn't been set yet,
		set it to the file's current position.
	*/
	if (waveinfo->factOffset == 0)
		waveinfo->factOffset = af_ftell(file->fh);
	else
		af_fseek(file->fh, waveinfo->factOffset, SEEK_SET);

	af_fwrite("fact", 4, 1, file->fh);
	factSize = HOST_TO_LENDIAN_INT32(factSize);
	af_fwrite(&factSize, 4, 1, file->fh);

	totalFrameCount = HOST_TO_LENDIAN_INT32(track->totalfframes);
	af_fwrite(&totalFrameCount, 4, 1, file->fh);

	return AF_SUCCEED;
}
Beispiel #2
0
status _af_wave_update (AFfilehandle file)
{
	_Track	*track;

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	if (track->fpos_first_frame != 0)
	{
		size_t	dataLength, fileLength;

		/*
			We call _af_format_frame_size to calculate the
			frame size of normal PCM data or compressed data.
		*/
		dataLength = track->totalfframes * _af_format_frame_size(&track->f, AF_FALSE);

		dataLength = HOST_TO_LENDIAN_INT32(dataLength);
		af_fseek(file->fh, track->fpos_first_frame - 4, SEEK_SET);
		af_fwrite(&dataLength, 4, 1, file->fh);

		fileLength = af_flength(file->fh);
		fileLength -= 8;
		fileLength = HOST_TO_LENDIAN_INT32(fileLength);

		af_fseek(file->fh, 4, SEEK_SET);
		af_fwrite(&fileLength, 4, 1, file->fh);
	}

	return AF_SUCCEED;
}
Beispiel #3
0
status _af_wave_update (AFfilehandle file)
{
	_Track		*track;
	_WAVEInfo	*wave = (_WAVEInfo *) file->formatSpecific;

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	if (track->fpos_first_frame != 0)
	{
		u_int32_t	dataLength, fileLength;

		/* Update the frame count chunk if present. */
		WriteFrameCount(file);

		/* Update the length of the data chunk. */
		af_fseek(file->fh, wave->dataSizeOffset, SEEK_SET);

		/*
			We call _af_format_frame_size to calculate the
			frame size of normal PCM data or compressed data.
		*/
		dataLength = (u_int32_t) track->totalfframes *
			_af_format_frame_size(&track->f, AF_FALSE);
		dataLength = HOST_TO_LENDIAN_INT32(dataLength);
		af_fwrite(&dataLength, 4, 1, file->fh);

		/* Update the length of the RIFF chunk. */
		fileLength = (u_int32_t) af_flength(file->fh);
		fileLength -= 8;
		fileLength = HOST_TO_LENDIAN_INT32(fileLength);

		af_fseek(file->fh, 4, SEEK_SET);
		af_fwrite(&fileLength, 4, 1, file->fh);
	}

	/*
		Write the actual data that was set after initializing
		the miscellaneous IDs.	The size of the data will be
		unchanged.
	*/
	WriteMiscellaneous(file);

	/* Write the new positions; the size of the data will be unchanged. */
	WriteCues(file);

	return AF_SUCCEED;
}
Beispiel #4
0
status af_write_uint32_le (const uint32_t *value, AFvirtualfile *vf)
{
	uint32_t	v;
	v = HOST_TO_LENDIAN_INT32(*value);
	if (af_fwrite(&v, sizeof (v), 1, vf) != 1)
		return AF_FAIL;
	return AF_SUCCEED;
}
Beispiel #5
0
static status WriteData (AFfilehandle file)
{
	_Track		*track;
	u_int32_t	frameSize, chunkSize;
	_WAVEInfo	*waveinfo;

	assert(file);

	waveinfo = file->formatSpecific;
	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	af_fwrite("data", 4, 1, file->fh);
	waveinfo->dataSizeOffset = af_ftell(file->fh);

	frameSize = _af_format_frame_size(&track->f, AF_FALSE);
	chunkSize = frameSize * track->totalfframes;
	chunkSize = HOST_TO_LENDIAN_INT32(chunkSize);
	af_fwrite(&chunkSize, 4, 1, file->fh);
	track->fpos_first_frame = af_ftell(file->fh);

	return AF_SUCCEED;
}
Beispiel #6
0
static status WriteFormat (AFfilehandle file)
{
	_Track		*track = NULL;

	u_int16_t	formatTag, channelCount;
	u_int32_t	sampleRate, averageBytesPerSecond;
	u_int16_t	blockAlign;
	u_int32_t	chunkSize;
	u_int16_t	bitsPerSample;

	assert(file != NULL);

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

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

	switch (track->f.compressionType)
	{
		case AF_COMPRESSION_NONE:
			chunkSize = 16;
			if (track->f.sampleFormat == AF_SAMPFMT_FLOAT)
			{
				formatTag = WAVE_FORMAT_IEEE_FLOAT;
			}
			else if (track->f.sampleFormat == AF_SAMPFMT_TWOSCOMP ||
				track->f.sampleFormat == AF_SAMPFMT_UNSIGNED)
			{
				formatTag = WAVE_FORMAT_PCM;
			}
			else
			{
				_af_error(AF_BAD_COMPTYPE, "bad sample format");
				return AF_FAIL;
			}

			blockAlign = _af_format_frame_size(&track->f, AF_FALSE);
			bitsPerSample = 8 * _af_format_sample_size(&track->f, AF_FALSE);
			break;

		/*
			G.711 compression uses eight bits per sample.
		*/
		case AF_COMPRESSION_G711_ULAW:
			chunkSize = 18;
			formatTag = IBM_FORMAT_MULAW;
			blockAlign = track->f.channelCount;
			bitsPerSample = 8;
			break;

		case AF_COMPRESSION_G711_ALAW:
			chunkSize = 18;
			formatTag = IBM_FORMAT_ALAW;
			blockAlign = track->f.channelCount;
			bitsPerSample = 8;
			break;

		default:
			_af_error(AF_BAD_COMPTYPE, "bad compression type");
			return AF_FAIL;
	}

	chunkSize = HOST_TO_LENDIAN_INT32(chunkSize);
	af_fwrite(&chunkSize, 4, 1, file->fh);

	formatTag = HOST_TO_LENDIAN_INT16(formatTag);
	af_fwrite(&formatTag, 2, 1, file->fh);
	formatTag = LENDIAN_TO_HOST_INT16(formatTag);

	channelCount = track->f.channelCount;
	channelCount = HOST_TO_LENDIAN_INT16(channelCount);
	af_fwrite(&channelCount, 2, 1, file->fh);

	sampleRate = track->f.sampleRate;
	sampleRate = HOST_TO_LENDIAN_INT32(sampleRate);
	af_fwrite(&sampleRate, 4, 1, file->fh);

	averageBytesPerSecond =
		track->f.sampleRate * _af_format_frame_size(&track->f, AF_FALSE);
	averageBytesPerSecond = HOST_TO_LENDIAN_INT32(averageBytesPerSecond);
	af_fwrite(&averageBytesPerSecond, 4, 1, file->fh);

	blockAlign = _af_format_frame_size(&track->f, AF_FALSE);
	blockAlign = HOST_TO_LENDIAN_INT16(blockAlign);
	af_fwrite(&blockAlign, 2, 1, file->fh);

	bitsPerSample = HOST_TO_LENDIAN_INT16(bitsPerSample);
	af_fwrite(&bitsPerSample, 2, 1, file->fh);

	if (track->f.compressionType == AF_COMPRESSION_G711_ULAW ||
		track->f.compressionType == AF_COMPRESSION_G711_ALAW)
	{
		u_int16_t	zero = 0;
		af_fwrite(&zero, 2, 1, file->fh);
	}

	return AF_SUCCEED;
}
Beispiel #7
0
static status WriteCues (AFfilehandle file)
{
	int		i, *markids, markCount;
	u_int32_t	numCues, cueChunkSize, listChunkSize;
	_Track		*track = &file->tracks[0];
	_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;
	cueChunkSize = HOST_TO_LENDIAN_INT32(cueChunkSize);
	af_fwrite(&cueChunkSize, sizeof (u_int32_t), 1, file->fh);
	numCues = HOST_TO_LENDIAN_INT32(markCount);
	af_fwrite(&numCues, sizeof (u_int32_t), 1, 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++)
	{
		u_int32_t	identifier, position, chunkStart, blockStart;
		u_int32_t	sampleOffset;
		AFframecount	markposition;

		identifier = HOST_TO_LENDIAN_INT32(markids[i]);
		af_fwrite(&identifier, sizeof (u_int32_t), 1, file->fh);

		position = HOST_TO_LENDIAN_INT32(i);
		af_fwrite(&position, sizeof (u_int32_t), 1, 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 (u_int32_t), 1, file->fh);

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

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

		/* Sample offsets are stored in the WAVE file as frames. */
		sampleOffset = HOST_TO_LENDIAN_INT32(markposition);
		af_fwrite(&sampleOffset, sizeof (u_int32_t), 1, 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);
	listChunkSize = HOST_TO_LENDIAN_INT32(listChunkSize);
	af_fwrite(&listChunkSize, sizeof (u_int32_t), 1, file->fh);
	af_fwrite("adtl", 4, 1, file->fh);

	for (i=0; i<markCount; i++)
	{
		const char	*name;
		u_int32_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);
		labelSize = HOST_TO_LENDIAN_INT32(labelSize);
		cuePointID = HOST_TO_LENDIAN_INT32(markids[i]);

		af_fwrite("labl", 4, 1, file->fh);
		af_fwrite(&labelSize, 4, 1, file->fh);
		af_fwrite(&cuePointID, 4, 1, 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)
		{
			u_int8_t	c=0;
			af_fwrite(&c, 1, 1, file->fh);
		}
	}

	free(markids);

	return AF_SUCCEED;
}
Beispiel #8
0
status WriteMiscellaneous (AFfilehandle filehandle)
{
	_WAVEInfo	*wave = (_WAVEInfo *) filehandle->formatSpecific;

	if (filehandle->miscellaneousCount != 0)
	{
		int		i;
		u_int32_t	miscellaneousBytes;
		u_int32_t 	chunkSize;

		/* Start at 12 to account for 'LIST', size, and 'INFO'. */
		miscellaneousBytes = 12;

		/* Then calculate the size of the whole INFO chunk. */
		for (i=0; i<filehandle->miscellaneousCount; i++)
		{
			u_int32_t	miscid;

			/* Skip miscellaneous data of an unsupported type. */
			if (misc_type_to_wave(filehandle->miscellaneous[i].type,
				&miscid) == AF_FAIL)
				continue;

			/* Account for miscellaneous type and size. */
			miscellaneousBytes += 8;
			miscellaneousBytes += filehandle->miscellaneous[i].size;

			/* Add a pad byte if necessary. */
			if (filehandle->miscellaneous[i].size % 2 != 0)
				miscellaneousBytes++;

			assert(miscellaneousBytes % 2 == 0);
		}

		if (wave->miscellaneousStartOffset == 0)
			wave->miscellaneousStartOffset = af_ftell(filehandle->fh);
		else
			af_fseek(filehandle->fh, wave->miscellaneousStartOffset, SEEK_SET);

		wave->totalMiscellaneousSize = miscellaneousBytes;

		/*
			Write the data.  On the first call to this
			function (from _af_wave_write_init), the
			data won't be available, af_fseek is used to
			reserve space until the data has been provided.
			On subseuent calls to this function (from
			_af_wave_update), the data will really be written.
		*/

		/* Write 'LIST'. */
		af_fwrite("LIST", 4, 1, filehandle->fh);

		/* Write the size of the following chunk. */
		chunkSize = miscellaneousBytes-8;
		chunkSize = HOST_TO_LENDIAN_INT32(chunkSize);
		af_fwrite(&chunkSize, sizeof (u_int32_t), 1, filehandle->fh);

		/* Write 'INFO'. */
		af_fwrite("INFO", 4, 1, filehandle->fh);

		/* Write each miscellaneous chunk. */
		for (i=0; i<filehandle->miscellaneousCount; i++)
		{
			u_int32_t	miscsize = HOST_TO_LENDIAN_INT32(filehandle->miscellaneous[i].size);
			u_int32_t 	miscid = 0;

			/* Skip miscellaneous data of an unsupported type. */
			if (misc_type_to_wave(filehandle->miscellaneous[i].type,
				&miscid) == AF_FAIL)
				continue;

			af_fwrite(&miscid, 4, 1, filehandle->fh);
			af_fwrite(&miscsize, 4, 1, filehandle->fh);
			if (filehandle->miscellaneous[i].buffer != NULL)
			{
				u_int8_t	zero = 0;

				af_fwrite(filehandle->miscellaneous[i].buffer, filehandle->miscellaneous[i].size, 1, filehandle->fh);

				/* Pad if necessary. */
				if ((filehandle->miscellaneous[i].size%2) != 0)
					af_fwrite(&zero, 1, 1, filehandle->fh);
			}
			else
			{
				int	size;
				size = filehandle->miscellaneous[i].size;

				/* Pad if necessary. */
				if ((size % 2) != 0)
					size++;
				af_fseek(filehandle->fh, size, SEEK_CUR);
			}
		}
	}

	return AF_SUCCEED;
}
Beispiel #9
0
static status WriteFormat (AFfilehandle file)
{
	_Track		*track = NULL;
	u_int16_t	formatTag, channelCount;
	u_int32_t	sampleRate, averageBytesPerSecond;
	u_int16_t	blockAlign;
	u_int32_t	chunkSize;
	u_int16_t	bitsPerSample;
	_WAVEInfo	*waveinfo = NULL;

	assert(file != NULL);

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);
	waveinfo = (_WAVEInfo *) file->formatSpecific;

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

	switch (track->f.compressionType)
	{
		case AF_COMPRESSION_NONE:
			chunkSize = 16;
			formatTag = WAVE_FORMAT_PCM;
			blockAlign = _af_format_frame_size(&track->f, AF_FALSE);
			bitsPerSample = 8 * _af_format_sample_size(&track->f, AF_FALSE);
			break;
		case AF_COMPRESSION_G711_ULAW:
			chunkSize = 18;
			formatTag = IBM_FORMAT_MULAW;
			blockAlign = _af_format_frame_size(&track->f, AF_FALSE);
			bitsPerSample = 8 * _af_format_sample_size(&track->f, AF_FALSE);
			break;
		case AF_COMPRESSION_G711_ALAW:
			chunkSize = 18;
			formatTag = IBM_FORMAT_ALAW;
			blockAlign = _af_format_frame_size(&track->f, AF_FALSE);
			bitsPerSample = 8 * _af_format_sample_size(&track->f, AF_FALSE);
			break;
		default:
			_af_error(AF_BAD_COMPTYPE, "bad compression type");
			return AF_FAIL;
	}

	chunkSize = HOST_TO_LENDIAN_INT32(chunkSize);
	af_fwrite(&chunkSize, 4, 1, file->fh);

	formatTag = HOST_TO_LENDIAN_INT16(formatTag);
	af_fwrite(&formatTag, 2, 1, file->fh);
	formatTag = LENDIAN_TO_HOST_INT16(formatTag);

	channelCount = track->f.channelCount;
	channelCount = HOST_TO_LENDIAN_INT16(channelCount);
	af_fwrite(&channelCount, 2, 1, file->fh);

	sampleRate = track->f.sampleRate;
	sampleRate = HOST_TO_LENDIAN_INT32(sampleRate);
	af_fwrite(&sampleRate, 4, 1, file->fh);

	averageBytesPerSecond =
		track->f.sampleRate * _af_format_frame_size(&track->f, AF_FALSE);
	averageBytesPerSecond = HOST_TO_LENDIAN_INT32(averageBytesPerSecond);
	af_fwrite(&averageBytesPerSecond, 4, 1, file->fh);

	blockAlign = _af_format_frame_size(&track->f, AF_FALSE);
	blockAlign = HOST_TO_LENDIAN_INT16(blockAlign);
	af_fwrite(&blockAlign, 2, 1, file->fh);

	bitsPerSample = HOST_TO_LENDIAN_INT16(bitsPerSample);
	af_fwrite(&bitsPerSample, 2, 1, file->fh);

	/*
		If the data is compressed we have additional
		format-specific information to write as well as the
		'fact' (frame count) chunk.
	*/
	if (track->f.compressionType != AF_COMPRESSION_NONE)
	{
		u_int32_t	factSize = 4;
		u_int32_t	totalFrameCount = 0;

		if (track->f.compressionType == AF_COMPRESSION_G711_ULAW ||
			track->f.compressionType == AF_COMPRESSION_G711_ALAW)
		{
			u_int16_t	zero = 0;
			af_fwrite(&zero, 2, 1, file->fh);
		}

		af_fwrite("fact", 4, 1, file->fh);
		factSize = HOST_TO_LENDIAN_INT32(factSize);
		af_fwrite(&factSize, 4, 1, file->fh);

		waveinfo->fileSizeOffset = af_ftell(file->fh);

		totalFrameCount = HOST_TO_LENDIAN_INT32(totalFrameCount);
		af_fwrite(&totalFrameCount, 4, 1, file->fh);
	}

	return AF_SUCCEED;
}