예제 #1
0
AL_API void AL_APIENTRY alListener3i(ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
{
    ALCcontext *Context;

    switch(eParam)
    {
        case AL_POSITION:
        case AL_VELOCITY:
            alListener3f(eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
            return;
    }

    Context = GetContextRef();
    if(!Context) return;

    switch(eParam)
    {
        default:
            alSetError(Context, AL_INVALID_ENUM);
            break;
    }

    ALCcontext_DecRef(Context);
}
예제 #2
0
AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
{
    ALCcontext *Context;

    Context = GetContextRef();
    if(!Context) return;

    al_try
    {
        switch(capability)
        {
            case AL_SOURCE_DISTANCE_MODEL:
                Context->SourceDistanceModel = AL_FALSE;
                Context->UpdateSources = AL_TRUE;
                break;

            default:
                al_throwerr(Context, AL_INVALID_ENUM);
        }
    }
    al_endtry;

    ALCcontext_DecRef(Context);
}
예제 #3
0
AL_API ALvoid AL_APIENTRY alListenerf(ALenum eParam, ALfloat flValue)
{
    ALCcontext *Context;

    Context = GetContextRef();
    if(!Context) return;

    switch(eParam)
    {
        case AL_GAIN:
            if(flValue >= 0.0f && isfinite(flValue))
            {
                Context->Listener.Gain = flValue;
                Context->UpdateSources = AL_TRUE;
            }
            else
                alSetError(Context, AL_INVALID_VALUE);
            break;

        case AL_METERS_PER_UNIT:
            if(flValue > 0.0f && isfinite(flValue))
            {
                Context->Listener.MetersPerUnit = flValue;
                Context->UpdateSources = AL_TRUE;
            }
            else
                alSetError(Context, AL_INVALID_VALUE);
            break;

        default:
            alSetError(Context, AL_INVALID_ENUM);
            break;
    }

    ALCcontext_DecRef(Context);
}
예제 #4
0
AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3)
{
    ALCcontext *Context;

    Context = GetContextRef();
    if(!Context) return;

    al_try
    {
        CHECK_VALUE(Context, value1 && value2 && value3);
        switch (param)
        {
            case AL_POSITION:
                LockContext(Context);
                *value1 = (ALint)Context->Listener->Position[0];
                *value2 = (ALint)Context->Listener->Position[1];
                *value3 = (ALint)Context->Listener->Position[2];
                UnlockContext(Context);
                break;

            case AL_VELOCITY:
                LockContext(Context);
                *value1 = (ALint)Context->Listener->Velocity[0];
                *value2 = (ALint)Context->Listener->Velocity[1];
                *value3 = (ALint)Context->Listener->Velocity[2];
                UnlockContext(Context);
                break;

            default:
                al_throwerr(Context, AL_INVALID_ENUM);
        }
    }
    al_endtry;

    ALCcontext_DecRef(Context);
}
예제 #5
0
AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
{
    ALCdevice *device;
    ALCcontext *context;
    ALbuffer *albuf;

    context = GetContextRef();
    if(!context) return;

    device = context->Device;
    LockBuffersRead(device);
    if((albuf=LookupBuffer(device, buffer)) == NULL)
        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);

    switch(param)
    {
    case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
        if(!(value >= 0))
            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
        ATOMIC_STORE_SEQ(&albuf->UnpackAlign, value);
        break;

    case AL_PACK_BLOCK_ALIGNMENT_SOFT:
        if(!(value >= 0))
            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
        ATOMIC_STORE_SEQ(&albuf->PackAlign, value);
        break;

    default:
        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
    }

done:
    UnlockBuffersRead(device);
    ALCcontext_DecRef(context);
}
예제 #6
0
AL_API ALvoid AL_APIENTRY alListeneri(ALenum param, ALint value)
{
    ALCcontext *Context;

    (void)value;

    Context = GetContextRef();
    if(!Context) return;

    al_try
    {
        switch(param)
        {
            case AL_PRIORITY_SLOTS:
                Context->PrioritySlots = (ALsizei)value;
                break;
            default:
                al_throwerr(Context, AL_INVALID_ENUM);
        }
    }
    al_endtry;

    ALCcontext_DecRef(Context);
}
예제 #7
0
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots)
{
    ALCcontext *context;
    ALeffectslot *slot;
    ALsizei i;

    context = GetContextRef();
    if(!context) return;

    if(!(n >= 0))
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
    for(i = 0;i < n;i++)
    {
        if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
        if(ReadRef(&slot->ref) != 0)
            SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
    }

    // All effectslots are valid
    for(i = 0;i < n;i++)
    {
        if((slot=RemoveEffectSlot(context, effectslots[i])) == NULL)
            continue;
        FreeThunkEntry(slot->id);

        RemoveEffectSlotArray(context, slot);
        DELETE_OBJ(slot->EffectState);

        memset(slot, 0, sizeof(*slot));
        al_free(slot);
    }

done:
    ALCcontext_DecRef(context);
}
예제 #8
0
AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName)
{
    ALboolean bIsSupported = AL_FALSE;
    ALCcontext *Context;
    const char *ptr;
    size_t len;

    Context = GetContextRef();
    if(!Context) return AL_FALSE;

    if(!extName)
        alSetError(Context, AL_INVALID_VALUE);
    else
    {
        len = strlen(extName);
        ptr = Context->ExtensionList;
        while(ptr && *ptr)
        {
            if(strncasecmp(ptr, extName, len) == 0 &&
               (ptr[len] == '\0' || isspace(ptr[len])))
            {
                bIsSupported = AL_TRUE;
                break;
            }
            if((ptr=strchr(ptr, ' ')) != NULL)
            {
                do {
                    ++ptr;
                } while(isspace(*ptr));
            }
        }
    }

    ALCcontext_DecRef(Context);
    return bIsSupported;
}
예제 #9
0
파일: alState.c 프로젝트: Azaezel/Torque3D
AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
{
    ALCcontext *context;

    context = GetContextRef();
    if(!context) return;

    WriteLock(&context->PropLock);
    switch(capability)
    {
    case AL_SOURCE_DISTANCE_MODEL:
        context->SourceDistanceModel = AL_FALSE;
        break;

    default:
        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
    }
    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
        UpdateListenerProps(context);

done:
    WriteUnlock(&context->PropLock);
    ALCcontext_DecRef(context);
}
예제 #10
0
AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value)
{
    ALCdevice *device;
    ALCcontext *context;
    ALbuffer *albuf;

    context = GetContextRef();
    if(!context) return;

    device = context->Device;
    if((albuf=LookupBuffer(device, buffer)) == NULL)
        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);

    if(!(value))
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
    switch(param)
    {
    case AL_FREQUENCY:
        *value = albuf->Frequency;
        break;

    case AL_BITS:
        *value = BytesFromFmt(albuf->FmtType) * 8;
        break;

    case AL_CHANNELS:
        *value = ChannelsFromFmt(albuf->FmtChannels);
        break;

    case AL_SIZE:
        ReadLock(&albuf->lock);
        *value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels,
                                                     albuf->FmtType);
        ReadUnlock(&albuf->lock);
        break;

    case AL_INTERNAL_FORMAT_SOFT:
        *value = albuf->Format;
        break;

    case AL_BYTE_LENGTH_SOFT:
        *value = albuf->OriginalSize;
        break;

    case AL_SAMPLE_LENGTH_SOFT:
        *value = albuf->SampleLen;
        break;

    case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
        *value = albuf->UnpackAlign;
        break;

    case AL_PACK_BLOCK_ALIGNMENT_SOFT:
        *value = albuf->PackAlign;
        break;

    default:
        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
    }

