Csound Csound-dev Csound-tekno Search About

[Csnd] opcodes to write/read pfields

Date2019-12-08 14:02
FromEduardo Moguillansky
Subject[Csnd] opcodes to write/read pfields

Some time ago I wrote a set of opcodes pread/pwrite which can write/read to and from pfields of any active instance. This allows to create an instance and control/modulate its parameters from another instrument. They turned out to be very useful, much more straightforward than using globals, arrays, etc. These opcodes allow one-to-one and one-to-many communication. I would like to propose to include them (like this or modified) in the standard distribution.

instr generator
  pset p1, p2, p3, 0.5, 1000, 4000, 0.1
  kamp       = p4
  kfreq      = p5
  kcutoff    = p6
  kresonance = p7
  asaw vco2, kamp, kfreq
  aout moogladder2, asaw, kcutoff, kresonance
  aout *= linsegr(0, 0.05, 1, 0.05, 0)
  outs aout, aout  
endin

instr control
  iglissdur = p4

  inum = nstrnum("generator")
  inum1 = inum + 0.001
  inum2 = inum + 0.002

  ;                      amp
  schedule inum1, 0, p3, 0.2 
  schedule inum2, 0, p3, 0.2
  
  kfreq1 linseg ntof:i("4A"), iglissdur, ntof:i("3A")
  kfreq2 linseg ntof:i("4F"), iglissdur, ntof:i("3F")
  pwrite inum1, 5, kfreq1
  pwrite inum2, 5, kfreq2

endin

instr broadcast
  printf "filter start\n", 1
  inum = nstrnum("generator")
  kcutoff    linseg 4000, p3, 400
  kresonance linseg 0.1, p3*0.5, 0.9
  pwrite inum, 6, kcutoff, 7, kresonance
endin

schedule "control",   0, 8, 4
schedule "broadcast", 4, 4

Documentation lives here:

https://csound-plugins.github.io/csound-plugins/opcodes/pwrite.html

https://csound-plugins.github.io/csound-plugins/opcodes/pread.html

Source:

https://github.com/csound-plugins/csound-plugins


cheers,
Eduardo Moguillansky


Date2019-12-08 15:26
Fromjoachim heintz
SubjectRe: [Csnd] opcodes to write/read pfields
very cool.  i checked it (works well) and i am convinced it is a very 
nice extension of possible communication between instruments.  and 
moreover, it is really csoundish!

as this is a developer decision and mostly a developer discussion, i am 
only wondering whether it should not go to the user's list but to the 
developer's list?

	joachim



On 08/12/2019 15:02, Eduardo Moguillansky wrote:
> Some time ago I wrote a set of opcodes pread/pwrite which can write/read 
> to and from pfields of any active instance. This allows to create an 
> instance and control/modulate its parameters from another instrument. 
> They turned out to be very useful, much more straightforward than using 
> globals, arrays, etc. These opcodes allow one-to-one and one-to-many 
> communication. I would like to propose to include them (like this or 
> modified) in the standard distribution.
> 
> instr  generator
>    pset  p1,  p2,  p3,  0.5,  1000,  4000,  0.1
>    kamp        =  p4
>    kfreq       =  p5
>    kcutoff     =  p6
>    kresonance  =  p7
>    asaw  vco2,  kamp,  kfreq
>    aout  moogladder2,  asaw,  kcutoff,  kresonance
>    aout  *=  linsegr(0,  0.05,  1,  0.05,  0)
>    outs  aout,  aout   
> endin
> 
> instr  control
>    iglissdur  =  p4
> 
>    inum  =  nstrnum("generator")
>    inum1  =  inum  +  0.001
>    inum2  =  inum  +  0.002
> 
>    ; amp
>    schedule  inum1,  0,  p3,  0.2  
>    schedule  inum2,  0,  p3,  0.2
>    kfreq1  linseg  ntof:i("4A"),  iglissdur,  ntof:i("3A")
>    kfreq2  linseg  ntof:i("4F"),  iglissdur,  ntof:i("3F")pwrite  inum1,  5,  kfreq1
>    pwrite  inum2,  5,  kfreq2
> endin
> 
> instr  broadcast
>    printf  "filter start\n",  1
>    inum  =  nstrnum("generator")
>    kcutoff     linseg  4000,  p3,  400
>    kresonance  linseg  0.1,  p3*0.5,  0.9
>    pwrite  inum,  6,  kcutoff,  7,  kresonance
> endin
> 
> schedule  "control",  0,  8,  4
> schedule  "broadcast",  4,  4
> 
> 
> Documentation lives here:
> 
> https://csound-plugins.github.io/csound-plugins/opcodes/pwrite.html
> 
> https://csound-plugins.github.io/csound-plugins/opcodes/pread.html
> 
> Source:
> 
> https://github.com/csound-plugins/csound-plugins
> 
> 
> cheers,
> Eduardo Moguillansky
> 
> Csound mailing list Csound@listserv.heanet.ie 
>  
> https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to 
> https://github.com/csound/csound/issues Discussions of bugs and features 
> can be posted here

Csound mailing list
Csound@listserv.heanet.ie
https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
Send bugs reports to
        https://github.com/csound/csound/issues
Discussions of bugs and features can be posted here

Date2019-12-08 15:31
FromSteven Yi
SubjectRe: [Csnd] opcodes to write/read pfields
Hi Eduardo,

