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

de.sciss.synth.ugen.LocalBuf.scala Maven / Gradle / Ivy

/*
 *  LocalBuf.scala
 *  (ScalaColliderUGens)
 *
 *  Copyright (c) 2008-2016 Hanns Holger Rutz. All rights reserved.
 *
 *  This software is published under the GNU Lesser General Public License v2.1+
 *
 *
 *  For further information, please contact Hanns Holger Rutz at
 *  [email protected]
 */

package de.sciss.synth
package ugen

import UGenSource._

// XXX TODO - SetBuf, ClearBuf

/** A UGen that allocates a buffer local to the synth.
  * This is convenient for example when using an `FFT` chain.
  *
  * @see [[de.sciss.synth.ugen.FFT]]
  */
object LocalBuf
/** A UGen that allocates a buffer local to the synth.
  * This is convenient for example when using an `FFT` chain.
  *
  * @param numFrames    number of sample frames for the buffer
  * @param numChannels  number of channels for the buffer
  *
  * @see [[de.sciss.synth.ugen.FFT]]
  */
final case class LocalBuf(numFrames: GE, numChannels: GE = 1)
  extends UGenSource.SingleOut with ScalarRated with IsIndividual {

  protected def makeUGens: UGenInLike = unwrap(this, Vector(numChannels.expand, numFrames.expand))

  protected def makeUGen(_args: Vec[UGenIn]): UGenInLike = {
    // by 'visiting' we make sure exactly one instance of `MaxLocalBufs` exists per builder.
    // This is because we use the `MaxLocalBufs` companion object as key. ''Note'' that we
    // do not expand `MaxLocalBufs` at this moment. That is crucial, because we must be
    // able to increase its use count for all `LocalBuf` instances in a synth graph.
    // Instantiating `MaxLocalBufs` adds a lazy element to the builder. This will only be
    // expanded in the _next_ iteration of the builder, thereby freezing the count.
    // To ensure that `MaxLocalBufs` appears before all `LocalBuf` instances within the
    // final UGen graph, `MaxLocalBufs` uses `prependUGen`.
    val maxLocalBufs  = UGenGraph.builder.visit(MaxLocalBufs, MaxLocalBufs())
    val index         = maxLocalBufs.alloc()
    UGen.SingleOut(name, rate, _args :+ Constant(index), isIndividual = true)
  }

  /** Convenience method for `ClearBuf(this)` */
  def clear(): this.type = { ClearBuf(this); this }

  // XXX TODO: def set(values: GE, offset: GE = 0): this.type = { SetBuf(this, values, offset); this }
}

private[synth] final case class MaxLocalBufs() extends UGenSource.SingleOut with ScalarRated with HasSideEffect {
  @transient private[this] var count    = 0
  @transient private[this] var expanded = false

  def alloc(): Int = {
    if (expanded) throw new IllegalStateException(s"$name was already expanded")
    val res = count
    count += 1
    res
  }

  protected def makeUGen(_args: Vec[UGenIn]): UGenInLike = {
    // instead of UGen.SingleOut we do this because we want to _prepend_ not _append_
    val res = new impl.SingleOutImpl(name, rate, _args, isIndividual = false, hasSideEffect = true, specialIndex = 0)
    UGenGraph.builder.prependUGen(res)
    res
  }

  /** Abstract method which must be implemented by creating the actual `UGen`s
    * during expansion. This method is at most called once during graph
    * expansion
    *
    * @return  the expanded object (depending on the type parameter `U`)
    */
  protected def makeUGens: UGenInLike = {
    expanded = true
    unwrap(this, Vector(Constant(count)))
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy