//**************************************************************************
//*                     This file is part of the                           *
//*                      Mpxplay - audio player.                           *
//*                  The source code of Mpxplay is                         *
//*        (C) copyright 1998-2014 by PDSoft (Attila Padar)                *
//*                http://mpxplay.sourceforge.net                          *
//*                  email: mpxplay@freemail.hu                            *
//**************************************************************************
//*  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.                  *
//*  Please contact with the author (with me) if you want to use           *
//*  or modify this source.                                                *
//**************************************************************************
//function: crossfade (mixer) routines

#include "mpxplay.h"

extern unsigned int crossfadepart;

static int MIXER_var_pcmcrossfade;

static PCM_CV_TYPE_F *crossfade_config(struct mpxp_aumixer_passinfo_s *mpi,long *cf_v1,long *cf_v2)
{
 struct mainvars *mvp=mpi->mvp;
 struct crossfade_info *cfi=mvp->cfi;
 struct mpxpframe_s *frp0=mvp->fr_primary,*frp1=frp0->fro;
 struct mpxp_aumixer_passinfo_s *mpi0=frp0->mpi;
 long v,v1,v2;
 PCM_CV_TYPE_F *cf_pcm2;

 if(mpi->mmi->mixer_infobits & AUINFOS_MIXERINFOBIT_CROSSFADE){
  struct mpxp_aumixer_passinfo_s *mpi1=frp1->mpi; // valid in crossfade only
  cf_pcm2=(PCM_CV_TYPE_F *)mpi1->pcm_sample;
 }else{
  cf_pcm2=(PCM_CV_TYPE_F *)mpi0->pcm_sample;
 }

 if(crossfadepart&CFT_FADEOUT){
  struct mpxpframe_s *frp=(crossfadepart&CROSS_IN)? frp1:frp0;
  v=cfi->crossfadeend-frp->frameNum;
  if(v>0){
   if(cfi->crossfadetype&CFT_FADEOUT){
    v1=(v<<7)/cfi->crossfade_out_len;
    if(v1>128)
     v1=128;
   }else
    v1=128;
  }else{
   v1=0;
  }
 }else
  v1=0;
 if(crossfadepart&CFT_FADEIN){
  unsigned long index_pos=frp0->frameNum-frp0->index_start;
  v2=v1;
  v1=128;
  if(index_pos<cfi->crossfade_in_len){
   if(cfi->crossfadetype&CFT_FADEIN)
    v1=(index_pos<<7)/cfi->crossfade_in_len;
  }
 }else
  v2=0;

 *cf_v1=v1;
 *cf_v2=v2;

 return cf_pcm2;
}

//---------------------------------------------------------------------------
static void mixer_crossmix_process(struct mpxp_aumixer_passinfo_s *mpi)
{
 unsigned int i;
 PCM_CV_TYPE_F *pcm1,*pcm2;
 float fv1,fv2;
 long cf_v1,cf_v2;

 pcm2=(PCM_CV_TYPE_F *)crossfade_config(mpi,&cf_v1,&cf_v2);
 pcm1=(PCM_CV_TYPE_F *)mpi->pcm_sample;
 if(!pcm1 || !pcm2 || !mpi->samplenum)
  return;
 fv1=(float)cf_v1/128.0;
 fv2=(float)cf_v2/128.0;
 i=mpi->samplenum;
 do{
  pcm1[0]=pcm1[0]*fv1+pcm2[0]*fv2;
  pcm1++;pcm2++;
 }while(--i);
}

one_mixerfunc_info MIXER_FUNCINFO_crossfader={
 "MIX_CROSSFADER",
 NULL,
 &MIXER_var_pcmcrossfade,
 MIXER_INFOBIT_SWITCH,
 0,1,0,0,
 NULL,
 NULL,
 &mixer_crossmix_process,
 NULL,
 NULL
};
