Commit message: Refactor audio conversion.
CVE: CVE-2015-7747
Vulnerability description: Buffer overflow in the afReadFrames function in audiofile (aka libaudiofile and Audio File Library) allows user-assisted remote attackers to cause a denial of service (program crash) or possibly execute arbitrary code via a crafted audio file, as demonstrated by sixteen-stereo-to-eight-mono.c.

Project: audiofile

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;
}

Project: audiofile

int afGetByteOrder (AFfilehandle handle, int track)
{
	_Track *currentTrack;

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

	if ((currentTrack = _af_filehandle_get_track(handle, track)) == NULL)
		return -1;

	return (currentTrack->f.byteOrder);
}

Project: audiofile

bool _af_filehandle_can_write (AFfilehandle file)
{
	if (file->access != _AF_WRITE_ACCESS)
	{
		_af_error(AF_BAD_NOWRITEACC, "file not opened for write access");
		return false;
	}

	return true;
}

Project: audiofile

void _af_print_frame (AFframecount frameno, double *frame, int nchannels,
	char *formatstring, int numberwidth,
	double slope, double intercept, double minclip, double maxclip)
{
	char linebuf[81];
	int wavewidth = 78 - numberwidth*nchannels - 6;
	int c;

	memset(linebuf, ' ', 80);
	linebuf[0] = '|';
	linebuf[wavewidth-1] = '|';
	linebuf[wavewidth] = 0;

	printf("%05" AF_FRAMECOUNT_PRINT_FMT " ", frameno);

	for (c=0; c < nchannels; c++)
	{
		double pcm = frame[c];
		printf(formatstring, pcm);
	}
	for (c=0; c < nchannels; c++)
	{
		double pcm = frame[c], volts;
		if (maxclip > minclip)
		{
			if (pcm < minclip) pcm = minclip;
			if (pcm > maxclip) pcm = maxclip;
		}
		volts = (pcm - intercept) / slope;
		linebuf[(int)((volts/2 + 0.5)*(wavewidth-3)) + 1] = '0' + c;
	}
	printf("%s\n", linebuf);
}

Project: audiofile

static FormatCode getFormatCode(const _AudioFormat &format)
{
	if (format.sampleFormat == AF_SAMPFMT_FLOAT)
		return kFloat;
	if (format.sampleFormat == AF_SAMPFMT_DOUBLE)
		return kDouble;
	if (format.isInteger())
	{
		switch (format.bytesPerSample(false))
		{
			case 1: return kInt8;
			case 2: return kInt16;
			case 3: return kInt24;
			case 4: return kInt32;
		}
	}

	/* NOTREACHED */
	assert(false);
	return kUndefined;
}

Project: audiofile

	void allocate(size_t capacity)
	{
		if (ownsMemory)
			::operator delete(buffer);
		ownsMemory = true;
		buffer = ::operator new(capacity);
	}

Project: audiofile

int afReadFrames (AFfilehandle file, int trackid, void *samples,
	int nvframeswanted)
{
	_Track	*track;
	SharedPtr<Module> firstmod;
	SharedPtr<Chunk> 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->isDirty() && track->ms->setup(file, track) == AF_FAIL)
		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, true);

	firstmod = track->ms->modules().back();
	userc = track->ms->chunks().back();

	track->filemodhappy = true;

	vframe = 0;

	if (!track->ms->mustUseAtomicNVFrames())
	{
		assert(track->frames2ignore == 0);
		userc->buffer = samples;
		userc->frameCount = nvframes2read;

		firstmod->runPull();
		if (track->filemodhappy)
			vframe += userc->frameCount;
	}
	else
	{
		bool	eof = false;

		if (track->frames2ignore != 0)
		{
			userc->frameCount = track->frames2ignore;
			userc->allocate(track->frames2ignore * bytes_per_vframe);
			if (userc->buffer == NULL)
				return 0;

			firstmod->runPull();

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

			track->frames2ignore = 0;

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

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

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

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

			userc->frameCount = nvframes2pull;

			firstmod->runPull();

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

	track->nextvframe += vframe;

	return vframe;
}

Project: audiofile

	void run(const void *input, void *output, int count)
	{
		const T *in = reinterpret_cast<const T *>(input);
		uint8_t *out = reinterpret_cast<uint8_t *>(output);
		for (int i=0; i<count; i++)
		{
			uint8_t c0, c1, c2;
			extract3(in[i], c0, c1, c2);
			out[3*i] = c0;
			out[3*i+1] = c1;
			out[3*i+2] = c2;
		}
	}

Project: audiofile

bool write(AFvirtualfile *vf, const T *value)
{
	return vf->write(value, sizeof (*value)) == sizeof (*value);
}

Project: audiofile

status ModuleState::init(AFfilehandle file, _Track *track)
{
	if (initFileModule(file, track) == AF_FAIL)
		return AF_FAIL;

	return AF_SUCCEED;
}

Project: audiofile

	virtual void run(Chunk &inChunk, Chunk &outChunk)
	{
		switch (m_inChunk->f.bytesPerSample(false))
		{
			case 2:
				run<2, int16_t>(inChunk, outChunk); break;
			case 3:
				run<3, char>(inChunk, outChunk); break;
			case 4:
				run<4, int32_t>(inChunk, outChunk); break;
			case 8:
				run<8, int64_t>(inChunk, outChunk); break;
			default:
				assert(false); break;
		}
	}

Project: audiofile

FileModule::FileModule(Mode mode, _Track *track, AFvirtualfile *fh, bool canSeek) :
	m_mode(mode),
	m_track(track),
	m_fh(fh),
	m_canSeek(canSeek)
{
	track->fpos_next_frame = track->fpos_first_frame;
	track->frames2ignore = 0;
}

Project: audiofile

void Module::runPush()
{
}

Project: audiofile

	void run(const void *srcData, void *dstData, int count)
	{
		const T minValue = m_outputMapping.minClip;
		const T maxValue = m_outputMapping.maxClip;

		const T *src = reinterpret_cast<const T *>(srcData);
		T *dst = reinterpret_cast<T *>(dstData);

		for (int i=0; i<count; i++)
		{
			T t = src[i];
			t = std::min(t, maxValue);
			t = std::max(t, minValue);
			dst[i] = t;
		}
	}

Project: audiofile

Module::Module() :
	m_sink(NULL)
{
}

Project: audiofile

	ConvertInt(FormatCode inFormat, FormatCode outFormat) :
		m_inFormat(inFormat),
		m_outFormat(outFormat)
	{
		assert(isInteger(m_inFormat));
		assert(isInteger(m_outFormat));
	}

Project: audiofile

_Track *_af_filehandle_get_track (AFfilehandle file, int trackid)
{
	int	i;
	for (i=0; i<file->trackCount; i++)
	{
		if (file->tracks[i].id == trackid)
			return &file->tracks[i];
	}

	_af_error(AF_BAD_TRACKID, "bad track id %d", trackid);

	return NULL;
}

Project: audiofile

void _af_print_audioformat (_AudioFormat *fmt)
{
	/* sampleRate, channelCount */
	printf("{ %7.2f Hz %d ch ", fmt->sampleRate, fmt->channelCount);

	/* sampleFormat, sampleWidth */
	switch (fmt->sampleFormat)
	{
		case AF_SAMPFMT_TWOSCOMP:
			printf("%db 2 ", fmt->sampleWidth);
			break;
		case AF_SAMPFMT_UNSIGNED:
			printf("%db u ", fmt->sampleWidth);
			break;
		case AF_SAMPFMT_FLOAT:
			printf("flt ");
			break;
		case AF_SAMPFMT_DOUBLE:
			printf("dbl ");
			break;
		default:
			printf("%dsampfmt? ", fmt->sampleFormat);
	}

	/* pcm */
	printf("(%.30g+-%.30g [%.30g,%.30g]) ",
		fmt->pcm.intercept, fmt->pcm.slope,
		fmt->pcm.minClip, fmt->pcm.maxClip);

	/* byteOrder */
	switch (fmt->byteOrder)
	{
		case AF_BYTEORDER_BIGENDIAN:
			printf("big ");
			break;
		case AF_BYTEORDER_LITTLEENDIAN:
			printf("little ");
			break;
		default:
			printf("%dbyteorder? ", fmt->byteOrder);
			break;
	}

	/* compression */
	{
		int idx = _af_compression_index_from_id(fmt->compressionType);
		if (idx < 0)
		{
			printf("%dcompression?", fmt->compressionType);
		}
		else if (fmt->compressionType == AF_COMPRESSION_NONE)
			printf("pcm");
		else
			printf("%s", _af_compression[idx].label);
	}

	printf(" }");
}

Project: audiofile

inline float _af_byteswap_float32 (float x)
{
	union
	{
		uint32_t i;
		float f;
	} u;
	u.f = x;
	u.i = _af_byteswap_int32(u.i);
	return u.f;
}

Project: audiofile

	Compress4To3Module(bool isSigned) : m_isSigned(isSigned)
	{
	}

Project: audiofile

status af_read_pstring (char s[256], AFvirtualfile *vf)
{
	uint8_t length;
	/* Read the Pascal-style string containing the name. */
	if (vf->read(&length, 1) != 1)
		return AF_FAIL;
	if (vf->read(s, length) != (ssize_t) length)
		return AF_FAIL;
	s[length] = '\0';
	return AF_SUCCEED;
}

Project: audiofile

	virtual void reset1() { }

Project: audiofile

	void getDefaultPCMMapping(int &bits, double &slope, double &intercept,
		double &minClip, double &maxClip)
	{
		bits = (m_outFormat + 1) * CHAR_BIT;
		slope = (1LL << (bits - 1));
		intercept = 0;
		minClip = -(1 << (bits - 1));
		maxClip = (1LL << (bits - 1)) - 1;
	}

Project: audiofile

static bool isTrivialIntClip(const _AudioFormat &format, FormatCode code)
{
	return intmappings[code] != NULL &&
		format.pcm.minClip == intmappings[code]->minClip &&
		format.pcm.maxClip == intmappings[code]->maxClip;
}

Project: audiofile

void ApplyChannelMatrix::run(Chunk &inChunk, Chunk &outChunk)
{
	switch (m_format)
	{
		case kInt8:
			run<int8_t>(inChunk.buffer, outChunk.buffer, inChunk.frameCount);
			break;
		case kInt16:
			run<int16_t>(inChunk.buffer, outChunk.buffer, inChunk.frameCount);
			break;
		case kInt24:
		case kInt32:
			run<int32_t>(inChunk.buffer, outChunk.buffer, inChunk.frameCount);
			break;
		case kFloat:
			run<float>(inChunk.buffer, outChunk.buffer, inChunk.frameCount);
			break;
		case kDouble:
			run<double>(inChunk.buffer, outChunk.buffer, inChunk.frameCount);
			break;
		default:
			assert(false);
	}
}

Project: audiofile

Module *G711::createDecompress(_Track *track, AFvirtualfile *fh,
	bool canSeek, bool headerless, AFframecount *chunkframes)
{
	return new G711(Decompress, track, fh, canSeek);
}

Project: audiofile

	Shared() : m_refCount(0)
	{
	}

Project: audiofile

void ModuleState::addConvertFloatToFloat(FormatCode input, FormatCode output)
{
	if (input == output)
		return;

	assert((input == kFloat && output == kDouble) ||
		(input == kDouble && output == kFloat));
	addModule(new ConvertFloat(input, output));
}

Project: audiofile

bool _AudioFormat::isCompressed() const
{
	return compressionType != AF_COMPRESSION_NONE;
}

Project: audiofile

	SharedPtr(const SharedPtr &p) : m_ptr(p.m_ptr)
	{
		if (m_ptr) m_ptr->retain();
	}

Project: audiofile

bool _af_filehandle_can_read (AFfilehandle file)
{
	if (file->access != _AF_READ_ACCESS)
	{
		_af_error(AF_BAD_NOREADACC, "file not opened for read access");
		return false;
	}

	return true;
}

Project: audiofile

	void release() { if (--m_refCount == 0) delete static_cast<T *>(this); }

Project: audiofile

void PCM::sync2()
{
	assert(!canSeek() || (tell() == m_track->fpos_next_frame));

	/* We can afford to seek because sync2 is rare. */
	m_track->fpos_after_data = tell();

	m_track->fpos_next_frame = m_saved_fpos_next_frame;
	m_track->nextfframe = m_saved_nextfframe;
}

Project: audiofile

void ApplyChannelMatrix::describe()
{
	m_outChunk->f.channelCount = m_outChannels;
	m_outChunk->f.pcm.minClip = m_minClip;
	m_outChunk->f.pcm.maxClip = m_maxClip;
}

Project: audiofile

	virtual const char *name() const { return "sign"; }

Project: audiofile

		UnsignedType operator()(SignedType x) { return x - kMinSignedValue; }

Project: audiofile

	static void run(const void *src, void *dst, int count)
	{
		transform<intToFloat<Arg, Result> >(src, dst, count);
	}

Project: audiofile

	void run(const void *srcData, void *dstData, int count)
	{
		const T *src = reinterpret_cast<const T *>(srcData);
		T *dst = reinterpret_cast<T *>(dstData);

		double m = m_outputMapping.slope / m_inputMapping.slope;
		double b = m_outputMapping.intercept - m * m_inputMapping.intercept;

		for (int i=0; i<count; i++)
			dst[i] = m * src[i] + b;
	}

Project: audiofile

size_t _AudioFormat::bytesPerSample() const
{
	return bytesPerSample(!isPacked());
}

Project: audiofile

status ModuleState::sync(AFfilehandle file, _Track *track)
{
	track->filemodhappy = true;
	for (std::vector<SharedPtr<Module> >::reverse_iterator i=m_modules.rbegin();
			i != m_modules.rend(); ++i)
		(*i)->sync1();
	if (!track->filemodhappy)
		return AF_FAIL;
	for (std::vector<SharedPtr<Module> >::iterator i=m_modules.begin();
			i != m_modules.end(); ++i)
		(*i)->sync2();
	return AF_SUCCEED;
}

Project: audiofile

static status _afOpenFile (int access, AFvirtualfile *vf, const char *filename,
	AFfilehandle *file, AFfilesetup filesetup)
{
	int	fileFormat = AF_FILE_UNKNOWN;
	int	implemented = true;
	char	*formatName;
	status	(*initfunc) (AFfilesetup, AFfilehandle);

	int		userSampleFormat = 0;
	double		userSampleRate = 0.0;
	_PCMInfo	userPCM;
	bool		userFormatSet = false;

	int	t;

	AFfilehandle	filehandle = AF_NULL_FILEHANDLE;
	AFfilesetup	completesetup = AF_NULL_FILESETUP;

	*file = AF_NULL_FILEHANDLE;

	if (access == _AF_WRITE_ACCESS || filesetup != AF_NULL_FILESETUP)
	{
		if (!_af_filesetup_ok(filesetup))
			return AF_FAIL;

		fileFormat = filesetup->fileFormat;
		if (access == _AF_READ_ACCESS && fileFormat != AF_FILE_RAWDATA)
		{
			_af_error(AF_BAD_FILESETUP,
				"warning: opening file for read access: "
				"ignoring file setup with non-raw file format");
			filesetup = AF_NULL_FILESETUP;
			fileFormat = _af_identify(vf, &implemented);
		}
	}
	else if (filesetup == AF_NULL_FILESETUP)
		fileFormat = _af_identify(vf, &implemented);

	if (fileFormat == AF_FILE_UNKNOWN)
	{
		if (filename != NULL)
			_af_error(AF_BAD_NOT_IMPLEMENTED,
				"'%s': unrecognized audio file format",
				filename);
		else
			_af_error(AF_BAD_NOT_IMPLEMENTED,
				"unrecognized audio file format");
		return AF_FAIL;
	}

	formatName = _af_units[fileFormat].name;

	if (!implemented)
	{
		_af_error(AF_BAD_NOT_IMPLEMENTED,
			"%s format not currently supported", formatName);
	}

	assert(_af_units[fileFormat].completesetup != NULL);
	assert(_af_units[fileFormat].read.init != NULL);

	if (access == _AF_WRITE_ACCESS &&
		_af_units[fileFormat].write.init == NULL)
	{
		_af_error(AF_BAD_NOT_IMPLEMENTED,
			"%s format is currently supported for reading only",
			formatName);
		return AF_FAIL;
	}

	completesetup = NULL;
	if (filesetup != AF_NULL_FILESETUP)
	{
		userSampleFormat = filesetup->tracks[0].f.sampleFormat;
		userPCM = filesetup->tracks[0].f.pcm;
		userSampleRate = filesetup->tracks[0].f.sampleRate;
		userFormatSet = true;
		if ((completesetup = _af_units[fileFormat].completesetup(filesetup)) == NULL)
			return AF_FAIL;
	}

	filehandle = (AFfilehandle) _af_malloc(sizeof (_AFfilehandle));
	if (filehandle == NULL)
	{
		if (completesetup)
			afFreeFileSetup(completesetup);
		return AF_FAIL;
	}
	memset(filehandle, 0, sizeof (_AFfilehandle));

	filehandle->valid = _AF_VALID_FILEHANDLE;
	filehandle->fh = vf;
	filehandle->access = access;
	if (filename != NULL)
		filehandle->fileName = strdup(filename);
	else
		filehandle->fileName = NULL;
	filehandle->fileFormat = fileFormat;
	filehandle->formatSpecific = NULL;

	initfunc = (access == _AF_READ_ACCESS) ?
		_af_units[fileFormat].read.init : _af_units[fileFormat].write.init;

	if (initfunc(completesetup, filehandle) != AF_SUCCEED)
	{
		freeFileHandle(filehandle);
		filehandle = AF_NULL_FILEHANDLE;
		if (completesetup)
			afFreeFileSetup(completesetup);
		return AF_FAIL;
	}

	if (completesetup)
	{
		afFreeFileSetup(completesetup);
		completesetup = NULL;
	}

	/*
		Initialize virtual format.
	*/
	for (t=0; t<filehandle->trackCount; t++)
	{
		_Track	*track = &filehandle->tracks[t];

		track->v = track->f;

		if (userFormatSet)
		{
			track->v.sampleFormat = userSampleFormat;
			track->v.pcm = userPCM;
			track->v.sampleRate = userSampleRate;
		}

		track->v.compressionType = AF_COMPRESSION_NONE;
		track->v.compressionParams = NULL;

#if WORDS_BIGENDIAN
		track->v.byteOrder = AF_BYTEORDER_BIGENDIAN;
#else
		track->v.byteOrder = AF_BYTEORDER_LITTLEENDIAN;
#endif

		track->ms = new ModuleState();
		if (track->ms->init(filehandle, track) == AF_FAIL)
		{
			freeFileHandle(filehandle);
			return AF_FAIL;
		}
	}

	*file = filehandle;

	return AF_SUCCEED;
}

Project: audiofile

	Expand3To4Module(bool isSigned) : m_isSigned(isSigned)
	{
	}

Project: audiofile

float afGetVirtualFrameSize (AFfilehandle file, int trackid, int stretch3to4)
{
	_Track	*track;

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

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

	return _af_format_frame_size(&track->v, stretch3to4);
}

Project: audiofile

	virtual void run(Chunk &inChunk, Chunk &outChunk)
	{
		const void *src = inChunk.buffer;
		void *dst = outChunk.buffer;
		int count = inChunk.frameCount * inChunk.f.channelCount;

		switch (m_format)
		{
			case kInt8:
				run<int8_t>(src, dst, count); break;
			case kInt16:
				run<int16_t>(src, dst, count); break;
			case kInt24:
			case kInt32:
				run<int32_t>(src, dst, count); break;
			case kFloat:
				run<float>(src, dst, count); break;
			case kDouble:
				run<double>(src, dst, count); break;
			default:
				assert(false);
		}
	}

Project: audiofile

	~Chunk()
	{
		if (ownsMemory)
			::operator delete(buffer);
		buffer = NULL;
	}

Project: audiofile

void Module::push(size_t frames)
{
	m_outChunk->frameCount = frames;
	m_sink->runPush();
}

Project: audiofile

void _af_setup_free_tracks (AFfilesetup setup)
{
	int	i;

	if (setup->tracks)
	{
		for (i=0; i<setup->trackCount; i++)
		{
			_af_setup_free_markers(setup, i);
		}

		free(setup->tracks);
	}

	setup->tracks = NULL;
	setup->trackCount = 0;
}

Project: audiofile

void *_af_malloc (size_t size)
{
	void	*p;

	if (size <= 0)
	{
		_af_error(AF_BAD_MALLOC, "bad memory allocation size request %d", size);
		return NULL;
	}

	p = malloc(size);

#ifdef AF_DEBUG
	if (p)
		memset(p, 0xff, size);
#endif

	if (p == NULL)
	{
		_af_error(AF_BAD_MALLOC, "allocation of %d bytes failed", size);
		return NULL;
	}

	return p;
}

Project: audiofile

bool _AudioFormat::isUnsigned() const
{
	return sampleFormat == AF_SAMPFMT_UNSIGNED;
}

Project: audiofile

void afInitRate (AFfilesetup setup, int trackid, double rate)
{
	_TrackSetup	*track;

	if (!_af_filesetup_ok(setup))
		return;

	if ((track = _af_filesetup_get_tracksetup(setup, trackid)) == NULL)
		return;

	if (rate <= 0.0)
	{
		_af_error(AF_BAD_RATE, "invalid sample rate %.30g", rate);
		return;
	}

	track->f.sampleRate = rate;
	track->rateSet = true;
}

Project: audiofile

	int numModules() const { return m_modules.size(); }

Project: audiofile

bool _AudioFormat::isSigned() const
{
	return sampleFormat == AF_SAMPFMT_TWOSCOMP;
}

Project: audiofile

const std::vector<SharedPtr<Module> > &ModuleState::modules() const
{
	return m_modules;
}

Project: audiofile

void Module::setSource(Module *module) { m_source = module; }

Project: audiofile

void SimpleModule::runPush()
{
	m_outChunk->frameCount = m_inChunk->frameCount;
	run(*m_inChunk, *m_outChunk);
	push(m_outChunk->frameCount);
}

Project: audiofile

void G711::describe()
{
	if (mode() == Compress)
	{
		m_outChunk->f.compressionType = m_track->f.compressionType;
	}
	else
	{
		m_outChunk->f.byteOrder = _AF_BYTEORDER_NATIVE;
		m_outChunk->f.compressionType = AF_COMPRESSION_NONE;
	}
}

Project: audiofile

void *_af_realloc (void *p, size_t size)
{
	if (size <= 0)
	{
		_af_error(AF_BAD_MALLOC, "bad memory allocation size request %d", size);
		return NULL;
	}

	p = realloc(p, size);

	if (p == NULL)
	{
		_af_error(AF_BAD_MALLOC, "allocation of %d bytes failed", size);
		return NULL;
	}

	return p;
}

Project: audiofile

Module *_AFg711initcompress(_Track *track, AFvirtualfile *fh, bool canSeek,
	bool headerless, AFframecount *chunkFrames)
{
	return G711::createCompress(track, fh, canSeek, headerless, chunkFrames);
}

Project: audiofile

void MSADPCM::reset1()
{
	AFframecount nextTrackFrame = m_track->nextfframe;
	m_track->nextfframe = (nextTrackFrame / m_framesPerBlock) *
		m_framesPerBlock;

	m_framesToIgnore = nextTrackFrame - m_track->nextfframe;
	/* postroll = frames2ignore */
}

Project: audiofile

bool _af_ms_adpcm_format_ok (_AudioFormat *f)
{
	if (f->channelCount != 1 && f->channelCount != 2)
	{
		_af_error(AF_BAD_COMPRESSION,
			"MS ADPCM compression requires 1 or 2 channels");
		return false;
	}

	if (f->sampleFormat != AF_SAMPFMT_TWOSCOMP || f->sampleWidth != 16)
	{
		_af_error(AF_BAD_COMPRESSION,
			"MS ADPCM compression requires 16-bit signed integer format");
		f->sampleFormat = AF_SAMPFMT_TWOSCOMP;
		f->sampleWidth = 16;
		/* non-fatal */
	}

	if (f->byteOrder != AF_BYTEORDER_BIGENDIAN)
	{
		_af_error(AF_BAD_COMPRESSION,
			"MS ADPCM compression requires big endian format");
		f->byteOrder = AF_BYTEORDER_BIGENDIAN;
		/* non-fatal */
	}

	return true;
}

Project: audiofile

void G711::reset2()
{
	int framesize = m_inChunk->f.channelCount;

	m_track->fpos_next_frame = m_track->fpos_first_frame +
		framesize * m_track->nextfframe;

	m_track->frames2ignore = 0;
}

Project: audiofile

int afGetVirtualChannels (AFfilehandle file, int trackid)
{
	_Track	*track;

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

	return track->v.channelCount;
}

Project: audiofile

const char *Module::name() const { return ""; }

Project: audiofile

	void setOutChunk(Chunk *chunk) { m_outChunk = chunk; }

Project: audiofile

void afGetVirtualSampleFormat (AFfilehandle file, int trackid, int *sampleFormat, int *sampleWidth)
{
	_Track	*track;

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

	if (sampleFormat != NULL)
		*sampleFormat = track->v.sampleFormat;

	if (sampleFormat != NULL)
		*sampleWidth = track->v.sampleWidth;
}

Project: audiofile

size_t _AudioFormat::bytesPerSample(bool stretch3to4) const
{
	return _af_format_sample_size_uncompressed(this, stretch3to4);
}

Project: audiofile

static void linear2ulaw_buf (const int16_t *linear, uint8_t *ulaw, int nsamples)
{
	for (int i=0; i < nsamples; i++)
		ulaw[i] = _af_linear2ulaw(linear[i]);
}

Project: audiofile

ModuleState::~ModuleState()
{
}

Project: audiofile

int afCloseFile (AFfilehandle file)
{
	int	err;

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

	afSyncFile(file);

	err = af_fclose(file->fh);
	if (err < 0)
		_af_error(AF_BAD_CLOSE, "close returned %d", err);

	freeFileHandle(file);

	return 0;
}

Project: audiofile

inline uint16_t byteswap(uint16_t value) { return _af_byteswap_int16(value); }

Project: audiofile

inline int64_t byteswap(int64_t value) { return _af_byteswap_int64(value); }

Project: audiofile

off_t FileModule::tell()
{
	return m_fh->tell();
}

Project: audiofile

void *_af_calloc (size_t nmemb, size_t size)
{
	void	*p;

	if (nmemb <= 0 || size <= 0)
	{
		_af_error(AF_BAD_MALLOC, "bad memory allocation size request "
			"%d elements of %d bytes each", nmemb, size);
		return NULL;
	}

	p = calloc(nmemb, size);

	if (p == NULL)
	{
		_af_error(AF_BAD_MALLOC, "allocation of %d bytes failed",
			nmemb*size);
		return NULL;
	}

	return p;
}

Project: audiofile

	ConvertFloatToIntClip(FormatCode inputFormat, FormatCode outputFormat,
		const _PCMInfo &inputMapping, const _PCMInfo &outputMapping) :
		m_inputFormat(inputFormat),
		m_outputFormat(outputFormat),
		m_inputMapping(inputMapping),
		m_outputMapping(outputMapping)
	{
		assert(m_inputFormat == kFloat || m_inputFormat == kDouble);
		assert(m_outputFormat == kInt8 ||
			m_outputFormat == kInt16 ||
			m_outputFormat == kInt24 ||
			m_outputFormat == kInt32);
	}

Project: audiofile

void PCM::sync1()
{
	m_saved_fpos_next_frame = m_track->fpos_next_frame;
	m_saved_nextfframe = m_track->nextfframe;
}

Project: audiofile

		SignedType operator()(UnsignedType x) { return x + kMinSignedValue; }

Project: audiofile

ApplyChannelMatrix::ApplyChannelMatrix(FormatCode format, bool isReading,
	int inChannels, int outChannels,
	double minClip, double maxClip, const double *matrix) :
	m_format(format),
	m_inChannels(inChannels),
	m_outChannels(outChannels),
	m_minClip(minClip),
	m_maxClip(maxClip),
	m_matrix(NULL)
{
	m_matrix = new double[m_inChannels * m_outChannels];
	if (matrix)
	{
		if (isReading)
		{
			// Copy channel matrix for reading.
			std::copy(matrix, matrix + m_inChannels * m_outChannels, m_matrix);
		}
		else
		{
			// Transpose channel matrix for writing.
			for (int i=0; i < inChannels; i++)
				for (int j=0; j < outChannels; j++)
					m_matrix[j*inChannels + i] = matrix[i*outChannels + j];
		}
	}
	else
	{
		initDefaultMatrix();
	}
}

Project: audiofile

	virtual const char *name() const { return "convertPCMMapping"; }

Project: audiofile

AFfilesetup afNewFileSetup (void)
{
	AFfilesetup	setup;

	setup = _af_malloc(sizeof (_AFfilesetup));
	if (setup == NULL) return AF_NULL_FILESETUP;

	*setup = _af_default_file_setup;

	setup->tracks = _af_tracksetup_new(setup->trackCount);

	setup->instruments = _af_instsetup_new(setup->instrumentCount);

	if (setup->miscellaneousCount == 0)
		setup->miscellaneous = NULL;
	else
	{
		int	i;

		setup->miscellaneous = _af_calloc(setup->miscellaneousCount,
			sizeof (_MiscellaneousSetup));
		for (i=0; i<setup->miscellaneousCount; i++)
		{
			setup->miscellaneous[i].id = i+1;
			setup->miscellaneous[i].type = 0;
			setup->miscellaneous[i].size = 0;
		}
	}

	return setup;
}

Project: audiofile

void afGetPCMMapping (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->f.pcm.slope;
	if (intercept)
		*intercept = track->f.pcm.intercept;
	if (minClip)
		*minClip = track->f.pcm.minClip;
	if (maxClip)
		*maxClip = track->f.pcm.maxClip;
}

Project: audiofile

	virtual const char *name() const { return "ms_adpcm_decompress"; }

Project: audiofile

status af_write_uint8 (const uint8_t *value, AFvirtualfile *vf)
{
	if (!write(vf, value))
		return AF_FAIL;
	return AF_SUCCEED;
}

Project: audiofile

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->setDirty();

	return 0;
}

