예제 #1
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;
}
예제 #2
0
static status next_write_header (AFfilehandle file)
{
	_Track		*track;
	int		frameSize;
	uint32_t	offset, length, encoding, sampleRate, channelCount;

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	frameSize = _af_format_frame_size(&track->f, false);

	offset = track->fpos_first_frame;
	length = track->totalfframes * frameSize;
	encoding = nextencodingtype(&track->f);
	sampleRate = track->f.sampleRate;
	channelCount = track->f.channelCount;

	if (af_fseek(file->fh, 0, SEEK_SET) != 0)
		_af_error(AF_BAD_LSEEK, "bad seek");

	af_fwrite(".snd", 4, 1, file->fh);
	af_write_uint32_be(&offset, file->fh);
	af_write_uint32_be(&length, file->fh);
	af_write_uint32_be(&encoding, file->fh);
	af_write_uint32_be(&sampleRate, file->fh);
	af_write_uint32_be(&channelCount, file->fh);

	return AF_SUCCEED;
}
예제 #3
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;
}
예제 #4
0
static status WriteFrameCount (AFfilehandle file)
{
	_Track		*track = NULL;
	_WAVEInfo	*waveinfo = NULL;
	uint32_t	factSize = 4;
	uint32_t	totalFrameCount;

	assert(file != NULL);

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

	/* Omit the fact chunk only for uncompressed integer audio formats. */
	if (track->f.compressionType == AF_COMPRESSION_NONE &&
		(track->f.sampleFormat == AF_SAMPFMT_TWOSCOMP ||
		track->f.sampleFormat == AF_SAMPFMT_UNSIGNED))
		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);
	af_write_uint32_le(&factSize, file->fh);

	totalFrameCount = track->totalfframes;
	af_write_uint32_le(&totalFrameCount, file->fh);

	return AF_SUCCEED;
}
예제 #5
0
int afSetTrackPCMMapping (AFfilehandle file, int trackid,
	double slope, double intercept, double minClip, double maxClip)
{
	_Track	*track;

	if (!_af_filehandle_ok(file))
		return -1;

	if ((track = _af_filehandle_get_track(file, trackid)) == NULL)
		return -1;

	/*
		NOTE: this is highly unusual: we don't ordinarily
		change track.f after the file is opened.

		PCM mapping is the exception because this information
		is not encoded in sound files' headers using today's
		formats, so the user will probably want to set this
		information on a regular basis.  The defaults may or
		may not be what the user wants.
	*/

	track->f.pcm.slope = slope;
	track->f.pcm.intercept = intercept;
	track->f.pcm.minClip = minClip;
	track->f.pcm.maxClip = maxClip;

	track->ms.modulesdirty = AF_TRUE;

	return 0;
}
예제 #6
0
/*
	Parse voice header chunk.
*/
static status ParseVHDR (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
	size_t size)
{
	_Track		*track;
	uint32_t	oneShotSamples, repeatSamples, samplesPerRepeat;
	uint16_t	sampleRate;
	uint8_t		octaves, compression;
	uint32_t	volume;

	assert(!memcmp(&type, "VHDR", 4));

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	af_read_uint32_be(&oneShotSamples, fh);
	af_read_uint32_be(&repeatSamples, fh);
	af_read_uint32_be(&samplesPerRepeat, fh);
	af_read_uint16_be(&sampleRate, fh);
	af_read_uint8(&octaves, fh);
	af_read_uint8(&compression, fh);
	af_read_uint32_be(&volume, fh);

	track->f.sampleWidth = 8; 
	track->f.sampleRate = sampleRate;
	track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP;
	track->f.compressionType = AF_COMPRESSION_NONE;
	track->f.byteOrder = AF_BYTEORDER_BIGENDIAN;
	track->f.channelCount = 1;

	_af_set_sample_format(&track->f, track->f.sampleFormat, track->f.sampleWidth);

	return AF_SUCCEED;
}
예제 #7
0
static status next_write_header (AFfilehandle file)
{
	_Track		*track;
	int		frameSize;
	u_int32_t	offset, length, encoding, sampleRate, channelCount;

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	frameSize = _af_format_frame_size(&track->f, AF_FALSE);

        if (track->f.compressionType == AF_COMPRESSION_G711_ULAW ||
            track->f.compressionType == AF_COMPRESSION_G711_ALAW)
           frameSize = frameSize / 2;

	offset = HOST_TO_BENDIAN_INT32(track->fpos_first_frame);
	length = HOST_TO_BENDIAN_INT32(track->totalfframes * frameSize);
	encoding = HOST_TO_BENDIAN_INT32(nextencodingtype(&track->f));
	sampleRate = HOST_TO_BENDIAN_INT32(track->f.sampleRate);
	channelCount = HOST_TO_BENDIAN_INT32(track->f.channelCount);

	if (af_fseek(file->fh, 0, SEEK_SET) != 0)
		_af_error(AF_BAD_LSEEK, "bad seek");

	af_fwrite(".snd", 4, 1, file->fh);
	af_fwrite(&offset, 4, 1, file->fh);
	af_fwrite(&length, 4, 1, file->fh);
	af_fwrite(&encoding, 4, 1, file->fh);
	af_fwrite(&sampleRate, 4, 1, file->fh);
	af_fwrite(&channelCount, 4, 1, file->fh);

	return AF_SUCCEED;
}
예제 #8
0
/*
	Parse marker chunks, which contain the positions and names of loop markers.
*/
static status ParseMARK (AFfilehandle file, AFvirtualfile *fh, u_int32_t type,
	size_t size)
{
	_Track		*track;
	int		i;
	u_int16_t	numMarkers;

	assert(!memcmp(&type, "MARK", 4));

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	af_fread(&numMarkers, sizeof (u_int16_t), 1, fh);
	numMarkers = BENDIAN_TO_HOST_INT16(numMarkers);

	track->markerCount = numMarkers;
	if (numMarkers)
		track->markers = _af_marker_new(numMarkers);

	for (i=0; i<numMarkers; i++)
	{
		u_int16_t	markerID = 0;
		u_int32_t	markerPosition = 0;
		u_int8_t	sizeByte = 0;
		char		*markerName = NULL;

		af_fread(&markerID, sizeof (u_int16_t), 1, fh);
		markerID = BENDIAN_TO_HOST_INT16(markerID);
		af_fread(&markerPosition, sizeof (u_int32_t), 1, fh);
		markerPosition = BENDIAN_TO_HOST_INT32(markerPosition);
		af_fread(&sizeByte, sizeof (unsigned char), 1, fh);
		markerName = _af_malloc(sizeByte + 1);
		af_fread(markerName, sizeof (unsigned char), sizeByte, fh);

		markerName[sizeByte] = '\0';

#ifdef DEBUG
		printf("marker id: %d, position: %d, name: %s\n",
			markerID, markerPosition, markerName);

		printf("size byte: %d\n", sizeByte);
#endif

		/*
			If sizeByte is even, then 1+sizeByte (the length
			of the string) is odd.	Skip an extra byte to
			make it even.
		*/

		if ((sizeByte % 2) == 0)
			af_fseek(fh, 1, SEEK_CUR);

		track->markers[i].id = markerID;
		track->markers[i].position = markerPosition;
		track->markers[i].name = markerName;
		track->markers[i].comment = _af_strdup("");
	}

	return AF_SUCCEED;
}
예제 #9
0
int afGetCompression (AFfilehandle file, int trackid)
{
	_Track	*track;

	if (!_af_filehandle_ok(file))
		return -1;

	if ((track = _af_filehandle_get_track(file, trackid)) == NULL)
		return -1;

	return track->f.compressionType;
}
예제 #10
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;
}
예제 #11
0
/*
	What is with these return values?
*/
int afGetAESChannelData (AFfilehandle file, int trackid, unsigned char buf[24])
{
	_Track *track;

	if ((track = _af_filehandle_get_track(file, trackid)) == NULL)
		return -1;

	if (track->hasAESData == AF_FALSE)
	{
		if (buf)
			memset(buf, 0, 24);
		return 0;
	}

	if (buf)
		memcpy(buf, track->aesData, 24);

	return 1;
}
예제 #12
0
static status ParseBODY (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
	size_t size)
{
	_Track		*track;

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	/*
		IFF/8SVX files have only one audio channel with one
		byte per sample, so the number of frames is equal to
		the number of bytes.
	*/
	track->totalfframes = size;
	track->data_size = size;

	/* Sound data follows. */
	track->fpos_first_frame = af_ftell(fh);

	return AF_SUCCEED;
}
예제 #13
0
void afGetVirtualPCMMapping (AFfilehandle file, int trackid,
	double *slope, double *intercept, double *minClip, double *maxClip)
{
	_Track	*track;

	if (!_af_filehandle_ok(file))
		return;

	if ((track = _af_filehandle_get_track(file, trackid)) == NULL)
		return;

	if (slope)
		*slope = track->v.pcm.slope;
	if (intercept)
		*intercept = track->v.pcm.intercept;
	if (minClip)
		*minClip = track->v.pcm.minClip;
	if (maxClip)
		*maxClip = track->v.pcm.maxClip;
}
예제 #14
0
int afSetVirtualPCMMapping (AFfilehandle file, int trackid,
	double slope, double intercept, double minClip, double maxClip)
{
	_Track	*track;

	if (!_af_filehandle_ok(file))
		return -1;

	if ((track = _af_filehandle_get_track(file, trackid)) == NULL)
		return -1;

	track->v.pcm.slope = slope;
	track->v.pcm.intercept = intercept;
	track->v.pcm.minClip = minClip;
	track->v.pcm.maxClip = maxClip;

	track->ms.modulesdirty = AF_TRUE;

	return 0;
}
예제 #15
0
void afSetAESChannelData (AFfilehandle file, int trackid, unsigned char buf[24])
{
	_Track	*track;

	if ((track = _af_filehandle_get_track(file, trackid)) == NULL)
		return;

	if (!_af_filehandle_can_write(file))
		return;

	if (track->hasAESData)
	{
		memcpy(track->aesData, buf, 24);
	}
	else
	{
		_af_error(AF_BAD_NOAESDATA,
			"unable to store AES channel status data for track %d",
			trackid);
	}
}
예제 #16
0
static status WriteData (AFfilehandle file)
{
	_Track		*track;
	uint32_t	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);

	chunkSize = (int) _af_format_frame_size(&track->f, false) *
		track->totalfframes;

	af_write_uint32_le(&chunkSize, file->fh);
	track->fpos_first_frame = af_ftell(file->fh);

	return AF_SUCCEED;
}
예제 #17
0
status _af_avr_update (AFfilehandle file)
{
	_Track		*track;
	uint32_t	size, loopStart, loopEnd;

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	/* Seek to the position of the size field. */
	af_fseek(file->fh, 26, SEEK_SET);

	size = track->totalfframes;

	/* For the case of no loops, loopStart = 0 and loopEnd = size. */
	loopStart = 0;
	loopEnd = size;

	af_write_uint32_be(&size, file->fh);
	af_write_uint32_be(&loopStart, file->fh);
	af_write_uint32_be(&loopEnd, file->fh);

	return AF_SUCCEED;
}
예제 #18
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;
}
예제 #19
0
/*
	Parse AES recording data.
*/
static status ParseAESD (AFfilehandle file, AFvirtualfile *fh, u_int32_t type, size_t size)
{
	_Track		*track;
	unsigned char	aesChannelStatusData[24];

	assert(!memcmp(&type, "AESD", 4));
	assert(size == 24);

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	track->hasAESData = AF_TRUE;

	/*
		Try to read 24 bytes of AES nonaudio data from the file.
		Fail if the file disappoints.
	*/
	if (af_fread(aesChannelStatusData, 1, 24, fh) != 24)
		return AF_FAIL;

	memcpy(track->aesData, aesChannelStatusData, 24);

	return AF_SUCCEED;
}
예제 #20
0
/*
	Parse the stored sound chunk, which usually contains little more
	than the sound data.
*/
static status ParseSSND (AFfilehandle file, AFvirtualfile *fh, u_int32_t type,
	size_t size)
{
	_Track		*track;
	u_int32_t	offset, blockSize;

	assert(!memcmp(&type, "SSND", 4));

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	af_fread(&offset, sizeof (u_int32_t), 1, fh);
	offset = BENDIAN_TO_HOST_INT32(offset);
	af_fread(&blockSize, sizeof (u_int32_t), 1, fh);
	blockSize = BENDIAN_TO_HOST_INT32(blockSize);

	/*
		This seems like a reasonable way to calculate the number of
		bytes in an SSND chunk.
	*/
	track->data_size = size - 8 - offset;

#ifdef DEBUG
	printf("offset: %d\n", offset);
	printf("block size: %d\n", blockSize);
#endif

	track->fpos_first_frame = af_ftell(fh) + offset;

#ifdef DEBUG
	printf("data start: %d\n", track->fpos_first_frame);
#endif

	/* Sound data follows. */

	return AF_SUCCEED;
}
예제 #21
0
status _af_next_write_init (AFfilesetup setup, AFfilehandle filehandle)
{
	_Track	*track;

	if (_af_filesetup_make_handle(setup, filehandle) == AF_FAIL)
		return AF_FAIL;

	filehandle->formatSpecific = NULL;

	if (filehandle->miscellaneousCount > 0)
	{
		_af_error(AF_BAD_NUMMISC, "NeXT format supports no miscellaneous chunks");
		return AF_FAIL;
	}

	next_write_header(filehandle);

	track = _af_filehandle_get_track(filehandle, AF_DEFAULT_TRACK);
	track->fpos_first_frame = 28;

	track->f.byteOrder = AF_BYTEORDER_BIGENDIAN;

	return AF_SUCCEED;
}
예제 #22
0
static status WriteFormat (AFfilehandle file)
{
	_Track		*track = NULL;

	uint16_t	formatTag, channelCount;
	uint32_t	sampleRate, averageBytesPerSecond;
	uint16_t	blockAlign;
	uint32_t	chunkSize;
	uint16_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 ||
				track->f.sampleFormat == AF_SAMPFMT_DOUBLE)
			{
				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, false);
			bitsPerSample = 8 * _af_format_sample_size(&track->f, 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;
	}

	af_write_uint32_le(&chunkSize, file->fh);
	af_write_uint16_le(&formatTag, file->fh);

	channelCount = track->f.channelCount;
	af_write_uint16_le(&channelCount, file->fh);

	sampleRate = track->f.sampleRate;
	af_write_uint32_le(&sampleRate, file->fh);

	averageBytesPerSecond =
		track->f.sampleRate * _af_format_frame_size(&track->f, false);
	af_write_uint32_le(&averageBytesPerSecond, file->fh);

	blockAlign = _af_format_frame_size(&track->f, false);
	af_write_uint16_le(&blockAlign, file->fh);

	af_write_uint16_le(&bitsPerSample, file->fh);

	if (track->f.compressionType == AF_COMPRESSION_G711_ULAW ||
		track->f.compressionType == AF_COMPRESSION_G711_ALAW)
	{
		uint16_t	zero = 0;
		af_write_uint16_le(&zero, file->fh);
	}

	return AF_SUCCEED;
}
예제 #23
0
/*
	Parse common data chunks, which contain information regarding the
	sampling rate, the number of sample frames, and the number of
	sound channels.
*/
static status ParseCOMM (AFfilehandle file, AFvirtualfile *fh, u_int32_t type,
	size_t size)
{
	_Track		*track;
	u_int16_t	numChannels;
	u_int32_t	numSampleFrames;
	u_int16_t	sampleSize;
	unsigned char	sampleRate[10];

	assert(!memcmp(&type, "COMM", 4));

	track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);

	af_fread(&numChannels, sizeof (u_int16_t), 1, fh);
	track->f.channelCount = BENDIAN_TO_HOST_INT16(numChannels);

	af_fread(&numSampleFrames, sizeof (u_int32_t), 1, fh);
	track->totalfframes = BENDIAN_TO_HOST_INT32(numSampleFrames);

	af_fread(&sampleSize, sizeof (u_int16_t), 1, fh);
	track->f.sampleWidth = BENDIAN_TO_HOST_INT16(sampleSize);

	af_fread(sampleRate, 10, 1, fh);
	track->f.sampleRate = _af_convert_from_ieee_extended(sampleRate);

	track->f.compressionType = AF_COMPRESSION_NONE;
	track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP;
	track->f.byteOrder = AF_BYTEORDER_BIGENDIAN;

	if (file->fileFormat == AF_FILE_AIFFC)
	{
		u_int8_t	compressionID[4];
		/* Pascal strings are at most 255 bytes long. */
		unsigned char	compressionName[256];
		unsigned char	compressionNameLength;

		af_fread(compressionID, 4, 1, fh);

		/* Read the Pascal-style string containing the name. */
		af_fread(&compressionNameLength, 1, 1, fh);
		af_fread(compressionName, compressionNameLength, 1, fh);
		compressionName[compressionNameLength] = '\0';

		if (!memcmp(compressionID, "NONE", 4))
			track->f.compressionType = AF_COMPRESSION_NONE;
		else if (!memcmp(compressionID, "ACE2", 4) ||
			!memcmp(compressionID, "ACE8", 4) ||
			!memcmp(compressionID, "MAC3", 4) ||
			!memcmp(compressionID, "MAC6", 4))
		{
			_af_error(AF_BAD_NOT_IMPLEMENTED, "AIFF-C format does not support Apple's proprietary %s compression format", compressionName);
			return AF_FAIL;
		}
		else if (!memcmp(compressionID, "ulaw", 4) ||
			!memcmp(compressionID, "ULAW", 4))
		{
			track->f.compressionType = AF_COMPRESSION_G711_ULAW;
		}
		else if (!memcmp(compressionID, "alaw", 4) ||
			!memcmp(compressionID, "ALAW", 4))
		{
			track->f.compressionType = AF_COMPRESSION_G711_ALAW;
		}
		else if (!memcmp(compressionID, "fl32", 4) ||
			!memcmp(compressionID, "FL32", 4))
		{
			track->f.sampleFormat = AF_SAMPFMT_FLOAT;
			track->f.sampleWidth = 32;
			track->f.compressionType = AF_COMPRESSION_NONE;
		}
		else if (!memcmp(compressionID, "fl64", 4) ||
			!memcmp(compressionID, "FL64", 4))
		{
			track->f.sampleFormat = AF_SAMPFMT_DOUBLE;
			track->f.sampleWidth = 64;
			track->f.compressionType = AF_COMPRESSION_NONE;
		}
		else if (!memcmp(compressionID, "sowt", 4))
		{
			track->f.compressionType = AF_COMPRESSION_NONE;
			track->f.byteOrder = AF_BYTEORDER_LITTLEENDIAN;
		}
		else
		{
			_af_error(AF_BAD_NOT_IMPLEMENTED, "AIFF-C compression type '%c%c%c%c' not currently supported",
				compressionID[0],
				compressionID[1],
				compressionID[2],
				compressionID[3]);
			return AF_FAIL;
		}
	}

	_af_set_sample_format(&track->f, track->f.sampleFormat, track->f.sampleWidth);

	return AF_SUCCEED;
}
예제 #24
0
status _af_avr_write_init (AFfilesetup setup, AFfilehandle filehandle)
{
	_Track		*track;
	char		name[8];
	uint16_t	mono, resolution, sign, loop, midi;
	uint32_t	rate, size, loopStart, loopEnd;
	char		reserved[26];
	char		user[64];

	if (_af_filesetup_make_handle(setup, filehandle) == AF_FAIL)
		return AF_FAIL;

	filehandle->formatSpecific = NULL;

	track = _af_filehandle_get_track(filehandle, AF_DEFAULT_TRACK);

	if (af_fseek(filehandle->fh, 0, SEEK_SET) != 0)
	{
		_af_error(AF_BAD_LSEEK, "bad seek");
		return AF_FAIL;
	}

	af_fwrite("2BIT", 4, 1, filehandle->fh);
	memset(name, 0, 8);
	if (filehandle->fileName != NULL)
		strncpy(name, af_basename(filehandle->fileName), 8);
	af_fwrite(name, 8, 1, filehandle->fh);

	if (track->f.channelCount == 1)
		mono = 0x0;
	else
		mono = 0xffff;
	af_write_uint16_be(&mono, filehandle->fh);

	resolution = track->f.sampleWidth;
	af_write_uint16_be(&resolution, filehandle->fh);

	if (track->f.sampleFormat == AF_SAMPFMT_UNSIGNED)
		sign = 0x0;
	else
		sign = 0xffff;
	af_write_uint16_be(&sign, filehandle->fh);

	/* We do not currently support loops. */
	loop = 0;
	af_write_uint16_be(&loop, filehandle->fh);
	midi = 0xffff;
	af_write_uint16_be(&midi, filehandle->fh);

	rate = track->f.sampleRate;
	/* Set the high-order byte of rate to 0xff. */
	rate |= 0xff000000;
	size = track->totalfframes;
	loopStart = 0;
	loopEnd = size;

	af_write_uint32_be(&rate, filehandle->fh);
	af_write_uint32_be(&size, filehandle->fh);
	af_write_uint32_be(&loopStart, filehandle->fh);
	af_write_uint32_be(&loopEnd, filehandle->fh);

	memset(reserved, 0, 26);
	af_fwrite(reserved, 26, 1, filehandle->fh);

	memset(user, 0, 64);
	af_fwrite(user, 64, 1, filehandle->fh);

	if (track->fpos_first_frame == 0)
		track->fpos_first_frame = af_ftell(filehandle->fh);

	return AF_SUCCEED;
}
예제 #25
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;
}
예제 #26
0
int afReadFrames (AFfilehandle file, int trackid, void *samples,
	int nvframeswanted)
{
	_Track	*track;
	_AFmoduleinst	*firstmod;
	_AFchunk	*userc;
	AFframecount	nvframesleft, nvframes2read;
	int		bytes_per_vframe;
	AFframecount	vframe;

	if (!_af_filehandle_ok(file))
		return -1;

	if (!_af_filehandle_can_read(file))
		return -1;

	if ((track = _af_filehandle_get_track(file, trackid)) == NULL)
		return -1;

	if (track->ms.modulesdirty)
	{
		if (_AFsetupmodules(file, track) != AF_SUCCEED)
			return -1;
	}

	/*if (file->seekok) {*/

	if (af_fseek(file->fh, track->fpos_next_frame, SEEK_SET) < 0)
	{
		_af_error(AF_BAD_LSEEK, "unable to position read pointer at next frame");
		return -1;
	}

	/* } */

	if (track->totalvframes == -1)
		nvframes2read = nvframeswanted;
	else
	{
		nvframesleft = track->totalvframes - track->nextvframe;
		nvframes2read = (nvframeswanted > nvframesleft) ?
			nvframesleft : nvframeswanted;
	}
	bytes_per_vframe = _af_format_frame_size(&track->v, AF_TRUE);

	firstmod = &track->ms.module[track->ms.nmodules-1];
	userc = &track->ms.chunk[track->ms.nmodules];

	track->filemodhappy = AF_TRUE;

	vframe = 0;

	if (!track->ms.mustuseatomicnvframes)
	{
		assert(track->frames2ignore == 0);
		userc->buf = samples;
		userc->nframes = nvframes2read;

		(*firstmod->mod->run_pull)(firstmod);
		if (track->filemodhappy)
			vframe += userc->nframes;
	}
	else
	{
		bool	eof = AF_FALSE;

		if (track->frames2ignore != 0)
		{
			userc->nframes = track->frames2ignore;
			userc->buf = _af_malloc(track->frames2ignore * bytes_per_vframe);
			if (userc->buf == AF_NULL)
				return 0;

			(*firstmod->mod->run_pull)(firstmod);

			/* Have we hit EOF? */
			if (userc->nframes < track->frames2ignore)
				eof = AF_TRUE;

			track->frames2ignore = 0;

			free(userc->buf);
			userc->buf = NULL;
		}

		/*
			Now start reading useful frames, until EOF or
			premature EOF.
		*/

		while (track->filemodhappy && !eof && vframe < nvframes2read)
		{
			AFframecount	nvframes2pull;
			userc->buf = (char *) samples + bytes_per_vframe * vframe;

			if (vframe <= nvframes2read - _AF_ATOMIC_NVFRAMES)
				nvframes2pull = _AF_ATOMIC_NVFRAMES;
			else
				nvframes2pull = nvframes2read - vframe;

			userc->nframes = nvframes2pull;

			(*firstmod->mod->run_pull)(firstmod);

			if (track->filemodhappy)
			{
				vframe += userc->nframes;
				if (userc->nframes < nvframes2pull)
					eof = AF_TRUE;
			}
		}
	}

	track->nextvframe += vframe;

	return vframe;
}
예제 #27
0
int afWriteFrames (AFfilehandle file, int trackid, const void *samples,
	int nvframes2write)
{
	_AFmoduleinst	*firstmod;
	_AFchunk	*userc;
	_Track		*track;
	int		bytes_per_vframe;
	AFframecount	vframe;

	if (!_af_filehandle_ok(file))
		return -1;

	if (!_af_filehandle_can_write(file))
		return -1;

	if ((track = _af_filehandle_get_track(file, trackid)) == NULL)
		return -1;

	if (track->ms.modulesdirty)
	{
		if (_AFsetupmodules(file, track) != AF_SUCCEED)
			return -1;
	}

	/*if (file->seekok) {*/

	if (af_fseek(file->fh, track->fpos_next_frame, SEEK_SET) < 0)
	{
		_af_error(AF_BAD_LSEEK, "unable to position write pointer at next frame");
		return -1;
	}

	/* } */

	bytes_per_vframe = _af_format_frame_size(&track->v, AF_TRUE);

	firstmod = &track->ms.module[0];
	userc = &track->ms.chunk[0];

	track->filemodhappy = AF_TRUE;

	vframe = 0;
#ifdef UNLIMITED_CHUNK_NVFRAMES
	/*
		OPTIMIZATION: see the comment at the very end of
		arrangemodules() in modules.c for an explanation of this:
	*/
	if (!trk->ms.mustuseatomicnvframes)
	{
		userc->buf = (char *)buf;
		userc->nframes = nvframes2write;

		(*firstmod->mod->run_push)(firstmod);

		/* Count this chunk if there was no i/o error. */
		if (trk->filemodhappy)
			vframe += userc->nframes;
	}
	else
#else
	/* Optimization must be off. */
	assert(track->ms.mustuseatomicnvframes);
#endif
	{
		while (vframe < nvframes2write)
		{
			userc->buf = (char *) samples + bytes_per_vframe * vframe;
			if (vframe <= nvframes2write - _AF_ATOMIC_NVFRAMES)
				userc->nframes = _AF_ATOMIC_NVFRAMES;
			else
				userc->nframes = nvframes2write - vframe;

			(*firstmod->mod->run_push)(firstmod);

			if (track->filemodhappy == AF_FALSE)
				break;

			vframe += userc->nframes;
		}
	}

	track->nextvframe += vframe;
	track->totalvframes += vframe;

	return vframe;
}