/* 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 "blender.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void blender_set_strength(blender *this,int amp,int index)
{
  int i;
  /* make sure we don't run off the end of the array */
  if(index >= this->length || index < 0)
    return;
  this->strength[index] = amp;
  this->blend_factor = 1;
  for(i = 0;i < this->length; i++)
    this->blend_factor += this->strength[i];
}

void blender_next_buffer(blender *this)
{
  this->next = 1;
}

sample *blender_get_buffer(blender *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->strength[x]) / this->blend_factor);
      this->buffer[i] = tmp;
    }
  }

  return this->buffer; 
  
}


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

static char **get_header(blender *this)
{
  if (!this->header) {
    int i;
    this->header = (char **)malloc(sizeof(char *) * this->length + 2);
    this->header[0] = "int $n_blend = ((blender *)$t)->blend_factor;";
    for (i=0; i < this->length; i++) {
      this->header[i + 1] = (char *)malloc(sizeof(char) * 80);
      sprintf(this->header[i + 1],
	      "int $n_strength%d = ((blender *)$t)->strength[%d];",
	      i, i);
    }
    this->header[this->length + 1] = NULL;
  }

  return this->header;
}

static char **get_code(blender *this)
{
  if (!this->code) {
    int i;
    char *cp;
    this->code = (char **)malloc(sizeof(char *) * 2);
    // XXX make sure this is enough memory
    this->code[0] = (char *)malloc(sizeof(char) * (this->length * 20 + 50));
    cp = this->code[0];
    cp += sprintf(cp, "$o = ");
    for (i=0; i < this->length; i++) {
      cp += sprintf(cp, "($i%d * $n_strength%d / $n_blend)%s",
		    i, i, (i == this->length - 1) ? "" : " + ");
    }
    sprintf(cp, ";");
    this->code[1] = NULL;
  }

  return this->code;
}

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


blender* blender_new(sample_producer **sources)
{
  int i;
  sample_producer **tmp = sources;

  blender* out      = (blender *)malloc(sizeof(blender));
  out->source       = sources;
  out->length       = 0;
  while (*tmp++) out->length++;
  out->strength     = (int *)malloc(sizeof(int) * out->length);
  out->get_buffer   = blender_get_buffer;
  out->next_buffer  = blender_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->blend_factor = 0;
  for(i=0; i < out->length; i++)
    out->strength[i] = 0;
  return out;
}

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







