
de.sciss.synth.ResolveGE.scala Maven / Gradle / Ivy
/*
* ResolveGE.scala
* (SoundProcesses)
*
* Copyright (c) 2010-2024 Hanns Holger Rutz. All rights reserved.
*
* This software is published under the GNU Affero General Public License v3+
*
*
* For further information, please contact Hanns Holger Rutz at
* [email protected]
*/
package de.sciss.synth
import de.sciss.proc.UGenGraphBuilder
import de.sciss.proc.UGenGraphBuilder.MissingIn
import de.sciss.synth.proc.graph.Attribute
object ResolveGE {
def test(in: GE): Either[String, Unit] = {
import ugen._
in match {
case _: Constant => Right(())
case _: Attribute => Right(())
case UnaryOpUGen (_, a ) => ResolveGE.test(a)
case BinaryOpUGen(_, a, b) =>
for {
_ <- ResolveGE.test(a).right
_ <- ResolveGE.test(b).right
} yield ()
case _: SampleRate => Right(())
case _: NumChannels => Right(())
case _ => Left(s"Element: $in")
}
}
def float(in: GE, builder: UGenGraphBuilder): Either[String, Float] = {
import ugen._
in match {
case Constant(f) => Right(f)
case a: Attribute =>
val input = UGenGraphBuilder.Input.Attribute(a.key)
val opt = builder.requestInput(input) // .asInstanceOf[UGenGraphBuilder.Input.Attribute.Value]
opt.peer.fold[Either[String, Float]] {
a.default.fold[Either[String, Float]] {
throw MissingIn(input.key)
} { sq =>
if (sq.size == 1) Right(sq.head)
else Left(s"Cannot use multi-channel element as single Float: $sq")
}
} {
case i: Int => Right(i.toFloat)
case d: Double => Right(d.toFloat)
case n: Long => Right(n.toFloat)
case b: Boolean => Right(if (b) 1f else 0f)
case other => Left(s"Cannot convert attribute value to Float: $other")
}
case UnaryOpUGen(op: UnaryOpUGen.PureOp, a) =>
val af = ResolveGE.float(a, builder)
af.right.map(op.make1)
case BinaryOpUGen(op: BinaryOpUGen.PureOp, a, b) =>
for {
af <- ResolveGE.float(a, builder).right
bf <- ResolveGE.float(b, builder).right
} yield op.make1(af, bf)
case _: SampleRate =>
val sr = builder.server.sampleRate.toFloat
Right(sr)
case NumChannels(in0) =>
var uIns = Vector.empty[UGenIn]
var uInsOk = true
var exp = 0
val args = in0.expand.outputs
args.foreach(_.unbubble match {
case u: UGenIn => if (uInsOk) uIns :+= u
case g: ugen.UGenInGroup =>
exp = math.max(exp, g.numOutputs)
uInsOk = false // don't bother adding further UGenIns to uIns
})
if (uInsOk) {
Right(uIns.size.toFloat)
} else {
Left(s"Cannot use multi-channel element as single Float: $in0")
}
// case g: ugen.UGenInGroup =>
// if (g.numOutputs == 1) resolveFloat(g.outputs.head, builder)
// else Left(s"Cannot convert multi-channel element to Float: $in")
case other => Left(s"Cannot convert element to Float: $other")
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy