All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.sciss.synth.GE.scala Maven / Gradle / Ivy

The newest version!
/*
 *  GE.scala
 *  (ScalaCollider)
 *
 *  Copyright (c) 2008-2012 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
 *  [email protected]
 */

package de.sciss.synth

import scala.{Seq => SSeq}
import collection.breakOut
import collection.immutable.{ IndexedSeq => IIdxSeq }
import ugen.{ChannelProxy, Flatten, Poll, Impulse, LinExp, LinLin, BinaryOp, UnaryOp, MulAdd}

/**
 *    The UGen graph is constructed from interconnecting graph elements (GE).
 *    Graph elements can be decomposed into a sequence of UGenIn objects.
 *    Graph elements are ordinary UGens, UGen proxies, Control proxies,
 *    Constants, and collections of UGen inputs which result from
 *    multichannel expansion (UGenInSeq). 
 */
object GE {
   // XXX is the ever in effect?
//   implicit def bubbleGen[ R <: Rate, G <: GE[ R ]]( g: G ) : Multi[ /* R, */ G ] = Multi.Joint( g )
//   implicit def bubble[ G <: AnyGE ]( g: G ) : Multi[ /* R, */ G ] = Multi.Joint( g )

//   implicit def bubble[ G <: AnyGE, T <% G ]( g: T ) : Multi[ /* R, */ G ] = Multi.Joint( g )

//   implicit def bubbleGE[ R <: Rate, G <: GE[ R ]]( g: G ) : Multi[ /* R, */ G ] = Multi.Joint( g )

//   implicit def fromAnySeq( x: Seq[ AnyGE ]) : GE[ Rate ] = {
//      x match {
//         case Seq( single ) => single // Multi.Joint( single )
////         case _ => GESeq[ R, U ]( x.toIndexedSeq ) // Multi.Group( x.toIndexedSeq ) // new RatedUGenInSeq( Rate.highest( x.map( _.rate ): _* ), x )
//         case _ => GESeqGaga( /* rate, */ x.toIndexedSeq ) // Multi.Group( x.toIndexedSeq ) // new RatedUGenInSeq( Rate.highest( x.map( _.rate ): _* ), x )
//      }
//   }

   // XXX don't we expect Multi[ GE[ R ]] ?
   implicit def fromSeq( xs: SSeq[ GE ]) : GE = xs match {
      case SSeq( x ) => x
      case _ => SeqImpl( xs.toIndexedSeq )
   }

   implicit def fromIntSeq( xs: SSeq[ Int ]) : GE = xs match {
      case SSeq( single ) => single: Constant
      case _ => SeqImpl( xs.map( i => Constant( i.toFloat ))( breakOut ))
   }

   implicit def fromFloatSeq( xs: SSeq[ Float ]) : GE = xs match {
      case SSeq( x ) => x: Constant
      case _ => SeqImpl( xs.map( f => Constant( f ))( breakOut ))
   }

   implicit def fromDoubleSeq( xs: SSeq[ Double ]) : GE = xs match {
      case SSeq( x ) => x: Constant
      case _ => SeqImpl( xs.map( d => Constant( d.toFloat ))( breakOut ))
   }

   def fromUGenIns( xs: SSeq[ UGenIn ]) : GE = SeqImpl2( xs.toIndexedSeq )

//   implicit def fromSeq[ R <: Rate, G ]( x: Seq[ G ])( implicit view: G => GE[ R ]) : GE[ R ] = {
//      x match {
//         case Seq( single ) => single // Multi.Joint( single )
//         case _ => GESeq[ R ]( x.map( view )( breakOut ))
//      }
//   }

