snocrash's picture

OpenAL Effects Extensions

Hello,

I am trying to use the Effects extensions included in Open AL, and I'm having trouble due to the lack of documentation. Would it be possible to get a simple example of how to apply an effect such as Reverb, Filter... to a source. I would greatly appreciate it. Until then I will keep plugging away :)


Comments

Comment viewing options

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

The primary source of documentation at this point is the OpenAL chapter in the manual and especially this page on applying EFX effects to sources.

Another useful resource is the official OpenAL programming guides.

We are lacking OpenAL samples, mainly because noone has volunteered to write any. I'm currently attacking items on the todo list (missing features and the like) and plan to focus on documentation and examples once all major features are implemented. Help, as always, appreaciated!

snocrash's picture

After going over the effects extension guide in openAL, this is what i have so far, but i've hit a wall...

the lines:

    EFX.Filter(filters[0], EfxFilteri.FilterType, EfxFilterType.Highpass);
    EFX.Effect(effects[0], EfxEffecti.EffectType,  EfxEffectType.Reverb);

generate an error: Argument '3': cannot convert from 'OpenTK.Audio.EfxEffectType' to 'int'

i can cast, or put in int values to get past the error, but i don't get any effects...

I think part of my problem is that I need to initialize the context with aux slots, but I'm not sure how that's done with OpenTks implementation of openAL...

here is the rest of the code:

                int buffer = AL.GenBuffer();
                int source = AL.GenSource();
                int state;
 
                int[] slots = new int[4] { 0, 0, 0, 0 };
                int[] effects = new int[2] { 0, 0 };
                int[] filters = new int[1] { 0 };
 
                EffectsExtension EFX = new EffectsExtension();
 
                EFX.GenAuxiliaryEffectSlots(1, out slots[0]);
                EFX.GenEffects(1, out effects[0]);
                EFX.GenFilters(1, out filters[0]);
 
                AL.BufferData(buffer, sound.ReadToEnd());
 
                EFX.AuxiliaryEffectSlot(slots[0], EfxAuxiliaryi.EffectslotEffect, effects[0]);
                EFX.Filter(filters[0], EfxFilteri.FilterType, EfxEffectType.Reverb);
                EFX.Effect(effects[0], EfxEffecti.EffectType, EfxFilterType.Highpass);
                EFX.Filter(filters[0], EfxFilterf.HighpassGain, 0.9f);
                EFX.Filter(filters[0], EfxFilterf.HighpassGainLF, 0.9f);
 
                AL.Source(source, ALSourcef.ConeOuterGain, 0.5f);
                AL.Source(source, ALSourcei.Buffer, buffer);
                AL.SourcePlay(source);

I'm hoping you can help me out here, I will gladly contribute examples to the project but I need some help getting started, thanks!

the Fiddler's picture
snocrash wrote:

After going over the effects extension guide in openAL, this is what i have so far, but i've hit a wall...

the lines:

    EFX.Filter(filters[0], EfxFilteri.FilterType, EfxFilterType.Highpass);
    EFX.Effect(effects[0], EfxEffecti.EffectType,  EfxEffectType.Reverb);

generate an error: Argument '3': cannot convert from 'OpenTK.Audio.EfxEffectType' to 'int'

Unfortunately, you'll have to cast to an int. These functions can take both enum and int parameters and it's not known at compile time which one you'll use, so you'll have to cast enums to their base type (int).

Quote:

i can cast, or put in int values to get past the error, but i don't get any effects...

I think part of my problem is that I need to initialize the context with aux slots, but I'm not sure how that's done with OpenTks implementation of openAL...

Just looked and AudioContext doesn't initialize any aux slots. The necessary constructors exist, which means I probably forgot to add that functionality. I'll fix that asap.

(If you are curious, there's a solution inside the Build/ folder. The relevant code is in Source/OpenTK/Audio/AudioContext.cs).

Quote:

I'm hoping you can help me out here, I will gladly contribute examples to the project but I need some help getting started, thanks!

Great!

Question: Should OpenTK initialize aux slots by default (if they are supported) or should the user explicitly ask for them?

objarni's picture

Do whatever generates the least traffic on the forums. Another way to put it - choose the way that results in the API doing "the most expected thing". No surprises.

I don't know OpenAL enough to decide that. What does your stomach tell you ;)

the Fiddler's picture
Quote:

I don't know OpenAL enough to decide that. What does your stomach tell you ;)

Neither do I, which is why I am asking.

My gut instinct is to enable support by default. However, I don't know if this could cause undesirable side-effects when you do *not* use the feature (e.g. worse performance or different output - things like that). Anyone knows what Alut does?

snocrash's picture

I was talking with some OpenAL people on IRC and it sounds like they should be enabled by default, and you should try to generate as many slots as the hardware will allow you.

the Fiddler's picture

Alright, I just committed EFX support to SVN. I've also fixed a couple of potential crash-bugs and added a large number of AudioContext constructors (functionality untested at this point).

@snocrash: if you have a SVN client, can you please check out the latest code (instructions) and see if it works now? After checking out, run Build.exe and type "vs", enter, enter to create a visual studio solution for OpenTK.

snocrash's picture

Okay I tested the new build, and it builds fine but still no sound. I'm still a little confused with the API. Shouldn't there be an EffectsExtension.BindFilter(filter, filter.type); ?

like the EffectsExtension.BindEffect(..., ...);

I'll keep playing around with it and let you know if I have any luck.

snocrash's picture

Yay it works now!!!!!!!!!!!!!!

using System;
using System.Threading;
using System.IO;
 
using OpenTK.Audio;
 
namespace Examples
{
 
    public class Playback
    {
        static readonly string filename = Path.Combine(Path.Combine("Data", "Audio"), "APACHE.wav");
 
        public static void Main()
        {
            using (AudioContext context = new AudioContext())
            using (AudioReader sound = new AudioReader(filename))
            {
                Console.WriteLine("Testing WaveReader({0}).ReadToEnd()", filename);
 
                int buffer = AL.GenBuffer();
                int source = AL.GenSource();
                int state;
                EffectsExtension EFX = new EffectsExtension();
                int[] slots = new int[4] { 0, 0, 0, 0 };
                int[] effects = new int[2] { 0, 0 };
                int[] filters = new int[1] { 0 };
 
                EFX.GenEffects(1, out effects[0]);
                EFX.GenFilters(1, out filters[0]);
                EFX.GenAuxiliaryEffectSlots(1, out slots[0]);
                AL.BufferData(buffer, sound.ReadToEnd());
 
               // EFX.Filter(filters[0], EfxFilteri.FilterType, EfxFilterType.Lowpass);
                EFX.BindEffect(effects[0], EfxEffectType.Reverb);
                EFX.Filter(filters[0], EfxFilterf.HighpassGain, 0.9f);
                EFX.Filter(filters[0], EfxFilterf.HighpassGainLF, 0.9f);
                EFX.AuxiliaryEffectSlot(slots[0], EfxAuxiliaryi.EffectslotEffect, effects[0]);
                AL.Source(source, ALSourcef.ConeOuterGain, 0.5f);
                AL.Source(source, ALSourcei.Buffer, buffer);
                AL.SourcePlay(source);
 
                Console.Write("Playing");
 
                // Query the source to find out when it stops playing.
                do
                {
                    Thread.Sleep(250);
                    Console.Write(".");
                    AL.GetSource(source, ALGetSourcei.SourceState, out state);
                }
                while ((ALSourceState)state == ALSourceState.Playing);
 
                Console.WriteLine();
 
                AL.SourceStop(source);
                AL.DeleteSource(source);
                AL.DeleteBuffer(buffer);
            }
        }
    }
}

I think we still need a BindFilter(filter, filter.type); what do you think? I dont know how else I can create a filter.

EFX.Filter(filters[0], EfxFilteri.FilterType, (int)EfxFilterType.Lowpass);

doesn't seem to work

Mincus's picture

Forgive me if I'm wrong, I've not played with OpenAL, but I just took a look at the functions available and it seems there's a BindFilterToSource() one.
Is that what you're looking for?