/* Extended Module Player
 * Copyright (C) 1996-1999 Claudio Matsuoka and Hipolito Carraro Jr.
 *
 * This file is part of the Extended Module Player and is distributed
 * under the terms of the GNU General Public License. See docs/COPYING
 * for more information.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "xmpi.h"
#include "driver.h"
#include "mixer.h"

/* Mixers
 *
 * To increase performance eight mixers are defined, one for each
 * combination of the following parameters: interpolation, resolution
 * and number of channels.
 */
#define INTERPOLATE() \
    if (itpt >> SMIX_SFT_FT) { \
	cur_bk += itpt >> SMIX_SFT_FT; \
	smp_x1 = in_bk[cur_bk]; \
	smp_dt = in_bk[cur_bk + 1] - smp_x1; \
	itpt &= SMIX_AND_FT; \
    } \
    smp_in = smp_x1 + ((itpt * smp_dt) >> SMIX_SFT_FT);

#define DONT_INTERPOLATE() \
    smp_in = in_bk[itpt >> SMIX_SFT_FT];


/* Handler for 8 bit samples, interpolated stereo output
 */
void smix_st8itpt (int* tmp_bk, char* in_bk, int count, int vl, int vr,
		   int cur_bk, register int itpt, int itpt_inc)
{
    int smp_x1 = 0, smp_dt = 0;
    register int smp_in;

    vl <<= 8;
    vr <<= 8;
    while (count--) {
	INTERPOLATE ();
	*(tmp_bk++) += smp_in * vr;
	*(tmp_bk++) += smp_in * vl;
	itpt += itpt_inc;
    }
}


/* Handler for 16 bit samples, interpolated stereo output
 */
void smix_st16itpt (int* tmp_bk, int16* in_bk, int count, int vl, int vr,
		    int cur_bk, register int itpt, int itpt_inc)
{
    int smp_x1 = 0, smp_dt = 0;
    register int smp_in;

    while (count--) {
	INTERPOLATE ();
	*(tmp_bk++) += smp_in * vr;
	*(tmp_bk++) += smp_in * vl;
	itpt += itpt_inc;
    }
}


/* Handler for 8 bit samples, non-interpolated stereo output
 */
void smix_st8norm (int* tmp_bk, char* in_bk, int count, int vl, int vr,
		   int cur_bk, register int itpt, int itpt_inc)
{
    register int smp_in;

    vl <<= 8;
    vr <<= 8;
    in_bk += cur_bk;
    while (count--) {
	DONT_INTERPOLATE ();
	*(tmp_bk++) += smp_in * vr;
	*(tmp_bk++) += smp_in * vl;
	itpt += itpt_inc;
    }
}


/* Handler for 16 bit samples, non-interpolated stereo output
 */
void smix_st16norm (int* tmp_bk, int16* in_bk, int count, int vl, int vr,
		    int cur_bk, register int itpt, int itpt_inc)
{
    register int smp_in;

    in_bk += cur_bk;
    while (count--) {
	DONT_INTERPOLATE ();
	*(tmp_bk++) += smp_in * vr;
	*(tmp_bk++) += smp_in * vl;
	itpt += itpt_inc;
    }
}


/* Handler for 8 bit samples, interpolated mono output
 */
void smix_mn8itpt (int* tmp_bk, char* in_bk, int count, int vl, int vr,
		   int cur_bk, register int itpt, int itpt_inc)
{
    int smp_x1 = 0, smp_dt = 0;
    register int smp_in;

    vl <<= 9;
    while (count--) {
	INTERPOLATE ();
	*(tmp_bk++) += smp_in * vl;
	itpt += itpt_inc;
    }
}


/* Handler for 16 bit samples, interpolated mono output
 */
void smix_mn16itpt (int* tmp_bk, int16* in_bk, int count, int vl, int vr,
		    int cur_bk, register int itpt, int itpt_inc)
{
    int smp_x1 = 0, smp_dt = 0;
    register int smp_in;

    vl <<= 1;
    while (count--) {
	INTERPOLATE ();
	*(tmp_bk++) += smp_in * vl;
	itpt += itpt_inc;
    }
}


/* Handler for 8 bit samples, non-interpolated mono output
 */
void smix_mn8norm (int* tmp_bk, char* in_bk, int count, int vl, int vr,
		   int cur_bk, register int itpt, int itpt_inc)
{
    register int smp_in;

    vl <<= 9;
    in_bk += cur_bk;
    while (count--) {
	DONT_INTERPOLATE ();
	*(tmp_bk++) += smp_in * vl;
	itpt += itpt_inc;
    }
}


/* Handler for 16 bit samples, non-interpolated mono output
 */
void smix_mn16norm (int* tmp_bk, int16* in_bk, int count, int vl, int vr,
		    int cur_bk, register int itpt, int itpt_inc)
{
    register int smp_in;

    vl <<= 1;
    in_bk += cur_bk;
    while (count--) {
	DONT_INTERPOLATE ();
	*(tmp_bk++) += smp_in * vl;
	itpt += itpt_inc;
    }
}
