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); }
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); }
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); }
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); }
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); }
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); }
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); }
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; }
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); }
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); }
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); }
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); }
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); }
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; }
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); }
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); }