Csound Csound-dev Csound-tekno Search About

Re: [Csnd-dev] UDO compilation seclects i- instead of k-rate

Date2018-08-18 18:00
From"Mauro G."
SubjectRe: [Csnd-dev] UDO compilation seclects i- instead of k-rate
Hi, I think I understood why there is the strange behaviour you noticed.
First of all, it is independent from the polymorphism, because the problem arises when you use just a single UDO too.

The problem is in the way Csound manages the UDOs execution that is different from that of native opcodes.
For example, let's take a native opcode with k-time output:

  kSomething NATIVE_OPCODE ...params...

the above code will run ONLY at k-time because that native opcode returns a k-value. This is the expected behaviour and it works correctly.
Now, let's take an UDO opcode witk k-time output:

  kSomething UDO ...params...

In this case, Csound will run the UDO at i-time too, because inside the UDO definition there could be i-values to initialize. Of course, the k-rate native instructions inside the UDO will be skipped... All except two: "xin" and "xout". These statements are executed at init-time, and this is written in the Csound reference docs (https://csound.com/docs/manual/xout.html):

  "[...]These opcodes actually run only at i-time. Performance time copying is done by the user opcode call.[...]"

In your example, the problem is not in the presence of two "RndInt" UDOs, but in the fact that Csound will run the i-time part of your UDO code at i-time, regardless of the type of its output variable types... And, in doing this, your RndInt UDO will not be completely skipped at init-time (as it would be if it was a native opcode with k-value output):

instr 2 (at init-time:)
  EXECUTED: kBla init 10
  *SKIPPED* printk2 kBla
  EXECUTED: kBla RndInt 1, 2  <--- it will be executed the i-time part and kBla will be overwritten by a 0 value
  *SKIPPED* turnoff
endin

instr 2 (at performance-time:)
  *SKIPPED* kBla init 10
  EXECUTED: printk2 kBla
  EXECUTED: kBla RndInt 1, 2  <--- it will be executed the k-time part
  EXECUTED: turnoff
endin

Of course, at init-time, the instruction "kRnd random kMin, kMax+.999999" inside the RndInt UDO will be skipped because "random" is a native opcode and works, as expected, only at k-time.

So, when RndInt returns from its init-pass, the kBla variable will be set to RndInt->kRnd, that is 0, because during init-time the central line with the 'random' statement ("kRnd random kMin, kMax+.999999") was skipped (being that "random" is a native opcode and works, as expected, only at k-time), therefore RndInt->kRnd wasn't valued yet and Csound considers it as 0...

The result is that, at performance-time, the printed value of kBla, for the second instrument, will be 0, not 10.

This also explains why, in the case of the functional syntax, it works as you expected:

instr 3
  kBla init 10
  printk2 kBla
  ;forcing to select the k-rate version of the
  ;UDO works again
  kBla = RndInt:k(1, 2)
  turnoff
endin

This works not because you forced the ':k' (in fact you could skip the ':k' and it should work anyway), but because the '=' is like a native opcode to Csound, so its behaviour is to skip its execution at init-time... And the result is that, in "instr 3", kBla will not be touched at init-time, as you expect.

Anyway, altough this explains why there is this strange behaviour, I think it's not the "right" behaviour and it should be corrected in some way, because it is very confusing for the user. 

All the problems arise from this:

 kBla RndInt 1, 2  <--- at init-time Csound will run the i-time part of the UDO

At init-time it's ok to execute the i-time part of RndInt, I understand... but why you have to return its (undefined at init-time) value too, bein

Date2018-08-18 18:38
FromMauro Giubileo
SubjectRe: [Csnd-dev] UDO compilation seclects i- instead of k-rate

I want to add, regarding whether or not this is a bug, that in the Csound reference docs for "init" opcode (https://csound.com/docs/manual/init.html) you can read:

Note that init provides the only case of an init-time statement being permitted to write into a perf-time (k- or a-rate) result cell; the statement has no effect at perf-time.

Actually, this is not true, because in the example of joachim, the k-rate UDO "RndInt" write a 0 in the k-rate kBla variable at init-time! So, or the above note is false, or we have a bug! :-)

Regards,
Mauro


Il 2018-08-18 19:00 Mauro G. ha scritto:

Hi, I think I understood why there is the strange behaviour you noticed.
First of all, it is independent from the polymorphism, because the problem arises when you use just a single UDO too.

The problem is in the way Csound manages the UDOs execution that is different from that of native opcodes.
For example, let's take a native opcode with k-time output:

  kSomething NATIVE_OPCODE ...params...

the above code will run ONLY at k-time because that native opcode returns a k-value. This is the expected behaviour and it works correctly.
Now, let's take an UDO opcode witk k-time output:

  kSomething UDO ...params...

In this case, Csound will run the UDO at i-time too, because inside the UDO definition there could be i-values to initialize. Of course, the k-rate native instructions inside the UDO will be skipped... All except two: "xin" and "xout". These statements are executed at init-time, and this is written in the Csound reference docs (https://csound.com/docs/manual/xout.html):

  "[...]These opcodes actually run only at i-time. Performance time copying is done by the user opcode call.[...]"

In your example, the problem is not in the presence of two "RndInt" UDOs, but in the fact that Csound will run the i-time part of your UDO code at i-time, regardless of the type of its output variable types... And, in doing this, your RndInt UDO will not be completely skipped at init-time (as it would be if it was a native opcode with k-value output):

instr 2 (at init-time:)
  EXECUTED: kBla init 10
  *SKIPPED* printk2 kBla
  EXECUTED: kBla RndInt 1, 2  <--- it will be executed the i-time part and kBla will be overwritten by a 0 value
  *SKIPPED* turnoff
endin

instr 2 (at performance-time:)
  *SKIPPED* kBla init 10
  EXECUTED: printk2 kBla
  EXECUTED: kBla RndInt 1, 2  <--- it will be executed the k-time part
  EXECUTED: turnoff
endin

Of course, at init-time, the instruction "kRnd random kMin, kMax+.999999" inside the RndInt UDO will be skipped because "random" is a native opcode and works, as expected, only at k-time.

So, when RndInt returns from its init-pass, the kBla variable will be set to RndInt->kRnd, that is 0, because during init-time the central line with the 'random' statement ("kRnd random kMin, kMax+.999999") was skipped (being that "random" is a native opcode and works, as expected, only at k-time), therefore RndInt->kRnd wasn't valued yet and Csound considers it as 0...

The result is that, at performance-time, the printed value of kBla, for the second instrument, will be 0, not 10.

This also explains why, in the case of the functional syntax, it works as you expected:

instr 3
  kBla init 10
  printk2 kBla
  ;forcing to select the k-rate version of the
  ;UDO works again
  kBla = RndInt:k(1, 2)
  turnoff
endin

This works not because you forced the ':k' (in fact you could skip the ':k' and it should work anyway), but because the '=' is like a native opcode to Csound, so its behaviour is to skip its execution at init-time... And the result is that, in "instr 3", kBla will not be touched at init-time, as you expect.

Anyway, altough this explains why there is this strange behaviour, I think it's not the "right" behaviour and it should be corrected in some way, because it is very confusing for the user.

All the problems arise from this:

 kBla RndInt 1, 2  <--- at init-time Csound will run the i-time part of the UDO

At init-time it's ok to execute the i-time part of RndInt, I understand... but why you have to return its (undefined at init-time) value too, being that the return value in this case is a k-type variable?

Date2018-08-18 20:25
Fromjoachim heintz
SubjectRe: [Csnd-dev] UDO compilation seclects i- instead of k-rate
thanks, mauro, for these illuminating explanations.

i am curious whether others think it should be changed, too.  i agree 
with you that it is confusing for users.

	joachim



On 18/08/18 19:00, Mauro G. wrote:
> Hi, I think I understood why there is the strange behaviour you noticed.
> First of all, it is independent from the polymorphism, because the problem arises when you use just a single UDO too.
>
> The problem is in the way Csound manages the UDOs execution that is different from that of native opcodes.
> For example, let's take a native opcode with k-time output:
>
>   kSomething NATIVE_OPCODE ...params...
>
> the above code will run ONLY at k-time because that native opcode returns a k-value. This is the expected behaviour and it works correctly.
> Now, let's take an UDO opcode witk k-time output:
>
>   kSomething UDO ...params...
>
> In this case, Csound will run the UDO at i-time too, because inside the UDO definition there could be i-values to initialize. Of course, the k-rate native instructions inside the UDO will be skipped... All except two: "xin" and "xout". These statements are executed at init-time, and this is written in the Csound reference docs (https://csound.com/docs/manual/xout.html):
>
>   "[...]These opcodes actually run only at i-time. Performance time copying is done by the user opcode call.[...]"
>
> In your example, the problem is not in the presence of two "RndInt" UDOs, but in the fact that Csound will run the i-time part of your UDO code at i-time, regardless of the type of its output variable types... And, in doing this, your RndInt UDO will not be completely skipped at init-time (as it would be if it was a native opcode with k-value output):
>
> instr 2 (at init-time:)
>   EXECUTED: kBla init 10
>   *SKIPPED* printk2 kBla
>   EXECUTED: kBla RndInt 1, 2  <--- it will be executed the i-time part and kBla will be overwritten by a 0 value
>   *SKIPPED* turnoff
> endin
>
> instr 2 (at performance-time:)
>   *SKIPPED* kBla init 10
>   EXECUTED: printk2 kBla
>   EXECUTED: kBla RndInt 1, 2  <--- it will be executed the k-time part
>   EXECUTED: turnoff
> endin
>
> Of course, at init-time, the instruction "kRnd random kMin, kMax+.999999" inside the RndInt UDO will be skipped because "random" is a native opcode and works, as expected, only at k-time.
>
> So, when RndInt returns from its init-pass, the kBla variable will be set to RndInt->kRnd, that is 0, because during init-time the central line with the 'random' statement ("kRnd random kMin, kMax+.999999") was skipped (being that "random" is a native opcode and works, as expected, only at k-time), therefore RndInt->kRnd wasn't valued yet and Csound considers it as 0...
>
> The result is that, at performance-time, the printed value of kBla, for the second instrument, will be 0, not 10.
>
> This also explains why, in the case of the functional syntax, it works as you expected:
>
> instr 3
>   kBla init 10
>   printk2 kBla
>   ;forcing to select the k-rate version of the
>   ;UDO works again
>   kBla = RndInt:k(1, 2)
>   turnoff
> endin
>
> This works not because you forced the ':k' (in fact you could skip the ':k' and it should work anyway), but because the '=' is like a native opcode to Csound, so its behaviour is to skip its execution at init-time... And the result is that, in "instr 3", kBla will not be touched at init-time, as you expect.
>
> Anyway, altough this explains why there is this strange behaviour, I think it's not the "right" behaviour and it should be corrected in some way, because it is very confusing for the user.
>
> All the problems arise from this:
>
>  kBla RndInt 1, 2  <--- at init-time Csound will run the i-time part of the UDO
>
> At init-time it's ok to execute the i-time part of RndInt, I understand... but why you have to return its (undefined at init-time) value too, being that the return value in this case is a k-type variable?

Date2018-08-18 21:35
FromMauro Giubileo
SubjectRe: [Csnd-dev] UDO compilation seclects i- instead of k-rate

I'm glad I could be of help. :-)

I'm learning Csound myself so I thank you for giving me the opportunity to deepen these aspects of the language. It is useful to know these little and misleading quirks that otherwise can cause you a lot of headaches. :-D

Regards,
Mauro


Il 2018-08-18 21:25 joachim heintz ha scritto:

thanks, mauro, for these illuminating explanations.

i am curious whether others think it should be changed, too.  i agree with you that it is confusing for users.

    joachim



On 18/08/18 19:00, Mauro G. wrote:
Hi, I think I understood why there is the strange behaviour you noticed.
First of all, it is independent from the polymorphism, because the problem arises when you use just a single UDO too.

The problem is in the way Csound manages the UDOs execution that is different from that of native opcodes.
For example, let's take a native opcode with k-time output:

  kSomething NATIVE_OPCODE ...params...

the above code will run ONLY at k-time because that native opcode returns a k-value. This is the expected behaviour and it works correctly.
Now, let's take an UDO opcode witk k-time output:

  kSomething UDO ...params...

In this case, Csound will run the UDO at i-time too, because inside the UDO definition there could be i-values to initialize. Of course, the k-rate native instructions inside the UDO will be skipped... All except two: "xin" and "xout". These statements are executed at init-time, and this is written in the Csound reference docs (https://csound.com/docs/manual/xout.html):

  "[...]These opcodes actually run only at i-time. Performance time copying is done by the user opcode call.[...]"

In your example, the problem is not in the presence of two "RndInt" UDOs, but in the fact that Csound will run the i-time part of your UDO code at i-time, regardless of the type of its output variable types... And, in doing this, your RndInt UDO will not be completely skipped at init-time (as it would be if it was a native opcode with k-value output):

instr 2 (at init-time:)
  EXECUTED: kBla init 10
  *SKIPPED* printk2 kBla
  EXECUTED: kBla RndInt 1, 2  <--- it will be executed the i-time part and kBla will be overwritten by a 0 value
  *SKIPPED* turnoff
endin

instr 2 (at performance-time:)
  *SKIPPED* kBla init 10
  EXECUTED: printk2 kBla
  EXECUTED: kBla RndInt 1, 2  <--- it will be executed the k-time part
  EXECUTED: turnoff
endin

Of course, at init-time, the instruction "kRnd random kMin, kMax+.999999" inside the RndInt UDO will be skipped because "random" is a native opcode and works, as expected, only at k-time.

So, when RndInt returns from its init-pass, the kBla variable will be set to RndInt->kRnd, that is 0, because during init-time the central line with the 'random' statement ("kRnd random kMin, kMax+.999999") was skipped (being that "random" is a native opcode and works, as expected, only at k-time), therefore RndInt->kRnd wasn't valued yet and Csound considers it as 0...

The result is that, at performance-time, the printed value of kBla, for the second instrument, will be 0, not 10.

This also explains why, in the case of the functional syntax, it works as you expected:

instr 3
  kBla init 10
  printk2 kBla
  ;forcing to select the k-rate version of the
  ;UDO works again
  kBla = RndInt:k(1, 2)
  turnoff
endin

This works not because you forced the ':k' (in fact you could skip the ':k' and it should work anyway), but because the '=' is like a native opcode to Csound, so its behaviour is to skip its execution at init-time... And the result is that, in "instr 3", kBla will not be touched at init-time, as you expect.

Anyway, altough this explains why there is this strange behaviour, I think it's not the "right" behaviour and it should be corrected in some way, because it is very confusing for the user.

All the problems arise from this:

 kBla RndInt 1, 2  <--- at init-time Csound will run the i-time part of the UDO

At init-time it's ok to execute the i-time part of RndInt, I understand... but why you have to return its (undefined at init-time) value too, being that the return value in this case is a k-type variable?