   private final case class SeqImpl( elems: IIdxSeq[ GE ]) extends GE {
def numOutputs = elems.size
      def expand : UGenInLike = UGenInGroup( elems.map( _.expand ))
      def rate = MaybeRate.reduce( elems.map( _.rate ): _* )
      override def displayName = "GE.Seq"
      override def toString = displayName + elems.mkString( "(", ",", ")" )
   }
   private final case class SeqImpl2( elems: IIdxSeq[ UGenIn ]) extends GE {
def numOutputs = elems.size
      def expand : UGenInLike = UGenInGroup( elems )
      def rate = MaybeRate.reduce( elems.map( _.rate ): _* )
      override def displayName = "GE.Seq"
      override def toString = displayName + elems.mkString( "(", ",", ")" )
   }

//   object Seq {
////      implicit def toIndexedSeq[ R <: Rate ]( g: Seq[ R ]) : IIdxSeq[ GE[ R ]] = g.elems
////      def apply[ R <: Rate ]( elems: IIdxSeq[ GE[ R ]]) : Seq[ R ] = new SeqImpl( elems )
//      def apply[ R <: Rate ]( xs: GE[ R ]* ) : Seq[ R ] = new SeqImpl( xs.toIndexedSeq )
//      def apply( xs: UGenIn* ) : Seq[ Rate ] = new SeqImpl2( xs.toIndexedSeq )
//   }
//   sealed trait Seq[ R <: Rate ] extends GE[ R ]

   /**
    * Simply a trait composed of `Lazy.Expander[UGenInLike]` and `GE`
    */
   trait Lazy extends Lazy.Expander[ UGenInLike ] with GE
}
//private[synth] sealed trait GEIn
//private[synth] final case class GEMultiple( elem: GE ) extends GEIn
/**
 * The main trait used in synthesis graph, a graph element, abbreviated as `GE`.
 *
 * Graph elements are characterized by having a calculation rate (possibly unknown),
 * and they embody future UGens, which are created by invoking the `expand` method.
 * For each ugen in SuperCollider, there is a corresponding graph element defined
 * in the `ugen` package, and these elements take again graph elements as arguments.
 * Multi-channel expansion is thus deferred to the transition from `SynthGraph` to `UGenGraph`.
 *
 * Currently, also a lot of unary and binary operations are directly defined on the `GE` trait,
 * although they might go into a separate `GEOps` implicit class in future versions.
 *
 * @see [[de.sciss.synth.SynthGraph]]
 */
trait GE /* extends GEIn */ {
   ge =>

//   type Rate = R

   def rate: MaybeRate

//   private[synth] def multiple: GEIn = GEMultiple( this )

//   def expand: IIdxSeq[ UGenIn ]
//   def mexpand: IIdxSeq[ GE[ R ]]

   def expand: UGenInLike

//   final def mexpand = IIdxSeq( ge )

   def displayName: String

//   def displayName = {
//      val cn = getClass.getName
//      cn.substring( cn.lastIndexOf( '.' ) + 1 )
//   }

   /**
    * Decomposes the graph element into its distinct outputs. For a single-output UGen
    * or a Constant,  this will just return that UGen or Constant (wrapped in a Vector),
    * for multi-channel UGens this will return the corresponding output proxies. For
    * sequences wrapped into a UGenInSeq, this will return the underlying elements.
    *
    * @return  the sequence containing the output elements of the graph element. When
    *          being certain about the number of elements returned, pattern matching can
    *          be used to extract the different channels, e.g.
    *          `val Seq( left, right ) = Pan.ar( ... ).outputs`
    */
//   def outputs : IIdxSeq[ GE ]

   /**
    * The number of outputs produced when calling `expand`. Do not
    * confuse this with the number of `UGenIn` instances produced
    * which can be higher due to multichannel expansion.
    */
//   def numOutputs : Int // = outputs.size

   def `\\`( index: Int ) = ChannelProxy( this, index )

//   private[synth] def ops = new GEOps( this )

   def madd( mul: GE, add: GE ) = MulAdd( this, mul, add )

   def flatten = Flatten( this )

   def poll: Poll = poll()

   /**
    * Polls the output values of this graph element, and prints the result to the console.
    * This is a convenient method for wrapping this graph element in a `Poll` UGen.
    *
    * @param   trig     a signal to trigger the printing. If this is a constant, it is
    *    interpreted as a frequency value and an `Impulse` generator of that frequency
    *    is used instead.
    * @param   label    a string to print along with the values, in order to identify
    *    different polls. Using the special label `"#auto"` (default) will generated
    *    automatic useful labels using information from the polled graph element
    * @param   trigID   if greater then 0, a `"/tr"` OSC message is sent back to the client
    *    (similar to `SendTrig`)
    *
    * @see  [[de.sciss.synth.ugen.Poll]]
    */
//   def poll( trig: Constant = 10, label: String = "#auto", trigID: AnyGE = -1 ) : Poll[ R ] =
//      poll( Impulse( trig.rate max freq ), label, trigID )

