Multiply samples with the cubic coeffs before transposing
[openal-soft.git] / OpenAL32 / alBuffer.c
blob904fd61d2698103abafa9441da4d8673131d272e
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <assert.h>
26 #include <limits.h>
27 #ifdef HAVE_MALLOC_H
28 #include <malloc.h>
29 #endif
31 #include "alMain.h"
32 #include "alu.h"
33 #include "alError.h"
34 #include "alBuffer.h"
35 #include "alThunk.h"
36 #include "sample_cvt.h"
39 extern inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id);
40 extern inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id);
41 extern inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
42 extern inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
44 static ALboolean IsValidType(ALenum type) DECL_CONST;
45 static ALboolean IsValidChannels(ALenum channels) DECL_CONST;
46 static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type) DECL_CONST;
47 static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type) DECL_CONST;
48 static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align);
51 AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
53 ALCcontext *context;
54 ALsizei cur = 0;
56 context = GetContextRef();
57 if(!context) return;
59 if(!(n >= 0))
60 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
62 for(cur = 0;cur < n;cur++)
64 ALbuffer *buffer = NewBuffer(context);
65 if(!buffer)
67 alDeleteBuffers(cur, buffers);
68 break;
71 buffers[cur] = buffer->id;
74 done:
75 ALCcontext_DecRef(context);
78 AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
80 ALCdevice *device;
81 ALCcontext *context;
82 ALbuffer *ALBuf;
83 ALsizei i;
85 context = GetContextRef();
86 if(!context) return;
88 if(!(n >= 0))
89 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
91 device = context->Device;
92 for(i = 0;i < n;i++)
94 if(!buffers[i])
95 continue;
97 /* Check for valid Buffer ID */
98 if((ALBuf=LookupBuffer(device, buffers[i])) == NULL)
99 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
100 if(ReadRef(&ALBuf->ref) != 0)
101 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
104 for(i = 0;i < n;i++)
106 if((ALBuf=LookupBuffer(device, buffers[i])) != NULL)
107 DeleteBuffer(device, ALBuf);
110 done:
111 ALCcontext_DecRef(context);
114 AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
116 ALCcontext *context;
117 ALboolean ret;
119 context = GetContextRef();
120 if(!context) return AL_FALSE;
122 ret = ((!buffer || LookupBuffer(context->Device, buffer)) ?
123 AL_TRUE : AL_FALSE);
125 ALCcontext_DecRef(context);
127 return ret;
131 AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
133 enum UserFmtChannels srcchannels;
134 enum UserFmtType srctype;
135 ALCdevice *device;
136 ALCcontext *context;
137 ALbuffer *albuf;
138 ALenum newformat = AL_NONE;
139 ALuint framesize;
140 ALsizei align;
141 ALenum err;
143 context = GetContextRef();
144 if(!context) return;
146 device = context->Device;
147 if((albuf=LookupBuffer(device, buffer)) == NULL)
148 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
149 if(!(size >= 0 && freq > 0))
150 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
151 if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
152 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
154 align = ATOMIC_LOAD(&albuf->UnpackAlign);
155 if(SanitizeAlignment(srctype, &align) == AL_FALSE)
156 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
157 switch(srctype)
159 case UserFmtByte:
160 case UserFmtUByte:
161 case UserFmtShort:
162 case UserFmtUShort:
163 case UserFmtFloat:
164 framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
165 if((size%framesize) != 0)
166 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
168 err = LoadData(albuf, freq, format, size/framesize*align,
169 srcchannels, srctype, data, align, AL_TRUE);
170 if(err != AL_NO_ERROR)
171 SET_ERROR_AND_GOTO(context, err, done);
172 break;
174 case UserFmtInt:
175 case UserFmtUInt:
176 case UserFmtByte3:
177 case UserFmtUByte3:
178 case UserFmtDouble:
179 framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
180 if((size%framesize) != 0)
181 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
183 switch(srcchannels)
185 case UserFmtMono: newformat = AL_FORMAT_MONO_FLOAT32; break;
186 case UserFmtStereo: newformat = AL_FORMAT_STEREO_FLOAT32; break;
187 case UserFmtRear: newformat = AL_FORMAT_REAR32; break;
188 case UserFmtQuad: newformat = AL_FORMAT_QUAD32; break;
189 case UserFmtX51: newformat = AL_FORMAT_51CHN32; break;
190 case UserFmtX61: newformat = AL_FORMAT_61CHN32; break;
191 case UserFmtX71: newformat = AL_FORMAT_71CHN32; break;
192 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_FLOAT32; break;
193 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_FLOAT32; break;
195 err = LoadData(albuf, freq, newformat, size/framesize*align,
196 srcchannels, srctype, data, align, AL_TRUE);
197 if(err != AL_NO_ERROR)
198 SET_ERROR_AND_GOTO(context, err, done);
199 break;
201 case UserFmtMulaw:
202 case UserFmtAlaw:
203 framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
204 if((size%framesize) != 0)
205 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
207 switch(srcchannels)
209 case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
210 case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
211 case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
212 case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
213 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
214 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
215 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
216 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
217 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
219 err = LoadData(albuf, freq, newformat, size/framesize*align,
220 srcchannels, srctype, data, align, AL_TRUE);
221 if(err != AL_NO_ERROR)
222 SET_ERROR_AND_GOTO(context, err, done);
223 break;
225 case UserFmtIMA4:
226 framesize = (align-1)/2 + 4;
227 framesize *= ChannelsFromUserFmt(srcchannels);
228 if((size%framesize) != 0)
229 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
231 switch(srcchannels)
233 case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
234 case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
235 case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
236 case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
237 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
238 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
239 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
240 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
241 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
243 err = LoadData(albuf, freq, newformat, size/framesize*align,
244 srcchannels, srctype, data, align, AL_TRUE);
245 if(err != AL_NO_ERROR)
246 SET_ERROR_AND_GOTO(context, err, done);
247 break;
249 case UserFmtMSADPCM:
250 framesize = (align-2)/2 + 7;
251 framesize *= ChannelsFromUserFmt(srcchannels);
252 if((size%framesize) != 0)
253 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
255 switch(srcchannels)
257 case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
258 case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
259 case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
260 case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
261 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
262 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
263 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
264 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
265 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
267 err = LoadData(albuf, freq, newformat, size/framesize*align,
268 srcchannels, srctype, data, align, AL_TRUE);
269 if(err != AL_NO_ERROR)
270 SET_ERROR_AND_GOTO(context, err, done);
271 break;
274 done:
275 ALCcontext_DecRef(context);
278 AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length)
280 enum UserFmtChannels srcchannels;
281 enum UserFmtType srctype;
282 ALCdevice *device;
283 ALCcontext *context;
284 ALbuffer *albuf;
285 ALuint byte_align;
286 ALuint channels;
287 ALuint bytes;
288 ALsizei align;
290 context = GetContextRef();
291 if(!context) return;
293 device = context->Device;
294 if((albuf=LookupBuffer(device, buffer)) == NULL)
295 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
296 if(!(length >= 0 && offset >= 0))
297 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
298 if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
299 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
301 WriteLock(&albuf->lock);
302 align = ATOMIC_LOAD(&albuf->UnpackAlign);
303 if(SanitizeAlignment(srctype, &align) == AL_FALSE)
305 WriteUnlock(&albuf->lock);
306 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
308 if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType)
310 WriteUnlock(&albuf->lock);
311 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
313 if(align != albuf->OriginalAlign)
315 WriteUnlock(&albuf->lock);
316 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
319 if(albuf->OriginalType == UserFmtIMA4)
321 byte_align = (albuf->OriginalAlign-1)/2 + 4;
322 byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
324 else if(albuf->OriginalType == UserFmtMSADPCM)
326 byte_align = (albuf->OriginalAlign-2)/2 + 7;
327 byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
329 else
331 byte_align = albuf->OriginalAlign;
332 byte_align *= FrameSizeFromUserFmt(albuf->OriginalChannels,
333 albuf->OriginalType);
336 if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset ||
337 (offset%byte_align) != 0 || (length%byte_align) != 0)
339 WriteUnlock(&albuf->lock);
340 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
343 channels = ChannelsFromFmt(albuf->FmtChannels);
344 bytes = BytesFromFmt(albuf->FmtType);
345 /* offset -> byte offset, length -> sample count */
346 offset = offset/byte_align * channels*bytes;
347 length = length/byte_align * albuf->OriginalAlign;
349 ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
350 data, srctype, channels, length, align);
351 WriteUnlock(&albuf->lock);
353 done:
354 ALCcontext_DecRef(context);
358 AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
359 ALuint samplerate, ALenum internalformat, ALsizei samples,
360 ALenum channels, ALenum type, const ALvoid *data)
362 ALCdevice *device;
363 ALCcontext *context;
364 ALbuffer *albuf;
365 ALsizei align;
366 ALenum err;
368 context = GetContextRef();
369 if(!context) return;
371 device = context->Device;
372 if((albuf=LookupBuffer(device, buffer)) == NULL)
373 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
374 if(!(samples >= 0 && samplerate != 0))
375 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
376 if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
377 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
379 align = ATOMIC_LOAD(&albuf->UnpackAlign);
380 if(SanitizeAlignment(type, &align) == AL_FALSE)
381 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
382 if((samples%align) != 0)
383 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
385 err = LoadData(albuf, samplerate, internalformat, samples,
386 channels, type, data, align, AL_FALSE);
387 if(err != AL_NO_ERROR)
388 SET_ERROR_AND_GOTO(context, err, done);
390 done:
391 ALCcontext_DecRef(context);
394 AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
395 ALsizei offset, ALsizei samples,
396 ALenum channels, ALenum type, const ALvoid *data)
398 ALCdevice *device;
399 ALCcontext *context;
400 ALbuffer *albuf;
401 ALsizei align;
403 context = GetContextRef();
404 if(!context) return;
406 device = context->Device;
407 if((albuf=LookupBuffer(device, buffer)) == NULL)
408 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
409 if(!(samples >= 0 && offset >= 0))
410 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
411 if(IsValidType(type) == AL_FALSE)
412 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
414 WriteLock(&albuf->lock);
415 align = ATOMIC_LOAD(&albuf->UnpackAlign);
416 if(SanitizeAlignment(type, &align) == AL_FALSE)
418 WriteUnlock(&albuf->lock);
419 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
421 if(channels != (ALenum)albuf->FmtChannels)
423 WriteUnlock(&albuf->lock);
424 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
426 if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
428 WriteUnlock(&albuf->lock);
429 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
431 if((samples%align) != 0)
433 WriteUnlock(&albuf->lock);
434 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
437 /* offset -> byte offset */
438 offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
439 ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
440 data, type, ChannelsFromFmt(albuf->FmtChannels), samples, align);
441 WriteUnlock(&albuf->lock);
443 done:
444 ALCcontext_DecRef(context);
447 AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
448 ALsizei offset, ALsizei samples,
449 ALenum channels, ALenum type, ALvoid *data)
451 ALCdevice *device;
452 ALCcontext *context;
453 ALbuffer *albuf;
454 ALsizei align;
456 context = GetContextRef();
457 if(!context) return;
459 device = context->Device;
460 if((albuf=LookupBuffer(device, buffer)) == NULL)
461 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
462 if(!(samples >= 0 && offset >= 0))
463 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
464 if(IsValidType(type) == AL_FALSE)
465 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
467 ReadLock(&albuf->lock);
468 align = ATOMIC_LOAD(&albuf->PackAlign);
469 if(SanitizeAlignment(type, &align) == AL_FALSE)
471 ReadUnlock(&albuf->lock);
472 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
474 if(channels != (ALenum)albuf->FmtChannels)
476 ReadUnlock(&albuf->lock);
477 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
479 if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
481 ReadUnlock(&albuf->lock);
482 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
484 if((samples%align) != 0)
486 ReadUnlock(&albuf->lock);
487 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
490 /* offset -> byte offset */
491 offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
492 ConvertData(data, type, (char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
493 ChannelsFromFmt(albuf->FmtChannels), samples, align);
494 ReadUnlock(&albuf->lock);
496 done:
497 ALCcontext_DecRef(context);
500 AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format)
502 enum FmtChannels dstchannels;
503 enum FmtType dsttype;
504 ALCcontext *context;
505 ALboolean ret;
507 context = GetContextRef();
508 if(!context) return AL_FALSE;
510 ret = DecomposeFormat(format, &dstchannels, &dsttype);
512 ALCcontext_DecRef(context);
514 return ret;
518 AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(value))
520 ALCdevice *device;
521 ALCcontext *context;
523 context = GetContextRef();
524 if(!context) return;
526 device = context->Device;
527 if(LookupBuffer(device, buffer) == NULL)
528 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
530 switch(param)
532 default:
533 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
536 done:
537 ALCcontext_DecRef(context);
541 AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(value1), ALfloat UNUSED(value2), ALfloat UNUSED(value3))
543 ALCdevice *device;
544 ALCcontext *context;
546 context = GetContextRef();
547 if(!context) return;
549 device = context->Device;
550 if(LookupBuffer(device, buffer) == NULL)
551 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
553 switch(param)
555 default:
556 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
559 done:
560 ALCcontext_DecRef(context);
564 AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values)
566 ALCdevice *device;
567 ALCcontext *context;
569 context = GetContextRef();
570 if(!context) return;
572 device = context->Device;
573 if(LookupBuffer(device, buffer) == NULL)
574 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
576 if(!(values))
577 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
578 switch(param)
580 default:
581 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
584 done:
585 ALCcontext_DecRef(context);
589 AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
591 ALCdevice *device;
592 ALCcontext *context;
593 ALbuffer *albuf;
595 context = GetContextRef();
596 if(!context) return;
598 device = context->Device;
599 if((albuf=LookupBuffer(device, buffer)) == NULL)
600 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
602 switch(param)
604 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
605 if(!(value >= 0))
606 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
607 ATOMIC_STORE(&albuf->UnpackAlign, value);
608 break;
610 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
611 if(!(value >= 0))
612 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
613 ATOMIC_STORE(&albuf->PackAlign, value);
614 break;
616 default:
617 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
620 done:
621 ALCcontext_DecRef(context);
625 AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint UNUSED(value1), ALint UNUSED(value2), ALint UNUSED(value3))
627 ALCdevice *device;
628 ALCcontext *context;
630 context = GetContextRef();
631 if(!context) return;
633 device = context->Device;
634 if(LookupBuffer(device, buffer) == NULL)
635 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
637 switch(param)
639 default:
640 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
643 done:
644 ALCcontext_DecRef(context);
648 AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values)
650 ALCdevice *device;
651 ALCcontext *context;
652 ALbuffer *albuf;
654 if(values)
656 switch(param)
658 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
659 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
660 alBufferi(buffer, param, values[0]);
661 return;
665 context = GetContextRef();
666 if(!context) return;
668 device = context->Device;
669 if((albuf=LookupBuffer(device, buffer)) == NULL)
670 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
672 if(!(values))
673 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
674 switch(param)
676 case AL_LOOP_POINTS_SOFT:
677 WriteLock(&albuf->lock);
678 if(ReadRef(&albuf->ref) != 0)
680 WriteUnlock(&albuf->lock);
681 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
683 if(values[0] >= values[1] || values[0] < 0 ||
684 values[1] > albuf->SampleLen)
686 WriteUnlock(&albuf->lock);
687 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
690 albuf->LoopStart = values[0];
691 albuf->LoopEnd = values[1];
692 WriteUnlock(&albuf->lock);
693 break;
695 default:
696 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
699 done:
700 ALCcontext_DecRef(context);
704 AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value)
706 ALCdevice *device;
707 ALCcontext *context;
708 ALbuffer *albuf;
710 context = GetContextRef();
711 if(!context) return;
713 device = context->Device;
714 if((albuf=LookupBuffer(device, buffer)) == NULL)
715 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
717 if(!(value))
718 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
719 switch(param)
721 case AL_SEC_LENGTH_SOFT:
722 ReadLock(&albuf->lock);
723 if(albuf->SampleLen != 0)
724 *value = albuf->SampleLen / (ALfloat)albuf->Frequency;
725 else
726 *value = 0.0f;
727 ReadUnlock(&albuf->lock);
728 break;
730 default:
731 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
734 done:
735 ALCcontext_DecRef(context);
739 AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
741 ALCdevice *device;
742 ALCcontext *context;
744 context = GetContextRef();
745 if(!context) return;
747 device = context->Device;
748 if(LookupBuffer(device, buffer) == NULL)
749 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
751 if(!(value1 && value2 && value3))
752 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
753 switch(param)
755 default:
756 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
759 done:
760 ALCcontext_DecRef(context);
764 AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values)
766 ALCdevice *device;
767 ALCcontext *context;
769 switch(param)
771 case AL_SEC_LENGTH_SOFT:
772 alGetBufferf(buffer, param, values);
773 return;
776 context = GetContextRef();
777 if(!context) return;
779 device = context->Device;
780 if(LookupBuffer(device, buffer) == NULL)
781 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
783 if(!(values))
784 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
785 switch(param)
787 default:
788 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
791 done:
792 ALCcontext_DecRef(context);
796 AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value)
798 ALCdevice *device;
799 ALCcontext *context;
800 ALbuffer *albuf;
802 context = GetContextRef();
803 if(!context) return;
805 device = context->Device;
806 if((albuf=LookupBuffer(device, buffer)) == NULL)
807 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
809 if(!(value))
810 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
811 switch(param)
813 case AL_FREQUENCY:
814 *value = albuf->Frequency;
815 break;
817 case AL_BITS:
818 *value = BytesFromFmt(albuf->FmtType) * 8;
819 break;
821 case AL_CHANNELS:
822 *value = ChannelsFromFmt(albuf->FmtChannels);
823 break;
825 case AL_SIZE:
826 ReadLock(&albuf->lock);
827 *value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels,
828 albuf->FmtType);
829 ReadUnlock(&albuf->lock);
830 break;
832 case AL_INTERNAL_FORMAT_SOFT:
833 *value = albuf->Format;
834 break;
836 case AL_BYTE_LENGTH_SOFT:
837 *value = albuf->OriginalSize;
838 break;
840 case AL_SAMPLE_LENGTH_SOFT:
841 *value = albuf->SampleLen;
842 break;
844 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
845 *value = ATOMIC_LOAD(&albuf->UnpackAlign);
846 break;
848 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
849 *value = ATOMIC_LOAD(&albuf->PackAlign);
850 break;
852 default:
853 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
856 done:
857 ALCcontext_DecRef(context);
861 AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3)
863 ALCdevice *device;
864 ALCcontext *context;
866 context = GetContextRef();
867 if(!context) return;
869 device = context->Device;
870 if(LookupBuffer(device, buffer) == NULL)
871 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
873 if(!(value1 && value2 && value3))
874 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
875 switch(param)
877 default:
878 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
881 done:
882 ALCcontext_DecRef(context);
886 AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values)
888 ALCdevice *device;
889 ALCcontext *context;
890 ALbuffer *albuf;
892 switch(param)
894 case AL_FREQUENCY:
895 case AL_BITS:
896 case AL_CHANNELS:
897 case AL_SIZE:
898 case AL_INTERNAL_FORMAT_SOFT:
899 case AL_BYTE_LENGTH_SOFT:
900 case AL_SAMPLE_LENGTH_SOFT:
901 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
902 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
903 alGetBufferi(buffer, param, values);
904 return;
907 context = GetContextRef();
908 if(!context) return;
910 device = context->Device;
911 if((albuf=LookupBuffer(device, buffer)) == NULL)
912 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
914 if(!(values))
915 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
916 switch(param)
918 case AL_LOOP_POINTS_SOFT:
919 ReadLock(&albuf->lock);
920 values[0] = albuf->LoopStart;
921 values[1] = albuf->LoopEnd;
922 ReadUnlock(&albuf->lock);
923 break;
925 default:
926 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
929 done:
930 ALCcontext_DecRef(context);
935 * LoadData
937 * Loads the specified data into the buffer, using the specified formats.
938 * Currently, the new format must have the same channel configuration as the
939 * original format.
941 ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc)
943 ALuint NewChannels, NewBytes;
944 enum FmtChannels DstChannels;
945 enum FmtType DstType;
946 ALuint64 newsize;
947 ALvoid *temp;
949 if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE ||
950 (long)SrcChannels != (long)DstChannels)
951 return AL_INVALID_ENUM;
953 NewChannels = ChannelsFromFmt(DstChannels);
954 NewBytes = BytesFromFmt(DstType);
956 newsize = frames;
957 newsize *= NewBytes;
958 newsize *= NewChannels;
959 if(newsize > INT_MAX)
960 return AL_OUT_OF_MEMORY;
962 WriteLock(&ALBuf->lock);
963 if(ReadRef(&ALBuf->ref) != 0)
965 WriteUnlock(&ALBuf->lock);
966 return AL_INVALID_OPERATION;
969 temp = realloc(ALBuf->data, (size_t)newsize);
970 if(!temp && newsize)
972 WriteUnlock(&ALBuf->lock);
973 return AL_OUT_OF_MEMORY;
975 ALBuf->data = temp;
977 if(data != NULL)
978 ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align);
980 if(storesrc)
982 ALBuf->OriginalChannels = SrcChannels;
983 ALBuf->OriginalType = SrcType;
984 if(SrcType == UserFmtIMA4)
986 ALsizei byte_align = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels);
987 ALBuf->OriginalSize = frames / align * byte_align;
988 ALBuf->OriginalAlign = align;
990 else if(SrcType == UserFmtMSADPCM)
992 ALsizei byte_align = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels);
993 ALBuf->OriginalSize = frames / align * byte_align;
994 ALBuf->OriginalAlign = align;
996 else
998 ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType);
999 ALBuf->OriginalAlign = 1;
1002 else
1004 ALBuf->OriginalChannels = (enum UserFmtChannels)DstChannels;
1005 ALBuf->OriginalType = (enum UserFmtType)DstType;
1006 ALBuf->OriginalSize = frames * NewBytes * NewChannels;
1007 ALBuf->OriginalAlign = 1;
1010 ALBuf->Frequency = freq;
1011 ALBuf->FmtChannels = DstChannels;
1012 ALBuf->FmtType = DstType;
1013 ALBuf->Format = NewFormat;
1015 ALBuf->SampleLen = frames;
1016 ALBuf->LoopStart = 0;
1017 ALBuf->LoopEnd = ALBuf->SampleLen;
1019 WriteUnlock(&ALBuf->lock);
1020 return AL_NO_ERROR;
1024 ALuint BytesFromUserFmt(enum UserFmtType type)
1026 switch(type)
1028 case UserFmtByte: return sizeof(ALbyte);
1029 case UserFmtUByte: return sizeof(ALubyte);
1030 case UserFmtShort: return sizeof(ALshort);
1031 case UserFmtUShort: return sizeof(ALushort);
1032 case UserFmtInt: return sizeof(ALint);
1033 case UserFmtUInt: return sizeof(ALuint);
1034 case UserFmtFloat: return sizeof(ALfloat);
1035 case UserFmtDouble: return sizeof(ALdouble);
1036 case UserFmtByte3: return sizeof(ALbyte[3]);
1037 case UserFmtUByte3: return sizeof(ALubyte[3]);
1038 case UserFmtMulaw: return sizeof(ALubyte);
1039 case UserFmtAlaw: return sizeof(ALubyte);
1040 case UserFmtIMA4: break; /* not handled here */
1041 case UserFmtMSADPCM: break; /* not handled here */
1043 return 0;
1045 ALuint ChannelsFromUserFmt(enum UserFmtChannels chans)
1047 switch(chans)
1049 case UserFmtMono: return 1;
1050 case UserFmtStereo: return 2;
1051 case UserFmtRear: return 2;
1052 case UserFmtQuad: return 4;
1053 case UserFmtX51: return 6;
1054 case UserFmtX61: return 7;
1055 case UserFmtX71: return 8;
1056 case UserFmtBFormat2D: return 3;
1057 case UserFmtBFormat3D: return 4;
1059 return 0;
1061 static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
1062 enum UserFmtType *type)
1064 static const struct {
1065 ALenum format;
1066 enum UserFmtChannels channels;
1067 enum UserFmtType type;
1068 } list[] = {
1069 { AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte },
1070 { AL_FORMAT_MONO16, UserFmtMono, UserFmtShort },
1071 { AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat },
1072 { AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble },
1073 { AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 },
1074 { AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM },
1075 { AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw },
1076 { AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw },
1078 { AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte },
1079 { AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort },
1080 { AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat },
1081 { AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble },
1082 { AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 },
1083 { AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM },
1084 { AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw },
1085 { AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw },
1087 { AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte },
1088 { AL_FORMAT_REAR16, UserFmtRear, UserFmtShort },
1089 { AL_FORMAT_REAR32, UserFmtRear, UserFmtFloat },
1090 { AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw },
1092 { AL_FORMAT_QUAD8_LOKI, UserFmtQuad, UserFmtUByte },
1093 { AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort },
1095 { AL_FORMAT_QUAD8, UserFmtQuad, UserFmtUByte },
1096 { AL_FORMAT_QUAD16, UserFmtQuad, UserFmtShort },
1097 { AL_FORMAT_QUAD32, UserFmtQuad, UserFmtFloat },
1098 { AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw },
1100 { AL_FORMAT_51CHN8, UserFmtX51, UserFmtUByte },
1101 { AL_FORMAT_51CHN16, UserFmtX51, UserFmtShort },
1102 { AL_FORMAT_51CHN32, UserFmtX51, UserFmtFloat },
1103 { AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw },
1105 { AL_FORMAT_61CHN8, UserFmtX61, UserFmtUByte },
1106 { AL_FORMAT_61CHN16, UserFmtX61, UserFmtShort },
1107 { AL_FORMAT_61CHN32, UserFmtX61, UserFmtFloat },
1108 { AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw },
1110 { AL_FORMAT_71CHN8, UserFmtX71, UserFmtUByte },
1111 { AL_FORMAT_71CHN16, UserFmtX71, UserFmtShort },
1112 { AL_FORMAT_71CHN32, UserFmtX71, UserFmtFloat },
1113 { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw },
1115 { AL_FORMAT_BFORMAT2D_8, UserFmtBFormat2D, UserFmtUByte },
1116 { AL_FORMAT_BFORMAT2D_16, UserFmtBFormat2D, UserFmtShort },
1117 { AL_FORMAT_BFORMAT2D_FLOAT32, UserFmtBFormat2D, UserFmtFloat },
1118 { AL_FORMAT_BFORMAT2D_MULAW, UserFmtBFormat2D, UserFmtMulaw },
1120 { AL_FORMAT_BFORMAT3D_8, UserFmtBFormat3D, UserFmtUByte },
1121 { AL_FORMAT_BFORMAT3D_16, UserFmtBFormat3D, UserFmtShort },
1122 { AL_FORMAT_BFORMAT3D_FLOAT32, UserFmtBFormat3D, UserFmtFloat },
1123 { AL_FORMAT_BFORMAT3D_MULAW, UserFmtBFormat3D, UserFmtMulaw },
1125 ALuint i;
1127 for(i = 0;i < COUNTOF(list);i++)
1129 if(list[i].format == format)
1131 *chans = list[i].channels;
1132 *type = list[i].type;
1133 return AL_TRUE;
1137 return AL_FALSE;
1140 ALuint BytesFromFmt(enum FmtType type)
1142 switch(type)
1144 case FmtByte: return sizeof(ALbyte);
1145 case FmtShort: return sizeof(ALshort);
1146 case FmtFloat: return sizeof(ALfloat);
1148 return 0;
1150 ALuint ChannelsFromFmt(enum FmtChannels chans)
1152 switch(chans)
1154 case FmtMono: return 1;
1155 case FmtStereo: return 2;
1156 case FmtRear: return 2;
1157 case FmtQuad: return 4;
1158 case FmtX51: return 6;
1159 case FmtX61: return 7;
1160 case FmtX71: return 8;
1161 case FmtBFormat2D: return 3;
1162 case FmtBFormat3D: return 4;
1164 return 0;
1166 static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type)
1168 static const struct {
1169 ALenum format;
1170 enum FmtChannels channels;
1171 enum FmtType type;
1172 } list[] = {
1173 { AL_MONO8_SOFT, FmtMono, FmtByte },
1174 { AL_MONO16_SOFT, FmtMono, FmtShort },
1175 { AL_MONO32F_SOFT, FmtMono, FmtFloat },
1177 { AL_STEREO8_SOFT, FmtStereo, FmtByte },
1178 { AL_STEREO16_SOFT, FmtStereo, FmtShort },
1179 { AL_STEREO32F_SOFT, FmtStereo, FmtFloat },
1181 { AL_REAR8_SOFT, FmtRear, FmtByte },
1182 { AL_REAR16_SOFT, FmtRear, FmtShort },
1183 { AL_REAR32F_SOFT, FmtRear, FmtFloat },
1185 { AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtByte },
1186 { AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort },
1188 { AL_QUAD8_SOFT, FmtQuad, FmtByte },
1189 { AL_QUAD16_SOFT, FmtQuad, FmtShort },
1190 { AL_QUAD32F_SOFT, FmtQuad, FmtFloat },
1192 { AL_5POINT1_8_SOFT, FmtX51, FmtByte },
1193 { AL_5POINT1_16_SOFT, FmtX51, FmtShort },
1194 { AL_5POINT1_32F_SOFT, FmtX51, FmtFloat },
1196 { AL_6POINT1_8_SOFT, FmtX61, FmtByte },
1197 { AL_6POINT1_16_SOFT, FmtX61, FmtShort },
1198 { AL_6POINT1_32F_SOFT, FmtX61, FmtFloat },
1200 { AL_7POINT1_8_SOFT, FmtX71, FmtByte },
1201 { AL_7POINT1_16_SOFT, FmtX71, FmtShort },
1202 { AL_7POINT1_32F_SOFT, FmtX71, FmtFloat },
1204 { AL_FORMAT_BFORMAT2D_8, FmtBFormat2D, FmtByte },
1205 { AL_FORMAT_BFORMAT2D_16, FmtBFormat2D, FmtShort },
1206 { AL_FORMAT_BFORMAT2D_FLOAT32, FmtBFormat2D, FmtFloat },
1208 { AL_FORMAT_BFORMAT3D_8, FmtBFormat3D, FmtByte },
1209 { AL_FORMAT_BFORMAT3D_16, FmtBFormat3D, FmtShort },
1210 { AL_FORMAT_BFORMAT3D_FLOAT32, FmtBFormat3D, FmtFloat },
1212 ALuint i;
1214 for(i = 0;i < COUNTOF(list);i++)
1216 if(list[i].format == format)
1218 *chans = list[i].channels;
1219 *type = list[i].type;
1220 return AL_TRUE;
1224 return AL_FALSE;
1227 static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align)
1229 if(*align < 0)
1230 return AL_FALSE;
1232 if(*align == 0)
1234 if(type == UserFmtIMA4)
1236 /* Here is where things vary:
1237 * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
1238 * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
1240 *align = 65;
1242 else if(type == UserFmtMSADPCM)
1243 *align = 64;
1244 else
1245 *align = 1;
1246 return AL_TRUE;
1249 if(type == UserFmtIMA4)
1251 /* IMA4 block alignment must be a multiple of 8, plus 1. */
1252 return ((*align)&7) == 1;
1254 if(type == UserFmtMSADPCM)
1256 /* MSADPCM block alignment must be a multiple of 2. */
1257 /* FIXME: Too strict? Might only require align*channels to be a
1258 * multiple of 2. */
1259 return ((*align)&1) == 0;
1262 return AL_TRUE;
1266 static ALboolean IsValidType(ALenum type)
1268 switch(type)
1270 case AL_BYTE_SOFT:
1271 case AL_UNSIGNED_BYTE_SOFT:
1272 case AL_SHORT_SOFT:
1273 case AL_UNSIGNED_SHORT_SOFT:
1274 case AL_INT_SOFT:
1275 case AL_UNSIGNED_INT_SOFT:
1276 case AL_FLOAT_SOFT:
1277 case AL_DOUBLE_SOFT:
1278 case AL_BYTE3_SOFT:
1279 case AL_UNSIGNED_BYTE3_SOFT:
1280 return AL_TRUE;
1282 return AL_FALSE;
1285 static ALboolean IsValidChannels(ALenum channels)
1287 switch(channels)
1289 case AL_MONO_SOFT:
1290 case AL_STEREO_SOFT:
1291 case AL_REAR_SOFT:
1292 case AL_QUAD_SOFT:
1293 case AL_5POINT1_SOFT:
1294 case AL_6POINT1_SOFT:
1295 case AL_7POINT1_SOFT:
1296 return AL_TRUE;
1298 return AL_FALSE;
1302 ALbuffer *NewBuffer(ALCcontext *context)
1304 ALCdevice *device = context->Device;
1305 ALbuffer *buffer;
1306 ALenum err;
1308 buffer = calloc(1, sizeof(ALbuffer));
1309 if(!buffer)
1310 SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
1311 RWLockInit(&buffer->lock);
1313 err = NewThunkEntry(&buffer->id);
1314 if(err == AL_NO_ERROR)
1315 err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer);
1316 if(err != AL_NO_ERROR)
1318 FreeThunkEntry(buffer->id);
1319 memset(buffer, 0, sizeof(ALbuffer));
1320 free(buffer);
1322 SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
1325 return buffer;
1328 void DeleteBuffer(ALCdevice *device, ALbuffer *buffer)
1330 RemoveBuffer(device, buffer->id);
1331 FreeThunkEntry(buffer->id);
1333 free(buffer->data);
1335 memset(buffer, 0, sizeof(*buffer));
1336 free(buffer);
1341 * ReleaseALBuffers()
1343 * INTERNAL: Called to destroy any buffers that still exist on the device
1345 ALvoid ReleaseALBuffers(ALCdevice *device)
1347 ALsizei i;
1348 for(i = 0;i < device->BufferMap.size;i++)
1350 ALbuffer *temp = device->BufferMap.array[i].value;
1351 device->BufferMap.array[i].value = NULL;
1353 free(temp->data);
1355 FreeThunkEntry(temp->id);
1356 memset(temp, 0, sizeof(ALbuffer));
1357 free(temp);