done:
    ALCcontext_DecRef(context);
}
예제 #11
0
AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length)
{
    enum UserFmtChannels srcchannels;
    enum UserFmtType srctype;
    ALCdevice *device;
    ALCcontext *context;
    ALbuffer *albuf;
    ALuint byte_align;
    ALuint channels;
    ALuint bytes;
    ALsizei align;

    context = GetContextRef();
    if(!context) return;

    device = context->Device;
    if((albuf=LookupBuffer(device, buffer)) == NULL)
        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
    if(!(length >= 0 && offset >= 0))
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
    if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);

    WriteLock(&albuf->lock);
    align = albuf->UnpackAlign;
    if(SanitizeAlignment(srctype, &align) == AL_FALSE)
    {
        WriteUnlock(&albuf->lock);
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
    }
    if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType)
    {
        WriteUnlock(&albuf->lock);
        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
    }
    if(align != albuf->OriginalAlign)
    {
        WriteUnlock(&albuf->lock);
        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
    }

    if(albuf->OriginalType == UserFmtIMA4)
    {
        byte_align  = (albuf->OriginalAlign-1)/2 + 4;
        byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
    }
    else if(albuf->OriginalType == UserFmtMSADPCM)
    {
        byte_align  = (albuf->OriginalAlign-2)/2 + 7;
        byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
    }
    else
    {
        byte_align  = albuf->OriginalAlign;
        byte_align *= FrameSizeFromUserFmt(albuf->OriginalChannels,
                                           albuf->OriginalType);
    }

    if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset ||
       (offset%byte_align) != 0 || (length%byte_align) != 0)
    {
        WriteUnlock(&albuf->lock);
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
    }

    channels = ChannelsFromFmt(albuf->FmtChannels);
    bytes = BytesFromFmt(albuf->FmtType);
    /* offset -> byte offset, length -> sample count */
    offset = offset/byte_align * channels*bytes;
    length = length/byte_align * albuf->OriginalAlign;

    ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
                data, srctype, channels, length, align);
    WriteUnlock(&albuf->lock);

