/*

<This Java Class is part of the jMusic API version 1.5, March 2004.>

Copyright (C) 2000 Andrew Sorensen & Andrew Brown

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 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; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

package jm.audio.synth;

import java.io.IOException;
import jm.audio.AOException;
import jm.audio.AudioObject;
import jm.audio.Instrument;
import jm.music.data.Note;

/**
 * @author Andrew Brown
 * @version 1.0, 10 October 2001
 */
public class Spring extends AudioObject{
	//----------------------------------------------
	// Attributes
	//----------------------------------------------
	private SpringPipe springNetwork;
	private int numberOfNodes = 8;
	private double springConstant;
	private double massFriction;
	private double jitter;
		
	//----------------------------------------------
	// Constructors
	//----------------------------------------------
        /**
        * The Spring constructor that acts as a generator of a 
        * linear spring-mass network.
        * @param Instrument The instrument class of which this is a part - usually 'this'
        * @param nodes The number of spring-mass pairs in the network.
        */
	public Spring(Instrument inst, int nodes) {
		this(inst, nodes, 44100, 1);
	}
	
        /**
        * The Spring constructor that acts as a generator of a 
        * linear spring-mass network.
        * @param Instrument The instrument class of which this is a part - usually 'this'
        * @param nodes The number of spring-mass pairs in the network.
        * @param springConstant The stiffness of the spring.
        * @param massFriction The weight, inertia, of the virtual mass.
        */
	public Spring(Instrument inst, int nodes, double springConstant, double massFriction){
		this(inst, nodes, springConstant, massFriction, 0.0, 44100, 1);
	}
        
	/**
        * The Spring constructor that acts as a generator of a 
        * linear spring-mass network.
        * @param Instrument The instrument class of which this is a part - usually 'this'
        * @param nodes The number of spring-mass pairs in the network.
        * @param springConstant The stiffness of the spring.
        * @param massFriction The weight, inertia, of the virtual mass.
        * @param jitter The amount of randomness (non linearity) in the network.
        * @param sampleRate The number of spring recalulations per second of sound.
        * @param channels The nuber of channels, 1 = mono, 2 = stereo, etc.
        */
	public Spring(Instrument inst, int nodes, double springConstant, 
            double massFriction, double jitter, int sampleRate, int channels){
		super(inst, sampleRate, "[WaveTable]");
		this.numberOfNodes = nodes;
		this.springConstant = springConstant;
		this.jitter = jitter;
		this.massFriction = massFriction;
		this.channels = channels;
	}	

	//----------------------------------------------
	// Methods
	//----------------------------------------------
	public void build() {
		springNetwork = new SpringPipe(numberOfNodes, springConstant, massFriction, jitter);
	}
	
	/**
	 * Returns a sample value to each channel generated by the spring model.
	 * @param buffer The sample buffer.
	 */
	public int work(float[] buffer)throws AOException{
            int ret=0; //the number of samples to return
            // run the appropiate code for the chosen noise type
            for(;ret<buffer.length;){
                for(int j=0;j<channels;j++) { 
                    // change to an int ( before csting as float) for soem cool gaininess.
                    buffer[ret++] = (float)(springNetwork.getNextNodePosition(0) / (40/numberOfNodes) - 3.0);
                }
            }            
            return ret; 
        }
}