Project: audiofile

	bool canSeek() const { return m_canSeek; }

Project: audiofile

int _af_identify (AFvirtualfile *vf, int *implemented)
{
	AFfileoffset	curpos;
	int		i;

	curpos = af_ftell(vf);

	for (i=0; i<_AF_NUM_UNITS; i++)
	{
		if (_af_units[i].read.recognize &&
			_af_units[i].read.recognize(vf))
		{
			if (implemented != NULL)
				*implemented = _af_units[i].implemented;
			af_fseek(vf, curpos, SEEK_SET);
			return _af_units[i].fileFormat;
		}
	}

	af_fseek(vf, curpos, SEEK_SET);

	if (implemented != NULL)
		*implemented = false;

	return AF_FILE_UNKNOWN;
}

Project: audiofile

status ModuleState::reset(AFfilehandle file, _Track *track)
{
	track->filemodhappy = true;
	for (std::vector<SharedPtr<Module> >::reverse_iterator i=m_modules.rbegin();
			i != m_modules.rend(); ++i)
		(*i)->reset1();
	track->frames2ignore = 0;
	if (!track->filemodhappy)
		return AF_FAIL;
	for (std::vector<SharedPtr<Module> >::iterator i=m_modules.begin();
			i != m_modules.end(); ++i)
		(*i)->reset2();
	if (!track->filemodhappy)
		return AF_FAIL;
	return AF_SUCCEED;
}

Project: audiofile

void ModuleState::addConvertIntToFloat(FormatCode input, FormatCode output)
{
	addModule(new ConvertIntToFloat(input, output));
}

Project: audiofile

std::string _AudioFormat::description() const
{
	std::string d;
	char s[1024];
	/* sampleRate, channelCount */
	sprintf(s, "{ %7.2f Hz %d ch ", sampleRate, channelCount);
	d += s;

	/* sampleFormat, sampleWidth */
	switch (sampleFormat)
	{
		case AF_SAMPFMT_TWOSCOMP:
			sprintf(s, "%db 2 ", sampleWidth);
			break;
		case AF_SAMPFMT_UNSIGNED:
			sprintf(s, "%db u ", sampleWidth);
			break;
		case AF_SAMPFMT_FLOAT:
			sprintf(s, "flt ");
			break;
		case AF_SAMPFMT_DOUBLE:
			sprintf(s, "dbl ");
			break;
		default:
			assert(false);
			break;
	}

	d += s;

	/* pcm */
	sprintf(s, "(%.30g+-%.30g [%.30g,%.30g]) ",
		pcm.intercept, pcm.slope,
		pcm.minClip, pcm.maxClip);
	d += s;

	/* byteOrder */
	switch (byteOrder)
	{
		case AF_BYTEORDER_BIGENDIAN:
			d += "big ";
			break;
		case AF_BYTEORDER_LITTLEENDIAN:
			d += "little ";
			break;
		default:
			assert(false);
			break;
	}

	if (isCompressed())
	{
		int compressionIndex = _af_compression_index_from_id(compressionType);
		assert(compressionIndex >= 0);
		d += "compression: ";
		d += _af_compression[compressionIndex].label;
	}

	return d;
}

Project: audiofile

bool _af_unique_ids (int *ids, int nids, char *idname, int iderr)
{
	int i;

	for (i = 0; i < nids; i++)
	{
		int j;
		for (j = 0; j < i; j++)
			if (ids[i] == ids[j])
			{
				_af_error(iderr, "nonunique %s id %d",
					idname, ids[i]);
				return false;
			}
	}

	return true;
}

Project: audiofile

	virtual void run(Chunk &inChunk, Chunk &outChunk)
	{
		const void *src = inChunk.buffer;
		void *dst = outChunk.buffer;
		size_t count = inChunk.frameCount * inChunk.f.channelCount;

		switch (m_outFormat)
		{
			case kFloat:
				transform<floatToFloat<double, float> >(src, dst, count);
				break;
			case kDouble:
				transform<floatToFloat<float, double> >(src, dst, count);
				break;
			default:
				assert(false);
		}
	}

Project: audiofile

void Module::setSink(Module *module) { m_sink = module; }

Project: audiofile

void Module::runPull()
{
}

