/*
 *  Copyright (c) 2007 - 2008 by Damien Di Fede <ddf@compartmental.net>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library 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 Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package ddf.minim;

/**
 * <code>MAudioBuffer</code> encapsulates a sample buffer of floats. All Minim
 * classes that give you access to audio samples do so with an
 * <code>MAudioBuffer</code>. The underlying array is not immutable and this
 * class has a number of methods for reading and writing to that array. It is
 * even possible to be given a direct handle on the array to process it as you
 * wish.
 * 
 * @author Damien Di Fede
 * 
 */

final class MAudioBuffer implements AudioBuffer
{
  private float[] samples;

  /**
   * Constructs and MAudioBuffer that is <code>bufferSize</code> samples long.
   * 
   * @param bufferSize
   *          the size of the buffer
   */
  MAudioBuffer(int bufferSize)
  {
    samples = new float[bufferSize];
  }

  public synchronized int size()
  {
    return samples.length;
  }

  public synchronized float get(int i)
  {
    return samples[i];
  }

  public synchronized void set(float[] buffer)
  {
    if (buffer.length != samples.length)
      Minim
          .error("MAudioBuffer.set: passed array (" + buffer.length + ") " + 
              "must be the same length (" + samples.length + ") as this MAudioBuffer.");
    else
      samples = buffer;
  }

  /**
   * Mixes the two float arrays and puts the result in this buffer. The
   * passed arrays must be the same length as this buffer. If they are not, an
   * error will be reported and nothing will be done. The mixing function is:
   * <p>
   * <code>samples[i] = (b1[i] + b2[i]) / 2</code>
   * 
   * @param b1
   *          the first buffer
   * @param b2
   *          the second buffer
   */
  public synchronized void mix(float[] b1, float[] b2)
  {
    if ((b1.length != b2.length)
        || (b1.length != samples.length || b2.length != samples.length))
    {
      Minim.error("MAudioBuffer.mix: The two passed buffers must be the same size as this MAudioBuffer.");
    }
    else
    {
      for (int i = 0; i < samples.length; i++)
      {
        samples[i] = (b1[i] + b2[i]) / 2;
      }
    }
  }

  /**
   * Sets all of the values in this buffer to zero.
   */
  public synchronized void clear()
  {
    samples = new float[samples.length];
  }
  
  public synchronized float level()
  {
    float level = 0;
    for (int i = 0; i < samples.length; i++)
    {
      level += (samples[i] * samples[i]);
    }
    level /= samples.length;
    level = (float) Math.sqrt(level);
    return level;
  }

  public synchronized float[] toArray()
  {
    float[] ret = new float[samples.length];
    System.arraycopy(samples, 0, ret, 0, samples.length);
    return ret;
  }
}