done:
    ALCcontext_DecRef(context);
}
예제 #12
0
AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
{
    enum UserFmtChannels srcchannels;
    enum UserFmtType srctype;
    ALCdevice *device;
    ALCcontext *context;
    ALbuffer *albuf;
    ALenum newformat = AL_NONE;
    ALuint framesize;
    ALsizei align;
    ALenum err;

    context = GetContextRef();
    if(!context) return;

    device = context->Device;
    if((albuf=LookupBuffer(device, buffer)) == NULL)
        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
    if(!(size >= 0 && freq > 0))
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
    if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);

    align = albuf->UnpackAlign;
    if(SanitizeAlignment(srctype, &align) == AL_FALSE)
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
    switch(srctype)
    {
        case UserFmtByte:
        case UserFmtUByte:
        case UserFmtShort:
        case UserFmtUShort:
        case UserFmtFloat:
            framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
            if((size%framesize) != 0)
                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);

            err = LoadData(albuf, freq, format, size/framesize*align,
                           srcchannels, srctype, data, align, AL_TRUE);
            if(err != AL_NO_ERROR)
                SET_ERROR_AND_GOTO(context, err, done);
            break;

        case UserFmtInt:
        case UserFmtUInt:
        case UserFmtByte3:
        case UserFmtUByte3:
        case UserFmtDouble:
            framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
            if((size%framesize) != 0)
                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);

            switch(srcchannels)
            {
                case UserFmtMono: newformat = AL_FORMAT_MONO_FLOAT32; break;
                case UserFmtStereo: newformat = AL_FORMAT_STEREO_FLOAT32; break;
                case UserFmtRear: newformat = AL_FORMAT_REAR32; break;
                case UserFmtQuad: newformat = AL_FORMAT_QUAD32; break;
                case UserFmtX51: newformat = AL_FORMAT_51CHN32; break;
                case UserFmtX61: newformat = AL_FORMAT_61CHN32; break;
                case UserFmtX71: newformat = AL_FORMAT_71CHN32; break;
            }
            err = LoadData(albuf, freq, newformat, size/framesize*align,
                           srcchannels, srctype, data, align, AL_TRUE);
            if(err != AL_NO_ERROR)
                SET_ERROR_AND_GOTO(context, err, done);
            break;

        case UserFmtMulaw:
        case UserFmtAlaw:
            framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
            if((size%framesize) != 0)
                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);

            switch(srcchannels)
            {
                case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
                case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
                case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
                case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
                case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
                case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
                case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
            }
            err = LoadData(albuf, freq, newformat, size/framesize*align,
                           srcchannels, srctype, data, align, AL_TRUE);
            if(err != AL_NO_ERROR)
                SET_ERROR_AND_GOTO(context, err, done);
            break;

        case UserFmtIMA4:
            framesize  = (align-1)/2 + 4;
            framesize *= ChannelsFromUserFmt(srcchannels);
            if((size%framesize) != 0)
                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);

            switch(srcchannels)
            {
                case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
                case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
                case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
                case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
                case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
                case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
                case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
            }
            err = LoadData(albuf, freq, newformat, size/framesize*align,
                           srcchannels, srctype, data, align, AL_TRUE);
            if(err != AL_NO_ERROR)
                SET_ERROR_AND_GOTO(context, err, done);
            break;

        case UserFmtMSADPCM:
            framesize  = (align-2)/2 + 7;
            framesize *= ChannelsFromUserFmt(srcchannels);
            if((size%framesize) != 0)
                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);

            switch(srcchannels)
            {
                case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
                case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
                case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
                case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
                case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
                case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
                case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
            }
            err = LoadData(albuf, freq, newformat, size/framesize*align,
                           srcchannels, srctype, data, align, AL_TRUE);
            if(err != AL_NO_ERROR)
                SET_ERROR_AND_GOTO(context, err, done);
            break;
    }