Project: audiofile

	virtual void describe()
	{
		switch (m_outFormat)
		{
			case kFloat:
				m_outChunk->f.sampleFormat = AF_SAMPFMT_FLOAT;
				m_outChunk->f.sampleWidth = 32;
				break;
			case kDouble:
				m_outChunk->f.sampleFormat = AF_SAMPFMT_DOUBLE;
				m_outChunk->f.sampleWidth = 64;
				break;
			default:
				assert(false);
		}
	}

Project: audiofile

void G711::sync1()
{
	m_savedPositionNextFrame = m_track->fpos_next_frame;
	m_savedNextFrame = m_track->nextfframe;
}

Project: audiofile

void afInitByteOrder (AFfilesetup setup, int trackid, int byteorder)
{
	_TrackSetup	*track;

	if (!_af_filesetup_ok(setup))
		return;

	if ((track = _af_filesetup_get_tracksetup(setup, trackid)) == NULL)
		return;

	if (byteorder != AF_BYTEORDER_BIGENDIAN &&
		byteorder != AF_BYTEORDER_LITTLEENDIAN)
	{
		_af_error(AF_BAD_BYTEORDER, "invalid byte order %d", byteorder);
		return;
	}

	track->f.byteOrder = byteorder;
	track->byteOrderSet = true;
}

Project: audiofile

AUpvlist _af_pv_pointer (void *val)
{
	AUpvlist	ret = AUpvnew(1);
	AUpvsetparam(ret, 0, 0);
	AUpvsetvaltype(ret, 0, AU_PVTYPE_PTR);
	AUpvsetval(ret, 0, &val);
	return ret;
}

Project: audiofile

static bool isInteger(FormatCode code) { return code >= kInt8 && code <= kInt32; }

Project: audiofile

	virtual void describe()
	{
		m_outChunk->f.sampleFormat = m_outFormat == kDouble ?
			AF_SAMPFMT_DOUBLE : AF_SAMPFMT_FLOAT;
		m_outChunk->f.sampleWidth = m_outFormat == kDouble ? 64 : 32;
	}

Project: audiofile

void _af_setup_free_loops (AFfilesetup setup, int instno)
{
	if (setup->instruments[instno].loops)
	{
		free(setup->instruments[instno].loops);
	}

	setup->instruments[instno].loops = NULL;
	setup->instruments[instno].loopCount = 0;
}

Project: audiofile

	operator UnspecifiedBoolType() const { return m_ptr ? &SharedPtr::m_ptr : 0; }

Project: audiofile

	Chunk() : buffer(NULL), frameCount(0), ownsMemory(false) { }

Project: audiofile

AFfilehandle afOpenFD (int fd, const char *mode, AFfilesetup setup)
{
	FILE		*fp;
	AFvirtualfile	*vf;
	AFfilehandle	filehandle;
	int		access;

	if (mode == NULL)
	{
		_af_error(AF_BAD_ACCMODE, "null access mode");
		return AF_NULL_FILEHANDLE;
	}

	if (mode[0] == 'r')
		access = _AF_READ_ACCESS;
	else if (mode[0] == 'w')
		access = _AF_WRITE_ACCESS;
	else
	{
		_af_error(AF_BAD_ACCMODE, "unrecognized access mode '%s'", mode);
		return AF_NULL_FILEHANDLE;
	}

	vf = new File(fd, access == _AF_READ_ACCESS ?
		File::ReadAccess : File::WriteAccess);

	if (_afOpenFile(access, vf, NULL, &filehandle, setup) != AF_SUCCEED)
		af_fclose(vf);

	return filehandle;
}

Project: audiofile

	ConvertSign(FormatCode format, bool fromSigned) :
		m_format(format),
		m_fromSigned(fromSigned)
	{
	}

Project: audiofile

	SharedPtr &operator =(T *ptr)
	{
		if (m_ptr != ptr)
		{
			if (ptr) ptr->retain();
			if (m_ptr) m_ptr->release();
			m_ptr = ptr;
		}
		return *this;
	}

Project: audiofile

int afGetVirtualByteOrder (AFfilehandle handle, int track)
{
	_Track *currentTrack;

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

	if ((currentTrack = _af_filehandle_get_track(handle, track)) == NULL)
		return -1;

	return (currentTrack->v.byteOrder);
}

Project: audiofile

bool _af_ima_adpcm_format_ok (_AudioFormat *f)
{
	if (f->channelCount != 1)
	{
		_af_error(AF_BAD_COMPRESSION,
			"IMA ADPCM compression requires 1 channel");
		return false;
	}

	if (f->sampleFormat != AF_SAMPFMT_TWOSCOMP || f->sampleWidth != 16)
	{
		_af_error(AF_BAD_COMPRESSION,
			"IMA ADPCM compression requires 16-bit signed integer format");
		f->sampleFormat = AF_SAMPFMT_TWOSCOMP;
		f->sampleWidth = 16;
		/* non-fatal */
	}

	if (f->byteOrder != _AF_BYTEORDER_NATIVE)
	{
		_af_error(AF_BAD_COMPRESSION,
			"IMA ADPCM compression requires native byte order");
		f->byteOrder = _AF_BYTEORDER_NATIVE;
		/* non-fatal */
	}

	return true;
}

Project: audiofile

status af_read_uint8 (uint8_t *value, AFvirtualfile *vf)
{
	if (!read(vf, value))
		return AF_FAIL;
	return AF_SUCCEED;
}

Project: audiofile

void PCM::reset2()
{
	m_track->fpos_next_frame = m_track->fpos_first_frame +
		m_bytesPerFrame * m_track->nextfframe;

	m_track->frames2ignore = 0;
}

Project: audiofile

void afInitTrackIDs (AFfilesetup file, int *trackids, int trackCount)
{
	assert(file);
	assert(trackids);
	assert(trackCount == 1);
	assert(trackids[0] == AF_DEFAULT_TRACK);
}

Project: audiofile

int afWriteFrames (AFfilehandle file, int trackid, const void *samples,
	int nvframes2write)
{
	SharedPtr<Module> firstmod;
	SharedPtr<Chunk> 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->isDirty() && track->ms->setup(file, track) == AF_FAIL)
		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, true);

	firstmod = track->ms->modules().front();
	userc = track->ms->chunks().front();

	track->filemodhappy = 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->buffer = (char *) samples;
		userc->frameCount = nvframes2write;

		firstmod->runPush();

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

			firstmod->runPush();

			if (!track->filemodhappy)
				break;

			vframe += userc->frameCount;
		}
	}

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

	return vframe;
}

Project: audiofile

	T *operator ->() const { return m_ptr; }

Project: audiofile

bool _af_pv_getdouble (AUpvlist pvlist, int param, double *d)
{
	int	i;

	for (i=0; i<AUpvgetmaxitems(pvlist); i++)
	{
		int	p, t;

		AUpvgetparam(pvlist, i, &p);

		if (p != param)
			continue;

		AUpvgetvaltype(pvlist, i, &t);

		/* Ensure that this parameter is of type AU_PVTYPE_DOUBLE. */
		if (t != AU_PVTYPE_DOUBLE)
			return false;

		AUpvgetval(pvlist, i, d);
		return true;
	}

	return false;
}

Project: audiofile

static void linear2alaw_buf (const int16_t *linear, uint8_t *alaw, int nsamples)
{
	for (int i=0; i < nsamples; i++)
		alaw[i] = _af_linear2alaw(linear[i]);
}

Project: audiofile

char *_af_strdup (const char *s)
{
	char *p = (char *) malloc(strlen(s) + 1);

	if (p)
		strcpy(p, s);

	return p;
}

Project: audiofile

	virtual void describe()
	{
		m_outChunk->f.byteOrder = m_inChunk->f.byteOrder == AF_BYTEORDER_BIGENDIAN ?
			AF_BYTEORDER_LITTLEENDIAN : AF_BYTEORDER_BIGENDIAN;
	}

Project: audiofile

AFframecount afSeekFrame (AFfilehandle file, int trackid, AFframecount frame)
{
	_Track	*track;

	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->isDirty() && track->ms->setup(file, track) == AF_FAIL)
		return -1;

	if (frame < 0)
		return track->nextvframe;

	/* Optimize the case of seeking to the current position. */
	if (frame == track->nextvframe)
		return track->nextvframe;

	/* Limit request to the number of frames in the file. */
	if (track->totalvframes != -1)
		if (frame > track->totalvframes)
			frame = track->totalvframes - 1;

	/*
		Now that the modules are not dirty and frame
		represents a valid virtual frame, we call
		_AFsetupmodules again after setting track->nextvframe.

		_AFsetupmodules will look at track->nextvframe and
		compute track->nextfframe in clever and mysterious
		ways.
	*/
	track->nextvframe = frame;

	if (track->ms->setup(file, track) == AF_FAIL)
		return -1;

	return track->nextvframe;
}

Project: audiofile

	virtual void describe()
	{
		m_outChunk->f.sampleFormat = AF_SAMPFMT_TWOSCOMP;
		m_outChunk->f.sampleWidth = (m_outputFormat + 1) * CHAR_BIT;
		m_outChunk->f.pcm = m_outputMapping;
	}

Project: audiofile

void afInitChannels (AFfilesetup setup, int trackid, int channels)
{
	_TrackSetup	*track;

	if (!_af_filesetup_ok(setup))
		return;

	if ((track = _af_filesetup_get_tracksetup(setup, trackid)) == NULL)
		return;

	if (channels < 1)
	{
		_af_error(AF_BAD_CHANNELS, "invalid number of channels %d",
			channels);
		return;
	}

	track->f.channelCount = channels;
	track->channelCountSet = true;
}

Project: audiofile

G711::G711(Mode mode, _Track *track, AFvirtualfile *fh, bool canSeek) :
	FileModule(mode, track, fh, canSeek),
	m_savedPositionNextFrame(-1),
	m_savedNextFrame(-1)
{
	if (mode == Decompress)
		track->f.compressionParams = AU_NULL_PVLIST;
}

Project: audiofile

void Module::pull(size_t frames)
{
	m_inChunk->frameCount = frames;
	m_source->runPull();
}

Project: audiofile

void afSetChannelMatrix (AFfilehandle file, int trackid, double* matrix)
{
	_Track	*track;

	if (!_af_filehandle_ok(file))
		return;

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

	if (track->channelMatrix != NULL)
		free(track->channelMatrix);
	track->channelMatrix = NULL;

	if (matrix != NULL)
	{
		int	i, size;

		size = track->v.channelCount * track->f.channelCount;

		track->channelMatrix = (double *) malloc(size * sizeof (double));

		for (i = 0; i < size; i++)
			track->channelMatrix[i] = matrix[i];
	}
}

Project: audiofile

	static void convertInt(const void *src, void *dst, int count)
	{
		transform<shift<Input, Output> >(src, dst, count);
	}

Project: audiofile

	Chunk *outChunk() { return m_outChunk.get(); }

Project: audiofile

	virtual void run(Chunk &inChunk, Chunk &outChunk)
	{
		int count = inChunk.f.channelCount * inChunk.frameCount;
		if (m_isSigned)
			run<int32_t>(reinterpret_cast<const uint8_t *>(inChunk.buffer),
				reinterpret_cast<int32_t *>(outChunk.buffer),
				count);
		else
			run<uint32_t>(reinterpret_cast<const uint8_t *>(inChunk.buffer),
				reinterpret_cast<uint32_t *>(outChunk.buffer),
				count);
	}

Project: audiofile

	ConvertIntToFloat(FormatCode inFormat, FormatCode outFormat) :
		m_inFormat(inFormat), m_outFormat(outFormat)
	{
	}

Project: audiofile

bool read(AFvirtualfile *vf, T *value)
{
	return vf->read(value, sizeof (*value)) == sizeof (*value);
}

Project: audiofile

	bool isDirty() const { return m_isDirty; }

Project: audiofile

	void convertSignedToUnsigned(const void *src, void *dst, size_t count)
	{
		switch (m_format)
		{
			case kInt8:
				convertSignedToUnsigned<kInt8>(src, dst, count);
				break;
			case kInt16:
				convertSignedToUnsigned<kInt16>(src, dst, count);
				break;
			case kInt24:
				convertSignedToUnsigned<kInt24>(src, dst, count);
				break;
			case kInt32:
				convertSignedToUnsigned<kInt32>(src, dst, count);
				break;
			default:
				assert(false);
		}
	}

Project: audiofile

	virtual void describe()
	{
		m_outChunk->f.packed = false;
	}

Project: audiofile

int afGetChannels (AFfilehandle file, int trackid)
{
	_Track	*track;

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

	return track->f.channelCount;
}

Project: audiofile

void _af_setup_free_instruments (AFfilesetup setup)
{
	int i;

	if (setup->instruments)
	{
		for (i = 0; i < setup->instrumentCount; i++)
			_af_setup_free_loops(setup, i);

		free(setup->instruments);
	}

	setup->instruments = NULL;
	setup->instrumentCount = 0;
}

Project: audiofile

void _Track::print()
{
	fprintf(stderr, "totalfframes %ld\n", totalfframes);
	fprintf(stderr, "nextfframe %ld\n", nextfframe);
	fprintf(stderr, "frames2ignore %ld\n", frames2ignore);
	fprintf(stderr, "fpos_first_frame %ld\n", fpos_first_frame);
	fprintf(stderr, "fpos_next_frame %ld\n", fpos_next_frame);
	fprintf(stderr, "fpos_after_data %ld\n", fpos_after_data);
	fprintf(stderr, "totalvframes %ld\n", totalvframes);
	fprintf(stderr, "nextvframe %ld\n", nextvframe);
	fprintf(stderr, "data_size %ld\n", data_size);
}

Project: audiofile

void MSADPCM::runPull()
{
	AFframecount framesToRead = m_outChunk->frameCount;
	AFframecount framesRead = 0;

	assert(m_outChunk->frameCount % m_framesPerBlock == 0);
	int blockCount = m_outChunk->frameCount / m_framesPerBlock;

	/* Read the compressed frames. */
	ssize_t bytesRead = read(m_inChunk->buffer, m_blockAlign * blockCount);
	size_t blocksRead = bytesRead >= 0 ? bytesRead / m_blockAlign : 0;

	/* Decompress into m_outChunk. */
	for (int i=0; i<blockCount; i++)
	{
		size_t bytesDecoded = decodeBlock(static_cast<const uint8_t *>(m_inChunk->buffer) + i * m_blockAlign,
			static_cast<int16_t *>(m_outChunk->buffer) + i * m_framesPerBlock * m_track->f.channelCount);

		framesRead += m_framesPerBlock;
	}

	m_track->nextfframe += framesRead;

	if (blocksRead > 0)
		m_track->fpos_next_frame += blocksRead * m_blockAlign;

	assert(tell() == m_track->fpos_next_frame);

	/*
		If we got EOF from read, then we return the actual amount read.

		Complain only if there should have been more frames in the file.
	*/

	if (m_track->totalfframes != -1 && framesRead != framesToRead)
	{
		/* Report error if we haven't already */
		if (m_track->filemodhappy)
		{
			_af_error(AF_BAD_READ,
				"file missing data -- read %d frames, should be %d",
				m_track->nextfframe,
				m_track->totalfframes);
			m_track->filemodhappy = false;
		}
	}

	m_outChunk->frameCount = framesRead;
}

Project: audiofile

status ModuleState::setup(AFfilehandle file, _Track *track)
{
	AFframecount fframepos = llrint(track->nextvframe * track->f.sampleRate / track->v.sampleRate);
	bool isReading = file->access == _AF_READ_ACCESS;

	if (!track->v.isUncompressed())
	{
		_af_error(AF_BAD_NOT_IMPLEMENTED,
			"library does not support compression in virtual format yet");
		return AF_FAIL;
	}

	if (arrange(file, track) == AF_FAIL)
		return AF_FAIL;

	track->filemodhappy = true;
	int maxbufsize = 0;
	if (isReading)
	{
		m_chunks.back()->frameCount = _AF_ATOMIC_NVFRAMES;
		for (int i=m_modules.size() - 1; i >= 0; i--)
		{
			SharedPtr<Chunk> inChunk = m_chunks[i];
			SharedPtr<Chunk> outChunk = m_chunks[i+1];
			int bufsize = outChunk->frameCount * outChunk->f.bytesPerFrame(true);
			if (bufsize > maxbufsize)
				maxbufsize = bufsize;
			if (i != 0)
				m_modules[i]->setSource(m_modules[i-1].get());
			m_modules[i]->maxPull();
		}

		if (!track->filemodhappy)
			return AF_FAIL;
		int bufsize = m_fileModule->inChunk()->frameCount *
			m_fileModule->outChunk()->f.bytesPerFrame(true);
		if (bufsize > maxbufsize)
			maxbufsize = bufsize;
	}
	else
	{
		m_chunks.front()->frameCount = _AF_ATOMIC_NVFRAMES;
		for (size_t i=0; i<m_modules.size(); i++)
		{
			SharedPtr<Chunk> inChunk = m_chunks[i];
			SharedPtr<Chunk> outChunk = m_chunks[i+1];
			int bufsize = inChunk->frameCount * inChunk->f.bytesPerFrame(true);
			if (bufsize > maxbufsize)
				maxbufsize = bufsize;
			if (i != m_modules.size() - 1)
				m_modules[i]->setSink(m_modules[i+1].get());
			m_modules[i]->maxPush();
		}

		if (!track->filemodhappy)
			return AF_FAIL;

		int bufsize = m_fileModule->outChunk()->frameCount *
			m_fileModule->inChunk()->f.bytesPerFrame(true);
		if (bufsize > maxbufsize)
			maxbufsize = bufsize;
	}

	for (size_t i=0; i<m_chunks.size(); i++)
	{
		if ((isReading && i==m_chunks.size() - 1) || (!isReading && i==0))
			continue;
		m_chunks[i]->allocate(maxbufsize);
	}

	if (isReading)
	{
		if (track->totalfframes == -1)
			track->totalvframes = -1;
		else
			track->totalvframes = llrint(track->totalfframes *
				(track->v.sampleRate / track->f.sampleRate));

		track->nextfframe = fframepos;
		track->nextvframe = llrint(fframepos * track->v.sampleRate / track->f.sampleRate);

		m_isDirty = false;

		if (reset(file, track) == AF_FAIL)
			return AF_FAIL;
	}
	else
	{
		track->nextvframe = track->totalvframes =
			(AFframecount) (fframepos * track->v.sampleRate / track->f.sampleRate);
		m_isDirty = false;
	}

	return AF_SUCCEED;
}

