K-Rate, K-Loop or "What happens when an instrument is called?"

Hello Everybody!

I’m digging deeper into Csound and want to understand what happens behind the scenes.

Working through the floss manual there was this example of Joachim Heintz on printing k-values:

instr 1

kFreq init 100
aSine poscil .2, kFreq, giSine
outs aSine, aSine

kFreq = kFreq+10
kLast release
if kLast == 1 then
printk 0, kFreq
endif

endin

I’m asking myself, when is ‘release’ receiving a note-off and when a note-on message?
When i understand it right release gets informations about the k-rate through the k-variable ‘kLast’. How does these information looks like?

Also, because of the duration of the instrument call (in this example 3 seconds) i’m asking myself when is the computation of the samples und the k-samples happening? Only when an instrument is called? Or is the calculation always happening, so lang the code is running? Or are the informations about samples and k-samples only delivered to instruments, when they are called?

Maybe someone understands my thinking of these things and can help.
Just want to understand it, so i can really work with k-loops.

Philipp

Hi Philipp, welcome!

1 Like

Ok, i investigated a litte more. And now i can be more precise with my questions:

Is there always only one k-cycle running independent from the number of instruments that are called? So that all instruments are sharing the same k-cycle?

And: i still want to know where “release” is getting it’s note-off and note-on messages from. Is it jus because of the instrument call? Or is there something else happening?

hi philipp -
i replied yesterday but we have a problem in replies via email. so i logged in and you can read my text below. let me know if something remains unclear.
joachim


the “release” opcode returns “1” when the last control cycle has arrived. imagine that an instrument runs 10 k-cycles: for the first 9 release will return 0, but in the tenth it will return 1.

for an instrument instance which is called via a score statement, with a certain duration, the number of k-cycles is known at the start of the instrument. for instrument instances which have an “indefinite” duration, for instance when triggered via midi, the “release” opcode will return 1 when the note-off message arrives.

you can check with inserting a line like
printk2 release()
in the code of any instrument. i have no midi here, but i think it should work like this.

best -
joachim

1 Like

hi philipp -

the “release” opcode returns “1” when the last control cycle has
arrived. imagine that an instrument runs 10 k-cycles: for the first 9
release will return 0, but in the tenth it will return 1.

for an instrument instance which is called via a score statement, with a
certain duration, the number of k-cycles is known at the start of the
instrument. for instrument instances which have an “indefinite”
duration, for instance when triggered via midi, the “release” opcode
will return 1 when the note-off message arrives.

you can check with inserting a line like
printk2 release()
in the code of any instrument. i have no midi here, but i think it
should work like this.

best -
joachim

1 Like

Thanks, Joachim!

Now it’s clearer. So, the note-off (and note-on) message in this case is send through the score and has nothing to do with the k-cycle. It’s just that the duration of the k-cycle and the duration of the instrument call is set to work together. Am i right?

Greetings,
Philipp

perhaps not completely. let me go through it.

“the note-off (and note-on) message in this case is send through the score”:

  • yes the score is calling an instrument, or more precisely: one instance of an instrument.
  • in this instrument call (or instrument event), the start time and the duration of the instance which is called are given.
  • i would avoid the terms “note-on” and “note-off” here. because these terms are used when MIDI is triggering events, but here is no MIDI.

“and has nothing to do with the k-cycle”:

  • well it has to do with the k-cycle, because the k-cycles are somehow the internal clock in csound.
  • and because you call an instrument with a specified duration, you call it with a distinct number of k-cycles.
  • for instance, the instrument event “i 1 0 1” will call instrument 1 at start time 0 for 1 beat (default = second). say you have a sample rate of 44100, and ksmps=10 (one control cycle consists of ten samples), then this instrument event will call instrument 1 for exactly 4410 k-cycles.

hope that helps; otherwise others can probably explain more clear =)
j

Thanks! That was somehow i understood it. :slight_smile:

Hello everybody!