done:
    ALCcontext_DecRef(context);
}
예제 #13
0
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
{
    ALCdevice *device;
    ALCcontext *context;
    ALsizei cur;

    context = GetContextRef();
    if(!context) return;

    if(n < 0)
        SETERR_GOTO(context, AL_INVALID_VALUE, done, "Generating %d effect slots", n);
    if(n == 0) goto done;

    LockEffectSlotList(context);
    device = context->Device;
    for(cur = 0;cur < n;cur++)
    {
        ALeffectslotPtr *iter = VECTOR_BEGIN(context->EffectSlotList);
        ALeffectslotPtr *end = VECTOR_END(context->EffectSlotList);
        ALeffectslot *slot = NULL;
        ALenum err = AL_OUT_OF_MEMORY;

        for(;iter != end;iter++)
        {
            if(!*iter)
                break;
        }
        if(iter == end)
        {
            if(device->AuxiliaryEffectSlotMax == VECTOR_SIZE(context->EffectSlotList))
            {
                UnlockEffectSlotList(context);
                alDeleteAuxiliaryEffectSlots(cur, effectslots);
                SETERR_GOTO(context, AL_OUT_OF_MEMORY, done,
                    "Exceeding %u auxiliary effect slot limit", device->AuxiliaryEffectSlotMax);
            }
            VECTOR_PUSH_BACK(context->EffectSlotList, NULL);
            iter = &VECTOR_BACK(context->EffectSlotList);
        }
        slot = al_calloc(16, sizeof(ALeffectslot));
        if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR)
        {
            al_free(slot);
            UnlockEffectSlotList(context);

            alDeleteAuxiliaryEffectSlots(cur, effectslots);
            SETERR_GOTO(context, err, done, "Effect slot object allocation failed");
        }
        aluInitEffectPanning(slot);

        slot->id = (iter - VECTOR_BEGIN(context->EffectSlotList)) + 1;
        *iter = slot;

        effectslots[cur] = slot->id;
    }
    AddActiveEffectSlots(effectslots, n, context);
    UnlockEffectSlotList(context);

done:
    ALCcontext_DecRef(context);
}
예제 #14
0
파일: alState.c 프로젝트: Lorchik/libopenal
AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
{
    const ALchar *value = NULL;
    ALCcontext *Context;

    Context = GetContextRef();
    if(!Context) return NULL;

    al_try
    {
        switch(pname)
        {
            case AL_VENDOR:
                value = alVendor;
                break;

            case AL_VERSION:
                value = alVersion;
                break;

            case AL_RENDERER:
                value = alRenderer;
                break;

            case AL_EXTENSIONS:
                value = Context->ExtensionList;
                break;

            case AL_NO_ERROR:
                value = alNoError;
                break;

            case AL_INVALID_NAME:
                value = alErrInvalidName;
                break;

            case AL_INVALID_ENUM:
                value = alErrInvalidEnum;
                break;

            case AL_INVALID_VALUE:
                value = alErrInvalidValue;
                break;

            case AL_INVALID_OPERATION:
                value = alErrInvalidOp;
                break;

            case AL_OUT_OF_MEMORY:
                value = alErrOutOfMemory;
                break;

            default:
                al_throwerr(Context, AL_INVALID_ENUM);
        }
    }
    al_endtry;

    ALCcontext_DecRef(Context);

    return value;
}
예제 #15
0
AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const ALuint *pids)
{
    ALCdevice *device;
    ALCcontext *context;
    ALsoundfont *sfont;
    ALsfpreset **presets;
    ALsizei i;

    context = GetContextRef();
    if(!context) return;

    device = context->Device;
    if(id == 0)
        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
    if(!(sfont=LookupSfont(device, id)))
        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
    if(count < 0)
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);

    WriteLock(&sfont->Lock);
    if(ReadRef(&sfont->ref) != 0)
    {
        WriteUnlock(&sfont->Lock);
        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
    }

    if(count == 0)
        presets = NULL;
    else
    {
        presets = calloc(count, sizeof(presets[0]));
        if(!presets)
        {
            WriteUnlock(&sfont->Lock);
            SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
        }

        for(i = 0;i < count;i++)
        {
            if(!(presets[i]=LookupPreset(device, pids[i])))
            {
                free(presets);
                WriteUnlock(&sfont->Lock);
                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
            }
        }
    }

    for(i = 0;i < count;i++)
        IncrementRef(&presets[i]->ref);

    presets = ExchangePtr((XchgPtr*)&sfont->Presets, presets);
    count = ExchangeInt(&sfont->NumPresets, count);
    WriteUnlock(&sfont->Lock);

    for(i = 0;i < count;i++)
        DecrementRef(&presets[i]->ref);
    free(presets);

