Since xtratim
gets an i-arg for the extra time, I was hoping that changing p3 would be more flexible, but that's not actually the case...
For starters, p3 is treated as an i-var, i.e. it's only assignable on the initial pass, so something like
instr 1
if p3 < 9 then
p3 = p3 + 1 ; runs only once
printk 0.1, p3
endif
endin
will only run for three seconds if called from the score as
i1 0 2
This much was to be expected. On the other hand the following hack that calls reinit
to [re]run the initialization phase does update p3 more than once, but this has zero effect on the note play time, i.e. only the first ("real init") changes the actual note duration... the perf-time reinits, while changing p3 as read from the instrument, don't have any effect on the note play duration, i.e.
top:
p3 = p3 + 1
printk 0.1, p3
if p3 < 9 then
reinit top
endif
still plays for exactly 3 seconds with the same score (even if I make sure Csound runs long enough), i.e. with:
i1 0 2
e 10
although the printk does display p3 as reaching the value 9 with the latter instrument...
As for xtratim
it doesn't change p3 at all, the "extra time" is implemented outside this as Steven' Yi's answer correctly points out.
Looking at the source code for xtratim, it is actually possible to extend the "extra time", by calling xtratim several times, with ever increasing values, but not shorten it...
int32_t xtratim(CSOUND *csound, XTRADUR *p)
{
IGN(csound);
int32_t *xtra = &(p->h.insdshead->xtratim);
int32_t tim = (int32_t)(*p->extradur * p->h.insdshead->ekr);
if (*xtra < tim) /* gab-a5 revised */
*xtra = tim;
return OK;
}
So armed with this info, I tried
ixtr = 0
top:
ixtr += 1
xtratim ixtr
print ixtr
if ixtr < 8 then
reinit top
endif
And lo and behold, the latter hack does work, i.e. this latter code actually extends the instrument/note play time to 10 seconds using the previous score. So it's possible to extend the note programmatically this way from inside the instrument at perf time, for as much as you want, unlike hacking p3.
For those curious, xtratim
even takes effect (properly) on play (actually release) time even if called after release has been asserted, i.e. even from the "release segment", e.g.
xtratim 1
kflag release
kdone init 0
if (kflag == 1) && (kdone == 0) then
kdone = 1
reinit more
more:
xtratim 4
endif
will give 4 extra seconds of play. Given this, I'm not sure if p3 updates being ignored during perf time is a bug or "by design".