I have another question to an example in the floss manual regarding k-variables. Also an example from Joachim.
EXAMPLE 03A09_k-inits_in_multiple_calls_2.csd
It should create an error when the performs time is set to 2 seconds, but it doesn’t. I copied it and it doesn’t behave like it should. The kIndex variable is set back to 0 when the second instrument call is happening. Maybe an opcode has changed?

This is the code:

<CsoundSynthesizer>
<CsOptions>
-nm0
</CsOptions>
<CsInstruments>
ksmps = 32

gkArray[] fillarray 1, 2, 3, 5, 8

instr Call
kNumCall init 1
kTrig metro 1
if kTrig == 1 then
  event "i", "Called", 0, 1, kNumCall
  kNumCall += 1
endif
endin

instr Called
  ;get the number of the instrument instance
iNumCall = p4
  ;set the start index for the while-loop
kIndex = 0
  ;get the init value of kIndex
prints "Initialization value of kIndx in call %d = %d\n", iNumCall, i(kIndex)
  ;perform the while-loop until kIndex equals five
while kIndex < lenarray(gkArray) do
  printf "Index %d of gkArray has value %d\n", 
         kIndex+1, kIndex, gkArray[kIndex]
  kIndex += 1
od
  ;last value of kIndex is 5 because of increment
printks "  Last value of kIndex in call %d = %d\n", 0, iNumCall, kIndex
  ;turn this instance off after first k-cycle
turnoff
endin

</CsInstruments>
<CsScore>
i "Call" 0 1 ;change performance time to 2 to get an error!
</CsScore>
</CsoundSynthesizer>
;example by joachim heintz

true!

yes it looks like the gkArray[kIndx] is not any more executed at init
time, but only at k-time. i seem to remember a discussion about it on
the developer list.

thanks for the feedback; i will change the example.

if anyone is interested, here is a simplified version of the code which
shows that there is not any more an error although kIndx is 5 at init
time (thus pointing to a non-existent array location):

gkAtrray[] fillarray 1, 2, 3, 5, 8
instr 1
kIndx = 0
print i(kIndx)
while kIndx < 5 do
printk 0, gkAtrray[kIndx]
kIndx += 1
od
turnoff
endin
schedule(1,0,1)
schedule(1,1,1)

Hello Everybody!
Another topic related understanding-problem.
I got to this example from Joachim in the Floss-Manual and i try to get my head around this.

instr 2
kcount init 0
ktimek timeinstk
if ktimek == 100 kgoto loop
kgoto noloop
loop:
printks “k-cycle %d reached!%n”, 0, ktimek
kcount = kcount + 1
printk2 kcount
if kcount < 11 kgoto loop
printks “k-END!%n”, 0
noloop:
endin

So, basically i understand this loop thing. But my problem is: why isn’t “printks “k-cycle %d reached!%n”, 0, ktimek” called in every loop-call but “…printk2 kcount…” is?

I describe this how i see it it should work and then maybe you can correct me:

  • kcount gets initialised as 0 and ktimek counts every k-cycle
  • when the 100th k-cycle is counted the loop-facillity is getting started
  • in the loop the first thing to happen is the “printks “k-cycle %d reached!%n”, 0, ktimek”
  • after this the kcount var is getting a +1 and gets printed
  • this happens so long till kcount reaches 10 and is smaller then 11

What do i miss?

Greetings,
Philipp

hi philipp -

you got it perfectly right. it is only because of printks: this opcode
does only print once in a k-cycle, or in other words: you can call
printks in a k-loop ten times but it will only print once. actually it
should be mentioned on the printks manual page — if possible please
file an issue at Issues · csound/manual · GitHub

you can see the difference between printks and printk2 in this example:

instr 1
kIndx = 0
while kIndx < 10 do
printks “hello loop\n”, 0
printk2 kIndx
kIndx += 1
od
turnoff
endin
schedule(1,0,1)

best -
joachim

1 Like

Thanks, Joachim!
I’ve done it!