done:
    ALCcontext_DecRef(context);
}
예제 #16
0
AL_API ALvoid AL_APIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
{
    ALCcontext *Context;

    if(pflValues)
    {
        switch(eParam)
        {
            case AL_GAIN:
            case AL_METERS_PER_UNIT:
                alListenerf(eParam, pflValues[0]);
                return;

            case AL_POSITION:
            case AL_VELOCITY:
                alListener3f(eParam, pflValues[0], pflValues[1], pflValues[2]);
                return;
        }
    }

    Context = GetContextRef();
    if(!Context) return;

    if(pflValues)
    {
        switch(eParam)
        {
            case AL_ORIENTATION:
                if(isfinite(pflValues[0]) && isfinite(pflValues[1]) &&
                   isfinite(pflValues[2]) && isfinite(pflValues[3]) &&
                   isfinite(pflValues[4]) && isfinite(pflValues[5]))
                {
                    ALfloat U[3], V[3], N[3];

                    /* AT then UP */
                    N[0] = pflValues[0];
                    N[1] = pflValues[1];
                    N[2] = pflValues[2];
                    aluNormalize(N);
                    V[0] = pflValues[3];
                    V[1] = pflValues[4];
                    V[2] = pflValues[5];
                    aluNormalize(V);
                    /* Build and normalize right-vector */
                    aluCrossproduct(N, V, U);
                    aluNormalize(U);

                    LockContext(Context);
                    Context->Listener.Forward[0] = pflValues[0];
                    Context->Listener.Forward[1] = pflValues[1];
                    Context->Listener.Forward[2] = pflValues[2];
                    Context->Listener.Up[0] = pflValues[3];
                    Context->Listener.Up[1] = pflValues[4];
                    Context->Listener.Up[2] = pflValues[5];
                    Context->Listener.Matrix[0][0] =  U[0];
                    Context->Listener.Matrix[0][1] =  V[0];
                    Context->Listener.Matrix[0][2] = -N[0];
                    Context->Listener.Matrix[0][3] =  0.0f;
                    Context->Listener.Matrix[1][0] =  U[1];
                    Context->Listener.Matrix[1][1] =  V[1];
                    Context->Listener.Matrix[1][2] = -N[1];
                    Context->Listener.Matrix[1][3] =  0.0f;
                    Context->Listener.Matrix[2][0] =  U[2];
                    Context->Listener.Matrix[2][1] =  V[2];
                    Context->Listener.Matrix[2][2] = -N[2];
                    Context->Listener.Matrix[2][3] =  0.0f;
                    Context->Listener.Matrix[3][0] =  0.0f;
                    Context->Listener.Matrix[3][1] =  0.0f;
                    Context->Listener.Matrix[3][2] =  0.0f;
                    Context->Listener.Matrix[3][3] =  1.0f;
                    Context->UpdateSources = AL_TRUE;
                    UnlockContext(Context);
                }
                else
                    alSetError(Context, AL_INVALID_VALUE);
                break;

            default:
                alSetError(Context, AL_INVALID_ENUM);
                break;
        }
    }
    else
        alSetError(Context, AL_INVALID_VALUE);

    ALCcontext_DecRef(Context);
}