Project: audiofile

Module::~Module()
{
}

Project: audiofile

void IMA::reset2()
{
	m_track->fpos_next_frame = m_track->fpos_first_frame +
		m_blockAlign * (m_track->nextfframe / m_framesPerBlock);
	m_track->frames2ignore += m_framesToIgnore;

	assert(m_track->nextfframe % m_framesPerBlock == 0);
}

Project: audiofile

void afInitSampleFormat (AFfilesetup setup, int trackid, int sampfmt, int sampwidth)
{
	_TrackSetup	*track;

	if (!_af_filesetup_ok(setup))
		return;

	if ((track = _af_filesetup_get_tracksetup(setup, trackid)) == NULL)
		return;

	_af_set_sample_format(&track->f, sampfmt, sampwidth);

	track->sampleFormatSet = true;
	track->sampleWidthSet = true;
}

Project: audiofile

	virtual const char *name() const { return "transform"; }

Project: audiofile

	Result operator()(const Arg &x) const { return x >> shift; }

Project: audiofile

int afIdentifyNamedFD (int fd, const char *filename, int *implemented)
{
	FILE		*fp;
	AFvirtualfile	*vf;
	int		result;

	/*
		Duplicate the file descriptor since otherwise the
		original file descriptor would get closed when we close
		the virtual file below.
	*/
	fd = dup(fd);

	vf = new File(fd, File::ReadAccess);
	if (vf == NULL)
	{
		_af_error(AF_BAD_OPEN, "could not open file '%s'", filename);
		return AF_FILE_UNKNOWN;
	}

	result = _af_identify(vf, implemented);

	af_fclose(vf);

	return result;
}

Project: audiofile

status af_write_pstring (const char *s, AFvirtualfile *vf)
{
	size_t length = strlen(s);
	if (length > 255)
		return AF_FAIL;
	uint8_t sizeByte = (uint8_t) length;
	if (vf->write(&sizeByte, 1) != 1)
		return AF_FAIL;
	if (vf->write(s, length) != (ssize_t) length)
		return AF_FAIL;
	/*
		Add a pad byte if the length of the Pascal-style string
		(including the size byte) is odd.
	*/
	if ((length % 2) == 0)
	{
		uint8_t zero = 0;
		if (vf->write(&zero, 1) != 1)
			return AF_FAIL;
	}
	return AF_SUCCEED;
}

Project: audiofile

int _af_format_frame_size_uncompressed (const _AudioFormat *fmt, bool stretch3to4)
{
	return _af_format_sample_size_uncompressed(fmt, stretch3to4) *
		fmt->channelCount;
}

Project: audiofile

void ModuleState::print()
{
	fprintf(stderr, "modules:\n");
	for (size_t i=0; i<m_modules.size(); i++)
		fprintf(stderr, " %s (%p) in %p out %p\n",
			m_modules[i]->name(), m_modules[i].get(),
			m_modules[i]->inChunk(),
			m_modules[i]->outChunk());
	fprintf(stderr, "chunks:\n");
	for (size_t i=0; i<m_chunks.size(); i++)
		fprintf(stderr, " %p %s\n",
			m_chunks[i].get(),
			m_chunks[i]->f.description().c_str());
}

Project: audiofile

	Clip(FormatCode format, const _PCMInfo &outputMapping) :
		m_format(format),
		m_outputMapping(outputMapping)
	{
	}

Project: audiofile

const char *ApplyChannelMatrix::name() const { return "channelMatrix"; }

Project: audiofile

	virtual const char *name() const
	{
		return mode() == Compress ? "g711compress" : "g711decompress";
	}

Project: audiofile

	static void convertSignedToUnsigned(const void *src, void *dst, size_t count)
	{
		transform<typename signConverter<Format>::signedToUnsigned>(src, dst, count);
	}

Project: audiofile

static void alaw2linear_buf (const uint8_t *alaw, int16_t *linear, int nsamples)
{
	for (int i=0; i < nsamples; i++)
		linear[i] = _af_alaw2linear(alaw[i]);
}

Project: audiofile

MSADPCM::MSADPCM(_Track *track, AFvirtualfile *fh, bool canSeek) :
	FileModule(Decompress, track, fh, canSeek)
{
}

Project: audiofile

Module *_AFpcminitdecompress (_Track *track, AFvirtualfile *fh, bool canSeek,
	bool headerless, AFframecount *chunkFrames)
{
	return PCM::createDecompress(track, fh, canSeek, headerless, chunkFrames);
}

Project: audiofile

status ModuleState::initFileModule(AFfilehandle file, _Track *track)
{
	int compressionIndex = _af_compression_index_from_id(track->f.compressionType);
	const _CompressionUnit *unit = &_af_compression[compressionIndex];

	if (af_fseek(file->fh, track->fpos_first_frame, SEEK_SET) < 0)
	{
		_af_error(AF_BAD_LSEEK, "unable to position file handle at beginning of sound data");
		return AF_FAIL;
	}

	AFframecount chunkFrames;
	if (file->access == _AF_READ_ACCESS)
		m_fileModule = unit->initdecompress(track, file->fh, file->seekok,
			file->fileFormat == AF_FILE_RAWDATA, &chunkFrames);
	else
		m_fileModule = unit->initcompress(track, file->fh, file->seekok,
			file->fileFormat == AF_FILE_RAWDATA, &chunkFrames);

	track->filemodhappy = true;

	return AF_SUCCEED;
}

Project: audiofile

	T *get() const { return m_ptr; }

Project: audiofile

void afInitDataOffset (AFfilesetup setup, int trackid, AFfileoffset offset)
{
	_TrackSetup	*track;

	if (!_af_filesetup_ok(setup))
		return;

	if ((track = _af_filesetup_get_tracksetup(setup, trackid)) == NULL)
		return;

	if (offset < 0)
	{
		_af_error(AF_BAD_DATAOFFSET, "invalid data offset %d", offset);
		return;
	}

	track->dataOffset = offset;
	track->dataOffsetSet = true;
}

Project: audiofile

int MSADPCM::decodeBlock (const uint8_t *encoded, int16_t *decoded)
{
	int16_t *coefficient[2];
	ms_adpcm_state decoderState[2];
	ms_adpcm_state *state[2];

	int channelCount = m_track->f.channelCount;

	/* Calculate the number of bytes needed for decoded data. */
	int outputLength = m_framesPerBlock * sizeof (int16_t) * channelCount;

	state[0] = &decoderState[0];
	if (channelCount == 2)
		state[1] = &decoderState[1];
	else
		state[1] = &decoderState[0];

	/* Initialize predictor. */
	for (int i=0; i<channelCount; i++)
	{
		state[i]->predictor = *encoded++;
		assert(state[i]->predictor < m_numCoefficients);
	}

	/* Initialize delta. */
	for (int i=0; i<channelCount; i++)
	{
		state[i]->delta = (encoded[1]<<8) | encoded[0];
		encoded += sizeof (uint16_t);
	}

	/* Initialize first two samples. */
	for (int i=0; i<channelCount; i++)
	{
		state[i]->sample1 = (encoded[1]<<8) | encoded[0];
		encoded += sizeof (uint16_t);
	}

	for (int i=0; i<channelCount; i++)
	{
		state[i]->sample2 = (encoded[1]<<8) | encoded[0];
		encoded += sizeof (uint16_t);
	}

	coefficient[0] = m_coefficients[state[0]->predictor];
	coefficient[1] = m_coefficients[state[1]->predictor];

	for (int i=0; i<channelCount; i++)
		*decoded++ = state[i]->sample2;

	for (int i=0; i<channelCount; i++)
		*decoded++ = state[i]->sample1;

	/*
		The first two samples have already been 'decoded' in
		the block header.
	*/
	int samplesRemaining = (m_framesPerBlock - 2) * m_track->f.channelCount;

	while (samplesRemaining > 0)
	{
		uint8_t code;
		int16_t newSample;

		code = *encoded >> 4;
		newSample = ms_adpcm_decode_sample(state[0], code, coefficient[0]);
		*decoded++ = newSample;

		code = *encoded & 0x0f;
		newSample = ms_adpcm_decode_sample(state[1], code, coefficient[1]);
		*decoded++ = newSample;

		encoded++;
		samplesRemaining -= 2;
	}

	return outputLength;
}

Project: audiofile

AUpvlist _af_pv_long (long val)
{
	AUpvlist	ret = AUpvnew(1);
	AUpvsetparam(ret, 0, 0);
	AUpvsetvaltype(ret, 0, AU_PVTYPE_LONG);
	AUpvsetval(ret, 0, &val);
	return ret;
}

Project: audiofile

	virtual void run(Chunk &input, Chunk &output)
	{
		size_t count = input.frameCount * m_inChunk->f.channelCount;
		if (m_fromSigned)
			convertSignedToUnsigned(input.buffer, output.buffer, count);
		else
			convertUnsignedToSigned(input.buffer, output.buffer, count);
	}

Project: audiofile

inline uint64_t _af_byteswap_int64 (uint64_t x)
{
	return ((x & 0x00000000000000ffULL) << 56) |
		((x & 0x000000000000ff00ULL) << 40) |
		((x & 0x0000000000ff0000ULL) << 24) |
		((x & 0x00000000ff000000ULL) << 8) |
		((x & 0x000000ff00000000ULL) >> 8) |
		((x & 0x0000ff0000000000ULL) >> 24) |
		((x & 0x00ff000000000000ULL) >> 40) |
		((x & 0xff00000000000000ULL) >> 56);
}

Project: audiofile

ModuleState::ModuleState() :
	m_isDirty(true)
{
}

Project: audiofile

	virtual void sync2() { }

Project: audiofile

inline double _af_byteswap_float64 (double x)
{
	union
	{
		uint64_t i;
		double f;
	} u;
	u.f = x;
	u.i = _af_byteswap_int64(u.i);
	return u.f;
}

Project: audiofile

float afGetFrameSize (AFfilehandle file, int trackid, int stretch3to4)
{
	_Track	*track;

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

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

	return _af_format_frame_size(&track->f, stretch3to4);
}

Project: audiofile

PCM::PCM(Mode mode, _Track *track, AFvirtualfile *fh, bool canSeek) :
	FileModule(mode, track, fh, canSeek),
	m_bytesPerFrame(track->f.bytesPerFrame(false)),
	m_saved_fpos_next_frame(-1),
	m_saved_nextfframe(-1)
{
	if (mode == Decompress)
		track->f.compressionParams = AU_NULL_PVLIST;
}

Project: audiofile

void PCM::runPush()
{
	AFframecount frames2write = m_inChunk->frameCount;
	AFframecount n;

	/*
		WARNING: due to the optimization explained at the end
		of arrangemodules(), the pcm file module cannot depend
		on the presence of the intermediate working buffer
		which _AFsetupmodules usually allocates for file
		modules in their input or output chunk (for reading or
		writing, respectively).

		Fortunately, the pcm module has no need for such a buffer.
	*/

	ssize_t bytesWritten = write(m_inChunk->buffer, m_bytesPerFrame * frames2write);
	n = bytesWritten >= 0 ? bytesWritten / m_bytesPerFrame : 0;

	CHNK(printf("writing %" AF_FRAMECOUNT_PRINT_FMT " frames to pcm file\n",
		frames2write));

	if (n != frames2write)
	{
		/* Report error if we haven't already. */
		if (m_track->filemodhappy)
		{
			/* I/O error */
			if (n < 0)
				_af_error(AF_BAD_WRITE,
					"unable to write data (%s) -- "
					"wrote %d out of %d frames",
					strerror(errno),
					m_track->nextfframe + n,
					m_track->nextfframe + frames2write);
			/* usual disk full error */
			else
				_af_error(AF_BAD_WRITE,
					"unable to write data (disk full) -- "
					"wrote %d out of %d frames",
					m_track->nextfframe + n,
					m_track->nextfframe + frames2write);
			m_track->filemodhappy = false;
		}
	}

	m_track->nextfframe += n;
	m_track->totalfframes = m_track->nextfframe;
	m_track->fpos_next_frame += (n>0) ? n * m_bytesPerFrame : 0;
	assert(!canSeek() || (tell() == m_track->fpos_next_frame));
}

Project: audiofile

	virtual void describe()
	{
		getDefaultPCMMapping(m_outChunk->f.sampleWidth,
			m_outChunk->f.pcm.slope,
			m_outChunk->f.pcm.intercept,
			m_outChunk->f.pcm.minClip,
			m_outChunk->f.pcm.maxClip);
	}

Project: audiofile

ssize_t FileModule::write(const void *data, size_t nbytes)
{
	return m_fh->write(data, nbytes);
}

Project: audiofile

	virtual void describe()
	{
		m_outChunk->f.pcm = m_outputMapping;
	}

Project: audiofile

int _af_format_sample_size_uncompressed (const _AudioFormat *format, bool stretch3to4)
{
	int	size = 0;

	switch (format->sampleFormat)
	{
		case AF_SAMPFMT_FLOAT:
			size = sizeof (float);
			break;
		case AF_SAMPFMT_DOUBLE:
			size = sizeof (double);
			break;
		default:
			size = (int) (format->sampleWidth + 7) / 8;
			if (format->compressionType == AF_COMPRESSION_NONE &&
				size == 3 && stretch3to4)
				size = 4;
			break;
	}

	return size;
}

Project: audiofile

	~Shared()
	{
	}

Project: audiofile

int afGetTrackIDs (AFfilehandle file, int *trackids)
{
	assert(file);

	if (trackids != NULL)
		trackids[0] = AF_DEFAULT_TRACK;

	return 1;
}

Project: audiofile

	bool operator !() const { return !m_ptr; }

Project: audiofile

bool _af_pv_getptr (AUpvlist pvlist, int param, void **v)
{
	int	i;

	for (i=0; i<AUpvgetmaxitems(pvlist); i++)
	{
		int	p, t;

		AUpvgetparam(pvlist, i, &p);

		if (p != param)
			continue;

		AUpvgetvaltype(pvlist, i, &t);

		/* Ensure that this parameter is of type AU_PVTYPE_PTR. */
		if (t != AU_PVTYPE_PTR)
			return false;

		AUpvgetval(pvlist, i, v);
		return true;
	}

	return false;
}

Project: audiofile

bool _af_pv_getlong (AUpvlist pvlist, int param, long *l)
{
	int	i;

	for (i=0; i<AUpvgetmaxitems(pvlist); i++)
	{
		int	p, t;

		AUpvgetparam(pvlist, i, &p);

		if (p != param)
			continue;

		AUpvgetvaltype(pvlist, i, &t);

		/* Ensure that this parameter is of type AU_PVTYPE_LONG. */
		if (t != AU_PVTYPE_LONG)
			return false;

		AUpvgetval(pvlist, i, l);
		return true;
	}

	return false;
}

Project: audiofile

void Module::describe()
{
}

Project: audiofile

int afSetVirtualSampleFormat (AFfilehandle file, int trackid,
	int sampleFormat, int sampleWidth)
{
	_Track	*track;

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

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

	if (_af_set_sample_format(&track->v, sampleFormat, sampleWidth) == AF_FAIL)
		return -1;

	track->ms->setDirty();

	return 0;
}

Project: audiofile

AFfileoffset afGetDataOffset (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->fpos_first_frame;
}

Project: audiofile

double afGetVirtualRate (AFfilehandle file, int trackid)
{
	_Track	*track;

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

	return track->v.sampleRate;
}

Project: audiofile

AFfilehandle afOpenVirtualFile (AFvirtualfile *vfile, const char *mode,
	AFfilesetup setup)
{
	AFfilehandle	filehandle;
	int		access; 

	if (vfile == NULL)
	{
		_af_error(AF_BAD_FILEHANDLE, "null virtual filehandle");
		return AF_NULL_FILEHANDLE;
	}

	if (mode == NULL)
	{
		_af_error(AF_BAD_ACCMODE, "null access mode");
		return AF_NULL_FILEHANDLE;
	}

	if (mode[0] == 'r')
		access = _AF_READ_ACCESS;
	else if (mode[0] == 'w')
		access = _AF_WRITE_ACCESS;
	else
	{
		_af_error(AF_BAD_ACCMODE, "unrecognized access mode '%s'", mode);
		return AF_NULL_FILEHANDLE;
	}

	if (_afOpenFile(access, vfile, NULL, &filehandle, setup) != AF_SUCCEED)
		af_fclose(vfile);

	return filehandle;
}