   def poll( trig: GE = 10, label: Optional[ String ] = None, trigID: GE = -1 ) : Poll = {
      val trig1 = trig match {
         case Constant( freq ) => Impulse( (ge.rate ?| audio) max control, freq, 0 )  // XXX good? or throw an error? should have a maxRate?
         case x => x
      }
      Poll( trig1.rate, trig1, ge, label.getOrElse( ge.displayName ), trigID  )
   }

   import UnaryOp._

   // unary ops
   def unary_- : GE   = Neg.make( this )
// def bitNot : GE	         = BitNot.make( this )
   def abs : GE       = Abs.make( this )
// def toFloat : GE	         = UnOp.make( 'asFloat, this )
// def toInteger : GE	      = UnOp.make( 'asInteger, this )
   def ceil : GE      = Ceil.make( this )
   def floor : GE     = Floor.make( this )
   def frac : GE      = Frac.make( this )
   def signum : GE    = Signum.make( this )
   def squared : GE   = Squared.make( this )
   def cubed : GE     = Cubed.make( this )
   def sqrt : GE      = Sqrt.make( this )
   def exp : GE       = Exp.make( this )
   def reciprocal : GE= Reciprocal.make( this )
   def midicps : GE   = Midicps.make( this )
   def cpsmidi : GE   = Cpsmidi.make( this )
   def midiratio : GE = Midiratio.make( this )
   def ratiomidi : GE = Ratiomidi.make( this )
   def dbamp : GE     = Dbamp.make( this )
   def ampdb : GE     = Ampdb.make( this )
   def octcps : GE    = Octcps.make( this )
   def cpsoct : GE    = Cpsoct.make( this )
   def log : GE       = Log.make( this )
   def log2 : GE      = Log2.make( this )
   def log10 : GE     = Log10.make( this )
   def sin : GE       = Sin.make( this )
   def cos : GE       = Cos.make( this )
   def tan : GE       = Tan.make( this )
   def asin : GE      = Asin.make( this )
   def acos : GE      = Acos.make( this )
   def atan : GE      = Atan.make( this )
   def sinh : GE      = Sinh.make( this )
   def cosh : GE      = Cosh.make( this )
   def tanh : GE      = Tanh.make( this )
// def rand : GE              = UnOp.make( 'rand, this )
// def rand2 : GE             = UnOp.make( 'rand2, this )
// def linrand : GE           = UnOp.make( 'linrand, this )
// def bilinrand : GE         = UnOp.make( 'bilinrand, this )
// def sum3rand : GE          = UnOp.make( 'sum3rand, this )
   def distort : GE   = Distort.make( this )
   def softclip : GE  = Softclip.make( this )
// def coin : GE              = UnOp.make( 'coin, this )
// def even : GE              = UnOp.make( 'even, this )
// def odd : GE               = UnOp.make( 'odd, this )
// def rectWindow : GE        = UnOp.make( 'rectWindow, this )
// def hanWindow : GE         = UnOp.make( 'hanWindow, this )
// def welWindow : GE         = UnOp.make( 'sum3rand, this )
// def triWindow : GE         = UnOp.make( 'triWindow, this )
   def ramp : GE      = Ramp.make( this )
   def scurve : GE    = Scurve.make( this )
// def isPositive : GE        = UnOp.make( 'isPositive, this )
// def isNegative : GE        = UnOp.make( 'isNegative, this )
// def isStrictlyPositive : GE= UnOp.make( 'isStrictlyPositive, this )
// def rho : GE               = UnOp.make( 'rho, this )
// def theta : GE             = UnOp.make( 'theta, this )

   import BinaryOp._

   // binary ops
   private def binOp( op: BinaryOp.Op, b: GE ) : GE =
      op.make( /* r.getOrElse( this.rate, b.rate ), */ this, b )

   def +( b: GE) = binOp( Plus, b )
//      Plus.make /*[ R, S, T ]*/( r.getOrElse( this.rate, b.rate ), this, b )
   
   def -( b: GE) = binOp( Minus, b )

   def *( b: GE) = binOp( Times, b )

// def div( b: GE[ /*S,*/ UGenIn /*[ S ]*/])/**/ = : GE      = IDiv.make /*[ R, S, T ]*/( /* r.out,*/ this, b )

