fixed array compatibility checking (PATCH)
Hi! Here's another minor bug fix. Consider this example: UGen @osc[2]; new SinOsc @=> osc[0]; new PulseOsc @=> osc[1]; It will work because the type checker will consider SinOsc/PulseOsc and UGen compatible for assignment (using the "isa" function which in turn is using the <= operator). This is because Chuck_Type "<=" will check that SinOsc is a child of UGen. However, unintuitively you cannot use the array constructor: [new SinOsc, new PulseOsc] @=> UGen @osc[]; Since the left-hand-side type (Osc[] in this case) is not considered compatible to UGen[]. Neither are they directly the same nor are they descended. That's because "<=" does not check for the arrays' "actual" types (Osc and UGen) being compatible. You must either declare the "osc" variable with the same type as the constructed array: [new SinOsc, new PulseOsc] @=> Osc @osc[]; or you have to cast the array members to UGen so the lhs type is (predictably) UGen[]: [new SinOsc $ UGen, new PulseOsc $ UGen] @=> UGen @osc[]; Both options are not very intuitive for the user. The "Osc" class/type is not even documented I think. Not to mention that it's not always easy to guess the type of a constructed Object array. The attached patch fixes that by allowing arrays of the same depth and derived "actual" types being considered compatible. I think this is the last array patch for the time being, though I'm tempted to implement support for map keys in the inline array constructor :-). Best regards, Robin
btw. 1st) I see many places in the ChucK code where null pointers are checked like this: if( pointer )... This is a common mistake since the null pointer does not necessarily have to be 0. That's one of the reasons why there is a NULL macro which may be defined differently (by the operating system or a specific compiler). If I recall correctly it's even a Linux kernel build option. So instead it should read if( pointer != NULL ) 2nd) There have been significant changes on LiSa in ChucK v1.3.0.0 which are completely undocumented and not even mentioned in the change log. For once, it mas been made a multi-channel UGen (8 output channels for whatever reason), breaking existing ChucK programs. E.g. LiSa l => Gain g => dac; l's channel 0 is not chucked to g. You must do that explicitly. Could you tell me why it has been made a multi-channel UGen? I don't see how you can record multi-channel samples, set the number of channels used by a sample, etc. I will have a look at LiSa code next since it appears to be really really slow. So slow that a bank of 7 LiSas (not doing anything!) in my UGen graph completely swallows all of my remaining DSP load. cheers, Robin On 06/09/12 03:29, Robin Haberkorn wrote:
Hi!
Here's another minor bug fix.
Consider this example:
UGen @osc[2]; new SinOsc @=> osc[0]; new PulseOsc @=> osc[1];
It will work because the type checker will consider SinOsc/PulseOsc and UGen compatible for assignment (using the "isa" function which in turn is using the <= operator). This is because Chuck_Type "<=" will check that SinOsc is a child of UGen.
However, unintuitively you cannot use the array constructor:
[new SinOsc, new PulseOsc] @=> UGen @osc[];
Since the left-hand-side type (Osc[] in this case) is not considered compatible to UGen[]. Neither are they directly the same nor are they descended. That's because "<=" does not check for the arrays' "actual" types (Osc and UGen) being compatible.
You must either declare the "osc" variable with the same type as the constructed array:
[new SinOsc, new PulseOsc] @=> Osc @osc[];
or you have to cast the array members to UGen so the lhs type is (predictably) UGen[]:
[new SinOsc $ UGen, new PulseOsc $ UGen] @=> UGen @osc[];
Both options are not very intuitive for the user. The "Osc" class/type is not even documented I think. Not to mention that it's not always easy to guess the type of a constructed Object array.
The attached patch fixes that by allowing arrays of the same depth and derived "actual" types being considered compatible.
I think this is the last array patch for the time being, though I'm tempted to implement support for map keys in the inline array constructor :-).
Best regards, Robin
LiSa multichannel is for multichannel output. i haven't looked at it in a long while, as there were issues with the chuck implementation of multichannel stuff, and i welcome someone smarter than me to fix/finish it.... cheers, dan On Sep 5, 2012, at 10:06 PM, Robin Haberkorn wrote:
btw.
1st) I see many places in the ChucK code where null pointers are checked like this: if( pointer )... This is a common mistake since the null pointer does not necessarily have to be 0. That's one of the reasons why there is a NULL macro which may be defined differently (by the operating system or a specific compiler). If I recall correctly it's even a Linux kernel build option. So instead it should read if( pointer != NULL )
2nd) There have been significant changes on LiSa in ChucK v1.3.0.0 which are completely undocumented and not even mentioned in the change log. For once, it mas been made a multi-channel UGen (8 output channels for whatever reason), breaking existing ChucK programs. E.g. LiSa l => Gain g => dac; l's channel 0 is not chucked to g. You must do that explicitly. Could you tell me why it has been made a multi-channel UGen? I don't see how you can record multi-channel samples, set the number of channels used by a sample, etc. I will have a look at LiSa code next since it appears to be really really slow. So slow that a bank of 7 LiSas (not doing anything!) in my UGen graph completely swallows all of my remaining DSP load.
cheers, Robin
On 06/09/12 03:29, Robin Haberkorn wrote:
Hi!
Here's another minor bug fix.
Consider this example:
UGen @osc[2]; new SinOsc @=> osc[0]; new PulseOsc @=> osc[1];
It will work because the type checker will consider SinOsc/PulseOsc and UGen compatible for assignment (using the "isa" function which in turn is using the <= operator). This is because Chuck_Type "<=" will check that SinOsc is a child of UGen.
However, unintuitively you cannot use the array constructor:
[new SinOsc, new PulseOsc] @=> UGen @osc[];
Since the left-hand-side type (Osc[] in this case) is not considered compatible to UGen[]. Neither are they directly the same nor are they descended. That's because "<=" does not check for the arrays' "actual" types (Osc and UGen) being compatible.
You must either declare the "osc" variable with the same type as the constructed array:
[new SinOsc, new PulseOsc] @=> Osc @osc[];
or you have to cast the array members to UGen so the lhs type is (predictably) UGen[]:
[new SinOsc $ UGen, new PulseOsc $ UGen] @=> UGen @osc[];
Both options are not very intuitive for the user. The "Osc" class/type is not even documented I think. Not to mention that it's not always easy to guess the type of a constructed Object array.
The attached patch fixes that by allowing arrays of the same depth and derived "actual" types being considered compatible.
I think this is the last array patch for the time being, though I'm tempted to implement support for map keys in the inline array constructor :-).
Best regards, Robin
_______________________________________________ chuck-dev mailing list chuck-dev@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-dev
1st) I see many places in the ChucK code where null pointers are checked like this: if( pointer )... This is a common mistake since the null pointer does not necessarily have to be 0. That's one of the reasons why there is a NULL macro which may be defined differently (by the operating system or a specific compiler). If I recall correctly it's even a Linux kernel build option. So instead it should read if( pointer != NULL )
http://stackoverflow.com/questions/176989/do-you-use-null-or-0-zero-for-poin... from ANSI C Rationale (ANSI X3J11/88-151) (Published 18 November 1988) "An integral constant expression with the value 0, or such an expression cast to type void * , is called a null pointer constant. If a null pointer constant is assigned to or compared for equality to a pointer, the constant is converted to a pointer of that type. Such a pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function." C++98 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf "4.10 Pointer conversions 1 A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of pointer to object or pointer to function type. Such a conversion is called a null pointer conversion." "4.12 Boolean conversions A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false." so IMHO - NULL not being a zero value is pre-ANSI C (btw. that's my generation) - if(pointer) is C++ and C standard compliant (conversion to bool) - NULL is not sufficient in many other cases (like overloaded function selection) and in no way better than 0 here we have to use (CLASS*)0 instead, with the correct CLASS - in C++ NULL is usually explicitly defined as 0 whereas in C (#ifndef __cplusplus) it is defined as (void*)0, please look in mixed headers
On 06/09/12 09:50, Harald wrote:
...
so IMHO - NULL not being a zero value is pre-ANSI C (btw. that's my generation) - if(pointer) is C++ and C standard compliant (conversion to bool) - NULL is not sufficient in many other cases (like overloaded function selection) and in no way better than 0 here we have to use (CLASS*)0 instead, with the correct CLASS - in C++ NULL is usually explicitly defined as 0 whereas in C (#ifndef __cplusplus) it is defined as (void*)0, please look in mixed headers _______________________________________________
Ok, after researching the subject I have to admit that you are basically right though the matter is not as easy as you or I thought. It's another good example that shows that even plain C is not an easy/simple language as soon as you look into details. The machine's null-pointer *address* is in fact undefined. There are machines where the 0-address is valid or another bit-pattern is used for some reason... In C(++), the null-pointer constant is always zero and the NULL macro and can be defined in different ways but only regarding the type it yields (void *, int, long) whereas it must always be zero-valued. The definition of NULL as ((void*)0) is only allowed and common in plain C. The compiler must opaquely translate C null-pointers to the machine's internal null-pointer and vice versa. According to this answer in the comp.lang.c FAQ, the null-pointer should always effectively evaluate as false in boolean expressions regardless of its actual value: http://c-faq.com/null/ptrtest.html In plain C at least, this has nothing to do with the semantics of casting to the boolean type which does not even exist (prior to C99). AFAIK the type of boolean expressions is still int even in C99. Because of the confusion surrounding null-pointers in C(++), I would still consider it good coding style to explicitly compare with NULL, but who cares... My own confusion stemmed from the fact that I once argued with a teacher who told me he used a Windows C compiler where NULL was defined differently and the null-pointer test did not work as expected. Apparently the compiler he was using is broken or the NULL macro was redefined somewhere else - a condition which can indeed result in such unexpected behaviours (and much confusion) as you can easily try out yourself. Best regards, Robin
Ok, after researching the subject I have to admit that you are basically right though the matter is not as easy as you or I thought.
well C and C++ is a mess when it comes to standards. Most critical things are defined as undefined, instead of finding a proper definition. I think it's because some companies are involved, which don't want to change their proprietary super-duper-compilers (MS etc.). My main point was, that if(pointer) is probably more defined (for C++) than if(pointer == NULL), because conversion of null pointer to bool is explicitly defined.
It's another good example that shows that even plain C is not an > easy/simple language as soon as you look into details.
I think the language itself could be easy, but politics are poisoning all standards.
The machine's null-pointer *address* is in fact undefined. There are > machines where the 0-address is valid or another bit-pattern is used for
at the end, "null pointer" is just a definition. The machine/cpu doesn't have such a thing. It's simply nice to have a pointer value which isn't used anyway.
The compiler must opaquely translate C null-pointers to the machine's > internal null-pointer and vice versa.
again, there is no such thing like a machines null pointer
According to this answer in the comp.lang.c FAQ, the null-pointer should always effectively evaluate as false in boolean expressions regardless
that's the point
Because of the confusion surrounding null-pointers in C(++), I would > still consider it good coding style to explicitly compare with NULL, but > who cares...
I think we have to distinguish C and C++. They have different definitions and different sights. That's why the NULL constant is usually defined different.
My own confusion stemmed from the fact that I once argued with a teacher who told me he used a Windows C compiler where NULL was defined > differently and the null-pointer test did not work as expected.
Many teachers are not up to date. They often live in their own isolated world. So don't take them too seriously :-)
Apparently the compiler he was using is broken or the NULL macro was > redefined somewhere else - a condition which can indeed result in such > unexpected behaviours (and much confusion) as you can easily try out > yourself.
probably this was a pre ansi compiler. Or it was an academical curiosity.
On 06/09/12 04:18, Dan Trueman wrote:
LiSa multichannel is for multichannel output. i haven't looked at it in a long while, as there were issues with the chuck implementation of multichannel stuff, and i welcome someone smarter than me to fix/finish it....
cheers, dan
Hi Dan, apparently the LiSa buffer is still a single channel but you can pan the LiSa voices between the 8 output channels. The reason LiSa is so slow may be that in its tick-function (invoked at sample rate for every LiSa in the graph), there are some loops over the 8 output channels and 200 (possible) voices even if it doesn't play or record or only one voice is used. Should have nothing to do with unnecessary function/method calls since they are inlined. Will have a look soon how to optimize that. Would seem plausible to me that only a requested number of voices is actually used and there should be a dynamic number of output channels (one for each voice). I don't think the latter is currently possible in ChucK. If nothing works I think I'll just patch it for my setup to use a single output channel and only one voice. cheers, robin
right, single buffer, with multiple channels out => really lovely with hemispherical speakers and outside-in 8 channel systems. i think when i did this quite some time ago it was for a piece i was working on, and i hadn't actually meant for it to get checked in, due to the multichannel problems. i welcome any efforts to improve this, and thanks for taking a look Robin! it's possible the multichannel issues in Chuck have been resolved in the meantime, but if not, this may be a non-starter until they are. i wish i had time to work on this again, but i just don't at the moment. cheers, dan On Sep 7, 2012, at 10:38 AM, Robin Haberkorn wrote:
On 06/09/12 04:18, Dan Trueman wrote:
LiSa multichannel is for multichannel output. i haven't looked at it in a long while, as there were issues with the chuck implementation of multichannel stuff, and i welcome someone smarter than me to fix/finish it....
cheers, dan
Hi Dan,
apparently the LiSa buffer is still a single channel but you can pan the LiSa voices between the 8 output channels.
The reason LiSa is so slow may be that in its tick-function (invoked at sample rate for every LiSa in the graph), there are some loops over the 8 output channels and 200 (possible) voices even if it doesn't play or record or only one voice is used. Should have nothing to do with unnecessary function/method calls since they are inlined. Will have a look soon how to optimize that. Would seem plausible to me that only a requested number of voices is actually used and there should be a dynamic number of output channels (one for each voice). I don't think the latter is currently possible in ChucK. If nothing works I think I'll just patch it for my setup to use a single output channel and only one voice.
cheers, robin _______________________________________________ chuck-dev mailing list chuck-dev@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-dev
participants (3)
-
Dan Trueman
-
Harald
-
Robin Haberkorn