Project: audiofile

	virtual void run(Chunk &inChunk, Chunk &outChunk)
	{
		const void *src = inChunk.buffer;
		void *dst = outChunk.buffer;
		int count = inChunk.frameCount * inChunk.f.channelCount;

		if (m_inputFormat == kFloat)
		{
			switch (m_outputFormat)
			{
				case kInt8:
					run<float, int8_t>(src, dst, count); break;
				case kInt16:
					run<float, int16_t>(src, dst, count); break;
				case kInt24:
				case kInt32:
					run<float, int32_t>(src, dst, count); break;
				default:
					assert(false);
			}
		}
		else if (m_inputFormat == kDouble)
		{
			switch (m_outputFormat)
			{
				case kInt8:
					run<double, int8_t>(src, dst, count); break;
				case kInt16:
					run<double, int16_t>(src, dst, count); break;
				case kInt24:
				case kInt32:
					run<double, int32_t>(src, dst, count); break;
				default:
					assert(false);
			}
		}
	}

Project: audiofile

int afSyncFile (AFfilehandle handle)
{
	if (!_af_filehandle_ok(handle))
		return -1;

	if (handle->access == _AF_WRITE_ACCESS)
	{
		int	filefmt = handle->fileFormat;
		int	trackno;

		/* Finish writes on all tracks. */
		for (trackno = 0; trackno < handle->trackCount; trackno++)
		{
			_Track	*track = &handle->tracks[trackno];

			if (track->ms->isDirty() && track->ms->setup(handle, track) == AF_FAIL)
				return -1;

			if (track->ms->sync(handle, track) != AF_SUCCEED)
				return -1;
		}

		/* Update file headers. */
		if (_af_units[filefmt].write.update != NULL &&
			_af_units[filefmt].write.update(handle) != AF_SUCCEED)
			return AF_FAIL;
	}
	else if (handle->access == _AF_READ_ACCESS)
	{
		/* Do nothing. */
	}
	else
	{
		_af_error(AF_BAD_ACCMODE, "unrecognized access mode %d",
			handle->access);
		return AF_FAIL;
	}

	return AF_SUCCEED;
}

Project: audiofile

	SharedPtr(T *ptr) : m_ptr(ptr)
	{
		if (m_ptr) m_ptr->retain();
	}

Project: audiofile

const std::vector<SharedPtr<Chunk> > &ModuleState::chunks() const
{
	return m_chunks;
}

Project: audiofile

int afIdentifyFD (int fd)
{
	FILE		*fp;
	AFvirtualfile	*vf;
	int		result;

	/*
		Duplicate the file descriptor since otherwise the
		original file descriptor would get closed when we close
		the virtual file below.
	*/
	fd = dup(fd);
	vf = new File(fd, File::ReadAccess);

	result = _af_identify(vf, NULL);

	af_fclose(vf);

	return result;
}

Project: audiofile

	void convertUnsignedToSigned(const void *src, void *dst, size_t count)
	{
		switch (m_format)
		{
			case kInt8:
				convertUnsignedToSigned<kInt8>(src, dst, count);
				break;
			case kInt16:
				convertUnsignedToSigned<kInt16>(src, dst, count);
				break;
			case kInt24:
				convertUnsignedToSigned<kInt24>(src, dst, count);
				break;
			case kInt32:
				convertUnsignedToSigned<kInt32>(src, dst, count);
				break;
			default:
				assert(false);
		}
	}

Project: audiofile

	virtual void describe()
	{
		m_outChunk->f.packed = true;
	}

Project: audiofile

	virtual const char *name() const { return "convertFloat"; }

Project: audiofile

void Module::maxPull()
{
	m_inChunk->frameCount = m_outChunk->frameCount;
}

Project: audiofile

	Transform(FormatCode format,
		const _PCMInfo &inputMapping,
		const _PCMInfo &outputMapping) :
		m_format(format),
		m_inputMapping(inputMapping),
		m_outputMapping(outputMapping)
	{
		assert(m_format == kFloat || m_format == kDouble);
	}

Project: audiofile

size_t _AudioFormat::bytesPerFrame(bool stretch3to4) const
{
	return _af_format_frame_size_uncompressed(this, stretch3to4);
}

Project: audiofile

	virtual void run(Chunk &inChunk, Chunk &outChunk)
	{
		int count = inChunk.f.channelCount * inChunk.frameCount;
		if (m_isSigned)
			run<int32_t>(inChunk.buffer, outChunk.buffer, count);
		else
			run<uint32_t>(inChunk.buffer, outChunk.buffer, count);
	}

Project: audiofile

bool _af_filehandle_ok (AFfilehandle file)
{
	if (file == AF_NULL_FILEHANDLE)
	{
		_af_error(AF_BAD_FILEHANDLE, "null file handle");
		return false;
	}
	if (file->valid != _AF_VALID_FILEHANDLE)
	{
		_af_error(AF_BAD_FILEHANDLE, "invalid file handle");
		return false;
	}
	return true;
}

Project: audiofile

inline void SwapModule::runSwap<3, char>(const char *input, char *output, int count)
{
	for (int i=0; i<count; i++)
	{
		output[3*i] = input[3*i+2];
		output[3*i+1] = input[3*i+1];
		output[3*i+2] = input[3*i];
	}
}

Project: audiofile

bool _AudioFormat::isFloat() const
{
	return sampleFormat == AF_SAMPFMT_FLOAT ||
		sampleFormat == AF_SAMPFMT_DOUBLE;
}

Project: audiofile

float _af_format_frame_size (const _AudioFormat *fmt, bool stretch3to4)
{
	int	compressionIndex;
	float	squishFactor;

	compressionIndex = _af_compression_index_from_id(fmt->compressionType);
	squishFactor = _af_compression[compressionIndex].squishFactor;

	return _af_format_frame_size_uncompressed(fmt, stretch3to4) /
		squishFactor;
}

Project: audiofile

	~SharedPtr()
	{
		if (T *p = m_ptr) p->release();
	}

Project: audiofile

_Track *_af_track_new (void)
{
	_Track *t = (_Track *) _af_malloc(sizeof (_Track));

	t->id = AF_DEFAULT_TRACK;

	t->f.compressionParams = NULL;
	t->v.compressionParams = NULL;

	t->channelMatrix = NULL;

	t->markerCount = 0;
	t->markers = NULL;

	t->hasAESData = false;
	memset(t->aesData, 0, 24);

	t->totalfframes = 0;
	t->nextfframe = 0;
	t->frames2ignore = 0;
	t->fpos_first_frame = 0;
	t->fpos_next_frame = 0;
	t->fpos_after_data = 0;
	t->totalvframes = 0;
	t->nextvframe = 0;
	t->data_size = 0;

	t->ms = NULL;

	return t;
}

Project: audiofile

IMA::IMA(_Track *track, AFvirtualfile *fh, bool canSeek) :
	FileModule(Decompress, track, fh, canSeek),
	m_blockAlign(-1),
	m_framesPerBlock(-1),
	m_framesToIgnore(-1)
{
}

Project: audiofile

void ApplyChannelMatrix::initDefaultMatrix()
{
	const double *matrix = NULL;
	if (m_inChannels==1 && m_outChannels==2)
	{
		static const double m[]={1,1};
		matrix = m;
	}
	else if (m_inChannels==1 && m_outChannels==4)
	{
		static const double m[]={1,1,0,0};
		matrix = m;
	}
	else if (m_inChannels==2 && m_outChannels==1)
	{
		static const double m[]={.5,.5};
		matrix = m;
	}
	else if (m_inChannels==2 && m_outChannels==4)
	{
		static const double m[]={1,0,0,1,0,0,0,0};
		matrix = m;
	}
	else if (m_inChannels==4 && m_outChannels==1)
	{
		static const double m[]={.5,.5,.5,.5};
		matrix = m;
	}
	else if (m_inChannels==4 && m_outChannels==2)
	{
		static const double m[]={1,0,1,0,0,1,0,1};
		matrix = m;
	}

	if (matrix)
	{
		std::copy(matrix, matrix + m_inChannels * m_outChannels, m_matrix);
	}
	else
	{
		for (int i=0; i < m_inChannels; i++)
			for (int j=0; j < m_outChannels; j++)
				m_matrix[j*m_inChannels + i] = (i==j) ? 1 : 0;
	}
}

Project: audiofile

void _af_printid (uint32_t id)
{
	printf("%c%c%c%c",
		(id >> 24) & 0xff,
		(id >> 16) & 0xff,
		(id >> 8) & 0xff,
		id & 0xff);
}

Project: audiofile

void IMA::runPull()
{
	AFframecount framesToRead = m_outChunk->frameCount;
	AFframecount framesRead = 0;

	assert(m_outChunk->frameCount % m_framesPerBlock == 0);
	int blockCount = m_outChunk->frameCount / m_framesPerBlock;

	/* Read the compressed frames. */
	ssize_t bytesRead = read(m_inChunk->buffer, m_blockAlign * blockCount);
	ssize_t blocksRead = bytesRead >= 0 ? bytesRead / m_blockAlign : 0;

	/* This condition would indicate that the file is bad. */
	if (blocksRead < 0)
	{
		if (m_track->filemodhappy)
		{
			_af_error(AF_BAD_READ, "file missing data");
			m_track->filemodhappy = false;
		}
	}

	if (blocksRead < blockCount)
		blockCount = blocksRead;

	/* Decompress into module->outc. */
	for (int i=0; i<blockCount; i++)
	{
		ssize_t bytesDecoded = decodeBlock(static_cast<const uint8_t *>(m_inChunk->buffer) + i * m_blockAlign,
			static_cast<int16_t *>(m_outChunk->buffer) + i * m_framesPerBlock * m_track->f.channelCount);

		framesRead += m_framesPerBlock;
	}

	m_track->nextfframe += framesRead;

	if (blocksRead > 0)
		m_track->fpos_next_frame += blocksRead * m_blockAlign;

	assert(tell() == m_track->fpos_next_frame);

	/*
		If we got EOF from read, then we return the actual amount read.

		Complain only if there should have been more frames in the file.
	*/

	if (m_track->totalfframes != -1 && framesRead != framesToRead)
	{
		/* Report error if we haven't already */
		if (m_track->filemodhappy)
		{
			_af_error(AF_BAD_READ,
				"file missing data -- read %d frames, should be %d",
				m_track->nextfframe,
				m_track->totalfframes);
			m_track->filemodhappy = false;
		}
	}

	m_outChunk->frameCount = framesRead;
}

Project: audiofile

AFfilesetup _af_filesetup_copy (AFfilesetup setup, AFfilesetup defaultSetup,
	bool copyMarks)
{
	AFfilesetup	newsetup;
	int		i;
	int		instrumentCount, miscellaneousCount, trackCount;

	newsetup = _af_malloc(sizeof (_AFfilesetup));
	if (newsetup == AF_NULL_FILESETUP)
		return AF_NULL_FILESETUP;

#ifdef DEBUG
	printf("default: trackset=%d instset=%d miscset=%d\n",
		defaultSetup->trackSet, defaultSetup->instrumentSet,
		defaultSetup->miscellaneousSet);
	printf("setup: trackset=%d instset=%d miscset=%d\n",
		setup->trackSet, setup->instrumentSet, setup->miscellaneousSet);
#endif

	*newsetup = *defaultSetup;

	newsetup->tracks = NULL;
	newsetup->instruments = NULL;
	newsetup->miscellaneous = NULL;

	/* Copy tracks. */
	trackCount = setup->trackSet ? setup->trackCount :
		newsetup->trackSet ? newsetup->trackCount : 0;
	alloccopy(_TrackSetup, trackCount, newsetup->tracks, setup->tracks);
	newsetup->trackCount = trackCount;

	/* Copy instruments. */
	instrumentCount = setup->instrumentSet ? setup->instrumentCount :
		newsetup->instrumentSet ? newsetup->instrumentCount : 0;
	alloccopy(_InstrumentSetup, instrumentCount, newsetup->instruments, setup->instruments);
	newsetup->instrumentCount = instrumentCount;

	/* Copy miscellaneous information. */
	miscellaneousCount = setup->miscellaneousSet ? setup->miscellaneousCount :
		newsetup->miscellaneousSet ? newsetup->miscellaneousCount : 0;
	alloccopy(_MiscellaneousSetup, miscellaneousCount, newsetup->miscellaneous, setup->miscellaneous);
	newsetup->miscellaneousCount = miscellaneousCount;

	for (i=0; i<setup->trackCount; i++)
	{
		int	j;
		_TrackSetup	*track = &newsetup->tracks[i];

		/* XXXmpruett set compression information */

		if (!setup->tracks[i].markersSet && !copyMarks)
		{
			track->markers = NULL;
			track->markerCount = 0;
			continue;
		}

		alloccopy(_MarkerSetup, setup->tracks[i].markerCount,
			track->markers, setup->tracks[i].markers);
		track->markerCount = setup->tracks[i].markerCount;

		for (j=0; j<setup->tracks[i].markerCount; j++)
		{
			track->markers[j].name =
				_af_strdup(setup->tracks[i].markers[j].name);
			if (track->markers[j].name == NULL)
				goto fail;

			track->markers[j].comment =
				_af_strdup(setup->tracks[i].markers[j].comment);
			if (track->markers[j].comment == NULL)
				goto fail;
		}
	}

	for (i=0; i<newsetup->instrumentCount; i++)
	{
		_InstrumentSetup	*instrument = &newsetup->instruments[i];
		alloccopy(_LoopSetup, setup->instruments[i].loopCount,
			instrument->loops, setup->instruments[i].loops);
	}

	return newsetup;

	fail:
		if (newsetup->miscellaneous)
			free(newsetup->miscellaneous);
		if (newsetup->instruments)
			free(newsetup->instruments);
		if (newsetup->tracks)
			free(newsetup->tracks);
		if (newsetup)
			free(newsetup);

	return AF_NULL_FILESETUP;
}

Project: audiofile

void ApplyChannelMatrix::run(const void *inputData, void *outputData, int frameCount)
{
	const T *input = reinterpret_cast<const T *>(inputData);
	T *output = reinterpret_cast<T *>(outputData);
	for (int frame=0; frame<frameCount; frame++)
	{
		const T *inputSave = input;
		const double *m = m_matrix;
		for (int outChannel=0; outChannel < m_outChannels; outChannel++)
		{
			input = inputSave;
			double t = 0;
			for (int inChannel=0; inChannel < m_inChannels; inChannel++)
				t += *input++ * *m++;
			*output++ = t;
		}
	}
}

Project: audiofile

	virtual const char *name() const { return "expand3to4"; }

Project: audiofile

double afGetRate (AFfilehandle file, int trackid)
{
	_Track	*track;

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

	return track->f.sampleRate;
}

Project: audiofile

inline uint32_t byteswap(uint32_t value) { return _af_byteswap_int32(value); }

Project: audiofile

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->setDirty();

	return 0;
}

Project: audiofile

void ModuleState::addConvertIntToInt(FormatCode input, FormatCode output)
{
	if (input == output)
		return;

	assert(isInteger(input));
	assert(isInteger(output));
	addModule(new ConvertInt(input, output));
}

Project: audiofile

	virtual const char *name() const { return "intToFloat"; }

Project: audiofile

void ModuleState::addConvertFloatToInt(FormatCode input, FormatCode output,
	const _PCMInfo &inputMapping, const _PCMInfo &outputMapping)
{
	addModule(new ConvertFloatToIntClip(input, output, inputMapping, outputMapping));
}

Project: audiofile

	virtual const char *name() const { return "ima_adpcm_decompress"; }

Project: audiofile

status af_write_int8 (const int8_t *value, AFvirtualfile *vf)
{
	if (!write(vf, value))
		return AF_FAIL;
	return AF_SUCCEED;
}

Project: audiofile

int afSetVirtualChannels (AFfilehandle file, int trackid, int channelCount)
{
	_Track	*track;

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

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

	track->v.channelCount = channelCount;
	track->ms->setDirty();

	if (track->channelMatrix)
		free(track->channelMatrix);
	track->channelMatrix = NULL;

	return 0;
}

Project: audiofile

T littleToHost(T value)
{
	return _AF_BYTEORDER_NATIVE == AF_BYTEORDER_LITTLEENDIAN ? value : byteswap(value);
}

Project: audiofile

	static void convertUnsignedToSigned(const void *src, void *dst, size_t count)
	{
		transform<typename signConverter<Format>::unsignedToSigned>(src, dst, count);
	}

Project: audiofile

	Chunk *inChunk() { return m_inChunk.get(); }

Project: audiofile

	Mode mode() const { return m_mode; }

Project: audiofile

ssize_t FileModule::read(void *data, size_t nbytes)
{
	return m_fh->read(data, nbytes);
}

Project: audiofile

AUpvlist _af_pv_double (double val)
{
	AUpvlist	ret = AUpvnew(1);
	AUpvsetparam(ret, 0, 0);
	AUpvsetvaltype(ret, 0, AU_PVTYPE_DOUBLE);
	AUpvsetval(ret, 0, &val);
	return ret;
}

Project: audiofile

	bool mustUseAtomicNVFrames() const { return true; }

Project: audiofile

