objarni's picture

Some OpenAL reflections

Hi there!

I tried out the new AL API of OpenTK tonight, it stopped when downloading alut.dll was not enough to kickstart a simple Alut.Init()/OpenTK0.9 windows forms application.

I'm new to OpenAL, so I'm approaching the AL API with a "C#/OpenTK"-mindset.

Sorry if I sound rant-ish! I just want to express my opinion. Here we go:

1. AL.GenBuffers(out uint bufferid): maybe GenBuffer without 's' is better name..? Same with GenSources(out uint sourceid) and DeleteSources(..)
2. IntelliSense-documentation refers to "ALuint"'s and not uint, which are used in reality. In general,
the IntelliSense seems more "c-ish" than "OpenTK-ish" to me :)
3. Is it really necessary to error-check everything all the time..? Could we not have some kind of exception system? I think error-polling is so tedious, it gets really tempting to either
a) skip it altogether (not good)
b) write a thin AL-wrapper around the OpenTK-AL class (not nice either)
4. Alut.Init() returns a strange enum type called "AL.Bool" -- why not use .NET's bool type instead?
5. Why does AL.DeleteSources() take a ref to an uint instead of just an uint? If I want to set the id to 0, I'll rather do it myself.
6. I would like GenSource() to take no out parameter, just return a uint.
7. I would like GenSources(int) to take the number of source id's to generate, and return a uint[].
8. 6-7 applies to Buffers too. This is more C#-idiomatic, out and ref feel very C-idiomatic.


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Inertia's picture

1. Used to be like that in alpha stage, changed into an overload to help finding functions through intellisense (would bloat it, while the GenBuffer and GenBuffers basically do the same. Bad practice having 2 different named functions accomplishing the same task)
2. well, it's a binding to a C api ...
3. Fiddler had a bold idea regarding this: different debug and release versions of OpenTK.dll. While release builds will be unchanged, debug builds imply *L.GetError() after each and every function call and throw if the returned error != NoError. Until some details are sorted out (e.g. how do you copy Debug.dll to bin/Debug/OpenTK.dll, but Release.dll to bin/Release/OpenTK.dll when building from the IDE?) I'd recommend checking for errors only after context init and after each loading of sound data, and assign one key to print you the error on request while the app is running.
4. It will return bool in 0.9.1 (or for a couple of weeks already if you build from svn). AL.Bool is deprecated and was created due to some problem, which could be worked around with Fiddler's help.
5. because there's no 'in'?
6-8. Np, will add it. For Efx aswell.

the Fiddler's picture

2) Yep, should be changed to reflect the actual parameters. Docs are being improved from version to version.

3) The idea is to have a safety net while developing the app, to help you pinpoint and fix problems as soon as they come up. You should still manually check for errors in critical parts of the code, since the automatic error checking will not occur in release builds.

OpenTK will do this in (almost) all constructors in 0.9.1 (AudioContext, GraphicsContext, GameWindow, GLControl, DisplayDevice and so on)

5) Becuase the C it is expecting a pointer (this function may delete 1 or more sources I think?)

Inertia, if we are going to add GenSource() and GenSources(), maybe do the same for DeleteSource() and DeleteSources() for symmetry?

I don't know how far to take this, though, as changes like these aren't feasible on a large scale (e.g. OpenGL 2). It's still a good idea to streamline the API wherever we can though.

Inertia's picture

Wtf you convinced me to use overloads instead of 2 functions, now separate them again? :P

AL.GenSource(out uint bid) is _not_ a native OpenAL function .. it's basically calling AL.GenSources(1, out bid) internally. I don't think this is a good idea, because it will add 10 new functions to OpenAL, which have the same effect. If we start with separating functions like this, AL.SourcePlay's overloads must be split aswell (one overload plays only 1 source, the other plays an array of sources).

Imo the current solution using overloads isn't very error-prone, because the amount of parameters differs.

objarni's picture

In my humble opinion, the "i want to create an array of id's" is not so useful to begin with.

Since the syntax for generating such an array is cumbersome, and the alternative is really simple, is there really any reason to not just skip the incredibly ugly

GenBuffers(int, some-kind-of-quasi-pointer-thingie-here)

or, if there are performance reasons for having this array-allocation-way-of-doing-things, using the more C#-idiomatic

uint[] GenBuffers(int)

..? (same for GenSources and DeleteSources/Buffers).

Inertia's picture

Mhmm are you going to change GL.GenTextures() too? I think this should be consistent if changed. Would also make it harder to use C manuals/reference.

objarni's picture

GenTextures is another example, yes.

About making it harder to humanly parse c manuals/references - yes a little little harder. If you know how to read c, and are used to the C#/OpenTK way/idioms, I don't think it's any real difference in practice. I do think using ref/out/pointer/whatnot is harder for a C# developer, however.

my 2 cc as always :)

Inertia's picture

We really should leave it as is, be it for the sole reason not to change the API now, and change it again when generating IL codes directly comes into reach. uint[] DeleteBuffers(int n); makes little sense, it's like trying to make a women's shoe fit a man's foot with force, because it looks prettier. We already had this discussion iirc, and I'm not going to sacrifice performance just so you can save those 3 letters 'ref' which are right next to each other on the keyboard :P (the IDE will remind you kindly that the parameter requires a keyword, if it's missing)

objarni's picture
uint[] DeleteBuffers(int n);

Hehe! You're right, that makes no sense.

.. and I'm not going to sacrifice performance just so you can save those 3 letters 'ref' which are right next to each other on the keyboard :P

It's not my fingers I'm worried about, it's my eyes! And OpenTK's reputation as being elegant. Seriously, you can't claim performance reasons in this case:

DeleteBuffer(ref int);
DeleteBuffer(int);  // this should actually be faster :)

I'm getting the feeling you're just a little bit lazy Inertia hehe :)

Which of course is great when you're a programmer, but you really have to give me stronger arguments than "we can't change the oh-so-stable API of OpenTK". That really isn't a good argument! I believe the versions before v1.0 should be adressing issues of naming, idioms and such. This is the chance to fix the interface, which admittedly gets to be a more sore thing to do after v1.0!

the Fiddler's picture

Heh, why don't you give this a try yourself?

It's nothing difficult, just go over the 1528 OpenGL functions and write overloads like the above wherever it makes sense. Or limit yourself to the core - only 570 different functions to check then!

I'd really welcome such a patch. :)

objarni's picture

1. Why overloads ? Is there a technical reason the old ones should be left ?
2. What else besides checking out the SVN version of OpenTK do I need to do? (Install Ant?)
3. Which Visual Studio should I test-compile in? Is Express Edition 2005 OK?

I might do that, if that is what it takes (I'm quite sensitive maybe it's because I'm into literature also).

Edit: I might do that when it comes to name allocation for Textures/Buffers/Sources. What more names are there in GL/AL?