[openal] Alure 2.0
chris.kcat at gmail.com
Sun Oct 19 16:07:17 EDT 2014
On 10/19/2014 06:58 AM, Lex wrote:
> Hi Chris,
> As I am currently evaluating freely available c++ openal wrappers, it
> was particularly interesting to look at alure 2.0. For some reason I did
> not observed it while googling the thing.
It's still quite new. I had just put it online not long before the
announcement message. :)
> Answering your question about custom decoders interface:
> I like the option to pass decoder into getBuffer method. The problem
> about having decoder instantiated can be avoided by having
> DecoderFactory, which getBuffer code will ask to create a real decoder
> if it needs to.
Not a bad idea. Though I think the idea of passing in a decoder or
decoder factory to the getBuffer method is inherently problematic. It
would be possible to specify a name and factory to getBuffer in one
place, and in another place specify the same name with a different
factory, and the one that gets used to load it depends entirely on which
is called first. That doesn't feel very intuitive to me.
> Another option (which is not mutually exclusive with
> previous IMO) is that client has a way to register their decoders, and
> each decoder has 'recognize' method which get passed stream of data and
> which reads signature or whatever and returns a bool flag indicating
> whether it can decode this stream or not.
This is a possibility. The main thing with this is, how much data should
be passed in for the decoder to check? Or should the methods just be
given an abstract i/o object (e.g. an std::istream&), and it reads
however much it wants?
> Additional random notes that came to mind:
> * it would be great if library had abstractions for disk i/o, since
> games, for example, often have proprietary resource package format.
Currently the decoder itself handles disk i/o. Since I imagine that most
games will be using their own decoders as well, it could just implement
them with whatever i/o methods they use. Having the i/o separate, and
using virtual i/o in the decoders, is a possibility though.
> * efx support
Certainly planned. Still need to get standard AL fully supported first,
> * why disposing buffers / sources have to deal with context->finalize?
> it may be handled in the appropriate desttructors.
It's possible for those methods to throw exceptions in some situations,
e.g. trying to remove/delete a buffer that's still in use or if an
inappropriate context is current at the time. You can't throw from
destructors, the app will just terminate if an exception tries to leave
It's also possible that certain objects, such as Sources, aren't
actually deleted right away, but are instead held in a vector where they
can be reused the next time one is requested, thus avoiding unnecessary
> * Do you *really* have to use RTTI (dynamic_cast) in the library?
It was the easiest way to handle using abstract interfaces in user code
(so as to not expose implementation details), while internally allowing
the library to use the implementation classes directly so it can access
implementation-specific methods and details (and theoretically avoid
calling through the vtable thanks to C++11's 'final' keyword).
There are a few ways I can think of to avoid it, though. One is to
simply assume the object is the correct type and use static_cast instead
of dynamic_cast. Other than with the Decoder, an app shouldn't be
inheriting from those classes, though I don't know of a way to prevent
it while still allowing the lib to inherit from them.
Another way is to add a protected virtual getImplementation() method,
which effectively returns itself as a pointer to the implementation
A third option is to use the pImpl paradigm instead of a virtual
interface. I'm not sure how I feel about that, though.
On another subject, something else for consideration is whether the
interface should rely on C++11. It could be useful for some aspects of
the API to use things like unique_ptr, and at least internally using
auto and lambdas would be nice. Currently the implementation just uses
C++11 when available, but tries not to require it (though I think the
enumeration example uses for-range loops; I'll fix that if needed).
Something else that's come to mind. Should listener properties be set
through the context, or through a listener object? i.e. like this:
ctx->setListenerPosition(x, y, z);
alure::Listener *listener = ctx->getListener();
listener->setPosition(x, y, z);
Having a separate listener object makes the most sense to me from an
object orientation standpoint, but there's always and ever only one
listener per context, so it seems a bit redundant.
Thanks for the feedback so far! :)
More information about the openal