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.
objarni's picture

I've changed the source code for 2. I'd like to point out that you're basically doing nothing else but merging declaration and initialization. This is not a common use case, you typically want your arrays to survive the exit of the current method.

I guess we come from different backgrounds. To me this is the most basic use case:

uint id = AL.GenSource();
// use id 

It just feels very intuitive to me.

Important is the fact that removing current GL.GenTextures overloads in favor of compacting 2 lines into 1 will break pretty much every app written in OpenTK so far. I don't see removal as an option, no matter how much you keep nagging. I see no problem adding your suggestion as an additional overload though.

Well then please Inertia, could you add these kind of overloads, if only for me? Or at least not be religiously opposed to it if I do the hard work myself?

teichgraf's picture

I agree with objarni that OpenTK would benefit from such overloads. Isn't one of the OpenTK goals to provide a nice interface?
But these overloads should be an extra gimmick. Removing the original methods would involve a too big interface change. And I think this is not acceptabel for most users.
To make things clear, the current API is already really comfortable and intuitive. And this was the main reason why I decided to change from Tao to OpenTK.

Anyhow, it's a lot of work to do. And who should do this? :) Nevertheless, I think some of the overloads could also be generated automatically by a tool. Especially the simple stuff with one out keyword in the method siganture could be parsed and generated.

void Foo(out var p)
   // ...

// generates...

var Foo()
   var res;
   return res;
the Fiddler's picture

So we all agree that these functions would be nice to have. :)

Such overloads fall into the "nice feature" category: if someone is irked by their lack and implements them, I'll be happy to apply the patch; if noone bothers, they may be added in the future.

Edit: about automatically generating these, it's not as simple as it sounds.

Changing the generator may have unintended side-effects - how are you going to check the whole API to make sure it didn't change a function it shouldn't have?

Far easier to add them by hand, where you control exactly what you change.

Inertia's picture

Sure, go ahead and add them, here is a template:

public static void DeleteBuffers( uint[] buffers )
  AL.DeleteBuffers( buffers.Length, ref buffers );
public static uint[] GenBuffers( int n )
  uint[] result = new uint[n];
  AL.GenBuffers( result.Length, out result[0] );
  return result;

Still fail to see the greatness in this, but whatever makes you happy ...

the Fiddler's picture

To whomever tries to do this: provide int overloads (either forego uints, or add both). CLS-compliance rules:

public static void DeleteBuffers( int[] buffers )
  AL.DeleteBuffers( buffers.Length, ref buffers );
public static int[] GenBuffers( int n )
  int[] result = new int[n];
  AL.GenBuffers( result.Length, out result[0] );
  return result;
Inertia's picture

*Argh* Just managed to dispel that compliance nightmare. Thanks for the reminder. :p

P.S. Accurate inline docu would be nice too. Thanks :)

objarni's picture

Should both int and uint overloads exist?

the Fiddler's picture

Uints are not strictly necessary, but would be nice for reasons of symmetry.

Edit: Uints should be marked as [CLSCompliant(false)], too.

objarni's picture

When I get some free time during the next few days, I plan to make an effort to write "managed friendly versions" of Gen/Delete for the named objects OpenTK uses in GL and AL.

That is, I will write overloads with the following signatures, for example AL Buffers:

uint GenBuffer()
int GenBuffer()
uint[] GenBuffers(int n)
int[] GenBuffers(int n)
void DeleteBuffer(uint buffer)
void DeleteBuffer(int buffer)
void DeleteBuffers(uint[] buffers)
void DeleteBuffers(int[] buffers)

Same eight methods will be created for each of the following object types:

AL: Sources, Buffers
Efx: Effects, AuxiliaryEffectSlots, Filters
GL: Buffers, Lists, Queries, Textures

I will skip the array-versions in cases where there exist no corresponding "ref/out" array version (if any).

GLHelpers.cs has been mentioned as an apropriate target source file in the GL case; is there any such file for AL/Efx?

For me, the simplest thing would be to just post the result in this thread. Is this OK with you?

objarni's picture

Having both of these isn't allowed (compile time error):

    public static int GenTexture()
      int texture;
      GL.GenTextures(out texture);
      return texture;
    public static uint GenTexture()
      uint texture;
      GL.GenTextures(out texture);
      return texture;
// Error	1	Type 'GL' already defines a member called 'GenTexture' with the same parameter types

I guess it's because methods with equal parameter lists but different return type count as having the same signature in C#.

Should I ditch the CLSCompliant version of the uint version?