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

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

/*
 *  Ops.scala
 *  (ScalaCollider)
 *
 *  Copyright (c) 2008-2013 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 de.sciss.osc.Packet

object Ops {
   implicit def nodeOps( n: Node ) : NodeOps = new NodeOps( n )
   // this allows conversions to Group so that something like Server.default.freeAll becomes possible
   implicit def groupOps[ G <% Group ]( g: G ) : GroupOps = new GroupOps( g )
   implicit def bufferOps( b: Buffer ) : BufferOps = new BufferOps( b )
   implicit def controlBusOps( b: ControlBus ) : ControlBusOps = new ControlBusOps( b )

   final class NodeOps( n: Node ) {
      import n._

      def free() {
         server ! freeMsg
      }

      /**
       * Pauses or resumes the node.
       *
       * @param flag if `true` the node is resumed, if `false` it is paused.
       */
     	def run( flag: Boolean = true ) {
     		server ! runMsg( flag )
     	}

      def set( pairs: ControlSetMap* ) {
     		server ! setMsg( pairs: _* )
     	}

      def trace() {
     		server ! traceMsg
     	}

     	def release( releaseTime: Optional[ Double ] = None ) {
     		server ! releaseMsg( releaseTime )
     	}

      def map( pairs: ControlKBusMap.Single* ) {
         server ! mapMsg( pairs: _* )
      }

      /**
       * Creates a mapping from a mono-channel audio bus to one of the node's controls.
       *
       * Note that a mapped control acts similar to an `InFeedback` UGen in that it does not matter
       * whether the audio bus was written before the execution of the synth whose control is mapped or not.
       * If it was written before, no delay is introduced, otherwise a delay of one control block is introduced.
       *
       * @see  [[de.sciss.synth.ugen.InFeedback]]
       */
      def mapa( pairs: ControlABusMap.Single* ) {
         server ! mapaMsg( pairs: _* )
      }

      /**
       * Creates a mapping from a mono- or multi-channel audio bus to one of the node's controls.
       *
       * Note that a mapped control acts similar to an `InFeedback` UGen in that it does not matter
       * whether the audio bus was written before the execution of the synth whose control is mapped or not.
       * If it was written before, no delay is introduced, otherwise a delay of one control block is introduced.
       *
       * @see  [[de.sciss.synth.ugen.InFeedback]]
       */
      def mapan( mappings: ControlABusMap* ) {
         server ! mapanMsg( mappings: _* )
      }

      def fill( control: Any, numChannels: Int, value: Float ) {
         server ! fillMsg( control, numChannels, value )
      }

     	def fill( fillings: osc.NodeFillInfo* ) {
     		server ! fillMsg( fillings: _* )
     	}

      /**
       * Moves this node before another node
       *
       * @param   node  the node before which to move this node
       *
       * @see  [[de.sciss.synth.osc.osc.NodeBeforeMessage]]
       */
      def moveBefore( node: Node ) {
         server ! moveBeforeMsg( node )
      }

      /**
       * Moves this node after another node
       *
       * @param   node  the node after which to move this node
       *
       * @see  [[de.sciss.synth.osc.osc.NodeAfterMessage]]
       */
      def moveAfter( node: Node ) {
         server ! moveAfterMsg( node )
      }

      def moveToHead( group: Group ) {
         server ! moveToHeadMsg( group )
      }

      def moveToTail( group: Group ) {
         server ! moveToTailMsg( group )
      }
   }

   final class GroupOps( g: Group ) {
      import g._

      def freeAll() {
         server ! freeAllMsg
      }

      def deepFree() {
         server ! deepFreeMsg
      }

      def dumpTree( postControls: Boolean = false ) {
     		server ! dumpTreeMsg( postControls )
     	}
   }

   final class BufferOps( b: Buffer ) {
      import b._

      def alloc( numFrames: Int, numChannels: Int = 1, completion: Buffer.Completion = Buffer.NoCompletion ) {
     		server ! allocMsg( numFrames, numChannels, makePacket( completion ))
     	}

      def free( completion: Optional[ Packet ] = None ) {
     		server ! freeMsg( completion, release = true )
     	}

      def close( completion: Option[ Packet ] = None ) {
         server ! closeMsg( completion )
      }

      def allocRead( path: String, startFrame: Int = 0, numFrames: Int = -1,
                     completion: Buffer.Completion = Buffer.NoCompletion ) {
   //      path = argpath;
         server ! allocReadMsg( path, startFrame, numFrames, makePacket( completion, forceQuery = true ))
      }

      def allocReadChannel( path: String, startFrame: Int = 0, numFrames: Int = -1, channels: Seq[ Int ],
                            completion: Buffer.Completion = Buffer.NoCompletion ) {
   //      path = argpath;
         server ! allocReadChannelMsg( path, startFrame, numFrames, channels, makePacket( completion, forceQuery = true ))
      }

      def read( path: String, fileStartFrame: Int = 0, numFrames: Int = -1, bufStartFrame: Int = 0,
                leaveOpen: Boolean = false, completion: Buffer.Completion = Buffer.NoCompletion ) {
         server ! readMsg( path, fileStartFrame, numFrames, bufStartFrame, leaveOpen, makePacket( completion ))
      }

      def readChannel( path: String, fileStartFrame: Int = 0, numFrames: Int = -1, bufStartFrame: Int = 0,
                leaveOpen: Boolean = false, channels: Seq[ Int ],
                completion: Buffer.Completion = Buffer.NoCompletion ) {
         server ! readChannelMsg( path, fileStartFrame, numFrames, bufStartFrame, leaveOpen,
            channels, makePacket( completion ))
      }

      /**
       * Sets the contents of the buffer by replacing
       * individual sample values. An error is thrown if any of the given
       * offsets is out of range.
       *
       * @param   pairs a list of modifications to the buffer contents, each element
       *          being a sample offset and the sample value. The sample offset ranges
       *          from zero to the number of samples in the buffer (exclusive), i.e.
       *          `numChannels * numFrames`. For instance, in a stereo-buffer, the offset
       *          for the right channel's fifth frame is `(5-1) * 2 + 1 = 9`.
       */
      def set( pairs: (Int, Float)* ) {
         server ! setMsg( pairs: _* )
      }

      /**
       * Sets the entire contents of the buffer.
       * An error is thrown if the number of given values does not match the number
       * of samples in the buffer.
       *
       * @param   v  the new content of the buffer. the size of the sequence must be
       *          exactly the number of samples in the buffer, i.e.
       *          `numChannels * numFrames`. Values are channel-interleaved, that is
       *          for a stereo-buffer the first element specifies the value of the
       *          first frame of the left channel, the second element specifies the value
       *          of the first frame of the right channel, followed by the second frame
       *          of the left channel, etc.
       */
      def setn( v: IndexedSeq[ Float ]) {
         server ! setnMsg( v )
      }

      /**
       * Sets the contents of the buffer by replacing
       * individual contiguous chunks of data. An error is thrown if any of the given
       * ranges lies outside the valid range of the entire buffer.
       *
       * @param   pairs a list of modifications to the buffer contents, each element
       *          being a sample offset and a chunk of values. The data is channel-interleaved,
       *          e.g. for a stereo-buffer, the offset for the right channel's fifth frame
       *          is `(5-1) * 2 + 1 = 9`. Accordingly, values in the float-sequences are
       *          considered channel-interleaved, i.e. for a stereo buffer and an even offset,
       *          the first element of the sequence refers to frame `offset / 2` of the
       *          left channel, the second element to frame `offset / 2` of the right channel,
       *          followed by frame `offset / 2 + 1` of the left channel, and so on.
       */
      def setn( pairs: (Int, IndexedSeq[ Float ])* ) {
         server ! setnMsg( pairs: _* )
      }

      def zero( completion: Option[ Packet ] = None ) {
         server ! zeroMsg( completion )
      }

      def write( path: String, fileType: io.AudioFileType = io.AudioFileType.AIFF,
                 sampleFormat: io.SampleFormat = io.SampleFormat.Float, numFrames: Int = -1, startFrame: Int = 0,
                 leaveOpen: Boolean = false, completion: Buffer.Completion = Buffer.NoCompletion) {
   //         path = path ?? { thisProcess.platform.recordingsDir +/+ "SC_" ++ Date.localtime.stamp ++ "." ++ headerFormat };
            server ! writeMsg( path, fileType, sampleFormat, numFrames, startFrame, leaveOpen, makePacket( completion ))
         }

      // ---- utility methods ----
      def play : Synth = play()
      def play( loop: Boolean = false, amp: Float = 1f, out: Int = 0 ) : Synth = {
         import de.sciss.synth.{play => scplay}
         import ugen._
         scplay( server, out ) { // working around nasty compiler bug
            val ply = PlayBuf.ar( numChannels, id, BufRateScale.kr( id ), loop = if( loop ) 1 else 0 )
            if( !loop ) FreeSelfWhenDone.kr( ply )
            ply * "amp".kr( amp )
         }
      }
   }

   final class ControlBusOps( b: ControlBus ) {
      import b._

      def set( v: Float ) {
         server ! setMsg( v )
      }

      def set( pairs: (Int, Float)* ) {
         server ! setMsg( pairs: _* )
      }

      def setn( v: IndexedSeq[ Float ]) {
         server ! setnMsg( v )
      }

      def setn( pairs: (Int, IndexedSeq[ Float ])* ) {
         server ! setnMsg( pairs: _* )
      }
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy