/*
* UGen.java
* JCollider
*
* Copyright (c) 2004-2010 Hanns Holger Rutz. All rights reserved.
*
* This software 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, june 1991 of the License, or (at your option) any later version.
*
* This software 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 (gpl.txt) along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* For further information, please contact Hanns Holger Rutz at
* contact@sciss.de , or visit http://www.sciss.de/jcollider
*
*
* JCollider is closely modelled after SuperCollider Language,
* often exhibiting a direct translation from Smalltalk to Java.
* SCLang is a software originally developed by James McCartney,
* which has become an Open Source project.
* See http://supercollider.sourceforge.net/ for details.
*
*
* Changelog:
* 29-Jun-05 created
*/
package de.sciss.jcollider;
import java.util.ArrayList;
// Arg count statistics :
// 19 UGens with 0 arguments.
// 54 UGens with 1 arguments.
// 80 UGens with 2 arguments.
// 67 UGens with 3 arguments.
// 45 UGens with 4 arguments.
// 20 UGens with 5 arguments.
// 22 UGens with 6+ arguments.
// so for ease of use we create separate
// methods for up to 5 args (= 93% of all ugens)
/**
* The client side represenation of a unit generator.
* Unlike SClang, there are no subclasses for all the different
* ugens (few exceptions, such as <code>Control</code>), therefore
* to construct a ugen graph requires you to make successive calls
* to the static constructor methods provided by this class. See
* <code>SynthDef</code> and <code>JColliderDemo</code> for examples
* of how to construct a graph.
* <p>
* When you use the static constructor methods of <code>UGen</code>,
* the class relies on the UGen database to be loaded into <code>UGenInfo</code>.
* Please see the <code>UGenInfo</code> doc for details about this database.
* <p>
* While some methods like <code>array( ... )</code> would better
* fit into the <code>GraphElemArray</code> class, they have been included
* here, simply because it's shorter to write <code>UGen.array( ... )</code>
* and it gives your code a more homogeneous and pathological look.
* <p>
* To access a single output of a multi-output UGen, use either the
* <code>getOutput</code> or <code>getChannel</code> method. To create
* controls, use the separate <code>Control</code> class.
*
* @warning no rate checking is performed along the inputs
*
* @todo a keyword constructor variant has been removed because it
* wasn't too convincing (well, keywords is just a concept
* totally unknown to java). however to make constructor calls
* shorter and more readable, some sort of keyword constructor
* should be re-invented.
*
* @author Hanns Holger Rutz
* @version 0.35, 19-Sep-09
*/
public class UGen
implements Constants, GraphElem
{
private final String name;
private final Object rate;
private final Object[] outputRates;
private final UGenInput[] inputs;
private int specialIndex;
private static final GraphElem[] NO_ARGS = new GraphElem[0];
/**
* This constructor is used by <code>SynthDef</code>
* when building the UGen from a def file. Do not
* use this method yourself.
*/
protected UGen( String name, Object rate, Object[] outputRates, UGenInput[] inputs, int specialIndex )
{
this.name = name;
this.rate = rate;
this.outputRates = outputRates;
this.inputs = inputs;
this.specialIndex = specialIndex;
}
/**
* Returns the rate at which this UGen is running
*
* @return either of <code>kAudioRate</code>, <code>kControlRate</code>,
* <code>kDemandRate</code> or <code>kScalarRate</code>
*/
public Object getRate()
{
return rate;
}
/**
* Returns an array of the rates at which the individual
* output channels run. I know of no UGen any of whose
* outputs have a rate different from the UGen rate.
*/
public Object[] getOutputRates()
{
return outputRates;
}
/**
* Returns the rate of one of the UGens output channels.
* I know of no UGen any of whose
* outputs have a rate different from the UGen rate.
*/
public Object getOutputRate( int channel )
{
return outputRates[ channel ];
}
/**
* Returns an array of the UGen's inputs.
*/
public UGenInput[] getInputs()
{
return inputs;
}
/**
* Returns the UGen's input at the given index.
* Note that for UGens constructed with a variable
* length array argument, this argument is expanded
* to separate individual arguments. For example
* for <code>Out</code>, each element of the
* <code>channelsArray</code> argument is a separate
* input with a separate index (as you would expect
* from the binary compiled synth def format).
*/
public UGenInput getInput( int index )
{
return inputs[ index ];
}
/**
* Returns the so-called special index of the UGen.
* This is kind of an extra internal static parameter.
* Special indices are used by <code>BinaryOpUGen</code>
* and <code>UnaryOpUGen</code> to specify the mathematical operator,
* and by <code>Control</code> to specify the index in
* the control name table. Note that this index is invalid
* for <code>Control</code> until the graph has been constructed
* by <code>SynthDef</code>.
*/
public int getSpecialIndex()
{
return specialIndex;
}
/**
* This is called by <code>SynthDef</code> when assembling
* controls. Do not call this method directly.
* To create unary and binary operator ugens, simply
* construct them with their operator name and the
* ugen factory will set the right index itself. So to
* create a multiplying binary ugen, you will call:
* <pre>
* UGen.ar( "*", firstUGen, secondUGen );
* </pre>
* and not
* <pre>
* UGen myBin = UGen.ar( "BinaryOpUGen", firstUGen, secondUGen );
* myBin.setSpecialIndex( 2 );
* </pre>
*/
protected void setSpecialIndex( int idx )
{
specialIndex = idx;
}
/**
* Returns the number of input arguments.
* Arrays are expanded, so an <code>Out</code>
* UGen with three input channels will report
* <code>4</code> (three inputs plus bus parameter).
*/
public int getNumInputs()
{
return inputs.length;
}
// --------- GraphElem interface ---------
public int getNumOutputs()
{
return outputRates.length;
}
public GraphElem getOutput( int idx )
{
return getChannel( idx );
}
public UGenInput[] asUGenInputs()
{
final UGenInput[] result = new UGenInput[ getNumOutputs() ];
for( int i = 0; i < result.length; i++ ) {
result[ i ] = getChannel( i );
}
return result;
}
public UGenChannel getChannel( int ch )
{
return new UGenChannel( this, ch );
}
// XXX could be re-implemented using UGenInfo
// protected String argNameForInputAt( int argIndex )
// {
// }
/**
* Returns the <strong>class name</strong> of the UGen.
* In the case of unary and binary op ugens, this
* will report "UnaryOpUGen" and "BinaryOpUGen"
* and not their operators. To get the operator names
* look up the <code>UGen</code> in the <code>UGenInfo</code> dictionary.
*
* @see UGenInfo#infos
*/
public String getName()
{
return name;
// String className = this.getClass().getName();
// return className.substring( className.lastIndexOf( '.' ) + 1 );
}
// BinaryOpUGen could do this XXX
// protected void optimizeGraph() {}
/**
* Returns a string representation of the UGen.
*
* @todo should report the operator name or unary/binary op
*/
public String dumpName()
{
// return( getSynthIndex() + "_" + getName() );
if( specialIndex == 0 ) {
return getName();
} else {
return( getName() + '?' + specialIndex );
}
}
/**
* Constructs a new audio rate UGen
* with zero arguments and a required explict
* output channel number. This method should only
* be used for UGens that require the explicit
* setting of the number of output channels, such
* as <code>LocalIn.ar</code>.
* <p>
* This method can also be used for UGens with more
* than zero arguments, if the info dictionary contains
* default values for the missing arguments. An example
* is <code>BufRd</code> which actually has four arguments
* for bufNum, phase, loop and interolation, but specifies
* defaults for all of them (bufNum 0, phase zero, loop 1, interpolation 2).
*
* @param name either ugen class name or
* alias name (for unary/binary op)
* @param numChannels number of output channels to create
*
* @throws IllegalArgumentException if the UGen cannot be found in the info dictionary,
* if the rate is not allowed for the ugen
* @throws IllegalStateException if the UGens requires arguments
* which have not been provided and have no default values
*/
public static GraphElem ar( String name, int numChannels )
{
return UGen.construct( name, kAudioRate, numChannels, NO_ARGS );
}
/**
* Constructs a new audio rate UGen
* with zero arguments.
* <p>
* This method can also be used for UGens with more
* than zero arguments, if the info dictionary contains
* default values for the missing arguments. An example
* is <code>SinOsc</code> which actually has two arguments
* for frequency and phase, but both of them have default
* values (440 hertz, zero degrees phase).
*
* @param name either ugen class name or
* alias name (for unary/binary op)
*
* @throws IllegalArgumentException if the UGen cannot be found in the info dictionary,
* if the rate is not allowed for the ugen,
* or if the UGen requires the explicit specification of the
* number of output channels
* @throws IllegalStateException if the UGens requires arguments
* which have not been provided and have no default values
*/
public static GraphElem ar( String name )
{
return UGen.construct( name, kAudioRate, -1, NO_ARGS );
}
/**
* Constructs a new audio rate UGen
* with one given argument and an explicit
* number of output channels. This method should only
* be used for UGens that require the explicit
* setting of the number of output channels, such
* as <code>PanAz.ar</code>.
* <p>
* This method can also be used for UGens with more
* than one argument (e.g. <code>PanAz</code>), if the info
* dictionary contains
* default values for the missing arguments. For example,
* <code>PanAz</code> has five arguments, the first one
* being the input signal which needs to specified, but
* the other ones having default values (pos 0.0, level 1.0, width 2.0, orientation 0.5).
*
* @param name either ugen class name or
* alias name (for unary/binary op)
* @param numChannels number of output channels to create
* @param in1 first input argument
*
* @throws IllegalArgumentException if the UGen cannot be found in the info dictionary,
* if the rate is not allowed for the ugen
* @throws IllegalStateException if the UGens requires arguments
* which have not been provided and have no default values
*/
public static GraphElem ar( String name, int numChannels, GraphElem in1 )
{
return UGen.construct( name, kAudioRate, numChannels, new GraphElem[] { in1 });
}
/**
* Constructs a new audio rate UGen
* with one given argument
* <p>
* This method can also be used for UGens with more
* than one argument (e.g. <code>Osc</code>), if the info
* dictionary contains
* default values for the missing arguments.
*
* @param name either ugen class name or
* alias name (for unary/binary op)
* @param in1 first input argument
*
* @throws IllegalArgumentException if the UGen cannot be found in the info dictionary,
* if the rate is not allowed for the ugen,
* or if the UGen requires the explicit specification of the
* number of output channels
* @throws IllegalStateException if the UGens requires arguments
* which have not been provided and have no default values
*/
public static GraphElem ar( String name, GraphElem in1 )
{
return UGen.construct( name, kAudioRate, -1, new GraphElem[] { in1 });
}
public static GraphElem ar( String name, int numChannels, GraphElem in1, GraphElem in2 )
{
return UGen.construct( name, kAudioRate, numChannels, new GraphElem[] { in1, in2 });
}
public static GraphElem ar( String name, GraphElem in1, GraphElem in2 )
{
return UGen.construct( name, kAudioRate, -1, new GraphElem[] { in1, in2 });
}
public static GraphElem ar( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3 )
{
return UGen.construct( name, kAudioRate, numChannels, new GraphElem[] { in1, in2, in3 });
}
public static GraphElem ar( String name, GraphElem in1, GraphElem in2, GraphElem in3 )
{
return UGen.construct( name, kAudioRate, -1, new GraphElem[] { in1, in2, in3 });
}
public static GraphElem ar( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4 )
{
return UGen.construct( name, kAudioRate, numChannels, new GraphElem[] { in1, in2, in3, in4 });
}
public static GraphElem ar( String name, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4 )
{
return UGen.construct( name, kAudioRate, -1, new GraphElem[] { in1, in2, in3, in4 });
}
public static GraphElem ar( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3,
GraphElem in4, GraphElem in5 )
{
return UGen.construct( name, kAudioRate, numChannels, new GraphElem[] { in1, in2, in3, in4, in5 });
}
public static GraphElem ar( String name, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4, GraphElem in5 )
{
return UGen.construct( name, kAudioRate, -1, new GraphElem[] { in1, in2, in3, in4, in5 });
}
public static GraphElem ar( String name, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4, GraphElem in5, GraphElem in6 )
{
return UGen.construct( name, kAudioRate, -1, new GraphElem[] { in1, in2, in3, in4, in5, in6 });
}
// public static GraphElem ar( String name, Object[] inputs )
// {
// return UGen.construct( name, kAudioRate, -1, inputs );
// }
public static GraphElem kr( String name, int numChannels )
{
return UGen.construct( name, kControlRate, numChannels, NO_ARGS );
}
public static GraphElem kr( String name )
{
return UGen.construct( name, kControlRate, -1, NO_ARGS );
}
public static GraphElem kr( String name, int numChannels, GraphElem in1 )
{
return UGen.construct( name, kControlRate, numChannels, new GraphElem[] { in1 });
}
public static GraphElem kr( String name, GraphElem in1 )
{
return UGen.construct( name, kControlRate, -1, new GraphElem[] { in1 });
}
public static GraphElem kr( String name, int numChannels, GraphElem in1, GraphElem in2 )
{
return UGen.construct( name, kControlRate, numChannels, new GraphElem[] { in1, in2 });
}
public static GraphElem kr( String name, GraphElem in1, GraphElem in2 )
{
return UGen.construct( name, kControlRate, -1, new GraphElem[] { in1, in2 });
}
public static GraphElem kr( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3 )
{
return UGen.construct( name, kControlRate, numChannels, new GraphElem[] { in1, in2, in3 });
}
public static GraphElem kr( String name, GraphElem in1, GraphElem in2, GraphElem in3 )
{
return UGen.construct( name, kControlRate, -1, new GraphElem[] { in1, in2, in3 });
}
public static GraphElem kr( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4 )
{
return UGen.construct( name, kControlRate, numChannels, new GraphElem[] { in1, in2, in3, in4 });
}
public static GraphElem kr( String name, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4 )
{
return UGen.construct( name, kControlRate, -1, new GraphElem[] { in1, in2, in3, in4 });
}
public static GraphElem kr( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3,
GraphElem in4, GraphElem in5 )
{
return UGen.construct( name, kControlRate, numChannels, new GraphElem[] { in1, in2, in3, in4, in5 });
}
public static GraphElem kr( String name, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4, GraphElem in5 )
{
return UGen.construct( name, kControlRate, -1, new GraphElem[] { in1, in2, in3, in4, in5 });
}
public static GraphElem kr( String name, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4, GraphElem in5, GraphElem in6 )
{
return UGen.construct( name, kControlRate, -1, new GraphElem[] { in1, in2, in3, in4, in5, in6 });
}
// public static GraphElem kr( String name, Object[] inputs )
// {
// return UGen.construct( name, kControlRate, -1, inputs );
// }
/**
* "dr" stands for demand-rate
*/
public static GraphElem dr( String name, int numChannels )
{
return UGen.construct( name, kDemandRate, numChannels, NO_ARGS );
}
public static GraphElem dr( String name )
{
return UGen.construct( name, kDemandRate, -1, NO_ARGS );
}
public static GraphElem dr( String name, int numChannels, GraphElem in1 )
{
return UGen.construct( name, kDemandRate, numChannels, new GraphElem[] { in1 });
}
public static GraphElem dr( String name, GraphElem in1 )
{
return UGen.construct( name, kDemandRate, -1, new GraphElem[] { in1 });
}
public static GraphElem dr( String name, int numChannels, GraphElem in1, GraphElem in2 )
{
return UGen.construct( name, kDemandRate, numChannels, new GraphElem[] { in1, in2 });
}
public static GraphElem dr( String name, GraphElem in1, GraphElem in2 )
{
return UGen.construct( name, kDemandRate, -1, new GraphElem[] { in1, in2 });
}
public static GraphElem dr( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3 )
{
return UGen.construct( name, kDemandRate, numChannels, new GraphElem[] { in1, in2, in3 });
}
public static GraphElem dr( String name, GraphElem in1, GraphElem in2, GraphElem in3 )
{
return UGen.construct( name, kDemandRate, -1, new GraphElem[] { in1, in2, in3 });
}
public static GraphElem dr( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4 )
{
return UGen.construct( name, kDemandRate, numChannels, new GraphElem[] { in1, in2, in3, in4 });
}
public static GraphElem dr( String name, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4 )
{
return UGen.construct( name, kDemandRate, -1, new GraphElem[] { in1, in2, in3, in4 });
}
public static GraphElem dr( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3,
GraphElem in4, GraphElem in5 )
{
return UGen.construct( name, kDemandRate, numChannels, new GraphElem[] { in1, in2, in3, in4, in5 });
}
public static GraphElem dr( String name, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4, GraphElem in5 )
{
return UGen.construct( name, kDemandRate, -1, new GraphElem[] { in1, in2, in3, in4, in5 });
}
// public static GraphElem dr( String name, Object[] inputs )
// {
// return UGen.construct( name, kDemandRate, -1, inputs );
// }
/**
* A shorthand method for creating a constant
* in the ugen graph. This is equivalent
* to <code>new Constant( value )</code>.
*/
public static GraphElem ir( float value )
{
return new Constant( value );
}
public static GraphElem ir( String name, int numChannels )
{
return UGen.construct( name, kScalarRate, numChannels, NO_ARGS );
}
public static GraphElem ir( String name )
{
return UGen.construct( name, kScalarRate, -1, NO_ARGS );
}
public static GraphElem ir( String name, int numChannels, GraphElem in1 )
{
return UGen.construct( name, kScalarRate, numChannels, new GraphElem[] { in1 });
}
public static GraphElem ir( String name, GraphElem in1 )
{
return UGen.construct( name, kScalarRate, -1, new GraphElem[] { in1 });
}
public static GraphElem ir( String name, int numChannels, GraphElem in1, GraphElem in2 )
{
return UGen.construct( name, kScalarRate, numChannels, new GraphElem[] { in1, in2 });
}
public static GraphElem ir( String name, GraphElem in1, GraphElem in2 )
{
return UGen.construct( name, kScalarRate, -1, new GraphElem[] { in1, in2 });
}
public static GraphElem ir( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3 )
{
return UGen.construct( name, kScalarRate, numChannels, new GraphElem[] { in1, in2, in3 });
}
public static GraphElem ir( String name, GraphElem in1, GraphElem in2, GraphElem in3 )
{
return UGen.construct( name, kScalarRate, -1, new GraphElem[] { in1, in2, in3 });
}
public static GraphElem ir( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4 )
{
return UGen.construct( name, kScalarRate, numChannels, new GraphElem[] { in1, in2, in3, in4 });
}
public static GraphElem ir( String name, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4 )
{
return UGen.construct( name, kScalarRate, -1, new GraphElem[] { in1, in2, in3, in4 });
}
public static GraphElem ir( String name, int numChannels, GraphElem in1, GraphElem in2, GraphElem in3,
GraphElem in4, GraphElem in5 )
{
return UGen.construct( name, kScalarRate, numChannels, new GraphElem[] { in1, in2, in3, in4, in5 });
}
public static GraphElem ir( String name, GraphElem in1, GraphElem in2, GraphElem in3, GraphElem in4, GraphElem in5 )
{
return UGen.construct( name, kScalarRate, -1, new GraphElem[] { in1, in2, in3, in4, in5 });
}
// public static GraphElem ir( String name, Object[] inputs )
// {
// return UGen.construct( name, kScalarRate, -1, inputs );
// }
private static GraphElem construct( String name, Object rate, int numChannels, GraphElem[] inputs )
{
final UGenInfo ui = (UGenInfo) UGenInfo.infos.get( name );
final GraphElem[] ugens;
final UGenInput[][] ugenIns;
final java.util.List args;
final boolean hasArray;
final int outChan;
final Object[] outRates;
if( ui == null ) {
throw new IllegalArgumentException( "Unknown UGen class " + name );
}
if( !ui.rates.contains( rate )) {
throw new IllegalArgumentException( rate.toString() + " : illegal rate for UGen " + name );
}
UGenInfo.Arg argInfo;
UGenInput[] ins;
int chanExp = 1; // channel expansion : output numchan = max( each input's numchan)
int numArgs = ui.args.length;
int numIns = inputs.length;
int specialIndex= 0;
int i, j;
GraphElem graph;
Object o;
// last arg may be an array
if( (numArgs > 0) && (ui.args[ numArgs - 1 ].isArray) ) {
hasArray = true;
numArgs--;
numIns--;
args = new ArrayList( numArgs + inputs[ numIns ].getNumOutputs() );
} else {
hasArray = false;
args = new ArrayList( numArgs );
}
// fill in the non-array args
for( i = 0; (i < numArgs) && (i < numIns); i++ ) {
ins = inputs[ i ].asUGenInputs();
chanExp = Math.max( chanExp, ins.length ); // examine the channel expansion
args.add( ins );
}
// fill in omitted args which have a default value
for( ; i < numArgs; i++ ) {
argInfo = ui.args[ i ];
if( Float.isNaN( argInfo.def )) {
throw new IllegalStateException( "Missing argument " + argInfo.name + " for UGen " + name );
}
ins = new Constant( argInfo.def ).asUGenInputs();
args.add( ins );
}
// fill in array elements
if( hasArray ) {
graph = inputs[ numIns ]; // note: numIns has been decreased by one
for( i = 0; i < graph.getNumOutputs(); i++ ) {
ins = graph.getOutput( i ).asUGenInputs();
chanExp = Math.max( chanExp, ins.length );
args.add( ins );
}
}
if( ui.args.length < inputs.length ) {
System.err.println( name + ": Warning, illegal additional arguments (" + (inputs.length - numArgs) + ")" );
}
numArgs = args.size();
outChan = ui.getNumOutputs( numArgs, numChannels );
if( outChan == -1 ) {
throw new IllegalArgumentException( name + " : numChannels need to be specified" );
}
outRates = new Object[ outChan ];
for( i = 0; i < outChan; i++ ) {
outRates[ i ] = rate;
}
ugens = new GraphElem[ chanExp ];
ugenIns = new UGenInput[ chanExp ][ numArgs ];
// fill in and expand the ugen inputs
for( i = 0; i < numArgs; i++ ) {
ins = (UGenInput[]) args.get( i );
for( j = 0; j < chanExp; j++ ) {
ugenIns[ j ][ i ] = ins[ j % ins.length ];
}
}
// now instantiate the ugens
if( ui.specials != null ) {
o = ui.specials.get( name );
if( o != null ) {
specialIndex = ((Integer) o).intValue();
}
}
for( i = 0; i < chanExp; i++ ) {
ugens[ i ] = new UGen( ui.className, rate, outRates, ugenIns[ i ], specialIndex );
// XXX here is potential place for in place optimization,
// like exchanging a ugen for a constant
}
return( chanExp == 1 ? ugens[ 0 ] : new GraphElemArray( ugens ));
}
// public static GraphElem mulAdd( GraphElem in, float mul, float add )
// {
// return mulAdd( in, ir( mul ), ir( add ));
// }
//
// public static GraphElem mulAdd( GraphElem in, GraphElem mul, GraphElem add )
// {
// UGenInput[] uins = in.asUGenInputs()
// Object highestRate = kScalarRate;
// Object rate;
//
// for( int i = 0; i < uins.length; i++ ) {
// if( uins[ i ] instanceof UGenChannel ) {
// rate = ((UGenChannel) uins[ i ]).getRate();
// if( rate == kAudioRate ) {
// highestRate = kAudioRate;
// break;
// } else if( rate == kControlRate ) {
// highestRate = kControlRate;
// } else if( rate == kDemandRate ) {
// throw new IllegalArgumentException( "MulAdd : illegal rate " + rate );
// }
// }
// }
//
// return construct( "MulAdd", highestRate, -1, in, mul, add );
// }
/**
* Assembles two graph elements (such as UGens,
* or Constants) into one array which in turn
* can be used for multichannel expansion when passed
* as an argument to one of the UGen constructor
* methods
*
* @param g1 first graph element such as a <code>UGen</code>, <code>Constant</code>,
* <code>UGenChannel</code> or <code>GraphElemArray</code>
* @param g2 second graph element
* @return array'ed elements
*/
public static GraphElem array( GraphElem g1, GraphElem g2 )
{
return new GraphElemArray( new GraphElem[] { g1, g2 });
}
/**
* Assembles three graph elements (such as UGens,
* or Constants) into one array which in turn
* can be used for multichannel expansion when passed
* as an argument to one of the UGen constructor
* methods
*
* @param g1 first graph element
* @param g2 second graph element
* @param g3 third graph element
* @return array'ed elements
*/
public static GraphElem array( GraphElem g1, GraphElem g2, GraphElem g3 )
{
return new GraphElemArray( new GraphElem[] { g1, g2, g3 });
}
/**
* Assembles four graph elements (such as UGens,
* or Constants) into one array which in turn
* can be used for multichannel expansion when passed
* as an argument to one of the UGen constructor
* methods
*
* @param g1 first graph element
* @param g2 second graph element
* @param g3 third graph element
* @param g4 fourth graph element
* @return array'ed elements
*/
public static GraphElem array( GraphElem g1, GraphElem g2, GraphElem g3, GraphElem g4 )
{
return new GraphElemArray( new GraphElem[] { g1, g2, g3, g4 });
}
/**
* Assembles five graph elements (such as UGens,
* or Constants) into one array which in turn
* can be used for multichannel expansion when passed
* as an argument to one of the UGen constructor
* methods
*
* @param g1 first graph element
* @param g2 second graph element
* @param g3 third graph element
* @param g4 fourth graph element
* @param g5 fifth graph element
* @return array'ed elements
*/
public static GraphElem array( GraphElem g1, GraphElem g2, GraphElem g3, GraphElem g4, GraphElem g5 )
{
return new GraphElemArray( new GraphElem[] { g1, g2, g3, g4, g5 });
}
}