/**
 * audio_madresampler.c: The mp3 resampler
 * 
 * Copyright: See COPYING file that comes with this distribution
 *
 * Author: Matthias Feistel <hitman_47@users.sourceforge.net>, (C) 2007
 */
/*
 * vdr-podcatcher - A plugin for the Linux Video Disk Recorder
 * Copyright (c) 2006 Tobias Grimm <vdr@e-tobi.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: madresampler.cc 2272 2006-01-23 21:17:24Z svntobi $
 *
 */

#include <string.h>
#include "audio_madresampler.h" // hitman_47: #include "madresampler.h"
#include <iostream>

using namespace std;

int MadResampler::Init( unsigned int fromSampleRate, unsigned int toSampleRate )
{
	if( toSampleRate == 0 )
	{
		return -1;
	}

	ratio = mad_f_div( fromSampleRate, toSampleRate );

	if( ratio <= 0 )
	{
		return -1;
	}

	step = 0;
	last = 0;

	return toSampleRate / fromSampleRate + 1;
}

//
// This linear resampling algorithm has been borrowed from:
//
//     madplay - MPEG audio decoder and player
//     Copyright (C) 2000-2004 Robert Leslie
//
unsigned int MadResampler::Resample( mad_fixed_t const* inSamples,
										unsigned int numberOfSamples,
										mad_fixed_t* outSamples )
{
	mad_fixed_t const *end, *begin;

	/*
	 * This resampling algorithm is based on a linear interpolation, which is
	 * not at all the best sounding but is relatively fast and efficient.
	 *
	 * A better algorithm would be one that implements a bandlimited
	 * interpolation.
	 */

	if( ratio == MAD_F_ONE )
	{
		memcpy( outSamples, inSamples, numberOfSamples * sizeof(mad_fixed_t) );
		return numberOfSamples;
	}

	end = inSamples + numberOfSamples;
	begin = outSamples;

	if( step < 0 )
	{
		step = mad_f_fracpart( -step );

		while( step < MAD_F_ONE )
		{
			*outSamples++ = step ? last + mad_f_mul( *inSamples - last, step )
					: last;

			step += ratio;
			if( ((step + 0x00000080L) & 0x0fffff00L) == 0 )
			{
				step = (step + 0x00000080L) & ~0x0fffffffL;
			}
		}

		step -= MAD_F_ONE;
	}

	while( end - inSamples > 1 + mad_f_intpart( step ) )
	{
		inSamples += mad_f_intpart( step );
		step = mad_f_fracpart( step );

		*outSamples++ = step ? *inSamples + mad_f_mul( inSamples[1]
				- inSamples[0], step ) : *inSamples;

		step += ratio;
		if( ((step + 0x00000080L) & 0x0fffff00L) == 0 )
		{
			step = (step + 0x00000080L) & ~0x0fffffffL;
		}
	}

	if( end - inSamples == 1 + mad_f_intpart( step ) )
	{
		last = end[-1];
		step = -step;
	}
	else
	{
		step -= mad_f_fromint( end - inSamples );
	}
	return outSamples - begin;
}