   def / ( b: GE) = binOp( Div, b )

   def % ( b: GE) = binOp( Mod, b )

   def === ( b: GE) = binOp( Eq, b )

   def !== ( b: GE) = binOp( Neq, b )

   def < ( b: GE) = binOp( Lt, b )

   def > ( b: GE) = binOp( Gt, b )

   def <= ( b: GE) = binOp( Leq, b )

   def >= ( b: GE) = binOp( Geq, b )

   def min ( b: GE) = binOp( Min, b )

   def max( b: GE) = binOp( Max, b )

   def & ( b: GE) = binOp( BitAnd, b )

   def | ( b: GE) = binOp( BitOr, b )

   def ^ ( b: GE) = binOp( BitXor, b )

// def Lcm( b: GE[ /*S,*/ UGenIn /*[ S ]*/])/**/ = : GE      = Lcm.make /*[ R, S, T ]*/( /* r.out,*/ this, b )
// def Gcd( b: GE[ /*S,*/ UGenIn /*[ S ]*/])/**/ = : GE      = Gcd.make /*[ R, S, T ]*/( /* r.out,*/ this, b )

   def round ( b: GE) = binOp( Round, b )

   def roundup ( b: GE) = binOp( Roundup, b )

   def trunc ( b: GE) = binOp( Trunc, b )

   def atan2 ( b: GE) = binOp( Atan2, b )

   def hypot ( b: GE) = binOp( Hypot, b )

   def hypotx ( b: GE) = binOp( Hypotx, b )

   def pow ( b: GE) = binOp( Pow, b )

// def <<( b: GE[ /*S,*/ UGenIn /*[ S ]*/])/**/ = : GE       = <<.make /*[ R, S, T ]*/( /* r.out,*/ this, b )
// def >>( b: GE[ /*S,*/ UGenIn /*[ S ]*/])/**/ = : GE       = >>.make /*[ R, S, T ]*/( /* r.out,*/ this, b )
// def unsgnRghtShift( b: GE[ /*S,*/ UGenIn /*[ S ]*/])/**/ = : GE = UnsgnRghtShift.make /*[ R, S, T ]*/( /* r.out,*/ this, b )
// def fill( b: GE[ /*S,*/ UGenIn /*[ S ]*/])/**/ = : GE     = Fill.make /*[ R, S, T ]*/( /* r.out,*/ this, b )

   def ring1 ( b: GE) = binOp( Ring1, b )

   def ring2 ( b: GE) = binOp( Ring2, b )

   def ring3 ( b: GE) = binOp( Ring3, b )

   def ring4 ( b: GE) = binOp( Ring4, b )

   def difsqr ( b: GE) = binOp( Difsqr, b )

   def sumsqr ( b: GE) = binOp( Sumsqr, b )

   def sqrsum ( b: GE) = binOp( Sqrsum, b )

   def sqrdif ( b: GE) = binOp( Sqrdif, b )

   def absdif ( b: GE) = binOp( Absdif, b )

   def thresh ( b: GE) = binOp( Thresh, b )

   def amclip ( b: GE) = binOp( Amclip, b )

   def scaleneg ( b: GE) = binOp( Scaleneg, b )

   def clip2 ( b: GE) = binOp( Clip2, b )

   def excess ( b: GE) = binOp( Excess, b )

   def fold2 ( b: GE) = binOp( Fold2, b )

   def wrap2 ( b: GE) = binOp( Wrap2, b )

   def firstarg ( b: GE) = binOp( Firstarg, b )

// def rrand( b: GE[ /*S,*/ UGenIn /*[ S ]*/])/**/ = : GE    = Rrand.make /*[ R, S, T ]*/( /* r.out,*/ this, b )
// def exprrand( b: GE[ /*S,*/ UGenIn /*[ S ]*/])/**/ = : GE = Exprrand.make /*[ R, S, T ]*/( /* r.out,*/ this, b )

   def linlin( srcLo: GE, srcHi: GE, dstLo: GE, dstHi: GE ) : GE =
      LinLin( /* rate, */ this, srcLo, srcHi, dstLo, dstHi )

   def linexp( srcLo: GE, srcHi: GE, dstLo: GE, dstHi: GE ) : GE =
      LinExp( rate, this, srcLo, srcHi, dstLo, dstHi ) // should be highest rate of all inputs? XXX
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy