//**************************************************************************
//*                     This file is part of the                           *
//*                      Mpxplay - audio player.                           *
//*                  The source code of Mpxplay is                         *
//*        (C) copyright 1998-2006 by PDSoft (Attila Padar)                *
//*                    http://mpxplay.cjb.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: channel conversions

#include "au_mixer.h"

int MIXER_var_swapchan;

unsigned int cv_channels_1_to_n(PCM_CV_TYPE_S *pcm_sample,unsigned int samplenum,unsigned int newchannels,unsigned int bytespersample)
{
 register unsigned int i,ch,b;
 PCM_CV_TYPE_C *pcms=((PCM_CV_TYPE_C *)pcm_sample)+(samplenum*bytespersample);
 PCM_CV_TYPE_C *pcmt=((PCM_CV_TYPE_C *)pcm_sample)+(samplenum*bytespersample*newchannels);

 for(i=samplenum;i;i--){
  pcms-=bytespersample;
  for(ch=newchannels;ch;ch--){
   pcmt-=bytespersample;
   for(b=0;b<bytespersample;b++)
    pcmt[b]=pcms[b];
  }
 }
 return (samplenum*newchannels);
}

// this doesn't mix the channels, it takes the 1. (left channel) only
unsigned int cv_channels_n_to_1(PCM_CV_TYPE_S *pcm_sample,unsigned int samplenum,unsigned int oldchannels,unsigned int bytespersample)
{
 register unsigned int i,b;
 PCM_CV_TYPE_C *pcms=((PCM_CV_TYPE_C *)pcm_sample);
 PCM_CV_TYPE_C *pcmt=((PCM_CV_TYPE_C *)pcm_sample);

 for(i=0;i<samplenum;i+=oldchannels){
  for(b=0;b<bytespersample;b++)
   *pcmt++=pcms[b];
  pcms+=oldchannels*bytespersample;
 }
 return (samplenum/oldchannels);
}

// takes the left and right channels from a multichannel pcm stream (doesn't downmix the others)
unsigned int cv_channels_n_to_2(PCM_CV_TYPE_S *pcm_sample,unsigned int samplenum,unsigned int oldchannels,unsigned int bytespersample)
{
 register unsigned int i,b;
 PCM_CV_TYPE_C *pcms=((PCM_CV_TYPE_C *)pcm_sample);
 PCM_CV_TYPE_C *pcmt=((PCM_CV_TYPE_C *)pcm_sample);

 for(i=0;i<samplenum;i+=oldchannels){
  for(b=0;b<bytespersample*2;b++)
   *pcmt++=*pcms++;
  pcms+=(oldchannels-2)*bytespersample;
 }
 return (samplenum/oldchannels*2);
}

//-------------------------------------------------------------------------
static void mixer_swapchan_lqhq(struct mpxplay_audioout_info_s *aui)
{
 unsigned int samplenum=aui->samplenum,bytespersample=aui->bytespersample_mixer;
 unsigned int b;
 PCM_CV_TYPE_C *left=(PCM_CV_TYPE_C *)aui->pcm_sample;
 PCM_CV_TYPE_C *right=left+bytespersample;

 samplenum>>=1;
 do{
  for(b=bytespersample;b;b--){
   char cl=left[0];
   left[0]=right[0];
   right[0]=cl;
   left++;right++;
  }
  left+=bytespersample;
  right+=bytespersample;
 }while(--samplenum);
}

static int mixer_swapchan_checkvar(struct mpxplay_audioout_info_s *aui)
{
 if(MIXER_var_swapchan && (aui->chan_card==2))
  return 1;
 return 0;
}

one_mixerfunc_info MIXER_FUNCINFO_swapchan={
 "MIX_SWAPCHAN",
 "mxsw",
 &MIXER_var_swapchan,
 MIXER_INFOBIT_SWITCH|MIXER_INFOBIT_EXTERNAL_DEPENDENCY, // aui->chan_card
 0,1,0,0,
 NULL,
 &mixer_swapchan_lqhq,
 &mixer_swapchan_lqhq,
 &mixer_swapchan_checkvar,
 NULL
};