void G711::runPush()
{
	AFframecount framesToWrite = m_inChunk->frameCount;
	AFframecount samplesToWrite = m_inChunk->frameCount * m_inChunk->f.channelCount;
	int framesize = m_inChunk->f.channelCount;

	assert(m_track->f.compressionType == AF_COMPRESSION_G711_ULAW ||
		m_track->f.compressionType == AF_COMPRESSION_G711_ALAW);

	/* Compress frames into i->outc. */

	if (m_track->f.compressionType == AF_COMPRESSION_G711_ULAW)
		linear2ulaw_buf(static_cast<const int16_t *>(m_inChunk->buffer),
			static_cast<uint8_t *>(m_outChunk->buffer), samplesToWrite);
	else
		linear2alaw_buf(static_cast<const int16_t *>(m_inChunk->buffer),
			static_cast<uint8_t *>(m_outChunk->buffer), samplesToWrite);

	/* Write the compressed data. */

	ssize_t bytesWritten = write(m_outChunk->buffer, framesize * framesToWrite);
	AFframecount framesWritten = bytesWritten >= 0 ? bytesWritten / framesize : 0;

	CHNK(printf("writing %d frames to g711 file\n", framesToWrite));

	if (framesWritten != framesToWrite)
	{
		/* report error if we haven't already */
		if (m_track->filemodhappy)
		{
			/* i/o error */
			if (framesWritten < 0)
				_af_error(AF_BAD_WRITE,
					"unable to write data (%s) -- "
					"wrote %d out of %d frames",
					strerror(errno),
					m_track->nextfframe + framesWritten,
					m_track->nextfframe + framesToWrite);

			/* usual disk full error */
			else
				_af_error(AF_BAD_WRITE,
					"unable to write data (disk full) -- "
					"wrote %d out of %d frames",
					m_track->nextfframe + framesWritten,
					m_track->nextfframe + framesToWrite);

			m_track->filemodhappy = false;
		}
	}

	m_track->nextfframe += framesWritten;
	m_track->totalfframes = m_track->nextfframe;
	m_track->fpos_next_frame += (framesWritten>0) ? framesWritten*framesize : 0;

	assert(!canSeek() || (tell() == m_track->fpos_next_frame));
}

Project: audiofile

	virtual void run(Chunk &inChunk, Chunk &outChunk)
	{
		int count = inChunk.frameCount * inChunk.f.channelCount;
		if (m_format == kFloat)
			run<float>(inChunk.buffer, outChunk.buffer, count);
		else if (m_format == kDouble)
			run<double>(inChunk.buffer, outChunk.buffer, count);
		else
			assert(false);
	}

Project: audiofile

void IMA::reset1()
{
	AFframecount nextTrackFrame = m_track->nextfframe;
	m_track->nextfframe = (nextTrackFrame / m_framesPerBlock) *
		m_framesPerBlock;

	m_framesToIgnore = nextTrackFrame - m_track->nextfframe;
	/* postroll = frames2ignore */
}

Project: audiofile

inline uint32_t _af_byteswap_int32 (uint32_t x)
{
	return ((x & 0x000000ffU) << 24) |
		((x & 0x0000ff00U) << 8) |
		((x & 0x00ff0000U) >> 8) |
		((x & 0xff000000U) >> 24);
}

Project: audiofile

T hostToLittle(T value)
{
	return _AF_BYTEORDER_NATIVE == AF_BYTEORDER_LITTLEENDIAN ? value : byteswap(value);
}

Project: audiofile

float _af_format_sample_size (const _AudioFormat *fmt, bool stretch3to4)
{
	int	compressionIndex;
	float	squishFactor;

	compressionIndex = _af_compression_index_from_id(fmt->compressionType);
	squishFactor = _af_compression[compressionIndex].squishFactor;

	return _af_format_sample_size_uncompressed(fmt, stretch3to4) /
		squishFactor;
}

Project: audiofile

void transform(const void *srcData, void *dstData, size_t count)
{
	typedef typename UnaryFunction::argument_type InputType;
	typedef typename UnaryFunction::result_type OutputType;
	const InputType *src = reinterpret_cast<const InputType *>(srcData);
	OutputType *dst = reinterpret_cast<OutputType *>(dstData);
	std::transform(src, src + count, dst, UnaryFunction());
}

Project: audiofile

static void freeFileHandle (AFfilehandle filehandle)
{
	int	fileFormat;
	if (filehandle == NULL || filehandle->valid != _AF_VALID_FILEHANDLE)
	{
		_af_error(AF_BAD_FILEHANDLE, "bad filehandle");
		return;
	}

	filehandle->valid = 0;

	if (filehandle->fileName != NULL)
		free(filehandle->fileName);

	fileFormat = filehandle->fileFormat;

	if (filehandle->formatSpecific != NULL)
	{
		free(filehandle->formatSpecific);
		filehandle->formatSpecific = NULL;
	}

	if (filehandle->tracks)
	{
		int	i;
		for (i=0; i<filehandle->trackCount; i++)
		{
			/* Free the compression parameters. */
			if (filehandle->tracks[i].f.compressionParams)
			{
				AUpvfree((AUpvlist) filehandle->tracks[i].f.compressionParams);
				filehandle->tracks[i].f.compressionParams = AU_NULL_PVLIST;
			}

			if (filehandle->tracks[i].v.compressionParams)
			{
				AUpvfree((AUpvlist) filehandle->tracks[i].v.compressionParams);
				filehandle->tracks[i].v.compressionParams = AU_NULL_PVLIST;
			}

			/* Free the track's modules. */

			delete filehandle->tracks[i].ms;
			filehandle->tracks[i].ms = NULL;

			if (filehandle->tracks[i].channelMatrix)
			{
				free(filehandle->tracks[i].channelMatrix);
				filehandle->tracks[i].channelMatrix = NULL;
			}

			if (filehandle->tracks[i].markers)
			{
				int	j;
				for (j=0; j<filehandle->tracks[i].markerCount; j++)
				{
					if (filehandle->tracks[i].markers[j].name)
					{
						free(filehandle->tracks[i].markers[j].name);
						filehandle->tracks[i].markers[j].name = NULL;
					}
					if (filehandle->tracks[i].markers[j].comment)
					{
						free(filehandle->tracks[i].markers[j].comment);
						filehandle->tracks[i].markers[j].comment = NULL;
					}

				}

				free(filehandle->tracks[i].markers);
				filehandle->tracks[i].markers = NULL;
			}
		}

		free(filehandle->tracks);
		filehandle->tracks = NULL;
	}
	filehandle->trackCount = 0;

	if (filehandle->instruments)
	{
		int	i;
		for (i=0; i<filehandle->instrumentCount; i++)
		{
			if (filehandle->instruments[i].loops)
			{
				free(filehandle->instruments[i].loops);
				filehandle->instruments[i].loops = NULL;
			}
			filehandle->instruments[i].loopCount = 0;

			if (filehandle->instruments[i].values)
			{
				freeInstParams(filehandle->instruments[i].values, fileFormat);
				filehandle->instruments[i].values = NULL;
			}
		}
		free(filehandle->instruments);
		filehandle->instruments = NULL;
	}
	filehandle->instrumentCount = 0;

	if (filehandle->miscellaneous)
	{
		free(filehandle->miscellaneous);
		filehandle->miscellaneous = NULL;
	}
	filehandle->miscellaneousCount = 0;

	memset(filehandle, 0, sizeof (_AFfilehandle));
	free(filehandle);
}

Project: audiofile

status _af_set_sample_format (_AudioFormat *f, int sampleFormat, int sampleWidth)
{
	switch (sampleFormat)
	{
		case AF_SAMPFMT_UNSIGNED:
		case AF_SAMPFMT_TWOSCOMP:
		if (sampleWidth < 1 || sampleWidth > 32)
		{
			_af_error(AF_BAD_SAMPFMT,
				"illegal sample width %d for integer data",
				sampleWidth);
			return AF_FAIL;
		}
		else
		{
			int bytes;

			f->sampleFormat = sampleFormat;
			f->sampleWidth = sampleWidth;

			bytes = _af_format_sample_size_uncompressed(f, false);

			if (sampleFormat == AF_SAMPFMT_TWOSCOMP)
				f->pcm = _af_default_signed_integer_pcm_mappings[bytes];
			else
				f->pcm = _af_default_unsigned_integer_pcm_mappings[bytes];
		}
		break;

		case AF_SAMPFMT_FLOAT:
			f->sampleFormat = sampleFormat;
			f->sampleWidth = 32;
			f->pcm = _af_default_float_pcm_mapping;
			break;
		case AF_SAMPFMT_DOUBLE:
			f->sampleFormat = sampleFormat;
			f->sampleWidth = 64;      /*for convenience */
			f->pcm = _af_default_double_pcm_mapping;
			break;
		default:
			_af_error(AF_BAD_SAMPFMT, "unknown sample format %d",
				sampleFormat);
			return AF_FAIL;
	}

	return AF_SUCCEED;
}

Project: audiofile

AFframecount afGetFrameCount (AFfilehandle file, int trackid)
{
	_Track	*track;

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

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

	if (track->ms->isDirty() && track->ms->setup(file, track) == AF_FAIL)
		return -1;

	return track->totalvframes;
}

Project: audiofile

void Module::maxPush()
{
	m_outChunk->frameCount = m_inChunk->frameCount;
}

Project: audiofile

void afGetSampleFormat (AFfilehandle file, int trackid, int *sampleFormat, int *sampleWidth)
{
	_Track	*track;

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

	if (sampleFormat != NULL)
		*sampleFormat = track->f.sampleFormat;

	if (sampleFormat != NULL)
		*sampleWidth = track->f.sampleWidth;
}

Project: audiofile

void _af_print_pvlist (AUpvlist list)
{
	int i;

	assert(list);

	printf("list.valid: %d\n", list->valid);
	printf("list.count: %d\n", list->count);

	for (i=0; i<list->count; i++)
	{
		printf("item %d valid %d, should be %d\n",
			i, list->items[i].valid, _AU_VALID_PVITEM);

		switch (list->items[i].type)
		{
			case AU_PVTYPE_LONG:
				printf("item #%d, parameter %d, long: %ld\n",
					i, list->items[i].parameter,
					list->items[i].value.l);
				break;
			case AU_PVTYPE_DOUBLE:
				printf("item #%d, parameter %d, double: %f\n",
					i, list->items[i].parameter,
					list->items[i].value.d);
				break;
			case AU_PVTYPE_PTR:
				printf("item #%d, parameter %d, pointer: %p\n",
					i, list->items[i].parameter,
					list->items[i].value.v);
				break;

			default:
				printf("item #%d, invalid type %d\n", i,
					list->items[i].type);
				assert(0);
				break;
		}
	}
}

Project: audiofile

Module *_AFg711initdecompress(_Track *track, AFvirtualfile *fh, bool canSeek,
	bool headerless, AFframecount *chunkFrames)
{
	return G711::createDecompress(track, fh, canSeek, headerless, chunkFrames);
}

Project: audiofile

void _af_print_channel_matrix (double *matrix, int fchans, int vchans)
{
	int v, f;

	if (!matrix)
	{
		printf("NULL");
		return;
	}

	printf("{");
	for (v=0; v < vchans; v++)
	{
		if (v) printf(" ");
		printf("{");
		for (f=0; f < fchans; f++)
		{
			if (f) printf(" ");
			printf("%5.2f", *(matrix + v*fchans + f));
		}
		printf("}");
	}
	printf("}");
}

Project: audiofile

	virtual const char *name() const { return "swap"; }

Project: audiofile

inline int16_t byteswap(int16_t value) { return _af_byteswap_int16(value); }

Project: audiofile

T bigToHost(T value)
{
	return _AF_BYTEORDER_NATIVE == AF_BYTEORDER_BIGENDIAN ? value : byteswap(value);
}

Project: audiofile

inline uint64_t byteswap(uint64_t value) { return _af_byteswap_int64(value); }

Project: audiofile

Module *PCM::createDecompress(_Track *track, AFvirtualfile *fh, bool canSeek,
	bool headerless, AFframecount *chunkframes)
{
	return new PCM(Decompress, track, fh, canSeek);
}

Project: audiofile

	bool isPacked() const { return packed; }

Project: audiofile

	void setDirty() { m_isDirty = true; }

Project: audiofile

	SharedPtr() : m_ptr(0)
	{
	}

Project: audiofile

Module *IMA::createDecompress(_Track *track, AFvirtualfile *fh, bool canSeek,
	bool headerless, AFframecount *chunkFrames)
{
	assert(fh->tell() == track->fpos_first_frame);

	IMA *ima = new IMA(track, fh, canSeek);

	AUpvlist pv = (AUpvlist) track->f.compressionParams;

	long l;
	if (_af_pv_getlong(pv, _AF_FRAMES_PER_BLOCK, &l))
		ima->m_framesPerBlock = l;
	else
		_af_error(AF_BAD_CODEC_CONFIG, "samples per block not set");

	if (_af_pv_getlong(pv, _AF_BLOCK_SIZE, &l))
		ima->m_blockAlign = l;
	else
		_af_error(AF_BAD_CODEC_CONFIG, "block size not set");

	*chunkFrames = ima->m_framesPerBlock;

	return ima;
}

Project: audiofile

void PCM::runPull()
{
	AFframecount framesToRead = m_outChunk->frameCount;

	/*
		WARNING: Due to the optimization explained at the end of
		arrangemodules(), the pcm file module cannot depend on
		the presence of the intermediate working buffer which
		_AFsetupmodules usually allocates for file modules in
		their input or output chunk (for reading or writing,
		respectively).

		Fortunately, the pcm module has no need for such a buffer.
	*/

	/*
		Limit the number of frames to be read to the number of
		frames left in the track.
	*/
	if (m_track->totalfframes != -1 &&
		m_track->nextfframe + framesToRead > m_track->totalfframes)
	{
		framesToRead = m_track->totalfframes - m_track->nextfframe;
	}

	ssize_t bytesRead = read(m_outChunk->buffer, m_bytesPerFrame * framesToRead);
	AFframecount framesRead = bytesRead >= 0 ? bytesRead / m_bytesPerFrame : 0;

	CHNK(printf("reading %" AF_FRAMECOUNT_PRINT_FMT " frames from pcm file "
		"(got %" AF_FRAMECOUNT_PRINT_FMT ")\n",
		framesToRead, framesRead));

	m_track->nextfframe += framesRead;
	m_track->fpos_next_frame += (framesRead>0) ? framesRead * m_bytesPerFrame : 0;
	assert(!canSeek() || (tell() == m_track->fpos_next_frame));

	/*
		If we got EOF from read, then we return the actual amount read.

		Complain only if there should have been more frames in the file.
	*/

	if (framesRead != framesToRead && m_track->totalfframes != -1)
	{
		/* Report error if we haven't already. */
		if (m_track->filemodhappy)
		{
			_af_error(AF_BAD_READ,
				"file missing data -- read %d frames, "
				"should be %d",
				m_track->nextfframe,
				m_track->totalfframes);
			m_track->filemodhappy = false;
		}
	}

	m_outChunk->frameCount = framesRead;
}

Project: audiofile

void ModuleState::addModule(Module *module)
{
	if (!module)
		return;

	m_modules.push_back(module);
	module->setInChunk(m_chunks.back().get());
	Chunk *chunk = new Chunk();
	chunk->f = m_chunks.back()->f;
	m_chunks.push_back(chunk);
	module->setOutChunk(chunk);
	module->describe();
}

Project: audiofile

Module *MSADPCM::createDecompress(_Track *track, AFvirtualfile *fh,
	bool canSeek, bool headerless, AFframecount *chunkFrames)
{
	assert(fh->tell() == track->fpos_first_frame);

	MSADPCM *msadpcm = new MSADPCM(track, fh, canSeek);

	AUpvlist pv = (AUpvlist) track->f.compressionParams;
	long l;
	if (_af_pv_getlong(pv, _AF_MS_ADPCM_NUM_COEFFICIENTS, &l))
		msadpcm->m_numCoefficients = l;
	else
		_af_error(AF_BAD_CODEC_CONFIG, "number of coefficients not set");

	void *v;
	if (_af_pv_getptr(pv, _AF_MS_ADPCM_COEFFICIENTS, &v))
		memcpy(msadpcm->m_coefficients, v, sizeof (int16_t) * 2 * msadpcm->m_numCoefficients);
	else
		_af_error(AF_BAD_CODEC_CONFIG, "coefficient array not set");

	if (_af_pv_getlong(pv, _AF_FRAMES_PER_BLOCK, &l))
		msadpcm->m_framesPerBlock = l;
	else
		_af_error(AF_BAD_CODEC_CONFIG, "samples per block not set");

	if (_af_pv_getlong(pv, _AF_BLOCK_SIZE, &l))
		msadpcm->m_blockAlign = l;
	else
		_af_error(AF_BAD_CODEC_CONFIG, "block size not set");

	*chunkFrames = msadpcm->m_framesPerBlock;

	return msadpcm;
}

Project: audiofile

	virtual const char *name() const { return "compress4to3"; }

Project: audiofile

	void run(const uint8_t *input, T *output, int sampleCount)
	{
		for (int i=0; i<sampleCount; i++)
		{
			T t =
#ifdef WORDS_BIGENDIAN
				(input[3*i] << 24) |
				(input[3*i+1] << 16) |
				input[3*i+2] << 8;
#else
				(input[3*i+2] << 24) |
				(input[3*i+1] << 16) |
				input[3*i] << 8;
#endif
			output[i] = t >> 8;
		}
	}

