Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Hanns Holger Rutz
    @Sciss
    Ok. Hey, auxiliary classes is a problem to represent in the XML at the moment. Klang being another one, so I have a hand written KlangSpec. The XML really just has the UGens. Their arguments are either scalar values, e.g. Int for determining the number of channels (In.ar) or they are graph elements GE. So if your custom aux types can be converted to GE then this approach works. It's not optimal in terms of type-safety, but good enough IMO. Let me have a look at the original VBAP source to refresh my memory
    Hanns Holger Rutz
    @Sciss
    Alright. So basically you just need the meta data for VBAP, like you pasted above. The other classes it appears are only auxiliary classes, for example to calculate speaker angles and such, and are never directly used by the UGen class - if I'm not mistaken. So in order to use the UGen, you just need VBAP. If you want to use the functions of say VBAPSpeakerSet available from Scala, you'll have to translate that class. It's independent of ScalaCollider. Let me know if you need help with this.
    It would be good to have VBAP and some other commonly used 3rd party UGens available in ScalaCollider.
    Hanns Holger Rutz
    @Sciss
    Ajajajaj that class VBAPSpeakerArray is a mess
    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI
    I was waiting for this reaction on VBAPSpeakerArray haha! And actually that's the one we absolutely need! we now work on a 4.1 soul system and we have no choice but create a SpeakerArray of 4 directional speakers and a point one (the sub). I Started trying switching sc to scala code but my scala skills are not good enough yet. I come from Java progr
    *sorry
    programming so them i was thinking of recode it in java and use it as a class but i'm not sure it would be compatible to scala classes
    anyway maths are a mess in java also
    Hanns Holger Rutz
    @Sciss
    I'm looking into it. Problem is this code was translated originally from C to a python'ish SuperCollider. But it should be possible
    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI
    I like people not frightened by challenges :)
    You think of using your generator?
    Because recoding it in scala sounds like a loss time
    Hanns Holger Rutz
    @Sciss
    No, that needs manual rewriting. I'm almost done
    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI
    alright :)
    Hanns Holger Rutz
    @Sciss
    Have to remember how to install the plugins ;)
    Hanns Holger Rutz
    @Sciss
    I'm pushing a new version 1.14.1 of ScalaCollider-UGens that contains the VBAP plugin (in sub-project scalacolliderugens-plugins!). An example is included in the doc of VBAP.
    Hanns Holger Rutz
    @Sciss
    // 8 channel ring
    val a = VBAPSetup(2, Seq(0, 45, 90, 135, 180, -135, -90, -45))
    
    val b = Buffer.alloc(s, a.bufferData.size)
    b.setn(a.bufferData)
    
    val x = play {
      val azi = "azi".kr(0)
      val ele = "ele".kr(0)
      val spr = "spr".kr(0)
      VBAP.ar(8, PinkNoise.ar(0.2), b.id, azi, ele, spr)
    }
    
    // test them out
    x.set("azi" -> a.directions(1).azi)
    x.set("azi" -> a.directions(2).azi)
    x.set("azi" -> a.directions(3).azi)
    // ...
    x.set("azi" -> a.directions(7).azi)
    x.set("azi" -> a.directions(0).azi)
    
    // try the spread
    x.set("spr" -> 20)
    x.set("spr" -> 100) // all speakers
    
    x.free(); b.free();
    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI

    that works fine! thank you for this update.

    just a quick question.. I realized that release(float) works on your Swing app but i can't get it from the lib in my code.
    ```

    if (value == 1) Synth.play(ssa.name)
              if (value == 2) {
                ssa release(2)
                println("recu 2")
              }
    Hanns Holger Rutz
    @Sciss

    After I created 'transactional' systems based on ScalaCollider, I wanted to remove the plain side-effecting methods from the basic API. The basic API just supports generating the OSC message; when you call a method such as synth.set(...) or synth.free(...), this is facilitated by an additional import de.sciss.synth.Ops._. So when you look at the README, you have this preamble:

    import de.sciss.synth._
    import ugen._
    import Ops._

    The last import makes the side-effects available. The docs are here: https://sciss.github.io/ScalaCollider/latest/api/#de.sciss.synth.Ops$ - so for release, that is NodeOps: https://sciss.github.io/ScalaCollider/latest/api/#de.sciss.synth.Ops$$NodeOps

    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI
    ok got it
    had to assign the SynthDef to a new var Synth and apply the release() to the Synth and not the SynthDef
    great thanks
    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI
    server.run(cfg) { serv =>
    
              var synth = Synth()
              ssa.recv(serv)    //previous SynthDef
    
              receiver.action = {
                case (m@osc.Message("/test", value: Int), s) =>
                  if (value == 1) synth = Synth.play(ssa.name)
                  if (value == 2) println("recu 2"); synth.release(2.0)  //synth.free()
              }
    }
    compilation is ok, free() works fine, but release() has no action still :/
    n-chatzi
    @n-chatzi
    Same here. release() does not work for a Synth from a SynthDef. But it works on a var synth = play{...} What type is synth implicitly assigned to here?
    sorry thats val synth = play {}
    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI
    actually in the supercollider doc, release is applied to the Synth's superclass Node
    so logically it could be applied to Synth. idk i'm kinda lost haha
    Hanns Holger Rutz
    @Sciss

    That's the same as in SuperCollider - using play { } will add an envelope that has a control gate that is used by release. release is just a convention for synth.set("gate" -> -1 - releaseTime) (or similar). So if you want to add a similar kind of envelope to a SynthDef you either have to create an EnvGen with a gate argument, or you use the pseudo-UGen WrapOut instead (that's the thing that play {} uses):

    SynthDef.recv("test") {
      val sig = WhiteNoise.ar(Seq(0.2, 0.2))
      WrapOut(sig)  // !
    }
    
    val x = Synth.play("test")
    x.release(10)

    WrapOut creates controls "out" (for bus) and "gate" (for release)

    n-chatzi
    @n-chatzi
    Thanks, so play{} implicitly adds a control gate which is released
    Hanns Holger Rutz
    @Sciss
    exactly
    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI
    is it possible to write a SynthDef passing the VBAP Buffer on a textile? I feel like when reading it SCsynth doesn't recognize the live
    lib* exception in GraphDef_Recv: UGen 'VBAP' not installed.
    val a = VBAPSetup(2, Seq(Polar(-60,0), Polar(60,0), Polar(110,0), Polar(-110,0), 3.35))
    val b = Buffer.alloc(serv, a.bufferData.size)
    b.setn(a.bufferData)
    
    SynthDef.write("synthTest.txt", MySynths.load(b), 1)
    synthDefs = SynthDef.read("synthTest.txt")
    
    val ssa = synthDefs.find(_.name == "soudscape-1").get
    ssa.recv(serv)
    MySynths.load(Buffer) loads a Seq[SynthDef]to store
    Hanns Holger Rutz
    @Sciss
    The exception says the VBAP plugin is not installed. If this works from the SuperCollider IDE, my guess is you have more than one SuperCollider installation and the server you use from Scala does not have access to sc3-plugins. The error message has nothing to do with writing the synth-def to hard-disk or not. I don't understand what you mean by 'on a textile'?
    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI
    yes sorry i meant text file :)
    Hanns Holger Rutz
    @Sciss
    You should be able to write a synth def and load it onto the server. write will always write in the standard binary format of SuperCollider. Therefore, this is not a "text file".
    val sd = SynthDef("test") { ... }
    sd.write(dir = "my-dir")
    SynthDef.load(path = "my-dir/test.scsyndef")
    // ... synchronise! then
    Synth.play("test")
    The buffer required by VBAP you have to allocate and fill again explicitly, resources such as buffers are never stored with a synth def.
    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI
    so when i do the following it is not stored?
    WrapOut(FreeVerb.ar(VBAP.ar(4, sig, buffer.id, LFSaw.kr(0.1).madd(90, 90)), wet, rmz, dmp)*amp)
    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI
    D8AN2Xzt
    Hanns Holger Rutz
    @Sciss

    It is stored - the synth definition - but not the contents of buffer. If you want to store this, you should also never hard-code the buffer id. This is just an integer number associated with a live buffer on the server. If you load a synth def with a hard-coded buffer id (here it will be just the constant that you happened to have received by the allocator at the time you created the synth-def), it will be pure luck that you get to have the same buffer again. And it will not be allocated unless you do so.

    So in SuperCollider, for buffers it's always advisable - except for quick live coding - to use a control instead:

    SynthDef("test") {
        val bufId = "buf".kr
        VBAP.ar(4, sig, bufId, ...)
        ...
    }
    
    val b = Buffer.alloc(...)
    b.setn(...)
    val x = Synth.play("test", args = Seq("buf" -> b.id))

    That way the buffer-identifier becomes a parameter of the synth def.

    Is there a particular reason you want to store the synth-def, anyway? I have stopped doing this at all, it's quick enough to generate it ad hoc.

    I would advise reading through some introductory SuperCollider tutorials (even if the examples are for SC-lang not ScalaCollider, the system is essentially the same), to understand the server architecture and how resources such as buffers work.
    For example here http://doc.sccode.org/Tutorials/Getting-Started/00-Getting-Started-With-SC.html - the part under the heading 'Server Abstractions'
    Pierre-Alexandre ADAMSKI
    @PierreAlexandreADAMSKI
    We create a sound engine for a video game in a cave, so the graphic engine is talking with osc to the sound engine. We believe that if we store all synths ahead it would be faster to generate sound than if we interpret the synthdef at each launching event. But interpreting all synthdef before running the server is also an option. We have to test if the server will not crush then. I'd rather ask my collaborator to talk about this on that chat because he is more familiar with the synth gen and I'm more working on the interaction with the game but basically it's about it. It's also why I tried saving all synthdefs in one single text file but this are details
    Hanns Holger Rutz
    @Sciss
    I uploaded a new release 1.28.0 of the Swing IDE that adds submin dark-look-and-feel (via preferences) and basic help browser. Help browser currently only understands UGen names. So if you type Phasor and press Ctrl-D, you should see help file for the Phasor UGen. This saves you time to navigate to the scaladoc file on http://sciss.github.io/ScalaCollider/latest/api/
    Hanns Holger Rutz
    @Sciss

    you may have noticed, I pushed a minimal update to ScalaCollider 1.19.0; this (and ScalaCollider-UGens) relaxes the license from GPL to LGPL, allowing to link to it as a library without having to worry about applying the GPL to your own projects.

    I also wanted to share some thoughts on a research I have started to conduct...

    I have started to map out some directions of development for our sonification platform SysSon -- which you may know uses ScalaCollider at the bottom level. One thing that is interesting to explore is the possibility to decompose complex synth graphs with expensive optional "branches" into actually different synths. Here is a simplified model:

    // ---- Unit result ----
    
    If (freq > 100) {
      Out.ar(0, SinOsc.ar(freq))
    }
    
    If (freq > 100) {
      Out.ar(0, SinOsc.ar(freq))
    } Else {
      freq.poll(0, "freq")
    }
    
    // ---- GE result ----
    
    val res: GE = If (freq > 100) {
      SinOsc.ar(freq)
    } Else {
      WhiteNoise.ar
    }
    Out.ar(0, res)
    
    val res: GE = If (freq > 1000) {
      SinOsc.ar(freq)
    } ElseIf (freq > 100) {
      Dust.ar(freq)
    } Else {
      WhiteNoise.ar
    }
    Out.ar(0, res)

    Currently we can do something like this of course using signal comparators, like

    Out.ar(0, SinOsc.ar(freq) * (freq > 100))

    or

    val freqGt = freq > 100
    val res: GE = {
      SinOsc.ar(freq) * freqGt
    } + {
      WhiteNoise.ar * (1 - freqGt)
    }
    Out.ar(0, res)

    But these imply that all UGens compute at all times. So for expensive mutually exclusive branches (as they can occur in SysSon), it might be great to decompose this into sub-trees that end up in different synths:

    // ---- tree 1 ----
    val freq: GE = ???
    
    // ---- tree 2a
    val res = SinOsc.ar(freq)
    
    // ---- tree 2b
    val res = Dust.ar(freq)
    
    // ---- tree 2c
    val res = WhiteNoise.ar
    
    // ---- tree 3 ----
    Out.ar(0, res)

    This poses multiple challenges, of course. The most basic one, the syntax with which to declare this If, ElseIf, Else structure.
    Then how to automatically partition the graph into connected trees.
    We would need to inject bus-controls between shared signals.
    Imagine that tree 3 also made use of the freq parameter, so there
    might be actually quite a bit of wiring going on. And then the
    correct real-time control. I am currently thinking of pausing the
    synths for the inactive branches, this would still allow the
    If conditional expression to run at control rate. An even
    smarter UGen graph builder could try to parse the conditional
    to see if the graph can be decided already at building time
    (scalar condition that can be decided on the client).

    So if you have any thoughts on this, I'd like to hear them. The Gitter channel might be the best place for this. At this stage it is not clear whether this branching mechanism will be feasible at all.

    Hanns Holger Rutz
    @Sciss
    I have checked in a simple utility to visualise a UGen graph using GraphViz DOT: https://github.com/iem-projects/ScalaCollider-DOT - still not much tested. There is also a Prefuse based visualiser in ScalaCollider-Swing, but the renderer there is quite incomplete ATM (no UGen argument names etc.)
    Hanns Holger Rutz
    @Sciss
    ScalaCollider v1.20.0 is a major version bump because we deactivate some extension methods (.reciprocal) that are now provided by the Numbers library, and the conversion from String to ControlProxyFactory moved into the Ops object, meaning that you may have to add import Ops._ if you hadn't done already and are using the "control".kr syntax. The reason for this change is that I need to get hold of this syntax in SoundProcesses where controls are created differently.
    Hanns Holger Rutz
    @Sciss

    ScalaCollider v1.21.0 includes the fix for LocalIn; this is a breaking change from LocalIn.ar(numChannels: Int) to LocalIn.ar(init: GE). Unfortunately, this may appear source compatible if your code was previously LocalIn.ar(4) for example. So be sure to scan through your sources if you used LocalIn. LocalIn.ar without argument will work as before, and this also shows why using named arguments LocalIn.ar(numChannels = 4) can be very useful.

    A number of other issues on the -UGens and the main project have been closed, too.

    The UGenSource API has been changed to move out the unwrap and rewrap methods in the hope that the class files become significantly smaller (they do, but the gain is not very high). If you have written custom graph elements, you may need to import UGenSource._ which now contains these utility methods.

    ScalaColliderSwing v1.31.0 corresponds with this release. It includes the -DOT library now, and the syntax for getting GUI methods on a graph function. Before gui { ... } .waveform() which was odd because you needed to replace play by gui. Now: play { ... } and graph { ... } play() are equivalent. The gui is now graph { ... } .gui.waveform(), and the DOT is hidden behind graph { ... } .gui.diagram(). The latter is a bit hackish as it only works if the dot Unix command is found. Also the rendering on Swing using Apache Batik is quite horrible, so this will hopefully improve in the next versions. But for now, it's useful enough to get a visual overview of an expanded SynthGraph (the old viewDef based on Prefuse is not imported automatically any longer, as it was never really fully worked out and not very useful, although pretty).

    Hanns Holger Rutz
    @Sciss
    There is a new tiny library out that can help debugging intricate UGen graph structures and precise timings: https://github.com/iem-projects/ScalaCollider-Trace - README shows a couple of examples.
    Hanns Holger Rutz
    @Sciss
    Getting my genetic programming back to work. Soon more…
    play {
      val standardN = StandardN.ar(freq = Nyquist(), k = 0.37251696, xi = 0.0028863533, yi = 0.0028863533)
      val difsqr    = 0.37251696 difsqr standardN
      Pan2.ar(LeakDC.ar(difsqr))
    Hanns Holger Rutz
    @Sciss
    There will be soon a proper announcement with more details; so this is
    just a heads-up in advance -- I will be organising a workshop on
    ScalaCollider & Co
    at the Institute of Electronic Music and Acoustics
    (IEM) in Graz, on Saturday, 10 December. So if you are interested, mark
    the date, and watch this space!
    Hanns Holger Rutz
    @Sciss

    The call for the workshop on ScalaCollider & Co on 10 December is out. Details in German: http://iem.kug.ac.at/institut-aktuell/details/article/sc-meeting-iem-graz-10-dezember-2016.html :

    SC meeting @ IEM Graz, December 10th, 2016

    For the second time a SC meeting is scheduled at the Institute of Electronic Music and
    Acoustics at University of Music and Performing Arts Graz, Austria. Idea of the format: a
    thematic focus should be set by a lecturer with subsequent resp. included opportunity of
    practical programming, testing of examples and discussions with the participants. The
    event is open to all interested people, students and colleagues as well as the SC
    community in Austria and abroad. In this edition Hanns Holger Rutz will present his
    software developments.

    ScalaCollider is a dialect of SuperCollider based on Scala, a statically typed, object-
    functional language that principally targets the Java Virtual Machine (JVM). ScalaCollider
    comes with a mini-IDE and various extensions, and it forms the basis for the computer
    music platform SoundProcesses and its graphical environment Mellite, all of which are
    cross-platform and open source software. SoundProcesses/Mellite in turn contain further
    components, such as an interface for live improvisation, a timeline editor or multi-tracker,
    and furthermore the SysSon sonification platform is designed as an extension of Mellite.
    The workshop begins with an introduction to ScalaCollider and focuses on the specific
    architectural strengths and weaknesses that differentiate it from SuperCollider, making it
    an interesting alternative. In the further course of the workshop, we look at the Mellite
    application and some typical scenarios.

    Schedule:
    Saturday, December 10th, 2016, 10:00 h - ca. 14:45 h

    • 10:00 h until 11:30 h -- first block -- ScalaCollider
    • 11:45 h until 12:45 h -- second block -- SoundProcesses / Mellite
    • 12:45 h until 13:45 h -- lunch break
    • 13:45 h until 14:45 h -- third Block -- Specialisation: FScape-next (UGen based offline rendering)

    Requirements:
    Basic knowledge of SuperCollider: SynthDefs
    The participants are kindly asked to bring their own laptops and headphones and to
    register via e-mail, so they will receive on time information about software installation links
    (Linux, Mac, Windows).

    Fee: none

    Location:
    Institute of Electronic Music and Acoustics – CUBE
    Inffeldgasse 10 / 3, 8010 Graz, Austria
    http://iem.at

    Hanns Holger Rutz
    @Sciss
    ScalaCollider v1.22.0 is out. It adds improved support for buffer-generation commands (sine1, cheby etc.). Other changes include new channel range proxy element, e.g. ugen \ (0 until 4) (first four channels).