Hi,
I can't get it to work (CSound 5.06):
if ic2 == 1 igoto GT
if ic2 == 2 igoto H1
compiles and runs but H1 is never reached, indifferent of the value of ic2 (which is 2 as a prints shows). And I do not find a working example in the manual for "if..then" code, everything I try fails to compile.
And while I'm at it: are there any plans to update the language to allow for:
- writing statements across several lines without having to use "\"
- allowing for a construct like
if ic2 == 1 then
ax = a1
else if ic2 == 2 then
ax = a1 + a2
else if ic2 == 3 then
ax = a1 + a2 + a3
which is what I want to accomplish.
Sorry for sounding harsh, but goto's are really outdated, bad programming style and a pain when you're used to modern languages like Java, C# or the like.
Thanks in advance,
Rolix



Ok, sorry for judging too
Ok, sorry for judging too fast, if-statements work fine. This compiles:
if (ic2 == 1) then
ax = a1
elseif (ic2 == 2) then
ax = a1+a2
endif
but it doesn't work yet.
Regards,
Roland
...
Using conditionals in Csound is very tricky as they don't work at a-rate. This means having to write code that isn't human readable on occasion. The following code reworks your example so that it properly computes the a-rate signals.
if (ic2 == 1) thenifoo = 0
elseif (ic2 == 2) then
ifoo = 1
endif
ax = a1 + ( a2 * ifoo )
That's just one possibility out of many. Here's one more:
instr 2a1 oscils 10000, 440, 0
a2 oscils 10000, 1000, 0
ibool = ( p4 != 0 ? 1 : 0 ) ; ibool = 0 when p4 is 0, else ibool = 1
ax = a1 + ( a2 * ibool ) ; mix a2 when ibool = 1
out ax
endin
...
i 2 0 4 1
Best,
Jake
----
The Csound Blog
http://www.thumbuki.com/csound/blog
rate of 'if' statements
"Using conditionals in Csound is very tricky as they don't work at a-rate"
Mmm? I've been using i-rate variables to control k/a-rate flow in a few places, without noticing any problems, so I went and checked specifically with this short test case:
sr = 44100
kr = 4410
giSine1 ftgen 1, 0, 16384, 10, 1
; Instrument #1.
instr 1
icntrl = p4
ainA oscil 5000, 1000, giSine1
ainB oscil 5000, 1010, giSine1
if icntrl == 0 then
ainA = ainA + ainB
endif
display ainA, 1, 1, 1
endin
and running twice with p4 either 1 or 0 (I copied to an i-var just in case there was a difference -- there isn't.) The two beating signals was just a quick way of seeing a clear visual change.
; Play Instrument #1 for 2 seconds.
i 1 0 2 1
; and again.. p4 changed
i 1 2 2 0
e
Everything works just fine, even if I use a goto instead of the above. The only time it fails is if I switch to 'igoto'.
Cheers,
Pete
For if-then, all code should
For if-then, all code should agree at rate. If doing a comparison at irate, all code within the branches should be code that runs at i-time. If doing a comparison with krate, all code within branches should be done at k or a-rate.
The reason is that "if" is an opcode. All code, when compiled, is flattened into a single list of opcodes to run. If the if is compiled as an i-time if, when csound runs through the chain at i-time it will do the comparison and skip around. Then at performance time, the if doesn't do a check, and processing proceeds through the chain and should end up just going through all branches.
If you follow the rule at all rates agree, then you'll likely not come across strange behavior that could happen otherwise.
But....
If what you say is strictly true (about an i-time 'if' only being checked then), why does my example above work as I expect it to?
I'm using an i-variable in the if, but the a-variable is computed correctly (through all k-rate cycles) according to the i-value.
I.e, in the first 2 seconds (as in the test sco) where the variable is '1', I see just the ainA sine-wave. In the following 2 secs, with '0', I see the mixed waves.
On the other hand, if I switch to an 'if ... igoto', I see the mixed wave throughout (as I'd expect). I believe the behaviour of the opcode is determined by the nature of the '-goto' part, rather than just the 'if' itself. What the criterion for the 'then' version I used is, I'm not sure, but it seems to make the right decision!
(What is probably truly the case is the reverse situation, that -- as the manual states -- k-rate ifs are not checked at initialization time. I didn't look at that.)
I'm not exactly sure, it's
I'm not exactly sure, it's been a while since I looked at that part of the parser. It might be that if a generic then is used, it might compute at i and k if the conditional check is at i-rate. I would just caution about the situation and keep the rule I mentioned in mind as following it tends to lead to the right expected result and can save possible headaches.
Ifs, buts, and gotos -- a short essay on conditionals
[Being new to this forum, I wasn't aware how long and skinny this post would get. If you prefer an easier-toread full frame version, ive put it up here
And more apologies...! I wrote this offline and pasted it in, but things didn't work quite right, and I didn't proofread! Let me try again...]
Conditional tests and branches in Csound seem to have caused some misapprehension -- and just plain apprehension sometimes(!) -- in myself and others, so I've been induced to do some investigation and dig into the sources, to really clarify how they function, and where any traps might be. With luck the following might help others too.
My first surprised realization was that there is no actual 'if' opcode in Csound! (Check the output of "
csound?-z" if you doubt.) Instead there are a bunch of 'conditional gotos', such as "cggoto", that are immediately substituted for the "if" form by the orchestra compiler before doing anything else. (I don't know if anybody ever uses these directly -- I've never seen it -- but they're perfectly good opcodes to include in your orchestra if you want.) For example, "if?(ia?>?ib)?goto alabel" is translated into "cggoto?(ia>ib),?alabel". Similarly, "if ...?igoto" becomes "cigoto ...", "if?...?kgoto" becomes "ckgoto?...", and so on.The "
if?...?then" form is handled similarly, except that it needs an auto-created label to be inserted at the next correspondingelseorendif, and the jump to that is taken if the condition is false. (This causes a slight complication that we will return to later.) The opcode here is "cngoto?..."As you likely know, two action-lists are built from the opcodes, one traversed at instrument initialization and the other at performance time. The difference between the forms of conditional goto (and unconditional gotos, for that matter) is which lists they appear in.
cggotoandcngotoare inserted in both lists, the others in just one or the other. Straightforward, except that the condition expression is also effectively its own opcode, that will get evaluated in one list or the other (apparently never both) depending on whether it contains any k-variables or not. If it does, the result will never be available at init-time, and is therefore set to be false then. Consequently acggoto, although it appears in both lists, cannot actually ever jump at i-time if any k-variable is referenced; all the opcodes always get initialized.The complication with "
if?...?then"/cngotois that the jump would always be taken at i-time when a k-variable is involved, because it jumps on false. So cngoto makes a special test for the type of the expression, and if it is a p-time one will never jump at i-time.So, if the above makes any sense, you can see that an "
if?...?goto" or "if?...?then" with an i-variable condition is pretty sure to behave as you expect, whatever type of opcodes it controls: the condition is evaluated at i-time and remains available unchanged throughout that performance. All actions, i-rate, k-rate, and a-rate, will be invoked or skipped in the same way. Using a k-variable expression instead is also unlikely to surprise you: everything gets initialized, but only the selected opcodes get performed. (Be careful if you include any unconditional gotos in the controlled section, though. See below.)The "
if?...?igoto" and "if?...?kgoto" variants may need a little more thought. "if?...?kgoto" with a k-variable condition is obviously just the same as an "if?...?goto" with the same condition. With an i-variable condition it is much the same, except you know that all initialization will be done, regardless. Theigotoform is much more likely to throw you; it probably should only be used where all the opcodes it controls are init-time only.Here's a little cautionary tale:
if (1 > 0) igoto skipiprints "this i-time op should be skipped\\n"
printks "this should not be skipped... right?\\n", 1
skipi:
One might think that while the
prints, being an i-time statement, would be skipped, theprintks-- at p-time -- would not. However, if you run it, you will see nothing! The gotcha is that, like many opcodes, theprintkshas an initialization part, which is in fact where the string to be output is set up. When theigotoskips the initialization it is left with nothing to display&You could slip into the same sort of trap if you're not careful with gotos inside a conditional section. For instance, you should use
kgotoin a section controlled by a k-variable conditional; a plaingotowould cause some expected initializations to be skipped. Conversely onlyigotois correct inside an "if?...?igoto" section.