The C standard (and the C++ standard is the same here I'm pretty sure) say basically that enumerated types will increment sequentially from the preceding value when not assigned a specific value.
From Section 8.4 of the 2nd edition of K&R (the closest I have to a language spec I have immediately on hand): "The identifiers in an enumerator list are declared as constants of type int, and may appear wherever constants are required. If no enumerations with = appear, then the values of the corresponding constants begin at 0 and increase by 1 as the declaration is read from left to right. An enumerator with = gives the associated identifier the value specified; subsequent identifiers continue the progression from the assigned value."
So by one measure, the AU code cited could be considered pedantic or unnecessary.
However, Brian is completely accurate and correct when he says that it is generally common practice for (good) programmers to always explicitly define the value of each item in an enumeration even though it is not always necessary. This does two good things in my view. It makes it completely unambiguous about the value of each element in the enumeration and thus improves code readability and maintainability. It also prevents a non-compliant compiler from making a terrible (and potentially hard to track down!) mistake.
Personally, I've been bit by non-compliant compilers getting this aspect of the standard wrong in the past. So, IMHO, it is better to be safe than sorry and go ahead and explicitly define all the values in an enumeration all the time.
On Feb 28, 2008, at 5:31 PM, Brian Willoughby wrote: Michael,
You are partly complaining about the inelegance of C and C++.
The enum directive does indeed increment integers quite well, but I believe that the industry standard is to hard-code the values to guard against different compiler implementations, or perhaps mistakes in importing the same header more than once by mistake. If you want to leave them out, do so at your own risk. When compiling the core engine and UI as separate bundles, it helps to hard-code the enum values so you do not have any chance of different values being assigned in each binary.
kNumberOfParameters must always be set manually. It doesn't really need to be an enum, but that's the best way to keep it close to the parameters. C++ does not have a handy language construct that would allow automatic calculation of this value in a completely fool-proof manner. You could simply rely on the enum increment (again, at your own potential risk).
You absolutely should not duplicate the enum in two files. Perhaps you are being misled by the sample code, but the proper way to develop an AudioUnit is to create a shared header file whereby you maintain in a single file all the shared declarations.
The Cocoa UI part of your UI should be a little more elegantly coded than the audio engine, but Apple has chosen C++ for AudioUnits instead of Objective C. Perhaps some industrious engineer will implement the entire AudioUnit sample code and public sources as ObjC classes to implement the official API. If this were done, you could simply subclass the AUBase or AUEffectBase class and go on your merry way without so many switch statements. The dynamic binding nature of ObjC makes this possible, unlike C++. NeXT Computer based their IOKit on Objective C, and it worked quite well for all of the NEXTSTEP Operating System drivers. ObjC is a much better language for drivers than, say, Java. But, C++ was chosen for AudioUnits, and we are stuck with quite a bit of inelegance. Buck up, as they say. Sounds like you're prepared to grimace anyway, based on your URL. ;-)
Brian Willoughby Sound Consulting
On Feb 28, 2008, at 16:19, Michael Forrest wrote: Okay guys. I'm new to this list, I'm new to a lot of the syntax bouncing around these parts but I know what makes good code. So how can THIS be in the scaffold for a new Audio Unit: enum { kParam_One =0, kNumberOfParameters =1 }; Why does this anger me? - if I add a parameter I need to add it and also change the kNumberOfParameters value manually
- this enum increments integers perfectly well without being instructed, so why put the assignments in at all
- if I make a cocoa AU this is duplicated in two files so if I want to add a parameter I have to update two independant enums in two separate files
This makes my blood curdle. And I'm seeing a lot of switch statements. I seriously hope this is not indicative of what I will find as I delve further into the AU framework...
--
Jeff Moore Core Audio Apple
|