[Cs-dev] Ugen API Proposal
Date | 2014-09-23 13:08 |
From | Steven Yi |
Subject | [Cs-dev] Ugen API Proposal |
Hi All, I gave a presentation on "Extending Aura with Csound Opcodes" at the ICMC last week and wanted to follow up with some thoughts on a new API proposal. In the paper (available at http://kunstmusik.com/2014/09/23/extending-aura-with-csound-opcodes/), I went through the work I did to get Csound Opcodes to run individually outside of the Csound engine. In preparing for the conference, I had the thought that we might want move the work into the Csound public API. I think this could lead to a couple of interesting things: * Runtime, dynamic allocation and connection of Csound unit generators. This would be for use externally, generally by host languages. This would use a DAG-based model for interconnecting unit generators, rather than Csound's compilation of the AST into a flat list of operations. This would require the addition of a couple of things. One is that as a DAG, we would need to a single root node to call for execution. Because users can do multiple things like output to outs and write to globals, etc., we would have to add a "do" opcode that takes in multple other opcodes to deal with multiple operations. Also, we would need to add to the internals a way to schedule and run these DAG's of opcodes, much like an instrument instance. The DAG could be run externally by host apps (much like what was done for the work with Aura), or could be scheduled with an API call like csoundScheduleUgen(csound, myDAG). * Internally, we could look at modifying the internals of compilation to compile to a DAG instead of down to a list. This might be interesting research work. * We should maybe abstract out what parts opcodes use from CSOUND into a more generic struct that could possibly be overridden by hosts. I was thinking that we could label this work as the "UGen API", with the data structures for wrapping opcode instances to be called UGEN. Thoughts? steven ------------------------------------------------------------------------------ Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer Achieve PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports Are you Audit-Ready for PCI DSS 3.0 Compliance? Download White paper Comply to PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.clktrk _______________________________________________ Csound-devel mailing list Csound-devel@lists.sourceforge.net |
Date | 2014-09-23 13:20 |
From | Rory Walsh |
Subject | Re: [Cs-dev] Ugen API Proposal |
Sounds good Steven. It would certianly be nice to be able to modify the DAG during runtime from the API. Are there any issues with performance. As I understand it Csound currently compiles a 'flat' graph on startup. Will compiling new nodes during runtime incur any noticeable performance penalty? On 23 September 2014 14:08, Steven Yi |
Date | 2014-09-23 13:27 |
From | Rory Walsh |
Subject | Re: [Cs-dev] Ugen API Proposal |
Btw, can you provide a pseudo example of how this might look in a given implantation language? On 23 September 2014 14:20, Rory Walsh |
Date | 2014-09-23 13:50 |
From | Steven Yi |
Subject | Re: [Cs-dev] Ugen API Proposal |
Runtime should have a very minimal penalty really, one extra function call (call to wrapper calls to OENTRY perf function). Opcode instances would still have memory for arguments hooked up to each other by pointers. I'm sure if we go this route there'd be more that would have to be done, but I don't think it would be that bad. The penalty really comes at init time, and this would happen in a couple ways. Csound reuses instrument instances, which may be a little hard to do with DAG's just in how they would be constructed at runtime. Also, the job the compiler does now to verify the opcodes and variable types would have to be moved to happen at runtime vs. compile-time. I think it's comparable to the issues you get when working with an interpreted language vs compiled one. One good thing is that one wouldn't *need* to use the DAG system, we could always maintain the compiled instr model and have this as a separate possibility. On Tue, Sep 23, 2014 at 8:20 AM, Rory Walsh |
Date | 2014-09-23 13:57 |
From | Steven Yi |
Subject | Re: [Cs-dev] Ugen API Proposal |
Yes, I've pasted the code I used for the ICMC presentation. It uses Aura Ugens (Mult, Env) intermixed with Csound Opcodes. The code is written in Serpent[1][2], Roger Dannenberg's realtime programming language based on Python. Notice things like apply being used to apply the csound sum opcode to the dynamically generated list of oscil3's, or how the language is used in lieu of the Csound ORC language to define and assemble the graph of unit generators. (As a sidenote, the code has a functional-programming feel. I've found recently that there's a good correlation between the use of higher-order functions and unit generators, something I plan to talk about a bit at the Clojure/Conj conference this November.) [1] - http://www.cs.cmu.edu/~music/serpent/doc/serpent.htm [2] - http://repository.cmu.edu/compsci/510/?utm_source=repository.cmu.edu%2Fcompsci%2F510&utm_medium=PDF&utm_campaign=PDFCoverPages // CsoundOpcode Test -- example of using CsoundOpcodes within Aura // Steven Yi // Sept 2014 load "csoundopcode_rpc" load "csound_opcodes" def adsr(a, d, s, r, u) [a, 1, a + d, s, u, s, u + r, 0] tone3_bps = adsr(0.05, 0.1, 0.7, 0.5, 1.0) audio_play.set_gain(-10.0) running = true def csTest(amp, freq): if running rtsched.cause(random() * 3 + 4, nil, 'csTest', amp, freq) f = int(random() * 4) * freq if random() > 0.5 if random() > 0.5 tone = Mult(Moogladder(Vco2(amp * .75, Randomh(f, f + 400, 10), 0,0,0, 0.5), 2000, 0.9), Env(tone3_bps), t) tone.play() else f2 = f * 2 rf = random() * 5 + 5 r = Randomh(f, f + 400, rf) r2 = Randomh(f2, f2 + 400, rf) tone = Mult(Moogladder(Vco2(amp / 2, r, 0,0,0, 0.5), 2000, 0.9), Env(tone3_bps), t) tone2 = Mult(Moogladder(Vco2(amp / 2, r2 , 0,0,0, 0.5), 2000, 0.9), Env(tone3_bps), t) tone.play() tone2.play() else tone = Mult(Moogladder(Vco2(amp, f, 0, 0, 0, 0.5), Expon(2000, 1.00, 1000), 0.3), Env(tone3_bps), t) tone.play() waves_bps = [3.0, 0.5, 6.0, 0] def waves(amp, base_freq): if running rtsched.cause(random() * 10 + 10, nil, 'waves', amp, base_freq) f = (int(random() * 8) + 3) * base_freq oscs = [] numOscs = int(random() * 6) + 2 for i = 1 to numOscs tempF = f * i oscs.append(Oscil3_a(amp / i, Line(tempF, 6.0, tempF * 1.1))) sig = apply('Sum', oscs) a = Mult(sig, Env(waves_bps), t) a.play() def stop_example(): print "STOPPING..." running = false rtsched.cause(4.0, nil, 'csTest', 0.25, 300) rtsched.cause(4.5, nil, 'csTest', 0.25, 500) rtsched.cause(4.9, nil, 'csTest', 0.25, 800) rtsched.cause(2.0, nil, 'waves', 0.3, 100) rtsched.cause(120, nil, 'stop_example') On Tue, Sep 23, 2014 at 8:27 AM, Rory Walsh |
Date | 2014-09-23 14:01 |
From | Victor Lazzarini |
Subject | Re: [Cs-dev] Ugen API Proposal |
I like the idea, I think it might be very useful. I think we could proceed by adding this system to work alongside the usual compiled one. I like the schedule function idea, which could be used to produce 1 ksmps of audio at the end (that, optionally could be added to spout). So, in other words, csoundPerformKsmps() performs compiled instruments, as usual, and a separate function gets a DAG and runs it. The function could potentially return a pointer to the processed block of audio, and/or work with spout. ======================== Dr Victor Lazzarini Dean of Arts, Celtic Studies and Philosophy, Maynooth University, Maynooth, Co Kildare, Ireland Tel: 00 353 7086936 Fax: 00 353 1 7086952 On 23 Sep 2014, at 13:50, Steven Yi |
Date | 2014-09-23 14:13 |
From | Steven Yi |
Subject | Re: [Cs-dev] Ugen API Proposal |
I think we're going to run into a number of scenarios trying to use a different model of compilation/execution, such as the one you mentioned for pulling audio out or not, but that we should be able to manage a way to support multiple models okay. I do think that the compiled model should continue to be supported, and the DAG stuff to be a separate possibility. One interesting thing to note is that I've been contemplating different systems lately. The Music-N based ones tend to have a sort of mix of push and pull processing. CLM, SuperCollider, and Csound all have a concept of an out ugen that is essentially an impure function with side effects that is pushing audio to a bus or out channel. I think Aura uses a more fully pull-based model, and I'm using a pull-model in Pink. It'd be good to further analyze these systems, and I think supporting both in Csound would be a good thing. On Tue, Sep 23, 2014 at 9:01 AM, Victor Lazzarini |
Date | 2014-09-23 14:26 |
From | Michael Gogins |
Subject | Re: [Cs-dev] Ugen API Proposal |
Attachments | None None |
This all sounds good. I've played with DAG code and had some working models over the years. From this I learned: There is deep knowledge of DAG designs in academia and in embedded systems design. Later I will send some links. Csound's flat list design is simpler, more easily preforms dynamic allocation of new instrument instances, and might well be inherently a little more efficient. DAG designs are easier to parallelize and in general to make correct. Using DAG nodes to perform all input and output including sound file, audio, midi, and control channels could really simplify the internals. Best, On Sep 23, 2014 8:08 AM, "Steven Yi" <stevenyi@gmail.com> wrote: |