First reaction was that I have some reservations. Some initial thoughts:

1. p-fields have been, up until now, init-time values
2. Changing the possible rate of p-type might have longer-term
implications, especially if/when pfields change to be of any data type
(in particular, user-defined types).
3. One can modify audio and control-rate values already per-instrument
and per-instance using channels. The UDOs at [1] show some ways to
make channel reading/writing easier. A video at [2] shows modifying
channels during a live coding performance. Per-instance code example
visible in the touchscreen examples from Android and iOS SDKs (see
[3]).
4. However with channels, one can not easily set values for an
instance via note event fields. One can make helper instruments for
writing channel values once or over time and which are schedulable.
That isn't quite the same thing though. One could take pfield values
and always write that once at init-time into a channel though, then
read from the channel at perf-time as an alternative.
5. Victor and I had some conversations years ago about
per-instrument/per-instance channels. I think this also came up
somewhat in idea of static variables per instrument. I can't recall
much of the details unfortunately. I think it might be useful though
to frame the issue in this way moving forward.
6. What happens in pwrite when there is a broadcast as well as
per-instance writing of pfield? Is it order-dependent what value the
instrument receives? Is a desired rule about what value an instrument
should receive if it written to per-instance?

I suppose some related-work would be:

1. SC3 and args
2. WebAudio and it's AudioParams (which can bet set directly, or
automated over time, or written to by other generators)
3. DAWs which offer per-note data modification

