Ignore the listening angle for the wet path sound cones
[openal-soft.git] / OpenAL32 / alBuffer.c
blob8e2c5cf2796d3a73d67bddce254270a44d6c0a47
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 void LockBuffersRead(ALCdevice *device);
40 extern inline void UnlockBuffersRead(ALCdevice *device);
41 extern inline void LockBuffersWrite(ALCdevice *device);
42 extern inline void UnlockBuffersWrite(ALCdevice *device);
43 extern inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id);
44 extern inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id);
45 extern inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
46 extern inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
48 static ALboolean IsValidType(ALenum type) DECL_CONST;
49 static ALboolean IsValidChannels(ALenum channels) DECL_CONST;
50 static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type) DECL_CONST;
51 static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type) DECL_CONST;
52 static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align);
55 AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
57 ALCcontext *context;
58 ALsizei cur = 0;
60 context = GetContextRef();
61 if(!context) return;
63 if(!(n >= 0))
64 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
66 for(cur = 0;cur < n;cur++)
68 ALbuffer *buffer = NewBuffer(context);
69 if(!buffer)
71 alDeleteBuffers(cur, buffers);
72 break;
75 buffers[cur] = buffer->id;
78 done:
79 ALCcontext_DecRef(context);
82 AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
84 ALCdevice *device;
85 ALCcontext *context;
86 ALbuffer *ALBuf;
87 ALsizei i;
89 context = GetContextRef();
90 if(!context) return;
92 device = context->Device;
94 LockBuffersWrite(device);
95 if(!(n >= 0))
96 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
98 for(i = 0;i < n;i++)
100 if(!buffers[i])
101 continue;
103 /* Check for valid Buffer ID */
104 if((ALBuf=LookupBuffer(device, buffers[i])) == NULL)
105 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
106 if(ReadRef(&ALBuf->ref) != 0)
107 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
110 for(i = 0;i < n;i++)
112 if((ALBuf=LookupBuffer(device, buffers[i])) != NULL)
113 DeleteBuffer(device, ALBuf);
116 done:
117 UnlockBuffersWrite(device);
118 ALCcontext_DecRef(context);
121 AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
123 ALCcontext *context;
124 ALboolean ret;
126 context = GetContextRef();
127 if(!context) return AL_FALSE;
129 LockBuffersRead(context->Device);
130 ret = ((!buffer || LookupBuffer(context->Device, buffer)) ?
131 AL_TRUE : AL_FALSE);
132 UnlockBuffersRead(context->Device);
134 ALCcontext_DecRef(context);
136 return ret;
140 AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
142 enum UserFmtChannels srcchannels;
143 enum UserFmtType srctype;
144 ALCdevice *device;
145 ALCcontext *context;
146 ALbuffer *albuf;
147 ALenum newformat = AL_NONE;
148 ALuint framesize;
149 ALsizei align;
150 ALenum err;
152 context = GetContextRef();
153 if(!context) return;
155 device = context->Device;
156 LockBuffersRead(device);
157 if((albuf=LookupBuffer(device, buffer)) == NULL)
158 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
159 if(!(size >= 0 && freq > 0))
160 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
161 if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
162 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
164 align = ATOMIC_LOAD(&albuf->UnpackAlign);
165 if(SanitizeAlignment(srctype, &align) == AL_FALSE)
166 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
167 switch(srctype)
169 case UserFmtByte:
170 case UserFmtUByte:
171 case UserFmtShort:
172 case UserFmtUShort:
173 case UserFmtFloat:
174 framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
175 if((size%framesize) != 0)
176 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
178 err = LoadData(albuf, freq, format, size/framesize*align,
179 srcchannels, srctype, data, align, AL_TRUE);
180 if(err != AL_NO_ERROR)
181 SET_ERROR_AND_GOTO(context, err, done);
182 break;
184 case UserFmtInt:
185 case UserFmtUInt:
186 case UserFmtByte3:
187 case UserFmtUByte3:
188 case UserFmtDouble:
189 framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
190 if((size%framesize) != 0)
191 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
193 switch(srcchannels)
195 case UserFmtMono: newformat = AL_FORMAT_MONO_FLOAT32; break;
196 case UserFmtStereo: newformat = AL_FORMAT_STEREO_FLOAT32; break;
197 case UserFmtRear: newformat = AL_FORMAT_REAR32; break;
198 case UserFmtQuad: newformat = AL_FORMAT_QUAD32; break;
199 case UserFmtX51: newformat = AL_FORMAT_51CHN32; break;
200 case UserFmtX61: newformat = AL_FORMAT_61CHN32; break;
201 case UserFmtX71: newformat = AL_FORMAT_71CHN32; break;
202 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_FLOAT32; break;
203 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_FLOAT32; break;
205 err = LoadData(albuf, freq, newformat, size/framesize*align,
206 srcchannels, srctype, data, align, AL_TRUE);
207 if(err != AL_NO_ERROR)
208 SET_ERROR_AND_GOTO(context, err, done);
209 break;
211 case UserFmtMulaw:
212 case UserFmtAlaw:
213 framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
214 if((size%framesize) != 0)
215 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
217 switch(srcchannels)
219 case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
220 case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
221 case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
222 case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
223 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
224 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
225 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
226 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
227 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
229 err = LoadData(albuf, freq, newformat, size/framesize*align,
230 srcchannels, srctype, data, align, AL_TRUE);
231 if(err != AL_NO_ERROR)
232 SET_ERROR_AND_GOTO(context, err, done);
233 break;
235 case UserFmtIMA4:
236 framesize = (align-1)/2 + 4;
237 framesize *= ChannelsFromUserFmt(srcchannels);
238 if((size%framesize) != 0)
239 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
241 switch(srcchannels)
243 case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
244 case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
245 case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
246 case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
247 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
248 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
249 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
250 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
251 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
253 err = LoadData(albuf, freq, newformat, size/framesize*align,
254 srcchannels, srctype, data, align, AL_TRUE);
255 if(err != AL_NO_ERROR)
256 SET_ERROR_AND_GOTO(context, err, done);
257 break;
259 case UserFmtMSADPCM:
260 framesize = (align-2)/2 + 7;
261 framesize *= ChannelsFromUserFmt(srcchannels);
262 if((size%framesize) != 0)
263 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
265 switch(srcchannels)
267 case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
268 case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
269 case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
270 case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
271 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
272 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
273 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
274 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
275 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
277 err = LoadData(albuf, freq, newformat, size/framesize*align,
278 srcchannels, srctype, data, align, AL_TRUE);
279 if(err != AL_NO_ERROR)
280 SET_ERROR_AND_GOTO(context, err, done);
281 break;
284 done:
285 UnlockBuffersRead(device);
286 ALCcontext_DecRef(context);
289 AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length)
291 enum UserFmtChannels srcchannels;
292 enum UserFmtType srctype;
293 ALCdevice *device;
294 ALCcontext *context;
295 ALbuffer *albuf;
296 ALuint byte_align;
297 ALuint channels;
298 ALuint bytes;
299 ALsizei align;
301 context = GetContextRef();
302 if(!context) return;
304 device = context->Device;
305 LockBuffersRead(device);
306 if((albuf=LookupBuffer(device, buffer)) == NULL)
307 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
308 if(!(length >= 0 && offset >= 0))
309 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
310 if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
311 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
313 WriteLock(&albuf->lock);
314 align = ATOMIC_LOAD(&albuf->UnpackAlign);
315 if(SanitizeAlignment(srctype, &align) == AL_FALSE)
317 WriteUnlock(&albuf->lock);
318 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
320 if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType)
322 WriteUnlock(&albuf->lock);
323 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
325 if(align != albuf->OriginalAlign)
327 WriteUnlock(&albuf->lock);
328 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
331 if(albuf->OriginalType == UserFmtIMA4)
333 byte_align = (albuf->OriginalAlign-1)/2 + 4;
334 byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
336 else if(albuf->OriginalType == UserFmtMSADPCM)
338 byte_align = (albuf->OriginalAlign-2)/2 + 7;
339 byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
341 else
343 byte_align = albuf->OriginalAlign;
344 byte_align *= FrameSizeFromUserFmt(albuf->OriginalChannels,
345 albuf->OriginalType);
348 if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset ||
349 (offset%byte_align) != 0 || (length%byte_align) != 0)
351 WriteUnlock(&albuf->lock);
352 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
355 channels = ChannelsFromFmt(albuf->FmtChannels);
356 bytes = BytesFromFmt(albuf->FmtType);
357 /* offset -> byte offset, length -> sample count */
358 offset = offset/byte_align * channels*bytes;
359 length = length/byte_align * albuf->OriginalAlign;
361 ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
362 data, srctype, channels, length, align);
363 WriteUnlock(&albuf->lock);
365 done:
366 UnlockBuffersRead(device);
367 ALCcontext_DecRef(context);
371 AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
372 ALuint samplerate, ALenum internalformat, ALsizei samples,
373 ALenum channels, ALenum type, const ALvoid *data)
375 ALCdevice *device;
376 ALCcontext *context;
377 ALbuffer *albuf;
378 ALsizei align;
379 ALenum err;
381 context = GetContextRef();
382 if(!context) return;
384 device = context->Device;
385 LockBuffersRead(device);
386 if((albuf=LookupBuffer(device, buffer)) == NULL)
387 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
388 if(!(samples >= 0 && samplerate != 0))
389 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
390 if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
391 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
393 align = ATOMIC_LOAD(&albuf->UnpackAlign);
394 if(SanitizeAlignment(type, &align) == AL_FALSE)
395 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
396 if((samples%align) != 0)
397 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
399 err = LoadData(albuf, samplerate, internalformat, samples,
400 channels, type, data, align, AL_FALSE);
401 if(err != AL_NO_ERROR)
402 SET_ERROR_AND_GOTO(context, err, done);
404 done:
405 UnlockBuffersRead(device);
406 ALCcontext_DecRef(context);
409 AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
410 ALsizei offset, ALsizei samples,
411 ALenum channels, ALenum type, const ALvoid *data)
413 ALCdevice *device;
414 ALCcontext *context;
415 ALbuffer *albuf;
416 ALsizei align;
418 context = GetContextRef();
419 if(!context) return;
421 device = context->Device;
422 LockBuffersRead(device);
423 if((albuf=LookupBuffer(device, buffer)) == NULL)
424 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
425 if(!(samples >= 0 && offset >= 0))
426 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
427 if(IsValidType(type) == AL_FALSE)
428 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
430 WriteLock(&albuf->lock);
431 align = ATOMIC_LOAD(&albuf->UnpackAlign);
432 if(SanitizeAlignment(type, &align) == AL_FALSE)
434 WriteUnlock(&albuf->lock);
435 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
437 if(channels != (ALenum)albuf->FmtChannels)
439 WriteUnlock(&albuf->lock);
440 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
442 if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
444 WriteUnlock(&albuf->lock);
445 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
447 if((samples%align) != 0)
449 WriteUnlock(&albuf->lock);
450 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
453 /* offset -> byte offset */
454 offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
455 ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
456 data, type, ChannelsFromFmt(albuf->FmtChannels), samples, align);
457 WriteUnlock(&albuf->lock);
459 done:
460 UnlockBuffersRead(device);
461 ALCcontext_DecRef(context);
464 AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
465 ALsizei offset, ALsizei samples,
466 ALenum channels, ALenum type, ALvoid *data)
468 ALCdevice *device;
469 ALCcontext *context;
470 ALbuffer *albuf;
471 ALsizei align;
473 context = GetContextRef();
474 if(!context) return;
476 device = context->Device;
477 LockBuffersRead(device);
478 if((albuf=LookupBuffer(device, buffer)) == NULL)
479 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
480 if(!(samples >= 0 && offset >= 0))
481 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
482 if(IsValidType(type) == AL_FALSE)
483 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
485 ReadLock(&albuf->lock);
486 align = ATOMIC_LOAD(&albuf->PackAlign);
487 if(SanitizeAlignment(type, &align) == AL_FALSE)
489 ReadUnlock(&albuf->lock);
490 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
492 if(channels != (ALenum)albuf->FmtChannels)
494 ReadUnlock(&albuf->lock);
495 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
497 if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
499 ReadUnlock(&albuf->lock);
500 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
502 if((samples%align) != 0)
504 ReadUnlock(&albuf->lock);
505 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
508 /* offset -> byte offset */
509 offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
510 ConvertData(data, type, (char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
511 ChannelsFromFmt(albuf->FmtChannels), samples, align);
512 ReadUnlock(&albuf->lock);
514 done:
515 UnlockBuffersRead(device);
516 ALCcontext_DecRef(context);
519 AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format)
521 enum FmtChannels dstchannels;
522 enum FmtType dsttype;
523 ALCcontext *context;
524 ALboolean ret;
526 context = GetContextRef();
527 if(!context) return AL_FALSE;
529 ret = DecomposeFormat(format, &dstchannels, &dsttype);
531 ALCcontext_DecRef(context);
533 return ret;
537 AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(value))
539 ALCdevice *device;
540 ALCcontext *context;
542 context = GetContextRef();
543 if(!context) return;
545 device = context->Device;
546 LockBuffersRead(device);
547 if(LookupBuffer(device, buffer) == NULL)
548 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
550 switch(param)
552 default:
553 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
556 done:
557 UnlockBuffersRead(device);
558 ALCcontext_DecRef(context);
562 AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(value1), ALfloat UNUSED(value2), ALfloat UNUSED(value3))
564 ALCdevice *device;
565 ALCcontext *context;
567 context = GetContextRef();
568 if(!context) return;
570 device = context->Device;
571 LockBuffersRead(device);
572 if(LookupBuffer(device, buffer) == NULL)
573 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
575 switch(param)
577 default:
578 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
581 done:
582 UnlockBuffersRead(device);
583 ALCcontext_DecRef(context);
587 AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values)
589 ALCdevice *device;
590 ALCcontext *context;
592 context = GetContextRef();
593 if(!context) return;
595 device = context->Device;
596 LockBuffersRead(device);
597 if(LookupBuffer(device, buffer) == NULL)
598 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
600 if(!(values))
601 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
602 switch(param)
604 default:
605 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
608 done:
609 UnlockBuffersRead(device);
610 ALCcontext_DecRef(context);
614 AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
616 ALCdevice *device;
617 ALCcontext *context;
618 ALbuffer *albuf;
620 context = GetContextRef();
621 if(!context) return;
623 device = context->Device;
624 LockBuffersRead(device);
625 if((albuf=LookupBuffer(device, buffer)) == NULL)
626 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
628 switch(param)
630 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
631 if(!(value >= 0))
632 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
633 ATOMIC_STORE(&albuf->UnpackAlign, value);
634 break;
636 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
637 if(!(value >= 0))
638 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
639 ATOMIC_STORE(&albuf->PackAlign, value);
640 break;
642 default:
643 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
646 done:
647 UnlockBuffersRead(device);
648 ALCcontext_DecRef(context);
652 AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint UNUSED(value1), ALint UNUSED(value2), ALint UNUSED(value3))
654 ALCdevice *device;
655 ALCcontext *context;
657 context = GetContextRef();
658 if(!context) return;
660 device = context->Device;
661 if(LookupBuffer(device, buffer) == NULL)
662 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
664 switch(param)
666 default:
667 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
670 done:
671 ALCcontext_DecRef(context);
675 AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values)
677 ALCdevice *device;
678 ALCcontext *context;
679 ALbuffer *albuf;
681 if(values)
683 switch(param)
685 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
686 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
687 alBufferi(buffer, param, values[0]);
688 return;
692 context = GetContextRef();
693 if(!context) return;
695 device = context->Device;
696 LockBuffersRead(device);
697 if((albuf=LookupBuffer(device, buffer)) == NULL)
698 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
700 if(!(values))
701 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
702 switch(param)
704 case AL_LOOP_POINTS_SOFT:
705 WriteLock(&albuf->lock);
706 if(ReadRef(&albuf->ref) != 0)
708 WriteUnlock(&albuf->lock);
709 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
711 if(values[0] >= values[1] || values[0] < 0 ||
712 values[1] > albuf->SampleLen)
714 WriteUnlock(&albuf->lock);
715 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
718 albuf->LoopStart = values[0];
719 albuf->LoopEnd = values[1];
720 WriteUnlock(&albuf->lock);
721 break;
723 default:
724 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
727 done:
728 UnlockBuffersRead(device);
729 ALCcontext_DecRef(context);
733 AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value)
735 ALCdevice *device;
736 ALCcontext *context;
737 ALbuffer *albuf;
739 context = GetContextRef();
740 if(!context) return;
742 device = context->Device;
743 LockBuffersRead(device);
744 if((albuf=LookupBuffer(device, buffer)) == NULL)
745 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
747 if(!(value))
748 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
749 switch(param)
751 case AL_SEC_LENGTH_SOFT:
752 ReadLock(&albuf->lock);
753 if(albuf->SampleLen != 0)
754 *value = albuf->SampleLen / (ALfloat)albuf->Frequency;
755 else
756 *value = 0.0f;
757 ReadUnlock(&albuf->lock);
758 break;
760 default:
761 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
764 done:
765 UnlockBuffersRead(device);
766 ALCcontext_DecRef(context);
770 AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
772 ALCdevice *device;
773 ALCcontext *context;
775 context = GetContextRef();
776 if(!context) return;
778 device = context->Device;
779 LockBuffersRead(device);
780 if(LookupBuffer(device, buffer) == NULL)
781 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
783 if(!(value1 && value2 && value3))
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 UnlockBuffersRead(device);
793 ALCcontext_DecRef(context);
797 AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values)
799 ALCdevice *device;
800 ALCcontext *context;
802 switch(param)
804 case AL_SEC_LENGTH_SOFT:
805 alGetBufferf(buffer, param, values);
806 return;
809 context = GetContextRef();
810 if(!context) return;
812 device = context->Device;
813 LockBuffersRead(device);
814 if(LookupBuffer(device, buffer) == NULL)
815 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
817 if(!(values))
818 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
819 switch(param)
821 default:
822 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
825 done:
826 UnlockBuffersRead(device);
827 ALCcontext_DecRef(context);
831 AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value)
833 ALCdevice *device;
834 ALCcontext *context;
835 ALbuffer *albuf;
837 context = GetContextRef();
838 if(!context) return;
840 device = context->Device;
841 LockBuffersRead(device);
842 if((albuf=LookupBuffer(device, buffer)) == NULL)
843 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
845 if(!(value))
846 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
847 switch(param)
849 case AL_FREQUENCY:
850 *value = albuf->Frequency;
851 break;
853 case AL_BITS:
854 *value = BytesFromFmt(albuf->FmtType) * 8;
855 break;
857 case AL_CHANNELS:
858 *value = ChannelsFromFmt(albuf->FmtChannels);
859 break;
861 case AL_SIZE:
862 ReadLock(&albuf->lock);
863 *value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels,
864 albuf->FmtType);
865 ReadUnlock(&albuf->lock);
866 break;
868 case AL_INTERNAL_FORMAT_SOFT:
869 *value = albuf->Format;
870 break;
872 case AL_BYTE_LENGTH_SOFT:
873 *value = albuf->OriginalSize;
874 break;
876 case AL_SAMPLE_LENGTH_SOFT:
877 *value = albuf->SampleLen;
878 break;
880 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
881 *value = ATOMIC_LOAD(&albuf->UnpackAlign);
882 break;
884 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
885 *value = ATOMIC_LOAD(&albuf->PackAlign);
886 break;
888 default:
889 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
892 done:
893 UnlockBuffersRead(device);
894 ALCcontext_DecRef(context);
898 AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3)
900 ALCdevice *device;
901 ALCcontext *context;
903 context = GetContextRef();
904 if(!context) return;
906 device = context->Device;
907 LockBuffersRead(device);
908 if(LookupBuffer(device, buffer) == NULL)
909 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
911 if(!(value1 && value2 && value3))
912 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
913 switch(param)
915 default:
916 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
919 done:
920 UnlockBuffersRead(device);
921 ALCcontext_DecRef(context);
925 AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values)
927 ALCdevice *device;
928 ALCcontext *context;
929 ALbuffer *albuf;
931 switch(param)
933 case AL_FREQUENCY:
934 case AL_BITS:
935 case AL_CHANNELS:
936 case AL_SIZE:
937 case AL_INTERNAL_FORMAT_SOFT:
938 case AL_BYTE_LENGTH_SOFT:
939 case AL_SAMPLE_LENGTH_SOFT:
940 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
941 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
942 alGetBufferi(buffer, param, values);
943 return;
946 context = GetContextRef();
947 if(!context) return;
949 device = context->Device;
950 LockBuffersRead(device);
951 if((albuf=LookupBuffer(device, buffer)) == NULL)
952 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
954 if(!(values))
955 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
956 switch(param)
958 case AL_LOOP_POINTS_SOFT:
959 ReadLock(&albuf->lock);
960 values[0] = albuf->LoopStart;
961 values[1] = albuf->LoopEnd;
962 ReadUnlock(&albuf->lock);
963 break;
965 default:
966 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
969 done:
970 UnlockBuffersRead(device);
971 ALCcontext_DecRef(context);
976 * LoadData
978 * Loads the specified data into the buffer, using the specified formats.
979 * Currently, the new format must have the same channel configuration as the
980 * original format.
982 ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc)
984 ALuint NewChannels, NewBytes;
985 enum FmtChannels DstChannels;
986 enum FmtType DstType;
987 ALuint64 newsize;
988 ALvoid *temp;
990 if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE ||
991 (long)SrcChannels != (long)DstChannels)
992 return AL_INVALID_ENUM;
994 NewChannels = ChannelsFromFmt(DstChannels);
995 NewBytes = BytesFromFmt(DstType);
997 newsize = frames;
998 newsize *= NewBytes;
999 newsize *= NewChannels;
1000 if(newsize > INT_MAX)
1001 return AL_OUT_OF_MEMORY;
1003 WriteLock(&ALBuf->lock);
1004 if(ReadRef(&ALBuf->ref) != 0)
1006 WriteUnlock(&ALBuf->lock);
1007 return AL_INVALID_OPERATION;
1010 temp = realloc(ALBuf->data, (size_t)newsize);
1011 if(!temp && newsize)
1013 WriteUnlock(&ALBuf->lock);
1014 return AL_OUT_OF_MEMORY;
1016 ALBuf->data = temp;
1018 if(data != NULL)
1019 ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align);
1021 if(storesrc)
1023 ALBuf->OriginalChannels = SrcChannels;
1024 ALBuf->OriginalType = SrcType;
1025 if(SrcType == UserFmtIMA4)
1027 ALsizei byte_align = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels);
1028 ALBuf->OriginalSize = frames / align * byte_align;
1029 ALBuf->OriginalAlign = align;
1031 else if(SrcType == UserFmtMSADPCM)
1033 ALsizei byte_align = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels);
1034 ALBuf->OriginalSize = frames / align * byte_align;
1035 ALBuf->OriginalAlign = align;
1037 else
1039 ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType);
1040 ALBuf->OriginalAlign = 1;
1043 else
1045 ALBuf->OriginalChannels = (enum UserFmtChannels)DstChannels;
1046 ALBuf->OriginalType = (enum UserFmtType)DstType;
1047 ALBuf->OriginalSize = frames * NewBytes * NewChannels;
1048 ALBuf->OriginalAlign = 1;
1051 ALBuf->Frequency = freq;
1052 ALBuf->FmtChannels = DstChannels;
1053 ALBuf->FmtType = DstType;
1054 ALBuf->Format = NewFormat;
1056 ALBuf->SampleLen = frames;
1057 ALBuf->LoopStart = 0;
1058 ALBuf->LoopEnd = ALBuf->SampleLen;
1060 WriteUnlock(&ALBuf->lock);
1061 return AL_NO_ERROR;
1065 ALuint BytesFromUserFmt(enum UserFmtType type)
1067 switch(type)
1069 case UserFmtByte: return sizeof(ALbyte);
1070 case UserFmtUByte: return sizeof(ALubyte);
1071 case UserFmtShort: return sizeof(ALshort);
1072 case UserFmtUShort: return sizeof(ALushort);
1073 case UserFmtInt: return sizeof(ALint);
1074 case UserFmtUInt: return sizeof(ALuint);
1075 case UserFmtFloat: return sizeof(ALfloat);
1076 case UserFmtDouble: return sizeof(ALdouble);
1077 case UserFmtByte3: return sizeof(ALbyte[3]);
1078 case UserFmtUByte3: return sizeof(ALubyte[3]);
1079 case UserFmtMulaw: return sizeof(ALubyte);
1080 case UserFmtAlaw: return sizeof(ALubyte);
1081 case UserFmtIMA4: break; /* not handled here */
1082 case UserFmtMSADPCM: break; /* not handled here */
1084 return 0;
1086 ALuint ChannelsFromUserFmt(enum UserFmtChannels chans)
1088 switch(chans)
1090 case UserFmtMono: return 1;
1091 case UserFmtStereo: return 2;
1092 case UserFmtRear: return 2;
1093 case UserFmtQuad: return 4;
1094 case UserFmtX51: return 6;
1095 case UserFmtX61: return 7;
1096 case UserFmtX71: return 8;
1097 case UserFmtBFormat2D: return 3;
1098 case UserFmtBFormat3D: return 4;
1100 return 0;
1102 static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
1103 enum UserFmtType *type)
1105 static const struct {
1106 ALenum format;
1107 enum UserFmtChannels channels;
1108 enum UserFmtType type;
1109 } list[] = {
1110 { AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte },
1111 { AL_FORMAT_MONO16, UserFmtMono, UserFmtShort },
1112 { AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat },
1113 { AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble },
1114 { AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 },
1115 { AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM },
1116 { AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw },
1117 { AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw },
1119 { AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte },
1120 { AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort },
1121 { AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat },
1122 { AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble },
1123 { AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 },
1124 { AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM },
1125 { AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw },
1126 { AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw },
1128 { AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte },
1129 { AL_FORMAT_REAR16, UserFmtRear, UserFmtShort },
1130 { AL_FORMAT_REAR32, UserFmtRear, UserFmtFloat },
1131 { AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw },
1133 { AL_FORMAT_QUAD8_LOKI, UserFmtQuad, UserFmtUByte },
1134 { AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort },
1136 { AL_FORMAT_QUAD8, UserFmtQuad, UserFmtUByte },
1137 { AL_FORMAT_QUAD16, UserFmtQuad, UserFmtShort },
1138 { AL_FORMAT_QUAD32, UserFmtQuad, UserFmtFloat },
1139 { AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw },
1141 { AL_FORMAT_51CHN8, UserFmtX51, UserFmtUByte },
1142 { AL_FORMAT_51CHN16, UserFmtX51, UserFmtShort },
1143 { AL_FORMAT_51CHN32, UserFmtX51, UserFmtFloat },
1144 { AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw },
1146 { AL_FORMAT_61CHN8, UserFmtX61, UserFmtUByte },
1147 { AL_FORMAT_61CHN16, UserFmtX61, UserFmtShort },
1148 { AL_FORMAT_61CHN32, UserFmtX61, UserFmtFloat },
1149 { AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw },
1151 { AL_FORMAT_71CHN8, UserFmtX71, UserFmtUByte },
1152 { AL_FORMAT_71CHN16, UserFmtX71, UserFmtShort },
1153 { AL_FORMAT_71CHN32, UserFmtX71, UserFmtFloat },
1154 { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw },
1156 { AL_FORMAT_BFORMAT2D_8, UserFmtBFormat2D, UserFmtUByte },
1157 { AL_FORMAT_BFORMAT2D_16, UserFmtBFormat2D, UserFmtShort },
1158 { AL_FORMAT_BFORMAT2D_FLOAT32, UserFmtBFormat2D, UserFmtFloat },
1159 { AL_FORMAT_BFORMAT2D_MULAW, UserFmtBFormat2D, UserFmtMulaw },
1161 { AL_FORMAT_BFORMAT3D_8, UserFmtBFormat3D, UserFmtUByte },
1162 { AL_FORMAT_BFORMAT3D_16, UserFmtBFormat3D, UserFmtShort },
1163 { AL_FORMAT_BFORMAT3D_FLOAT32, UserFmtBFormat3D, UserFmtFloat },
1164 { AL_FORMAT_BFORMAT3D_MULAW, UserFmtBFormat3D, UserFmtMulaw },
1166 ALuint i;
1168 for(i = 0;i < COUNTOF(list);i++)
1170 if(list[i].format == format)
1172 *chans = list[i].channels;
1173 *type = list[i].type;
1174 return AL_TRUE;
1178 return AL_FALSE;
1181 ALuint BytesFromFmt(enum FmtType type)
1183 switch(type)
1185 case FmtByte: return sizeof(ALbyte);
1186 case FmtShort: return sizeof(ALshort);
1187 case FmtFloat: return sizeof(ALfloat);
1189 return 0;
1191 ALuint ChannelsFromFmt(enum FmtChannels chans)
1193 switch(chans)
1195 case FmtMono: return 1;
1196 case FmtStereo: return 2;
1197 case FmtRear: return 2;
1198 case FmtQuad: return 4;
1199 case FmtX51: return 6;
1200 case FmtX61: return 7;
1201 case FmtX71: return 8;
1202 case FmtBFormat2D: return 3;
1203 case FmtBFormat3D: return 4;
1205 return 0;
1207 static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type)
1209 static const struct {
1210 ALenum format;
1211 enum FmtChannels channels;
1212 enum FmtType type;
1213 } list[] = {
1214 { AL_MONO8_SOFT, FmtMono, FmtByte },
1215 { AL_MONO16_SOFT, FmtMono, FmtShort },
1216 { AL_MONO32F_SOFT, FmtMono, FmtFloat },
1218 { AL_STEREO8_SOFT, FmtStereo, FmtByte },
1219 { AL_STEREO16_SOFT, FmtStereo, FmtShort },
1220 { AL_STEREO32F_SOFT, FmtStereo, FmtFloat },
1222 { AL_REAR8_SOFT, FmtRear, FmtByte },
1223 { AL_REAR16_SOFT, FmtRear, FmtShort },
1224 { AL_REAR32F_SOFT, FmtRear, FmtFloat },
1226 { AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtByte },
1227 { AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort },
1229 { AL_QUAD8_SOFT, FmtQuad, FmtByte },
1230 { AL_QUAD16_SOFT, FmtQuad, FmtShort },
1231 { AL_QUAD32F_SOFT, FmtQuad, FmtFloat },
1233 { AL_5POINT1_8_SOFT, FmtX51, FmtByte },
1234 { AL_5POINT1_16_SOFT, FmtX51, FmtShort },
1235 { AL_5POINT1_32F_SOFT, FmtX51, FmtFloat },
1237 { AL_6POINT1_8_SOFT, FmtX61, FmtByte },
1238 { AL_6POINT1_16_SOFT, FmtX61, FmtShort },
1239 { AL_6POINT1_32F_SOFT, FmtX61, FmtFloat },
1241 { AL_7POINT1_8_SOFT, FmtX71, FmtByte },
1242 { AL_7POINT1_16_SOFT, FmtX71, FmtShort },
1243 { AL_7POINT1_32F_SOFT, FmtX71, FmtFloat },
1245 { AL_BFORMAT2D_8_SOFT, FmtBFormat2D, FmtByte },
1246 { AL_BFORMAT2D_16_SOFT, FmtBFormat2D, FmtShort },
1247 { AL_BFORMAT2D_32F_SOFT, FmtBFormat2D, FmtFloat },
1249 { AL_BFORMAT3D_8_SOFT, FmtBFormat3D, FmtByte },
1250 { AL_BFORMAT3D_16_SOFT, FmtBFormat3D, FmtShort },
1251 { AL_BFORMAT3D_32F_SOFT, FmtBFormat3D, FmtFloat },
1253 ALuint i;
1255 for(i = 0;i < COUNTOF(list);i++)
1257 if(list[i].format == format)
1259 *chans = list[i].channels;
1260 *type = list[i].type;
1261 return AL_TRUE;
1265 return AL_FALSE;
1268 static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align)
1270 if(*align < 0)
1271 return AL_FALSE;
1273 if(*align == 0)
1275 if(type == UserFmtIMA4)
1277 /* Here is where things vary:
1278 * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
1279 * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
1281 *align = 65;
1283 else if(type == UserFmtMSADPCM)
1284 *align = 64;
1285 else
1286 *align = 1;
1287 return AL_TRUE;
1290 if(type == UserFmtIMA4)
1292 /* IMA4 block alignment must be a multiple of 8, plus 1. */
1293 return ((*align)&7) == 1;
1295 if(type == UserFmtMSADPCM)
1297 /* MSADPCM block alignment must be a multiple of 2. */
1298 /* FIXME: Too strict? Might only require align*channels to be a
1299 * multiple of 2. */
1300 return ((*align)&1) == 0;
1303 return AL_TRUE;
1307 static ALboolean IsValidType(ALenum type)
1309 switch(type)
1311 case AL_BYTE_SOFT:
1312 case AL_UNSIGNED_BYTE_SOFT:
1313 case AL_SHORT_SOFT:
1314 case AL_UNSIGNED_SHORT_SOFT:
1315 case AL_INT_SOFT:
1316 case AL_UNSIGNED_INT_SOFT:
1317 case AL_FLOAT_SOFT:
1318 case AL_DOUBLE_SOFT:
1319 case AL_BYTE3_SOFT:
1320 case AL_UNSIGNED_BYTE3_SOFT:
1321 case AL_MULAW_SOFT:
1322 return AL_TRUE;
1324 return AL_FALSE;
1327 static ALboolean IsValidChannels(ALenum channels)
1329 switch(channels)
1331 case AL_MONO_SOFT:
1332 case AL_STEREO_SOFT:
1333 case AL_REAR_SOFT:
1334 case AL_QUAD_SOFT:
1335 case AL_5POINT1_SOFT:
1336 case AL_6POINT1_SOFT:
1337 case AL_7POINT1_SOFT:
1338 case AL_BFORMAT2D_SOFT:
1339 case AL_BFORMAT3D_SOFT:
1340 return AL_TRUE;
1342 return AL_FALSE;
1346 ALbuffer *NewBuffer(ALCcontext *context)
1348 ALCdevice *device = context->Device;
1349 ALbuffer *buffer;
1350 ALenum err;
1352 buffer = calloc(1, sizeof(ALbuffer));
1353 if(!buffer)
1354 SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
1355 RWLockInit(&buffer->lock);
1357 err = NewThunkEntry(&buffer->id);
1358 if(err == AL_NO_ERROR)
1359 err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer);
1360 if(err != AL_NO_ERROR)
1362 FreeThunkEntry(buffer->id);
1363 memset(buffer, 0, sizeof(ALbuffer));
1364 free(buffer);
1366 SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
1369 return buffer;
1372 void DeleteBuffer(ALCdevice *device, ALbuffer *buffer)
1374 RemoveBuffer(device, buffer->id);
1375 FreeThunkEntry(buffer->id);
1377 free(buffer->data);
1379 memset(buffer, 0, sizeof(*buffer));
1380 free(buffer);
1385 * ReleaseALBuffers()
1387 * INTERNAL: Called to destroy any buffers that still exist on the device
1389 ALvoid ReleaseALBuffers(ALCdevice *device)
1391 ALsizei i;
1392 for(i = 0;i < device->BufferMap.size;i++)
1394 ALbuffer *temp = device->BufferMap.array[i].value;
1395 device->BufferMap.array[i].value = NULL;
1397 free(temp->data);
1399 FreeThunkEntry(temp->id);
1400 memset(temp, 0, sizeof(ALbuffer));
1401 free(temp);