Csound Csound-dev Csound-tekno Search About

[Csnd] python language proxy

Date2008-01-17 22:07
FromEduardo Moguillansky
Subject[Csnd] python language proxy
Hi. I am new to this list and quite new to csound. 
For a project involving code generation in python using the api I have been
designing a language proxy in python, quite similar to what sclang is in
supercollider. I have already implemented many of the opcodes but was having
doubts about how to approach if/goto. So my questions are:
- how efficient are these constructs? 
- Supercollider does not have such constructs, uses always signals to
control flow. Is there a similar way in csound?

And one last question: is there any way to add instrs/opcodes on the fly? 

thanks!

The general approach is quite similar to the approach in supercollider, in
the sense that not every python expression is valid in an instrument or a
user defined opcode: only opcodes, mathematical expressions and other ad hoc
constructs.

Here is how an instrument looks, based on an example of the manual:

from cslang import *

orc = Orchestra(sr=44100, kr=4410, nchnls=1) 

@instr
def example_phaser1(amp, order, freq, feedback):
    amp *= 0.05
    harms = orc.sr * .4 / 100
    envelope = LinSeg.kr(0, 0.2, amp, self.dur - .2, amp, .2, 0)
    signal = GBuzz.ar(amp=1, cps=100, num_harmonics=harms,
lowest_harmonic=1, mul=0.95)
    kfreq = Oscili.kr(5500, freq) + 5600
    out = Phaser1.ar(source=signal, freq=kfreq, order=order,
feedback=feedback)
    Out((signal + out) * envelope)

The same, but with an alternative syntax based on pipes and partial
evaluation:

@instr
def example_phaser1_bis(amp, order, freq, feedback):
    amp *= 0.05
    harms = orc.sr * .4 / 100
    signal = GBuzz.ar(amp=1, cps=100, num_harmonics=harms,
lowest_harmonic=1, mul=0.95)
    envelope = LinSeg.kr(0, 0.2, amp, self.dur - .2, amp, .2, 0)
        
    (signal 
    | 
    Phaser1.ar(source=_, 
                 freq=Oscili.kr(5500, freq) + 5600, 
                 order=order, 
                 feedback=feedback) 
    | 
    (_ + signal ) * envelope 
    | 
    Out)

A still simpler instrument, played for 10 secs:

@instr
def simple(freq=440, amp=0.5):
    envelope = LinSeg.kr(0, dur * .2, amp, dur * .8, amp, dur, 0)

    (SinOsc.kr(20)
    | 
    SinOsc.ar(freq + _)
    | 
    (_ * envelope)
    | 
    Out)

sco = Score()
sco.play(Event(simple(freq=1000), t=now, dur=10))

A simple opcode (you do not need to say what the opcode returns, it is
inferred):

@opcode
def freq_upshift(ain, freq):
    """
    a variation of the freqShift UDO
    """
    real, imag = Hilbert.ar(ain)
    asin = SinOsc.ar(freq)
    acos = SinOsc.ar(freq, phase=0.25)
    mod1 = real * acos
    mod2 = imag * asin
    return (mod1 + mod2) * 0.7


-- 
View this message in context: http://www.nabble.com/python-language-proxy-tp14923098p14923098.html
Sent from the Csound - General mailing list archive at Nabble.com.


Date2008-01-18 10:53
FromCesare Marilungo
Subject[Csnd] Re: python language proxy
Interesting project!

-c.

Eduardo Moguillansky wrote:
> Hi. I am new to this list and quite new to csound. 
> For a project involving code generation in python using the api I have been
> designing a language proxy in python, quite similar to what sclang is in
> supercollider. I have already implemented many of the opcodes but was having
> doubts about how to approach if/goto. So my questions are:
> - how efficient are these constructs? 
> - Supercollider does not have such constructs, uses always signals to
> control flow. Is there a similar way in csound?
>
> And one last question: is there any way to add instrs/opcodes on the fly? 
>
> thanks!
>
> The general approach is quite similar to the approach in supercollider, in
> the sense that not every python expression is valid in an instrument or a
> user defined opcode: only opcodes, mathematical expressions and other ad hoc
> constructs.
>
> Here is how an instrument looks, based on an example of the manual:
>
> from cslang import *
>
> orc = Orchestra(sr=44100, kr=4410, nchnls=1) 
>
> @instr
> def example_phaser1(amp, order, freq, feedback):
>     amp *= 0.05
>     harms = orc.sr * .4 / 100
>     envelope = LinSeg.kr(0, 0.2, amp, self.dur - .2, amp, .2, 0)
>     signal = GBuzz.ar(amp=1, cps=100, num_harmonics=harms,
> lowest_harmonic=1, mul=0.95)
>     kfreq = Oscili.kr(5500, freq) + 5600
>     out = Phaser1.ar(source=signal, freq=kfreq, order=order,
> feedback=feedback)
>     Out((signal + out) * envelope)
>
> The same, but with an alternative syntax based on pipes and partial
> evaluation:
>
> @instr
> def example_phaser1_bis(amp, order, freq, feedback):
>     amp *= 0.05
>     harms = orc.sr * .4 / 100
>     signal = GBuzz.ar(amp=1, cps=100, num_harmonics=harms,
> lowest_harmonic=1, mul=0.95)
>     envelope = LinSeg.kr(0, 0.2, amp, self.dur - .2, amp, .2, 0)
>         
>     (signal 
>     | 
>     Phaser1.ar(source=_, 
>                  freq=Oscili.kr(5500, freq) + 5600, 
>                  order=order, 
>                  feedback=feedback) 
>     | 
>     (_ + signal ) * envelope 
>     | 
>     Out)
>
> A still simpler instrument, played for 10 secs:
>
> @instr
> def simple(freq=440, amp=0.5):
>     envelope = LinSeg.kr(0, dur * .2, amp, dur * .8, amp, dur, 0)
>
>     (SinOsc.kr(20)
>     | 
>     SinOsc.ar(freq + _)
>     | 
>     (_ * envelope)
>     | 
>     Out)
>
> sco = Score()
> sco.play(Event(simple(freq=1000), t=now, dur=10))
>
> A simple opcode (you do not need to say what the opcode returns, it is
> inferred):
>
> @opcode
> def freq_upshift(ain, freq):
>     """
>     a variation of the freqShift UDO
>     """
>     real, imag = Hilbert.ar(ain)
>     asin = SinOsc.ar(freq)
>     acos = SinOsc.ar(freq, phase=0.25)
>     mod1 = real * acos
>     mod2 = imag * asin
>     return (mod1 + mod2) * 0.7
>
>
>   


-- 
www.cesaremarilungo.com