and this brings up from programming public/private data as well as
static class data (i.e., something like "static public double
frequency = 440" from Java).

To summarize these thoughts:

1. This is a good problem to solve.
2. I'm not sure reusing the existing pfields implementation is the best solution
3. On the other hand, I like the clarity of the code in the
pread/pwrite example. Something that approaches that would be great.
4. I think we need to account for other data types besides numbers as
well as make this type safe.
5. We should think about how to expose this in the API as well.

Steven

p.s. - I will rewrite the example code using channels and post in a moment.

[1] - https://github.com/kunstmusik/csound-live-code/blob/master/livecode.orc#L761-L810
[2] - https://youtu.be/q6GKT5irCBc
[3] - https://github.com/csound/csound/blob/develop/Android/CsoundForAndroid/CsoundAndroidExamples/src/main/res/raw/multitouch_xy.csd

On Sun, Dec 8, 2019 at 9:02 AM Eduardo Moguillansky
 wrote:
>
> Some time ago I wrote a set of opcodes pread/pwrite which can write/read to and from pfields of any active instance. This allows to create an instance and control/modulate its parameters from another instrument. They turned out to be very useful, much more straightforward than using globals, arrays, etc. These opcodes allow one-to-one and one-to-many communication. I would like to propose to include them (like this or modified) in the standard distribution.
>
> instr generator
>   pset p1, p2, p3, 0.5, 1000, 4000, 0.1
>   kamp       = p4
>   kfreq      = p5
>   kcutoff    = p6
>   kresonance = p7
>   asaw vco2, kamp, kfreq
>   aout moogladder2, asaw, kcutoff, kresonance
>   aout *= linsegr(0, 0.05, 1, 0.05, 0)
>   outs aout, aout
> endin
>
> instr control
>   iglissdur = p4
>
>   inum = nstrnum("generator")
>   inum1 = inum + 0.001
>   inum2 = inum + 0.002
>
>   ;                      amp
>   schedule inum1, 0, p3, 0.2
>   schedule inum2, 0, p3, 0.2
>
>   kfreq1 linseg ntof:i("4A"), iglissdur, ntof:i("3A")
>   kfreq2 linseg ntof:i("4F"), iglissdur, ntof:i("3F")
>   pwrite inum1, 5, kfreq1
>   pwrite inum2, 5, kfreq2
>
> endin
>
> instr broadcast
>   printf "filter start\n", 1
>   inum = nstrnum("generator")
>   kcutoff    linseg 4000, p3, 400
>   kresonance linseg 0.1, p3*0.5, 0.9
>   pwrite inum, 6, kcutoff, 7, kresonance
> endin
>
> schedule "control",   0, 8, 4
> schedule "broadcast", 4, 4
>
>
> Documentation lives here:
>
> https://csound-plugins.github.io/csound-plugins/opcodes/pwrite.html
>
> https://csound-plugins.github.io/csound-plugins/opcodes/pread.html
>
> Source:
>
> https://github.com/csound-plugins/csound-plugins
>
>
> cheers,
> Eduardo Moguillansky
>
> Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here

Csound mailing list
Csound@listserv.heanet.ie
https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
Send bugs reports to
        https://github.com/csound/csound/issues
Discussions of bugs and features can be posted here

Date2019-12-08 16:13
FromSteven Yi
SubjectRe: [Csnd] opcodes to write/read pfields
And here's an equivalent example rewritten using channels. Code has
some UDO's, but code using the UDOs has roughly the same number of
lines as the original. A little more verbose, but I see it as +/- as
one can target instrument params by name rather than pfield index.


/* assemble fractional instrument number for named instrument and
instance number */
opcode ni, i, Si
  Sname, iinst xin
  xout nstrnum(Sname) + (iinst / 1000)
endop

/* Assemble channel name from instr name and param name */
opcode chan_name, S, SS
  Sinstr, Schan xin
  SchanName = sprintf("%s.%s", Sinstr, Schan)
  xout SchanName
endop

/* Assemble channel name from instr name, instance number, and param name */
opcode chan_name, S, SiS
  Sinstr, iinst, Schan xin
  SchanName = sprintf("%s.%d.%s", Sinstr, iinst, Schan)
  xout SchanName
endop

/* Read channel for instr and param name, initializing with default value */
opcode read_chan, k,SSi
  Sinstr, Schan, initVal xin
  SchanName = chan_name(Sinstr, Schan)
  chnset(initVal, SchanName)
  xout chnget:k(SchanName)
endop

/* Read channel for instr name, instance number, and  param name,
initializing with default value */
opcode read_chan, k,SiSi
  Sinstr, ifrac, Schan, initVal xin
  SchanName = chan_name(Sinstr, ifrac, Schan)
  chnset(initVal, SchanName)
  xout chnget:k(SchanName)
endop

instr generator
  pset p1, p2, p3, 0.5, 1000, 4000, 0.1

  iinst = round(frac(p1) * 1000)
  print iinst

  kamp       = read_chan("generator", "amp", p4)
  kfreq      = read_chan("generator", iinst, "freq", p5)
  kcutoff    = read_chan("generator", "cut", p6)
  kresonance = read_chan("generator", "res", p7)
  asaw vco2, kamp, kfreq
  aout moogladder2, asaw, kcutoff, kresonance
  aout *= linsegr(0, 0.05, 1, 0.05, 0)
  outs aout, aout
endin

instr control
  iglissdur = p4

  inum1 = ni("generator", 1)
  inum2 = ni("generator", 2)

  print inum1
  print inum2

  schedule(inum1, 0, p3, 0.2)
  schedule(inum2, 0, p3, 0.2)

  kfreq1 = linseg:k(cpsmidinn(69), iglissdur, cpsmidinn(57))
  kfreq2 = linseg:k(cpsmidinn(66), iglissdur, cpsmidinn(54))
  chnset(kfreq1, chan_name("generator", 1, "freq"))
  chnset(kfreq1, chan_name("generator", 2, "freq"))
endin

instr broadcast
  printf "filter start\n", 1
  inum = nstrnum("generator")
  kcutoff    linseg 4000, p3, 400
  kresonance linseg 0.1, p3*0.5, 0.9
  chnset(kcutoff, chan_name("generator", "cut"))
  chnset(kresonance, chan_name("generator", "res"))
endin

schedule "control",   0, 8, 4
schedule "broadcast", 4, 4

On Sun, Dec 8, 2019 at 10:31 AM Steven Yi  wrote:
>
> Hi Eduardo,
>
> First reaction was that I have some reservations. Some initial thoughts:
>
> 1. p-fields have been, up until now, init-time values
> 2. Changing the possible rate of p-type might have longer-term
> implications, especially if/when pfields change to be of any data type
> (in particular, user-defined types).
> 3. One can modify audio and control-rate values already per-instrument
> and per-instance using channels. The UDOs at [1] show some ways to
> make channel reading/writing easier. A video at [2] shows modifying
> channels during a live coding performance. Per-instance code example
> visible in the touchscreen examples from Android and iOS SDKs (see
> [3]).
> 4. However with channels, one can not easily set values for an
> instance via note event fields. One can make helper instruments for
> writing channel values once or over time and which are schedulable.
> That isn't quite the same thing though. One could take pfield values
> and always write that once at init-time into a channel though, then
> read from the channel at perf-time as an alternative.
> 5. Victor and I had some conversations years ago about
> per-instrument/per-instance channels. I think this also came up
> somewhat in idea of static variables per instrument. I can't recall
> much of the details unfortunately. I think it might be useful though
> to frame the issue in this way moving forward.
> 6. What happens in pwrite when there is a broadcast as well as
> per-instance writing of pfield? Is it order-dependent what value the
> instrument receives? Is a desired rule about what value an instrument
> should receive if it written to per-instance?
>
> I suppose some related-work would be:
>
> 1. SC3 and args
> 2. WebAudio and it's AudioParams (which can bet set directly, or
> automated over time, or written to by other generators)
> 3. DAWs which offer per-note data modification
>
> and this brings up from programming public/private data as well as
> static class data (i.e., something like "static public double
> frequency = 440" from Java).
>
> To summarize these thoughts:
>
> 1. This is a good problem to solve.
> 2. I'm not sure reusing the existing pfields implementation is the best solution
> 3. On the other hand, I like the clarity of the code in the
> pread/pwrite example. Something that approaches that would be great.
> 4. I think we need to account for other data types besides numbers as
> well as make this type safe.
> 5. We should think about how to expose this in the API as well.
>
> Steven
>
> p.s. - I will rewrite the example code using channels and post in a moment.
>
> [1] - https://github.com/kunstmusik/csound-live-code/blob/master/livecode.orc#L761-L810
> [2] - https://youtu.be/q6GKT5irCBc
> [3] - https://github.com/csound/csound/blob/develop/Android/CsoundForAndroid/CsoundAndroidExamples/src/main/res/raw/multitouch_xy.csd
>
> On Sun, Dec 8, 2019 at 9:02 AM Eduardo Moguillansky
>  wrote:
> >
> > Some time ago I wrote a set of opcodes pread/pwrite which can write/read to and from pfields of any active instance. This allows to create an instance and control/modulate its parameters from another instrument. They turned out to be very useful, much more straightforward than using globals, arrays, etc. These opcodes allow one-to-one and one-to-many communication. I would like to propose to include them (like this or modified) in the standard distribution.
> >
> > instr generator
> >   pset p1, p2, p3, 0.5, 1000, 4000, 0.1
> >   kamp       = p4
> >   kfreq      = p5
> >   kcutoff    = p6
> >   kresonance = p7
> >   asaw vco2, kamp, kfreq
> >   aout moogladder2, asaw, kcutoff, kresonance
> >   aout *= linsegr(0, 0.05, 1, 0.05, 0)
> >   outs aout, aout
> > endin
> >
> > instr control
> >   iglissdur = p4
> >
> >   inum = nstrnum("generator")
> >   inum1 = inum + 0.001
> >   inum2 = inum + 0.002
> >
> >   ;                      amp
> >   schedule inum1, 0, p3, 0.2
> >   schedule inum2, 0, p3, 0.2
> >
> >   kfreq1 linseg ntof:i("4A"), iglissdur, ntof:i("3A")
> >   kfreq2 linseg ntof:i("4F"), iglissdur, ntof:i("3F")
> >   pwrite inum1, 5, kfreq1
> >   pwrite inum2, 5, kfreq2
> >
> > endin
> >
> > instr broadcast
> >   printf "filter start\n", 1
> >   inum = nstrnum("generator")
> >   kcutoff    linseg 4000, p3, 400
> >   kresonance linseg 0.1, p3*0.5, 0.9
> >   pwrite inum, 6, kcutoff, 7, kresonance
> > endin
> >
> > schedule "control",   0, 8, 4
> > schedule "broadcast", 4, 4
> >
> >
> > Documentation lives here:
> >
> > https://csound-plugins.github.io/csound-plugins/opcodes/pwrite.html
> >
> > https://csound-plugins.github.io/csound-plugins/opcodes/pread.html
> >
> > Source:
> >
> > https://github.com/csound-plugins/csound-plugins
> >
> >
> > cheers,
> > Eduardo Moguillansky
> >
> > Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here

Csound mailing list
Csound@listserv.heanet.ie
https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
Send bugs reports to
        https://github.com/csound/csound/issues
Discussions of bugs and features can be posted here

Date2019-12-08 17:19
FromEduardo Moguillansky
SubjectRe: [Csnd] opcodes to write/read pfields
I like this approach. We just need to write opcodes that do this 
built-in (and without polluting the channel hash-table with short-lived 
entries which will make every channel opcode slower).


On 08.12.19 17:13, Steven Yi wrote:
> And here's an equivalent example rewritten using channels. Code has
> some UDO's, but code using the UDOs has roughly the same number of
> lines as the original. A little more verbose, but I see it as +/- as
> one can target instrument params by name rather than pfield index.
>
>
> /* assemble fractional instrument number for named instrument and
> instance number */
> opcode ni, i, Si
>    Sname, iinst xin
>    xout nstrnum(Sname) + (iinst / 1000)
> endop
>
> /* Assemble channel name from instr name and param name */
> opcode chan_name, S, SS
>    Sinstr, Schan xin
>    SchanName = sprintf("%s.%s", Sinstr, Schan)
>    xout SchanName
> endop
>
> /* Assemble channel name from instr name, instance number, and param name */
> opcode chan_name, S, SiS
>    Sinstr, iinst, Schan xin
>    SchanName = sprintf("%s.%d.%s", Sinstr, iinst, Schan)
>    xout SchanName
> endop
>
> /* Read channel for instr and param name, initializing with default value */
> opcode read_chan, k,SSi
>    Sinstr, Schan, initVal xin
>    SchanName = chan_name(Sinstr, Schan)
>    chnset(initVal, SchanName)
>    xout chnget:k(SchanName)
> endop
>
> /* Read channel for instr name, instance number, and  param name,
> initializing with default value */
> opcode read_chan, k,SiSi
>    Sinstr, ifrac, Schan, initVal xin
>    SchanName = chan_name(Sinstr, ifrac, Schan)
>    chnset(initVal, SchanName)
>    xout chnget:k(SchanName)
> endop
>
> instr generator
>    pset p1, p2, p3, 0.5, 1000, 4000, 0.1
>
>    iinst = round(frac(p1) * 1000)
>    print iinst
>
>    kamp       = read_chan("generator", "amp", p4)
>    kfreq      = read_chan("generator", iinst, "freq", p5)
>    kcutoff    = read_chan("generator", "cut", p6)
>    kresonance = read_chan("generator", "res", p7)
>    asaw vco2, kamp, kfreq
>    aout moogladder2, asaw, kcutoff, kresonance
>    aout *= linsegr(0, 0.05, 1, 0.05, 0)
>    outs aout, aout
> endin
>
> instr control
>    iglissdur = p4
>
>    inum1 = ni("generator", 1)
>    inum2 = ni("generator", 2)
>
>    print inum1
>    print inum2
>
>    schedule(inum1, 0, p3, 0.2)
>    schedule(inum2, 0, p3, 0.2)
>
>    kfreq1 = linseg:k(cpsmidinn(69), iglissdur, cpsmidinn(57))
>    kfreq2 = linseg:k(cpsmidinn(66), iglissdur, cpsmidinn(54))
>    chnset(kfreq1, chan_name("generator", 1, "freq"))
>    chnset(kfreq1, chan_name("generator", 2, "freq"))
> endin
>
> instr broadcast
>    printf "filter start\n", 1
>    inum = nstrnum("generator")
>    kcutoff    linseg 4000, p3, 400
>    kresonance linseg 0.1, p3*0.5, 0.9
>    chnset(kcutoff, chan_name("generator", "cut"))
>    chnset(kresonance, chan_name("generator", "res"))
> endin
>
> schedule "control",   0, 8, 4
> schedule "broadcast", 4, 4
>
> On Sun, Dec 8, 2019 at 10:31 AM Steven Yi  wrote:
>> Hi Eduardo,
>>
>> First reaction was that I have some reservations. Some initial thoughts:
>>
>> 1. p-fields have been, up until now, init-time values
>> 2. Changing the possible rate of p-type might have longer-term
>> implications, especially if/when pfields change to be of any data type
>> (in particular, user-defined types).
>> 3. One can modify audio and control-rate values already per-instrument
>> and per-instance using channels. The UDOs at [1] show some ways to
>> make channel reading/writing easier. A video at [2] shows modifying
>> channels during a live coding performance. Per-instance code example
>> visible in the touchscreen examples from Android and iOS SDKs (see
>> [3]).
>> 4. However with channels, one can not easily set values for an
>> instance via note event fields. One can make helper instruments for
>> writing channel values once or over time and which are schedulable.
>> That isn't quite the same thing though. One could take pfield values
>> and always write that once at init-time into a channel though, then
>> read from the channel at perf-time as an alternative.
>> 5. Victor and I had some conversations years ago about
>> per-instrument/per-instance channels. I think this also came up
>> somewhat in idea of static variables per instrument. I can't recall
>> much of the details unfortunately. I think it might be useful though
>> to frame the issue in this way moving forward.
>> 6. What happens in pwrite when there is a broadcast as well as
>> per-instance writing of pfield? Is it order-dependent what value the
>> instrument receives? Is a desired rule about what value an instrument
>> should receive if it written to per-instance?
>>
>> I suppose some related-work would be:
>>
>> 1. SC3 and args
>> 2. WebAudio and it's AudioParams (which can bet set directly, or
>> automated over time, or written to by other generators)
>> 3. DAWs which offer per-note data modification
>>
>> and this brings up from programming public/private data as well as
>> static class data (i.e., something like "static public double
>> frequency = 440" from Java).
>>
>> To summarize these thoughts:
>>
>> 1. This is a good problem to solve.
>> 2. I'm not sure reusing the existing pfields implementation is the best solution
>> 3. On the other hand, I like the clarity of the code in the
>> pread/pwrite example. Something that approaches that would be great.
>> 4. I think we need to account for other data types besides numbers as
>> well as make this type safe.
>> 5. We should think about how to expose this in the API as well.
>>
>> Steven
>>
>> p.s. - I will rewrite the example code using channels and post in a moment.
>>
>> [1] - https://github.com/kunstmusik/csound-live-code/blob/master/livecode.orc#L761-L810
>> [2] - https://youtu.be/q6GKT5irCBc
>> [3] - https://github.com/csound/csound/blob/develop/Android/CsoundForAndroid/CsoundAndroidExamples/src/main/res/raw/multitouch_xy.csd
>>
>> On Sun, Dec 8, 2019 at 9:02 AM Eduardo Moguillansky
>>  wrote:
>>> Some time ago I wrote a set of opcodes pread/pwrite which can write/read to and from pfields of any active instance. This allows to create an instance and control/modulate its parameters from another instrument. They turned out to be very useful, much more straightforward than using globals, arrays, etc. These opcodes allow one-to-one and one-to-many communication. I would like to propose to include them (like this or modified) in the standard distribution.
>>>
>>> instr generator
>>>    pset p1, p2, p3, 0.5, 1000, 4000, 0.1
>>>    kamp       = p4
>>>    kfreq      = p5
>>>    kcutoff    = p6
>>>    kresonance = p7
>>>    asaw vco2, kamp, kfreq
>>>    aout moogladder2, asaw, kcutoff, kresonance
>>>    aout *= linsegr(0, 0.05, 1, 0.05, 0)
>>>    outs aout, aout
>>> endin
>>>
>>> instr control
>>>    iglissdur = p4
>>>
>>>    inum = nstrnum("generator")
>>>    inum1 = inum + 0.001
>>>    inum2 = inum + 0.002
>>>
>>>    ;                      amp
>>>    schedule inum1, 0, p3, 0.2
>>>    schedule inum2, 0, p3, 0.2
>>>
>>>    kfreq1 linseg ntof:i("4A"), iglissdur, ntof:i("3A")
>>>    kfreq2 linseg ntof:i("4F"), iglissdur, ntof:i("3F")
>>>    pwrite inum1, 5, kfreq1
>>>    pwrite inum2, 5, kfreq2
>>>
>>> endin
>>>
>>> instr broadcast
>>>    printf "filter start\n", 1
>>>    inum = nstrnum("generator")
>>>    kcutoff    linseg 4000, p3, 400
>>>    kresonance linseg 0.1, p3*0.5, 0.9
>>>    pwrite inum, 6, kcutoff, 7, kresonance
>>> endin
>>>
>>> schedule "control",   0, 8, 4
>>> schedule "broadcast", 4, 4
>>>
>>>
>>> Documentation lives here:
>>>
>>> https://csound-plugins.github.io/csound-plugins/opcodes/pwrite.html
>>>
>>> https://csound-plugins.github.io/csound-plugins/opcodes/pread.html
>>>
>>> Source:
>>>
>>> https://github.com/csound-plugins/csound-plugins
>>>
>>>
>>> cheers,
>>> Eduardo Moguillansky
>>>
>>> Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here
> Csound mailing list
> Csound@listserv.heanet.ie
> https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
> Send bugs reports to
>          https://github.com/csound/csound/issues
> Discussions of bugs and features can be posted here

Csound mailing list
Csound@listserv.heanet.ie
https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
Send bugs reports to
        https://github.com/csound/csound/issues
Discussions of bugs and features can be posted here

Date2019-12-08 18:05
FromMichael Gogins
SubjectRe: [Csnd] opcodes to write/read pfields
I think this is a very good idea. 

Regards, 
Mike

On Sun, Dec 8, 2019, 09:02 Eduardo Moguillansky <eduardo.moguillansky@gmail.com> wrote:

Some time ago I wrote a set of opcodes pread/pwrite which can write/read to and from pfields of any active instance. This allows to create an instance and control/modulate its parameters from another instrument. They turned out to be very useful, much more straightforward than using globals, arrays, etc. These opcodes allow one-to-one and one-to-many communication. I would like to propose to include them (like this or modified) in the standard distribution.

instr generator
  pset p1, p2, p3, 0.5, 1000, 4000, 0.1
  kamp       = p4
  kfreq      = p5
  kcutoff    = p6
  kresonance = p7
  asaw vco2, kamp, kfreq
  aout moogladder2, asaw, kcutoff, kresonance
  aout *= linsegr(0, 0.05, 1, 0.05, 0)
  outs aout, aout  
endin

instr control
  iglissdur = p4

  inum = nstrnum("generator")
  inum1 = inum + 0.001
  inum2 = inum + 0.002

  ;                      amp
  schedule inum1, 0, p3, 0.2 
  schedule inum2, 0, p3, 0.2
  
  kfreq1 linseg ntof:i("4A"), iglissdur, ntof:i("3A")
  kfreq2 linseg ntof:i("4F"), iglissdur, ntof:i("3F")
  pwrite inum1, 5, kfreq1
  pwrite inum2, 5, kfreq2

endin

instr broadcast
  printf "filter start\n", 1
  inum = nstrnum("generator")
  kcutoff    linseg 4000, p3, 400
  kresonance linseg 0.1, p3*0.5, 0.9
  pwrite inum, 6, kcutoff, 7, kresonance
endin

schedule "control",   0, 8, 4
schedule "broadcast", 4, 4

Documentation lives here:

https://csound-plugins.github.io/csound-plugins/opcodes/pwrite.html

https://csound-plugins.github.io/csound-plugins/opcodes/pread.html

Source:

https://github.com/csound-plugins/csound-plugins


cheers,
Eduardo Moguillansky

Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here

Date2019-12-08 23:16
FromVictor Lazzarini
SubjectRe: [Csnd] opcodes to write/read pfields
I agree we should move with caution. The trouble with introducing these things is that we can't go back.

Also agree that instrument interfaces is an interesting topic to discuss.

The channel-based approach Steven mentioned works well and has been used in
several examples. Maybe we need to make it more seamless and fully builtin.

Prof. Victor Lazzarini
Maynooth University
Ireland

> On 8 Dec 2019, at 15:32, Steven Yi  wrote:
> 
> Hi Eduardo,
> 
> First reaction was that I have some reservations. Some initial thoughts:
> 
> 1. p-fields have been, up until now, init-time values
> 2. Changing the possible rate of p-type might have longer-term
> implications, especially if/when pfields change to be of any data type
> (in particular, user-defined types).
> 3. One can modify audio and control-rate values already per-instrument
> and per-instance using channels. The UDOs at [1] show some ways to
> make channel reading/writing easier. A video at [2] shows modifying
> channels during a live coding performance. Per-instance code example
> visible in the touchscreen examples from Android and iOS SDKs (see
> [3]).
> 4. However with channels, one can not easily set values for an
> instance via note event fields. One can make helper instruments for
> writing channel values once or over time and which are schedulable.
> That isn't quite the same thing though. One could take pfield values
> and always write that once at init-time into a channel though, then
> read from the channel at perf-time as an alternative.
> 5. Victor and I had some conversations years ago about
> per-instrument/per-instance channels. I think this also came up
> somewhat in idea of static variables per instrument. I can't recall
> much of the details unfortunately. I think it might be useful though
> to frame the issue in this way moving forward.
> 6. What happens in pwrite when there is a broadcast as well as
> per-instance writing of pfield? Is it order-dependent what value the
> instrument receives? Is a desired rule about what value an instrument
> should receive if it written to per-instance?
> 
> I suppose some related-work would be:
> 
> 1. SC3 and args
> 2. WebAudio and it's AudioParams (which can bet set directly, or
> automated over time, or written to by other generators)
> 3. DAWs which offer per-note data modification
> 
> and this brings up from programming public/private data as well as
> static class data (i.e., something like "static public double
> frequency = 440" from Java).
> 
> To summarize these thoughts:
> 
> 1. This is a good problem to solve.
> 2. I'm not sure reusing the existing pfields implementation is the best solution
> 3. On the other hand, I like the clarity of the code in the
> pread/pwrite example. Something that approaches that would be great.
> 4. I think we need to account for other data types besides numbers as
> well as make this type safe.
> 5. We should think about how to expose this in the API as well.
> 
> Steven
> 
> p.s. - I will rewrite the example code using channels and post in a moment.
> 
> [1] - https://github.com/kunstmusik/csound-live-code/blob/master/livecode.orc#L761-L810
> [2] - https://youtu.be/q6GKT5irCBc
> [3] - https://github.com/csound/csound/blob/develop/Android/CsoundForAndroid/CsoundAndroidExamples/src/main/res/raw/multitouch_xy.csd
> 
> On Sun, Dec 8, 2019 at 9:02 AM Eduardo Moguillansky
>  wrote:
>> 
>> Some time ago I wrote a set of opcodes pread/pwrite which can write/read to and from pfields of any active instance. This allows to create an instance and control/modulate its parameters from another instrument. They turned out to be very useful, much more straightforward than using globals, arrays, etc. These opcodes allow one-to-one and one-to-many communication. I would like to propose to include them (like this or modified) in the standard distribution.
>> 
>> instr generator
>>  pset p1, p2, p3, 0.5, 1000, 4000, 0.1
>>  kamp       = p4
>>  kfreq      = p5
>>  kcutoff    = p6
>>  kresonance = p7
>>  asaw vco2, kamp, kfreq
>>  aout moogladder2, asaw, kcutoff, kresonance
>>  aout *= linsegr(0, 0.05, 1, 0.05, 0)
>>  outs aout, aout
>> endin
>> 
>> instr control
>>  iglissdur = p4
>> 
>>  inum = nstrnum("generator")
>>  inum1 = inum + 0.001
>>  inum2 = inum + 0.002
>> 
>>  ;                      amp
>>  schedule inum1, 0, p3, 0.2
>>  schedule inum2, 0, p3, 0.2
>> 
>>  kfreq1 linseg ntof:i("4A"), iglissdur, ntof:i("3A")
>>  kfreq2 linseg ntof:i("4F"), iglissdur, ntof:i("3F")
>>  pwrite inum1, 5, kfreq1
>>  pwrite inum2, 5, kfreq2
>> 
>> endin
>> 
>> instr broadcast
>>  printf "filter start\n", 1
>>  inum = nstrnum("generator")
>>  kcutoff    linseg 4000, p3, 400
>>  kresonance linseg 0.1, p3*0.5, 0.9
>>  pwrite inum, 6, kcutoff, 7, kresonance
>> endin
>> 
>> schedule "control",   0, 8, 4
>> schedule "broadcast", 4, 4
>> 
>> 
>> Documentation lives here:
>> 
>> https://csound-plugins.github.io/csound-plugins/opcodes/pwrite.html
>> 
>> https://csound-plugins.github.io/csound-plugins/opcodes/pread.html
>> 
>> Source:
>> 
>> https://github.com/csound-plugins/csound-plugins
>> 
>> 
>> cheers,
>> Eduardo Moguillansky
>> 
>> Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here
> 
> Csound mailing list
> Csound@listserv.heanet.ie
> https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
> Send bugs reports to
>        https://github.com/csound/csound/issues
> Discussions of bugs and features can be posted here

Csound mailing list
Csound@listserv.heanet.ie
https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
Send bugs reports to
        https://github.com/csound/csound/issues
Discussions of bugs and features can be posted here

Date2019-12-08 23:57
FromEduardo Moguillansky
SubjectRe: [Csnd] opcodes to write/read pfields
On 09.12.19 00:16, Victor Lazzarini wrote:
> I agree we should move with caution. The trouble with introducing these things is that we can't go back.
>
> Also agree that instrument interfaces is an interesting topic to discuss.
>
> The channel-based approach Steven mentioned works well and has been used in
> several examples. Maybe we need to make it more seamless and fully builtin.

I would love to see a builtin solution for this. The other problem with 
the channel-based approach is the pollution of the global hash-table 
with entries which are by definition short-lived and would with time add 
up and make every channel operation slower. There could be a sepparate 
hash-table only for this communication layer, with the functionality to 
dispose entries when the instance becomes inactive. One feature which 
the original proposition had, which makes the code very clear, is that 
the same procedure used to read initial parameters is used to read 
dynamic parameters. Supercollider follows this same principle and makes 
for very terse code. Using channels, the instrument creating the 
instance should set-up the channels with initial values before creating 
the new instance, or should rely on the new instrument setting the 
initial value of the channel to the preset, etc. A lot of convention for 
a process which aims to be the default way of communicating between 
instruments.


>
> Prof. Victor Lazzarini
> Maynooth University
> Ireland
>
>> On 8 Dec 2019, at 15:32, Steven Yi  wrote:
>>
>> Hi Eduardo,
>>
>> First reaction was that I have some reservations. Some initial thoughts:
>>
>> 1. p-fields have been, up until now, init-time values
>> 2. Changing the possible rate of p-type might have longer-term
>> implications, especially if/when pfields change to be of any data type
>> (in particular, user-defined types).
>> 3. One can modify audio and control-rate values already per-instrument
>> and per-instance using channels. The UDOs at [1] show some ways to
>> make channel reading/writing easier. A video at [2] shows modifying
>> channels during a live coding performance. Per-instance code example
>> visible in the touchscreen examples from Android and iOS SDKs (see
>> [3]).
>> 4. However with channels, one can not easily set values for an
>> instance via note event fields. One can make helper instruments for
>> writing channel values once or over time and which are schedulable.
>> That isn't quite the same thing though. One could take pfield values
>> and always write that once at init-time into a channel though, then
>> read from the channel at perf-time as an alternative.
>> 5. Victor and I had some conversations years ago about
>> per-instrument/per-instance channels. I think this also came up
>> somewhat in idea of static variables per instrument. I can't recall
>> much of the details unfortunately. I think it might be useful though
>> to frame the issue in this way moving forward.
>> 6. What happens in pwrite when there is a broadcast as well as
>> per-instance writing of pfield? Is it order-dependent what value the
>> instrument receives? Is a desired rule about what value an instrument
>> should receive if it written to per-instance?
>>
>> I suppose some related-work would be:
>>
>> 1. SC3 and args
>> 2. WebAudio and it's AudioParams (which can bet set directly, or
>> automated over time, or written to by other generators)
>> 3. DAWs which offer per-note data modification
>>
>> and this brings up from programming public/private data as well as
>> static class data (i.e., something like "static public double
>> frequency = 440" from Java).
>>
>> To summarize these thoughts:
>>
>> 1. This is a good problem to solve.
>> 2. I'm not sure reusing the existing pfields implementation is the best solution
>> 3. On the other hand, I like the clarity of the code in the
>> pread/pwrite example. Something that approaches that would be great.
>> 4. I think we need to account for other data types besides numbers as
>> well as make this type safe.
>> 5. We should think about how to expose this in the API as well.
>>
>> Steven
>>
>> p.s. - I will rewrite the example code using channels and post in a moment.
>>
>> [1] - https://github.com/kunstmusik/csound-live-code/blob/master/livecode.orc#L761-L810
>> [2] - https://youtu.be/q6GKT5irCBc
>> [3] - https://github.com/csound/csound/blob/develop/Android/CsoundForAndroid/CsoundAndroidExamples/src/main/res/raw/multitouch_xy.csd
>>
>> On Sun, Dec 8, 2019 at 9:02 AM Eduardo Moguillansky
>>  wrote:
>>> Some time ago I wrote a set of opcodes pread/pwrite which can write/read to and from pfields of any active instance. This allows to create an instance and control/modulate its parameters from another instrument. They turned out to be very useful, much more straightforward than using globals, arrays, etc. These opcodes allow one-to-one and one-to-many communication. I would like to propose to include them (like this or modified) in the standard distribution.
>>>
>>> instr generator
>>>   pset p1, p2, p3, 0.5, 1000, 4000, 0.1
>>>   kamp       = p4
>>>   kfreq      = p5
>>>   kcutoff    = p6
>>>   kresonance = p7
>>>   asaw vco2, kamp, kfreq
>>>   aout moogladder2, asaw, kcutoff, kresonance
>>>   aout *= linsegr(0, 0.05, 1, 0.05, 0)
>>>   outs aout, aout
>>> endin
>>>
>>> instr control
>>>   iglissdur = p4
>>>
>>>   inum = nstrnum("generator")
>>>   inum1 = inum + 0.001
>>>   inum2 = inum + 0.002
>>>
>>>   ;                      amp
>>>   schedule inum1, 0, p3, 0.2
>>>   schedule inum2, 0, p3, 0.2
>>>
>>>   kfreq1 linseg ntof:i("4A"), iglissdur, ntof:i("3A")
>>>   kfreq2 linseg ntof:i("4F"), iglissdur, ntof:i("3F")
>>>   pwrite inum1, 5, kfreq1
>>>   pwrite inum2, 5, kfreq2
>>>
>>> endin
>>>
>>> instr broadcast
>>>   printf "filter start\n", 1
>>>   inum = nstrnum("generator")
>>>   kcutoff    linseg 4000, p3, 400
>>>   kresonance linseg 0.1, p3*0.5, 0.9
>>>   pwrite inum, 6, kcutoff, 7, kresonance
>>> endin
>>>
>>> schedule "control",   0, 8, 4
>>> schedule "broadcast", 4, 4
>>>
>>>
>>> Documentation lives here:
>>>
>>> https://csound-plugins.github.io/csound-plugins/opcodes/pwrite.html
>>>
>>> https://csound-plugins.github.io/csound-plugins/opcodes/pread.html
>>>
>>> Source:
>>>
>>> https://github.com/csound-plugins/csound-plugins
>>>
>>>
>>> cheers,
>>> Eduardo Moguillansky
>>>
>>> Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here
>> Csound mailing list
>> Csound@listserv.heanet.ie
>> https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
>> Send bugs reports to
>>         https://github.com/csound/csound/issues
>> Discussions of bugs and features can be posted here
> Csound mailing list
> Csound@listserv.heanet.ie
> https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
> Send bugs reports to
>          https://github.com/csound/csound/issues
> Discussions of bugs and features can be posted here

Csound mailing list
Csound@listserv.heanet.ie
https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
Send bugs reports to
        https://github.com/csound/csound/issues
Discussions of bugs and features can be posted here