Mercurial > audio-send
view OpenAL32/alFilter.c @ 19:22ac5a0367cd
finally, a first pass at ear.org
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Thu, 03 Nov 2011 14:54:45 -0700 |
parents | f9476ff7637e |
children |
line wrap: on
line source
1 /**2 * OpenAL cross platform audio library3 * Copyright (C) 1999-2007 by authors.4 * This library is free software; you can redistribute it and/or5 * modify it under the terms of the GNU Library General Public6 * License as published by the Free Software Foundation; either7 * version 2 of the License, or (at your option) any later version.8 *9 * This library is distributed in the hope that it will be useful,10 * but WITHOUT ANY WARRANTY; without even the implied warranty of11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12 * Library General Public License for more details.13 *14 * You should have received a copy of the GNU Library General Public15 * License along with this library; if not, write to the16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,17 * Boston, MA 02111-1307, USA.18 * Or go to http://www.gnu.org/copyleft/lgpl.html19 */21 #include "config.h"23 #include <stdlib.h>25 #include "AL/al.h"26 #include "AL/alc.h"27 #include "alMain.h"28 #include "alFilter.h"29 #include "alThunk.h"30 #include "alError.h"33 static void InitFilterParams(ALfilter *filter, ALenum type);35 #define LookupFilter(m, k) ((ALfilter*)LookupUIntMapKey(&(m), (k)))37 AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)38 {39 ALCcontext *Context;40 ALsizei i=0;42 Context = GetLockedContext();43 if(!Context) return;45 if(n < 0 || IsBadWritePtr((void*)filters, n * sizeof(ALuint)))46 alSetError(Context, AL_INVALID_VALUE);47 else48 {49 ALCdevice *device = Context->Device;50 ALenum err;52 while(i < n)53 {54 ALfilter *filter = calloc(1, sizeof(ALfilter));55 if(!filter)56 {57 alSetError(Context, AL_OUT_OF_MEMORY);58 alDeleteFilters(i, filters);59 break;60 }62 err = NewThunkEntry(&filter->filter);63 if(err == AL_NO_ERROR)64 err = InsertUIntMapEntry(&device->FilterMap, filter->filter, filter);65 if(err != AL_NO_ERROR)66 {67 FreeThunkEntry(filter->filter);68 memset(filter, 0, sizeof(ALfilter));69 free(filter);71 alSetError(Context, err);72 alDeleteFilters(i, filters);73 break;74 }76 filters[i++] = filter->filter;77 InitFilterParams(filter, AL_FILTER_NULL);78 }79 }81 UnlockContext(Context);82 }84 AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters)85 {86 ALCcontext *Context;87 ALCdevice *device;88 ALfilter *ALFilter;89 ALboolean Failed;90 ALsizei i;92 Context = GetLockedContext();93 if(!Context) return;95 Failed = AL_TRUE;96 device = Context->Device;97 if(n < 0)98 alSetError(Context, AL_INVALID_VALUE);99 else100 {101 Failed = AL_FALSE;102 // Check that all filters are valid103 for(i = 0;i < n;i++)104 {105 if(!filters[i])106 continue;108 if(LookupFilter(device->FilterMap, filters[i]) == NULL)109 {110 alSetError(Context, AL_INVALID_NAME);111 Failed = AL_TRUE;112 break;113 }114 }115 }117 if(!Failed)118 {119 // All filters are valid120 for(i = 0;i < n;i++)121 {122 // Recheck that the filter is valid, because there could be duplicated names123 if((ALFilter=LookupFilter(device->FilterMap, filters[i])) == NULL)124 continue;126 RemoveUIntMapKey(&device->FilterMap, ALFilter->filter);127 FreeThunkEntry(ALFilter->filter);129 memset(ALFilter, 0, sizeof(ALfilter));130 free(ALFilter);131 }132 }134 UnlockContext(Context);135 }137 AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)138 {139 ALCcontext *Context;140 ALboolean result;142 Context = GetLockedContext();143 if(!Context) return AL_FALSE;145 result = ((!filter || LookupFilter(Context->Device->FilterMap, filter)) ?146 AL_TRUE : AL_FALSE);148 UnlockContext(Context);150 return result;151 }153 AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)154 {155 ALCcontext *Context;156 ALCdevice *Device;157 ALfilter *ALFilter;159 Context = GetLockedContext();160 if(!Context) return;162 Device = Context->Device;163 if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)164 {165 switch(param)166 {167 case AL_FILTER_TYPE:168 if(iValue == AL_FILTER_NULL ||169 iValue == AL_FILTER_LOWPASS)170 InitFilterParams(ALFilter, iValue);171 else172 alSetError(Context, AL_INVALID_VALUE);173 break;175 default:176 alSetError(Context, AL_INVALID_ENUM);177 break;178 }179 }180 else181 alSetError(Context, AL_INVALID_NAME);183 UnlockContext(Context);184 }186 AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues)187 {188 ALCcontext *Context;189 ALCdevice *Device;191 switch(param)192 {193 case AL_FILTER_TYPE:194 alFilteri(filter, param, piValues[0]);195 return;196 }198 Context = GetLockedContext();199 if(!Context) return;201 Device = Context->Device;202 if(LookupFilter(Device->FilterMap, filter) != NULL)203 {204 switch(param)205 {206 default:207 alSetError(Context, AL_INVALID_ENUM);208 break;209 }210 }211 else212 alSetError(Context, AL_INVALID_NAME);214 UnlockContext(Context);215 }217 AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue)218 {219 ALCcontext *Context;220 ALCdevice *Device;221 ALfilter *ALFilter;223 Context = GetLockedContext();224 if(!Context) return;226 Device = Context->Device;227 if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)228 {229 switch(ALFilter->type)230 {231 case AL_FILTER_LOWPASS:232 switch(param)233 {234 case AL_LOWPASS_GAIN:235 if(flValue >= AL_LOWPASS_MIN_GAIN &&236 flValue <= AL_LOWPASS_MAX_GAIN)237 ALFilter->Gain = flValue;238 else239 alSetError(Context, AL_INVALID_VALUE);240 break;242 case AL_LOWPASS_GAINHF:243 if(flValue >= AL_LOWPASS_MIN_GAINHF &&244 flValue <= AL_LOWPASS_MAX_GAINHF)245 ALFilter->GainHF = flValue;246 else247 alSetError(Context, AL_INVALID_VALUE);248 break;250 default:251 alSetError(Context, AL_INVALID_ENUM);252 break;253 }254 break;256 default:257 alSetError(Context, AL_INVALID_ENUM);258 break;259 }260 }261 else262 alSetError(Context, AL_INVALID_NAME);264 UnlockContext(Context);265 }267 AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)268 {269 /* There are currently no multi-value filter parameters */270 alFilterf(filter, param, pflValues[0]);271 }273 AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue)274 {275 ALCcontext *Context;276 ALCdevice *Device;277 ALfilter *ALFilter;279 Context = GetLockedContext();280 if(!Context) return;282 Device = Context->Device;283 if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)284 {285 switch(param)286 {287 case AL_FILTER_TYPE:288 *piValue = ALFilter->type;289 break;291 default:292 alSetError(Context, AL_INVALID_ENUM);293 break;294 }295 }296 else297 alSetError(Context, AL_INVALID_NAME);299 UnlockContext(Context);300 }302 AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues)303 {304 ALCcontext *Context;305 ALCdevice *Device;307 switch(param)308 {309 case AL_FILTER_TYPE:310 alGetFilteri(filter, param, piValues);311 return;312 }314 Context = GetLockedContext();315 if(!Context) return;317 Device = Context->Device;318 if(LookupFilter(Device->FilterMap, filter) != NULL)319 {320 switch(param)321 {322 default:323 alSetError(Context, AL_INVALID_ENUM);324 break;325 }326 }327 else328 alSetError(Context, AL_INVALID_NAME);330 UnlockContext(Context);331 }333 AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue)334 {335 ALCcontext *Context;336 ALCdevice *Device;337 ALfilter *ALFilter;339 Context = GetLockedContext();340 if(!Context) return;342 Device = Context->Device;343 if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)344 {345 switch(ALFilter->type)346 {347 case AL_FILTER_LOWPASS:348 switch(param)349 {350 case AL_LOWPASS_GAIN:351 *pflValue = ALFilter->Gain;352 break;354 case AL_LOWPASS_GAINHF:355 *pflValue = ALFilter->GainHF;356 break;358 default:359 alSetError(Context, AL_INVALID_ENUM);360 break;361 }362 break;364 default:365 alSetError(Context, AL_INVALID_ENUM);366 break;367 }368 }369 else370 alSetError(Context, AL_INVALID_NAME);372 UnlockContext(Context);373 }375 AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)376 {377 /* There are currently no multi-value filter parameters */378 alGetFilterf(filter, param, pflValues);379 }382 ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)383 {384 ALfloat a = 0.0f;386 /* Be careful with gains < 0.01, as that causes the coefficient387 * head towards 1, which will flatten the signal */388 if(g < 0.9999f) /* 1-epsilon */389 {390 g = maxf(g, 0.01f);391 a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /392 (1 - g);393 }395 return a;396 }398 ALvoid ReleaseALFilters(ALCdevice *device)399 {400 ALsizei i;401 for(i = 0;i < device->FilterMap.size;i++)402 {403 ALfilter *temp = device->FilterMap.array[i].value;404 device->FilterMap.array[i].value = NULL;406 // Release filter structure407 FreeThunkEntry(temp->filter);408 memset(temp, 0, sizeof(ALfilter));409 free(temp);410 }411 }414 static void InitFilterParams(ALfilter *filter, ALenum type)415 {416 filter->type = type;418 filter->Gain = AL_LOWPASS_DEFAULT_GAIN;419 filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;420 }