Project: audiofile

bool _AudioFormat::isInteger() const
{
	return sampleFormat == AF_SAMPFMT_TWOSCOMP ||
		sampleFormat == AF_SAMPFMT_UNSIGNED;
}

Project: audiofile

	virtual const char *name() const { return "clip"; }

Project: audiofile

void afInitPCMMapping (AFfilesetup setup, int trackid,
	double slope, double intercept, double minClip, double maxClip)
{
	_TrackSetup	*track;

	if (!_af_filesetup_ok(setup))
		return;

	if ((track = _af_filesetup_get_tracksetup(setup, trackid)) == NULL)
		return;

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

Project: audiofile

void _af_print_filehandle (AFfilehandle filehandle)
{
	printf("file handle: 0x%p\n", filehandle);

	if (filehandle->valid == _AF_VALID_FILEHANDLE)
		printf("valid\n");
	else
		printf("invalid!\n");

	printf(" access: ");
	if (filehandle->access == _AF_READ_ACCESS)
		putchar('r');
	else
		putchar('w');

	printf(" fileFormat: %d\n", filehandle->fileFormat);

	printf(" instrument count: %d\n", filehandle->instrumentCount);
	printf(" instruments: 0x%p\n", filehandle->instruments);

	printf(" miscellaneous count: %d\n", filehandle->miscellaneousCount);
	printf(" miscellaneous: 0x%p\n", filehandle->miscellaneous);

	printf(" trackCount: %d\n", filehandle->trackCount);
	printf(" tracks: 0x%p\n", filehandle->tracks);
	_af_print_tracks(filehandle);
}

Project: audiofile

void _af_setup_free_markers (AFfilesetup setup, int trackno)
{
	if (setup->tracks[trackno].markerCount != 0)
	{
		int	i;
		for (i=0; i<setup->tracks[trackno].markerCount; i++)
		{
			free(setup->tracks[trackno].markers[i].name);
			free(setup->tracks[trackno].markers[i].comment);
		}

		free(setup->tracks[trackno].markers);
	}

	setup->tracks[trackno].markers = NULL;
	setup->tracks[trackno].markerCount = 0;
}

Project: audiofile

Module *_af_ima_adpcm_init_decompress(_Track *track, AFvirtualfile *fh,
	bool canSeek, bool headerless, AFframecount *chunkFrames)
{
	return IMA::createDecompress(track, fh, canSeek, headerless, chunkFrames);
}

Project: audiofile

	void runSwap(const T *input, T *output, int sampleCount)
	{
		for (int i=0; i<sampleCount; i++)
			output[i] = byteswap(input[i]);
	}

Project: audiofile

AFfilehandle afOpenFile (const char *filename, const char *mode, AFfilesetup setup)
{
	FILE		*fp;
	AFvirtualfile	*vf;
	AFfilehandle	filehandle;
	int		access;

	if (mode == NULL)
	{
		_af_error(AF_BAD_ACCMODE, "null access mode");
		return AF_NULL_FILEHANDLE;
	}

	if (mode[0] == 'r')
		access = _AF_READ_ACCESS;
	else if (mode[0] == 'w')
		access = _AF_WRITE_ACCESS;
	else
	{
		_af_error(AF_BAD_ACCMODE, "unrecognized access mode '%s'", mode);
		return AF_NULL_FILEHANDLE;
	}

	vf = File::open(filename,
		access == _AF_READ_ACCESS ? File::ReadAccess : File::WriteAccess);
	if (vf == NULL)
	{
		_af_error(AF_BAD_OPEN, "could not open file '%s'", filename);
		return AF_NULL_FILEHANDLE;
	}

	if (_afOpenFile(access, vf, filename, &filehandle, setup) != AF_SUCCEED)
		af_fclose(vf);

	return filehandle;
}

Project: audiofile

	virtual void reset2() { }

Project: audiofile

	virtual void sync1() { }

Project: audiofile

status _af_filesetup_make_handle (AFfilesetup setup, AFfilehandle handle)
{
	int	i;

	handle->valid = _AF_VALID_FILEHANDLE;

	if ((handle->trackCount = setup->trackCount) == 0)
		handle->tracks = NULL;
	else
	{
		handle->tracks = _af_calloc(handle->trackCount, sizeof (_Track));
		if (handle->tracks == NULL)
			return AF_FAIL;

		for (i=0; i<handle->trackCount; i++)
		{
			_Track		*track = &handle->tracks[i];
			_TrackSetup	*tracksetup = &setup->tracks[i];

			track->id = tracksetup->id;

			track->f = tracksetup->f;
			track->channelMatrix = NULL;

			/* XXXmpruett copy compression stuff too */

			if ((track->markerCount = tracksetup->markerCount) == 0)
				track->markers = NULL;
			else
			{
				int	j;

				track->markers = _af_marker_new(track->markerCount);
				if (track->markers == NULL)
					return AF_FAIL;
				for (j=0; j<track->markerCount; j++)
				{
					track->markers[j].id = tracksetup->markers[j].id;
					track->markers[j].name =
						_af_strdup(tracksetup->markers[j].name);
					if (track->markers[j].name == NULL)
						return AF_FAIL;

					track->markers[j].comment =
						_af_strdup(tracksetup->markers[j].comment);
					if (track->markers[j].comment == NULL)
						return AF_FAIL;
					track->markers[j].position = 0;
				}
			}

			track->hasAESData = tracksetup->aesDataSet;

			track->ms = NULL;
		}
	}

	/* Copy instrument data. */
	if ((handle->instrumentCount = setup->instrumentCount) == 0)
		handle->instruments = NULL;
	else
	{
		handle->instruments = _af_calloc(handle->instrumentCount,
			sizeof (_Instrument));
		if (handle->instruments == NULL)
			return AF_FAIL;

		for (i=0; i<handle->instrumentCount; i++)
		{
			int	instParamCount;

			handle->instruments[i].id = setup->instruments[i].id;

			/* Copy loops. */
			if ((handle->instruments[i].loopCount =
				setup->instruments[i].loopCount) == 0)
				handle->instruments[i].loops = NULL;
			else
			{
				int	j;

				handle->instruments[i].loops = _af_calloc(handle->instruments[i].loopCount, sizeof (_Loop));
				if (handle->instruments[i].loops == NULL)
					return AF_FAIL;
				for (j=0; j<handle->instruments[i].loopCount; j++)
				{
					_Loop	*loop;
					loop = &handle->instruments[i].loops[j];
					loop->id = setup->instruments[i].loops[j].id;
					loop->mode = AF_LOOP_MODE_NOLOOP;
					loop->count = 0;
					loop->trackid = AF_DEFAULT_TRACK;
					loop->beginMarker = 1 + (2*j);
					loop->endMarker = 2 + (2*j);
				}
			}

			/* Copy instrument parameters. */
			if ((instParamCount = _af_units[setup->fileFormat].instrumentParameterCount) == 0)
				handle->instruments[i].values = NULL;
			else
			{
				int	j;
				handle->instruments[i].values = _af_calloc(instParamCount, sizeof (AFPVu));
				if (handle->instruments[i].values == NULL)
					return AF_FAIL;
				for (j=0; j<instParamCount; j++)
				{
					handle->instruments[i].values[j] =
						_af_units[setup->fileFormat].instrumentParameters[j].defaultValue;
				}
			}
		}
	}

	/* Copy miscellaneous information. */

	if ((handle->miscellaneousCount = setup->miscellaneousCount) == 0)
		handle->miscellaneous = NULL;
	else
	{
		handle->miscellaneous = _af_calloc(handle->miscellaneousCount,
			sizeof (_Miscellaneous));
		if (handle->miscellaneous == NULL)
			return AF_FAIL;
		for (i=0; i<handle->miscellaneousCount; i++)
		{
			handle->miscellaneous[i].id = setup->miscellaneous[i].id;
			handle->miscellaneous[i].type = setup->miscellaneous[i].type;
			handle->miscellaneous[i].size = setup->miscellaneous[i].size;
			handle->miscellaneous[i].position = 0;
			handle->miscellaneous[i].buffer = NULL;
		}
	}

	return AF_SUCCEED;
}

Project: audiofile

AFfilehandle afOpenNamedFD (int fd, const char *mode, AFfilesetup setup,
	const char *filename)
{
	FILE		*fp;
	AFvirtualfile	*vf;
	AFfilehandle	filehandle;
	int		access;

	if (mode == NULL)
	{
		_af_error(AF_BAD_ACCMODE, "null access mode");
		return AF_NULL_FILEHANDLE;
	}

	if (mode[0] == 'r')
		access = _AF_READ_ACCESS;
	else if (mode[0] == 'w')
		access = _AF_WRITE_ACCESS;
	else
	{
		_af_error(AF_BAD_ACCMODE, "unrecognized access mode '%s'", mode);
		return AF_NULL_FILEHANDLE;
	}

	vf = new File(fd, access == _AF_READ_ACCESS ?
		File::ReadAccess : File::WriteAccess);

	if (_afOpenFile(access, vf, filename, &filehandle, setup) != AF_SUCCEED)
		af_fclose(vf);

	return filehandle;
}

Project: audiofile

int afSetVirtualByteOrder (AFfilehandle handle, int track, int byteorder)
{
	_Track *currentTrack;

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

	if (NULL == (currentTrack = _af_filehandle_get_track(handle, track)))
		return AF_FAIL;

	if (byteorder != AF_BYTEORDER_BIGENDIAN &&
		byteorder != AF_BYTEORDER_LITTLEENDIAN)
	{
		_af_error(AF_BAD_BYTEORDER, "invalid byte order %d", byteorder);
		return AF_FAIL;
	}

	currentTrack->v.byteOrder = byteorder;
	currentTrack->ms->setDirty();

	return AF_SUCCEED;
}

Project: audiofile

static bool isTrivialIntMapping(const _AudioFormat &format, FormatCode code)
{
	return intmappings[code] != NULL &&
		format.pcm.slope == intmappings[code]->slope &&
		format.pcm.intercept == intmappings[code]->intercept;
}

Project: audiofile

_InstrumentSetup *_af_instsetup_new (int instrumentCount)
{
	int	i;

	_InstrumentSetup	*instruments;

	if (instrumentCount == 0)
		return NULL;
	instruments = _af_calloc(instrumentCount, sizeof (_InstrumentSetup));
	if (instruments == NULL)
		return NULL;

	for (i=0; i<instrumentCount; i++)
	{
		instruments[i] = _af_default_instrumentsetup;
		instruments[i].id = AF_DEFAULT_INST + i;
		if (instruments[i].loopCount == 0)
			instruments[i].loops = NULL;
		else
		{
			int	j;
			instruments[i].loops = _af_calloc(instruments[i].loopCount, sizeof (_LoopSetup));
			if (instruments[i].loops == NULL)
				return NULL;

			for (j=0; j<instruments[i].loopCount; j++)
				instruments[i].loops[j].id = j+1;
		}
	}

	return instruments;
}

Project: audiofile

	virtual void describe()
	{
		const int scaleBits = m_inChunk->f.bytesPerSample(false) * CHAR_BIT;
		m_outChunk->f.sampleFormat =
			m_fromSigned ? AF_SAMPFMT_UNSIGNED : AF_SAMPFMT_TWOSCOMP;
		double shift = -(1 << (scaleBits - 1));
		if (m_fromSigned)
			shift = -shift;
		m_outChunk->f.pcm.intercept += shift;
		m_outChunk->f.pcm.minClip += shift;
		m_outChunk->f.pcm.maxClip += shift;
	}

Project: audiofile

	void run(const void *srcData, void *dstData, int count)
	{
		const Input *src = reinterpret_cast<const Input *>(srcData);
		Output *dst = reinterpret_cast<Output *>(dstData);

		double m = m_outputMapping.slope / m_inputMapping.slope;
		double b = m_outputMapping.intercept - m * m_inputMapping.intercept;
		double minValue = m_outputMapping.minClip;
		double maxValue = m_outputMapping.maxClip;

		for (int i=0; i<count; i++)
		{
			double t = m * src[i] + b;
			t = std::min(t, maxValue);
			t = std::max(t, minValue);
			dst[i] = static_cast<Output>(t);
		}
	}

Project: audiofile

void afInitFileFormat (AFfilesetup setup, int filefmt)
{
	if (!_af_filesetup_ok(setup))
		return;

	if (filefmt < 0 || filefmt > _AF_NUM_UNITS)
	{
		_af_error(AF_BAD_FILEFMT, "unrecognized file format %d",
			filefmt);
		return;
	}

	if (!_af_units[filefmt].implemented)
	{
		_af_error(AF_BAD_NOT_IMPLEMENTED,
			"%s format not currently supported",
			_af_units[filefmt].name);
		return;
	}

	setup->fileFormat = filefmt;
}

Project: audiofile

status ModuleState::arrange(AFfilehandle file, _Track *track)
{
	bool isReading = file->access == _AF_READ_ACCESS;
	_AudioFormat in, out;
	FormatCode infc, outfc;
	if (isReading)
	{
		in = track->f;
		out = track->v;
	}
	else
	{
		in = track->v;
		out = track->f;
	}

	infc = getFormatCode(in);
	outfc = getFormatCode(out);

	m_chunks.clear();
	m_chunks.push_back(new Chunk());
	m_chunks.back()->f = in;

	m_modules.clear();

	if (isReading)
		addModule(m_fileModule.get());

	// Convert to native byte order.
	if (in.byteOrder != _AF_BYTEORDER_NATIVE)
	{
		size_t bytesPerSample = in.bytesPerSample(!isReading);
		if (bytesPerSample > 1 && in.compressionType == AF_COMPRESSION_NONE)
			addModule(new SwapModule());
		else
			in.byteOrder = _AF_BYTEORDER_NATIVE;
	}

	// Handle 24-bit integer input format.
	if (in.isInteger() && in.bytesPerSample(false) == 3)
	{
		if (isReading || in.compressionType != AF_COMPRESSION_NONE)
			addModule(new Expand3To4Module(in.isSigned()));
	}

	// Make data signed.
	if (in.isUnsigned())
		addModule(new ConvertSign(infc, false));

	in.pcm = m_chunks.back()->f.pcm;

	// Reverse the unsigned shift for output.
	if (out.isUnsigned())
	{
		const double shift = intmappings[outfc]->minClip;
		out.pcm.intercept += shift;
		out.pcm.minClip += shift;
		out.pcm.maxClip += shift;
	}

	// Clip input samples if necessary.
	if (in.pcm.minClip < in.pcm.maxClip && !isTrivialIntClip(in, infc))
		addModule(new Clip(infc, in.pcm));

	bool alreadyClippedOutput = false;
	bool alreadyTransformedOutput = false;
	// Perform range transformation if input and output PCM mappings differ.
	bool transforming = (in.pcm.slope != out.pcm.slope ||
		in.pcm.intercept != out.pcm.intercept) &&
		!(isTrivialIntMapping(in, infc) &&
		isTrivialIntMapping(out, outfc));

	// Range transformation requires input to be floating-point.
	if (isInteger(infc) && transforming)
	{
		if (infc == kInt32 || outfc == kDouble || outfc == kInt32)
		{
			addConvertIntToFloat(infc, kDouble);
			infc = kDouble;
		}
		else
		{
			addConvertIntToFloat(infc, kFloat);
			infc = kFloat;
		}
	}

	if (transforming && infc == kDouble && isFloat(outfc))
		addModule(new Transform(infc, in.pcm, out.pcm));

	// Add format conversion if needed.
	if (isInteger(infc) && isInteger(outfc))
		addConvertIntToInt(infc, outfc);
	else if (isInteger(infc) && isFloat(outfc))
		addConvertIntToFloat(infc, outfc);
	else if (isFloat(infc) && isInteger(outfc))
	{
		addConvertFloatToInt(infc, outfc, in.pcm, out.pcm);
		alreadyClippedOutput = true;
		alreadyTransformedOutput = true;
	}
	else if (isFloat(infc) && isFloat(outfc))
		addConvertFloatToFloat(infc, outfc);

	if (transforming && !alreadyTransformedOutput && infc != kDouble)
		addModule(new Transform(outfc, in.pcm, out.pcm));

	if (in.channelCount != out.channelCount)
		addModule(new ApplyChannelMatrix(infc, isReading,
			in.channelCount, out.channelCount,
			in.pcm.minClip, in.pcm.maxClip,
			track->channelMatrix));

	// Perform clipping if necessary.
	if (!alreadyClippedOutput)
	{
		if (out.pcm.minClip < out.pcm.maxClip && !isTrivialIntClip(out, outfc))
			addModule(new Clip(outfc, out.pcm));
	}

	// Make data unsigned if necessary.
	if (out.isUnsigned())
		addModule(new ConvertSign(outfc, true));

	// Handle 24-bit integer output format.
	if (out.isInteger() && out.bytesPerSample(false) == 3)
	{
		if (!isReading || out.compressionType != AF_COMPRESSION_NONE)
			addModule(new Compress4To3Module(out.isSigned()));
	}

	if (out.byteOrder != _AF_BYTEORDER_NATIVE)
	{
		size_t bytesPerSample = out.bytesPerSample(isReading);
		if (bytesPerSample > 1 && out.compressionType == AF_COMPRESSION_NONE)
			addModule(new SwapModule());
		else
			out.byteOrder = _AF_BYTEORDER_NATIVE;
	}

	if (!isReading)
		addModule(m_fileModule.get());

	return AF_SUCCEED;
}

Project: audiofile

static void freeInstParams (AFPVu *values, int fileFormat)
{
	int	i;
	int	parameterCount = _af_units[fileFormat].instrumentParameterCount;

	for (i=0; i<parameterCount; i++)
	{
		if (_af_units[fileFormat].instrumentParameters[i].type == AU_PVTYPE_PTR)
			if (values[i].v != NULL)
				free(values[i].v);
	}

	free(values);
}

Project: audiofile

size_t _AudioFormat::bytesPerFrame() const
{
	return bytesPerFrame(!isPacked());
}

Project: audiofile

void G711::runPull()
{
	AFframecount framesToRead = m_outChunk->frameCount;
	AFframecount samplesToRead = m_outChunk->frameCount * m_outChunk->f.channelCount;
	int framesize = m_outChunk->f.channelCount;

	/* Read the compressed frames. */

	ssize_t bytesRead = read(m_inChunk->buffer, framesize * framesToRead);
	AFframecount framesRead = bytesRead >= 0 ? bytesRead / framesize : 0;

	/* Decompress into i->outc. */

	if (m_track->f.compressionType == AF_COMPRESSION_G711_ULAW)
		ulaw2linear_buf(static_cast<const uint8_t *>(m_inChunk->buffer),
			static_cast<int16_t *>(m_outChunk->buffer), samplesToRead);
	else
		alaw2linear_buf(static_cast<const uint8_t *>(m_inChunk->buffer),
			static_cast<int16_t *>(m_outChunk->buffer), samplesToRead);

	CHNK(printf("reading %d frames from g711 file (got %d)\n",
		framesToRead, framesRead));

	m_track->nextfframe += framesRead;
	m_track->fpos_next_frame += (framesRead>0) ? framesRead*framesize : 0;
	assert(!canSeek() || (tell() == m_track->fpos_next_frame));

	/*
		If we got EOF from read, then we return the actual amount read.

		Complain only if there should have been more frames in the file.
	*/

	if (m_track->totalfframes != -1 && framesRead != framesToRead)
	{
		/* Report error if we haven't already */
		if (m_track->filemodhappy)
		{
			_af_error(AF_BAD_READ,
				"file missing data -- read %d frames, should be %d",
				m_track->nextfframe,
				m_track->totalfframes);
			m_track->filemodhappy = false;
		}
	}

	m_outChunk->frameCount = framesRead;
}

Project: audiofile

Module *G711::createCompress(_Track *track, AFvirtualfile *fh,
	bool canSeek, bool headerless, AFframecount *chunkframes)
{
	return new G711(Compress, track, fh, canSeek);
}

Project: audiofile

int IMA::decodeBlock (const uint8_t *encoded, int16_t *decoded)
{
	int channelCount = m_track->f.channelCount;
	adpcm_state state[channelCount];

	for (int c=0; c<channelCount; c++)
	{
		state[c].valprev = (encoded[1]<<8) | encoded[0];
		if (encoded[1] & 0x80)
			state[c].valprev -= 0x10000;

		state[c].index = encoded[2];

		*decoded++ = state[c].valprev;

		encoded += 4;
	}

	_af_adpcm_decoder(encoded, decoded, m_framesPerBlock - 1, channelCount, state);

	return m_framesPerBlock * channelCount * sizeof (int16_t);
}

Project: audiofile

bool _AudioFormat::isUncompressed() const
{
	return compressionType == AF_COMPRESSION_NONE;
}

Project: audiofile

	T &operator *() const { return *m_ptr; }

Project: audiofile

int afSetVirtualRate (AFfilehandle file, int trackid, double rate)
{
	_Track	*track;

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

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

	if (rate < 0)
	{
		_af_error(AF_BAD_RATE, "invalid sampling rate %.30g", rate);
		return -1;
	}

	track->v.sampleRate = rate;
	track->ms->setDirty();

	return 0;
}

Project: audiofile

static bool isFloat(FormatCode code) { return code >= kFloat && code <= kDouble; }

Project: audiofile

inline int32_t byteswap(int32_t value) { return _af_byteswap_int32(value); }

Project: audiofile

_TrackSetup *_af_filesetup_get_tracksetup (AFfilesetup setup, int trackid)
{
	int	i;
	for (i=0; i<setup->trackCount; i++)
	{
		if (setup->tracks[i].id == trackid)
			return &setup->tracks[i];
	}

	_af_error(AF_BAD_TRACKID, "bad track id %d", trackid);

	return NULL;
}

Project: audiofile

Module *_AFpcminitcompress (_Track *track, AFvirtualfile *fh, bool canSeek,
	bool headerless, AFframecount *chunkFrames)
{
	return PCM::createCompress(track, fh, canSeek, headerless, chunkFrames);
}

Project: audiofile

void afInitFrameCount (AFfilesetup setup, int trackid, AFfileoffset count)
{
	_TrackSetup	*track;

	if (!_af_filesetup_ok(setup))
		return;

	if ((track = _af_filesetup_get_tracksetup(setup, trackid)) == NULL)
		return;

	if (count < 0)
	{
		_af_error(AF_BAD_FRAMECNT, "invalid frame count %d", count);
		return;
	}

	track->frameCount = count;
	track->frameCountSet = true;
}

Project: audiofile

inline uint16_t _af_byteswap_int16 (uint16_t x)
{
	return (x >> 8) | (x << 8);
}

Project: audiofile

void _af_print_tracks (AFfilehandle filehandle)
{
	int	i;
	for (i=0; i<filehandle->trackCount; i++)
	{
		_Track	*track = &filehandle->tracks[i];
		printf("track %d\n", i);
		printf(" id %d\n", track->id);
		printf(" sample format\n");
		_af_print_audioformat(&track->f);
		printf(" virtual format\n");
		_af_print_audioformat(&track->v);
		printf(" total file frames: %" AF_FRAMECOUNT_PRINT_FMT "\n",
			track->totalfframes);
		printf(" total virtual frames: %" AF_FRAMECOUNT_PRINT_FMT "\n",
			track->totalvframes);
		printf(" next file frame: %" AF_FRAMECOUNT_PRINT_FMT "\n",
			track->nextfframe);
		printf(" next virtual frame: %" AF_FRAMECOUNT_PRINT_FMT "\n",
			track->nextvframe);
		printf(" frames to ignore: %" AF_FRAMECOUNT_PRINT_FMT "\n",
			track->frames2ignore);

		printf(" data_size: %" AF_FILEOFFSET_PRINT_FMT "\n",
			track->data_size);
		printf(" fpos_first_frame: %" AF_FILEOFFSET_PRINT_FMT "\n",
			track->fpos_first_frame);
		printf(" fpos_next_frame: %" AF_FILEOFFSET_PRINT_FMT "\n",
			track->fpos_next_frame);
		printf(" fpos_after_data: %" AF_FILEOFFSET_PRINT_FMT "\n",
			track->fpos_after_data);

		printf(" channel matrix:");
		_af_print_channel_matrix(track->channelMatrix,
			track->f.channelCount, track->v.channelCount);
		printf("\n");

		printf(" marker count: %d\n", track->markerCount);
	}
}

Project: audiofile

T hostToBig(T value)
{
	return _AF_BYTEORDER_NATIVE == AF_BYTEORDER_BIGENDIAN ? value : byteswap(value);
}

Project: audiofile

bool _af_filesetup_ok (AFfilesetup setup)
{
	if (setup == AF_NULL_FILESETUP)
	{
		_af_error(AF_BAD_FILESETUP, "null file setup");
		return false;
	}
	if (setup->valid != _AF_VALID_FILESETUP)
	{
		_af_error(AF_BAD_FILESETUP, "invalid file setup");
		return false;
	}
	return true;
}

Project: audiofile

void G711::sync2()
{
	/* sanity check. */
	assert(!canSeek() || (tell() == m_track->fpos_next_frame));

	/* We can afford to do an lseek just in case because sync2 is rare. */
	m_track->fpos_after_data = tell();

	m_track->fpos_next_frame = m_savedPositionNextFrame;
	m_track->nextfframe = m_savedNextFrame;
}

Project: audiofile

void afFreeFileSetup (AFfilesetup setup)
{
	if (!_af_filesetup_ok(setup))
		return;

	_af_setup_free_tracks(setup);

	_af_setup_free_instruments(setup);

	if (setup->miscellaneousCount)
	{
		free(setup->miscellaneous);
		setup->miscellaneous = NULL;
		setup->miscellaneousCount = 0;
	}

	memset(setup, 0, sizeof (_AFfilesetup));
	free(setup);
}

Project: audiofile

	virtual void run(Chunk &inChunk, Chunk &outChunk)
	{
		const void *src = inChunk.buffer;
		void *dst = outChunk.buffer;
		size_t count = inChunk.frameCount * inChunk.f.channelCount;

#define MASK(N, M) (((N)<<3) | (M))
#define HANDLE(N, M) \
	case MASK(N, M): convertInt<N, M>(src, dst, count); break;
		switch (MASK(m_inFormat, m_outFormat))
		{
			HANDLE(kInt8, kInt16)
			HANDLE(kInt8, kInt24)
			HANDLE(kInt8, kInt32)
			HANDLE(kInt16, kInt8)
			HANDLE(kInt16, kInt24)
			HANDLE(kInt16, kInt32)
			HANDLE(kInt24, kInt8)
			HANDLE(kInt24, kInt16)
			HANDLE(kInt24, kInt32)
			HANDLE(kInt32, kInt8)
			HANDLE(kInt32, kInt16)
			HANDLE(kInt32, kInt24)
		}
#undef MASK
#undef HANDLE
	}

Project: audiofile

static void ulaw2linear_buf (const uint8_t *ulaw, int16_t *linear, int nsamples)
{
	for (int i=0; i < nsamples; i++)
		linear[i] = _af_ulaw2linear(ulaw[i]);
}

Project: audiofile

	void extract3(T in, uint8_t &c0, uint8_t &c1, uint8_t &c2)
	{
#ifdef WORDS_BIGENDIAN
			c0 = (in >> 16) & 0xff;
			c1 = (in >> 8) & 0xff;
			c2 = in & 0xff;
#else
			c2 = (in >> 16) & 0xff;
			c1 = (in >> 8) & 0xff;
			c0 = in & 0xff;
#endif
	}

Project: audiofile

Module *_af_ms_adpcm_init_decompress (_Track *track, AFvirtualfile *fh,
	bool canSeek, bool headerless, AFframecount *chunkFrames)
{
	return MSADPCM::createDecompress(track, fh, canSeek, headerless, chunkFrames);
}

Project: audiofile

	virtual const char *name() const { return "pcm"; }

Project: audiofile

AFfileoffset afTellFrame (AFfilehandle file, int trackid)
{
	return afSeekFrame(file, trackid, -1);
}

Project: audiofile

static int16_t ms_adpcm_decode_sample (ms_adpcm_state *state,
	uint8_t code, const int16_t *coefficient)
{
	const int32_t MAX_INT16 = 32767, MIN_INT16 = -32768;
	const int32_t adaptive[] =
	{
		230, 230, 230, 230, 307, 409, 512, 614,
		768, 614, 512, 409, 307, 230, 230, 230
	};
	int32_t	linearSample, delta;

	linearSample = ((state->sample1 * coefficient[0]) +
		(state->sample2 * coefficient[1])) / 256;

	if (code & 0x08)
		linearSample += state->delta * (code-0x10);
	else
		linearSample += state->delta * code;

	/* Clamp linearSample to a signed 16-bit value. */
	if (linearSample < MIN_INT16)
		linearSample = MIN_INT16;
	else if (linearSample > MAX_INT16)
		linearSample = MAX_INT16;

	delta = ((int32_t) state->delta * adaptive[code])/256;
	if (delta < 16)
	{
		delta = 16;
	}

	state->delta = delta;
	state->sample2 = state->sample1;
	state->sample1 = linearSample;

	/*
		Because of earlier range checking, new_sample will be
		in the range of an int16_t.
	*/
	return (int16_t) linearSample;
}

Project: audiofile

void MSADPCM::reset2()
{
	m_track->fpos_next_frame = m_track->fpos_first_frame +
		m_blockAlign * (m_track->nextfframe / m_framesPerBlock);
	m_track->frames2ignore += m_framesToIgnore;

	assert(m_track->nextfframe % m_framesPerBlock == 0);
}

Project: audiofile

ApplyChannelMatrix::~ApplyChannelMatrix()
{
	delete [] m_matrix;
}

Project: audiofile

	void setInChunk(Chunk *chunk) { m_inChunk = chunk; }

Project: audiofile

	virtual const char *name() const { return "convertInt"; }

Project: audiofile

	ConvertFloat(FormatCode inFormat, FormatCode outFormat) :
		m_inFormat(inFormat), m_outFormat(outFormat)
	{
		assert((m_inFormat == kFloat && m_outFormat == kDouble) ||
			(m_inFormat == kDouble && m_outFormat == kFloat));
	}

Project: audiofile

_TrackSetup *_af_tracksetup_new (int trackCount)
{
	int		i;
	_TrackSetup	*tracks;

	if (trackCount == 0)
		return NULL;

	tracks = _af_calloc(trackCount, sizeof (_TrackSetup));
	if (tracks == NULL)
		return NULL;

	for (i=0; i<trackCount; i++)
	{
		tracks[i] = _af_default_tracksetup;

		tracks[i].id = AF_DEFAULT_TRACK + i;

		/* XXXmpruett deal with compression */

		_af_set_sample_format(&tracks[i].f, tracks[i].f.sampleFormat,
			tracks[i].f.sampleWidth);

		if (tracks[i].markerCount == 0)
			tracks[i].markers = NULL;
		else
		{
			int	j;
			tracks[i].markers = _af_calloc(tracks[i].markerCount,
				sizeof (_MarkerSetup));

			if (tracks[i].markers == NULL)
				return NULL;

			for (j=0; j<tracks[i].markerCount; j++)
			{
				tracks[i].markers[j].id = j+1;

				tracks[i].markers[j].name = _af_strdup("");
				if (tracks[i].markers[j].name == NULL)
					return NULL;

				tracks[i].markers[j].comment = _af_strdup("");
				if (tracks[i].markers[j].comment == NULL)
					return NULL;
			}
		}
	}

	return tracks;
}

Project: audiofile

	void retain() { m_refCount++; }

Project: audiofile

	Result operator()(const Arg &x) const { return x << shift; }

Project: audiofile

	void run(Chunk &inChunk, Chunk &outChunk)
	{
		int sampleCount = inChunk.f.channelCount * inChunk.frameCount;
		runSwap<N, T>(reinterpret_cast<const T *>(inChunk.buffer),
			reinterpret_cast<T *>(outChunk.buffer),
			sampleCount);
	}

Project: audiofile

	virtual void run(Chunk &inChunk, Chunk &outChunk)
	{
		const void *src = inChunk.buffer;
		void *dst = outChunk.buffer;
		int count = inChunk.frameCount * inChunk.f.channelCount;
		if (m_outFormat == kFloat)
		{
			switch (m_inFormat)
			{
				case kInt8:
					run<int8_t, float>(src, dst, count); break;
				case kInt16:
					run<int16_t, float>(src, dst, count); break;
				case kInt24:
				case kInt32:
					run<int32_t, float>(src, dst, count); break;
				default:
					assert(false);
			}
		}
		else if (m_outFormat == kDouble)
		{
			switch (m_inFormat)
			{
				case kInt8:
					run<int8_t, double>(src, dst, count); break;
				case kInt16:
					run<int16_t, double>(src, dst, count); break;
				case kInt24:
				case kInt32:
					run<int32_t, double>(src, dst, count); break;
				default:
					assert(false);
			}
		}
	}

Project: audiofile

	Result operator()(Arg x) const { return x; }

Project: audiofile

int afGetFileFormat (AFfilehandle file, int *version)
{
	if (!_af_filehandle_ok(file))
		return -1;

	if (version != NULL)
	{
		if (_af_units[file->fileFormat].getversion)
			*version = _af_units[file->fileFormat].getversion(file);
		else
			*version = 0;
	}

	return file->fileFormat;
}

Project: audiofile

Module *PCM::createCompress(_Track *track, AFvirtualfile *fh, bool canSeek,
	bool headerless, AFframecount *chunkframes)
{
	return new PCM(Compress, track, fh, canSeek);
}

Project: audiofile

status af_read_int8 (int8_t *value, AFvirtualfile *vf)
{
	if (!read(vf, value))
		return AF_FAIL;
	return AF_SUCCEED;
}

Project: audiofile

	SharedPtr &operator =(const SharedPtr &p)
	{
		if (m_ptr != p.m_ptr)
		{
			if (p.m_ptr) p.m_ptr->retain();
			if (m_ptr) m_ptr->release();
			m_ptr = p.m_ptr;
		}
		return *this;
	}

Project: audiofile

AFfileoffset afGetTrackBytes (AFfilehandle file, int trackid)
{
	_Track	*track;

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

	track = _af_filehandle_get_track(file, trackid);

	return track->data_size;
}