/* Freebirth
 * Copyright (C) 1999 topher lafata <topher@topher.com>,
 *		      Jake Donham <jake@bitmechanic.com>
 *
 * 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 (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */


#include "mixer.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>



void mixer_set_amplitude(mixer *this,int amp,int index)
{
  /* make sure we don't run off the end of the array */
  if(index >= this->length || index < 0)
    return;
  if(amp == MUTE_SWITCH)
    this->mute_map[index] = - (this->mute_map[index]);
  else
    this->amplitude[index] = amp;
  
}


void mixer_next_buffer(mixer *this) {
  this->next = 1;
}

extern mixer *aux_1;

sample *mixer_get_buffer(mixer *this)
{
  int i,x;

  if (this->next) {
    this->next = 0;
    for(x = 0; x < this->length;x++)
      this->bufs[x] = this->source[x]->get_buffer(this->source[x]);
    
    for(i = 0; i < TBASS_BUFF_SIZE;i++) {
      long tmp = 0;
      for (x = 0; x < this->length; x++)
	tmp += (((long)(this->bufs[x][i] * this->amplitude[x]))/ MIX_MAX_AMP);
      /*PATCH BY: scott manley <spm@star.arm.ac.uk> */

      this->buffer[i] = tmp;
	
    }
  }


  return this->buffer; 
  
}

static sample_producer **get_children(mixer *this)
{
  return this->source;
}

static char **get_header(mixer *this)
{

  if (!this->header) {
    int i;
    int hdr_size;

    hdr_size = this->length * 2; /*one for amp vals, one for mix_map vals */
    this->header = (char **)malloc(sizeof(char *) * (hdr_size + 1));
    for (i=0; i < this->length; i++) {
      this->header[i] = (char *)malloc(sizeof(char) * 80);
      sprintf(this->header[i],
	      "int $n_amp%d = ((mixer *)$t)->amplitude[%d];",
	      i, i);
    }
    for(i = 0; i< this->length;i++)
      {
	int index = this->length + i;
	this->header[index] = (char *)malloc(sizeof(char) * 80);
	sprintf(this->header[index],
		"int $n_mute%d = ((mixer *)$t)->mute_map[%d];",
		i, i);

      }
      

    this->header[hdr_size] = NULL;
  }
      

  return this->header;
}


static char **get_code(mixer *this)
{


  if (!this->code) {
    int i;
    char *cp;
    this->code = (char **)malloc(sizeof(char *) * 3);
    // XXX make sure this is enough memory
    this->code[0] = (char *)malloc(sizeof(char) * (this->length * 40 + 50));
    cp = this->code[0];
    for(i = 0; i < this->length;i++)
      cp += sprintf(cp,"if($n_mute%d > 0)\n\t $n_amp%d = 0;\n",i,i);

    this->code[1] = (char *)malloc(sizeof(char) * (this->length * 40 + 50));
    cp = this->code[1];
    cp += sprintf(cp, "$o = ");
    for (i=0; i < this->length; i++) {
      cp += sprintf(cp, "($i%d * $n_amp%d / MIX_MAX_AMP)%s",
		    i, i, (i == this->length - 1) ? "" : " + ");
    }
    sprintf(cp, ";");
    this->code[2] = NULL;
  }


  return this->code;
}

static char **get_footer(mixer *this)
{
  static char *footer[] = { NULL };
  return footer;
}

mixer* mixer_new(sample_producer **sources)
{
  int i;
  sample_producer **tmp = sources;

  mixer* out     = (mixer *)malloc(sizeof(mixer));
  out->source    = sources;
  out->length    = 0;
  while (*tmp++) out->length++;
  out->amplitude = (int *)malloc(sizeof(int) * out->length);
  out->get_buffer = mixer_get_buffer;
  out->next_buffer = mixer_next_buffer;
  out->get_children = get_children;
  out->get_header   = get_header;
  out->get_code	    = get_code;
  out->get_footer   = get_footer;
  out->header	    = NULL;
  out->code	    = NULL;
  out->next      = 0;
  out->buffer = (sample*)malloc(sizeof(sample) * TBASS_BUFF_SIZE);
  out->bufs = (sample **)malloc(sizeof(sample *) * out->length);
  out->mute_map = (int *) malloc(sizeof(int) * out->length);
  for(i=0; i < out->length; i++)
    {
      out->amplitude[i] = 0;
      out->mute_map[i]  = -1;
    }
  return out;
}


/*
  Local Variables:
  mode: font-lock
  End:
*/

/*compression stuff? */

      /*      if(tmp >=0)
	this->buffer[i] = MIX_MAX_AMP * pow((double)tmp/(double)MIX_MAX_AMP,0.9);
      else
	this->buffer[i] = -MIX_MAX_AMP * pow((double)-tmp/(double)MIX_MAX_AMP,0.9);
      */






