Store the output limiter values as fixed-point integers
[openal-soft.git] / OpenAL32 / alBuffer.c
blob376741bdd1f3c30c6895cda6a11b60c8351c271f
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 ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
46 extern inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
48 static ALboolean IsValidType(ALenum type);
49 static ALboolean IsValidChannels(ALenum channels);
50 static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type);
51 static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type);
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 = UserFmtMono;
143 enum UserFmtType srctype = UserFmtByte;
144 ALCdevice *device;
145 ALCcontext *context;
146 ALbuffer *albuf;
147 ALenum newformat = AL_NONE;
148 ALsizei 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_SEQ(&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 UserFmtDouble:
187 framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
188 if((size%framesize) != 0)
189 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
191 switch(srcchannels)
193 case UserFmtMono: newformat = AL_FORMAT_MONO_FLOAT32; break;
194 case UserFmtStereo: newformat = AL_FORMAT_STEREO_FLOAT32; break;
195 case UserFmtRear: newformat = AL_FORMAT_REAR32; break;
196 case UserFmtQuad: newformat = AL_FORMAT_QUAD32; break;
197 case UserFmtX51: newformat = AL_FORMAT_51CHN32; break;
198 case UserFmtX61: newformat = AL_FORMAT_61CHN32; break;
199 case UserFmtX71: newformat = AL_FORMAT_71CHN32; break;
200 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_FLOAT32; break;
201 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_FLOAT32; break;
203 err = LoadData(albuf, freq, newformat, size/framesize*align,
204 srcchannels, srctype, data, align, AL_TRUE);
205 if(err != AL_NO_ERROR)
206 SET_ERROR_AND_GOTO(context, err, done);
207 break;
209 case UserFmtMulaw:
210 case UserFmtAlaw:
211 framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
212 if((size%framesize) != 0)
213 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
215 switch(srcchannels)
217 case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
218 case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
219 case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
220 case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
221 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
222 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
223 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
224 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
225 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
227 err = LoadData(albuf, freq, newformat, size/framesize*align,
228 srcchannels, srctype, data, align, AL_TRUE);
229 if(err != AL_NO_ERROR)
230 SET_ERROR_AND_GOTO(context, err, done);
231 break;
233 case UserFmtIMA4:
234 framesize = (align-1)/2 + 4;
235 framesize *= ChannelsFromUserFmt(srcchannels);
236 if((size%framesize) != 0)
237 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
239 switch(srcchannels)
241 case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
242 case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
243 case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
244 case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
245 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
246 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
247 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
248 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
249 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
251 err = LoadData(albuf, freq, newformat, size/framesize*align,
252 srcchannels, srctype, data, align, AL_TRUE);
253 if(err != AL_NO_ERROR)
254 SET_ERROR_AND_GOTO(context, err, done);
255 break;
257 case UserFmtMSADPCM:
258 framesize = (align-2)/2 + 7;
259 framesize *= ChannelsFromUserFmt(srcchannels);
260 if((size%framesize) != 0)
261 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
263 switch(srcchannels)
265 case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
266 case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
267 case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
268 case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
269 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
270 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
271 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
272 case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
273 case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
275 err = LoadData(albuf, freq, newformat, size/framesize*align,
276 srcchannels, srctype, data, align, AL_TRUE);
277 if(err != AL_NO_ERROR)
278 SET_ERROR_AND_GOTO(context, err, done);
279 break;
282 done:
283 UnlockBuffersRead(device);
284 ALCcontext_DecRef(context);
287 AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length)
289 enum UserFmtChannels srcchannels = UserFmtMono;
290 enum UserFmtType srctype = UserFmtByte;
291 ALCdevice *device;
292 ALCcontext *context;
293 ALbuffer *albuf;
294 ALsizei byte_align;
295 ALsizei channels;
296 ALsizei bytes;
297 ALsizei align;
299 context = GetContextRef();
300 if(!context) return;
302 device = context->Device;
303 LockBuffersRead(device);
304 if((albuf=LookupBuffer(device, buffer)) == NULL)
305 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
306 if(!(length >= 0 && offset >= 0))
307 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
308 if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
309 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
311 WriteLock(&albuf->lock);
312 align = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
313 if(SanitizeAlignment(srctype, &align) == AL_FALSE)
315 WriteUnlock(&albuf->lock);
316 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
318 if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType)
320 WriteUnlock(&albuf->lock);
321 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
323 if(align != albuf->OriginalAlign)
325 WriteUnlock(&albuf->lock);
326 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
329 if(albuf->OriginalType == UserFmtIMA4)
331 byte_align = (albuf->OriginalAlign-1)/2 + 4;
332 byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
334 else if(albuf->OriginalType == UserFmtMSADPCM)
336 byte_align = (albuf->OriginalAlign-2)/2 + 7;
337 byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
339 else
341 byte_align = albuf->OriginalAlign;
342 byte_align *= FrameSizeFromUserFmt(albuf->OriginalChannels,
343 albuf->OriginalType);
346 if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset ||
347 (offset%byte_align) != 0 || (length%byte_align) != 0)
349 WriteUnlock(&albuf->lock);
350 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
353 channels = ChannelsFromFmt(albuf->FmtChannels);
354 bytes = BytesFromFmt(albuf->FmtType);
355 /* offset -> byte offset, length -> sample count */
356 offset = offset/byte_align * channels*bytes;
357 length = length/byte_align * albuf->OriginalAlign;
359 ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
360 data, srctype, channels, length, align);
361 WriteUnlock(&albuf->lock);
363 done:
364 UnlockBuffersRead(device);
365 ALCcontext_DecRef(context);
369 AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
370 ALuint samplerate, ALenum internalformat, ALsizei samples,
371 ALenum channels, ALenum type, const ALvoid *data)
373 ALCdevice *device;
374 ALCcontext *context;
375 ALbuffer *albuf;
376 ALsizei align;
377 ALenum err;
379 context = GetContextRef();
380 if(!context) return;
382 device = context->Device;
383 LockBuffersRead(device);
384 if((albuf=LookupBuffer(device, buffer)) == NULL)
385 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
386 if(!(samples >= 0 && samplerate != 0))
387 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
388 if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
389 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
391 align = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
392 if(SanitizeAlignment(type, &align) == AL_FALSE)
393 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
394 if((samples%align) != 0)
395 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
397 err = LoadData(albuf, samplerate, internalformat, samples,
398 channels, type, data, align, AL_FALSE);
399 if(err != AL_NO_ERROR)
400 SET_ERROR_AND_GOTO(context, err, done);
402 done:
403 UnlockBuffersRead(device);
404 ALCcontext_DecRef(context);
407 AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
408 ALsizei offset, ALsizei samples,
409 ALenum channels, ALenum type, const ALvoid *data)
411 ALCdevice *device;
412 ALCcontext *context;
413 ALbuffer *albuf;
414 ALsizei align;
416 context = GetContextRef();
417 if(!context) return;
419 device = context->Device;
420 LockBuffersRead(device);
421 if((albuf=LookupBuffer(device, buffer)) == NULL)
422 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
423 if(!(samples >= 0 && offset >= 0))
424 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
425 if(IsValidType(type) == AL_FALSE)
426 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
428 WriteLock(&albuf->lock);
429 align = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
430 if(SanitizeAlignment(type, &align) == AL_FALSE)
432 WriteUnlock(&albuf->lock);
433 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
435 if(channels != (ALenum)albuf->FmtChannels)
437 WriteUnlock(&albuf->lock);
438 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
440 if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
442 WriteUnlock(&albuf->lock);
443 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
445 if((samples%align) != 0)
447 WriteUnlock(&albuf->lock);
448 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
451 /* offset -> byte offset */
452 offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
453 ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
454 data, type, ChannelsFromFmt(albuf->FmtChannels), samples, align);
455 WriteUnlock(&albuf->lock);
457 done:
458 UnlockBuffersRead(device);
459 ALCcontext_DecRef(context);
462 AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
463 ALsizei offset, ALsizei samples,
464 ALenum channels, ALenum type, ALvoid *data)
466 ALCdevice *device;
467 ALCcontext *context;
468 ALbuffer *albuf;
469 ALsizei align;
471 context = GetContextRef();
472 if(!context) return;
474 device = context->Device;
475 LockBuffersRead(device);
476 if((albuf=LookupBuffer(device, buffer)) == NULL)
477 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
478 if(!(samples >= 0 && offset >= 0))
479 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
480 if(IsValidType(type) == AL_FALSE)
481 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
483 ReadLock(&albuf->lock);
484 align = ATOMIC_LOAD_SEQ(&albuf->PackAlign);
485 if(SanitizeAlignment(type, &align) == AL_FALSE)
487 ReadUnlock(&albuf->lock);
488 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
490 if(channels != (ALenum)albuf->FmtChannels)
492 ReadUnlock(&albuf->lock);
493 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
495 if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
497 ReadUnlock(&albuf->lock);
498 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
500 if((samples%align) != 0)
502 ReadUnlock(&albuf->lock);
503 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
506 /* offset -> byte offset */
507 offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
508 ConvertData(data, type, (char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
509 ChannelsFromFmt(albuf->FmtChannels), samples, align);
510 ReadUnlock(&albuf->lock);
512 done:
513 UnlockBuffersRead(device);
514 ALCcontext_DecRef(context);
517 AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format)
519 enum FmtChannels dstchannels;
520 enum FmtType dsttype;
521 ALCcontext *context;
522 ALboolean ret;
524 context = GetContextRef();
525 if(!context) return AL_FALSE;
527 ret = DecomposeFormat(format, &dstchannels, &dsttype);
529 ALCcontext_DecRef(context);
531 return ret;
535 AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(value))
537 ALCdevice *device;
538 ALCcontext *context;
540 context = GetContextRef();
541 if(!context) return;
543 device = context->Device;
544 LockBuffersRead(device);
545 if(LookupBuffer(device, buffer) == NULL)
546 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
548 switch(param)
550 default:
551 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
554 done:
555 UnlockBuffersRead(device);
556 ALCcontext_DecRef(context);
560 AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(value1), ALfloat UNUSED(value2), ALfloat UNUSED(value3))
562 ALCdevice *device;
563 ALCcontext *context;
565 context = GetContextRef();
566 if(!context) return;
568 device = context->Device;
569 LockBuffersRead(device);
570 if(LookupBuffer(device, buffer) == NULL)
571 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
573 switch(param)
575 default:
576 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
579 done:
580 UnlockBuffersRead(device);
581 ALCcontext_DecRef(context);
585 AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values)
587 ALCdevice *device;
588 ALCcontext *context;
590 context = GetContextRef();
591 if(!context) return;
593 device = context->Device;
594 LockBuffersRead(device);
595 if(LookupBuffer(device, buffer) == NULL)
596 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
598 if(!(values))
599 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
600 switch(param)
602 default:
603 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
606 done:
607 UnlockBuffersRead(device);
608 ALCcontext_DecRef(context);
612 AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
614 ALCdevice *device;
615 ALCcontext *context;
616 ALbuffer *albuf;
618 context = GetContextRef();
619 if(!context) return;
621 device = context->Device;
622 LockBuffersRead(device);
623 if((albuf=LookupBuffer(device, buffer)) == NULL)
624 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
626 switch(param)
628 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
629 if(!(value >= 0))
630 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
631 ATOMIC_STORE_SEQ(&albuf->UnpackAlign, value);
632 break;
634 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
635 if(!(value >= 0))
636 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
637 ATOMIC_STORE_SEQ(&albuf->PackAlign, value);
638 break;
640 default:
641 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
644 done:
645 UnlockBuffersRead(device);
646 ALCcontext_DecRef(context);
650 AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint UNUSED(value1), ALint UNUSED(value2), ALint UNUSED(value3))
652 ALCdevice *device;
653 ALCcontext *context;
655 context = GetContextRef();
656 if(!context) return;
658 device = context->Device;
659 if(LookupBuffer(device, buffer) == NULL)
660 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
662 switch(param)
664 default:
665 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
668 done:
669 ALCcontext_DecRef(context);
673 AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values)
675 ALCdevice *device;
676 ALCcontext *context;
677 ALbuffer *albuf;
679 if(values)
681 switch(param)
683 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
684 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
685 alBufferi(buffer, param, values[0]);
686 return;
690 context = GetContextRef();
691 if(!context) return;
693 device = context->Device;
694 LockBuffersRead(device);
695 if((albuf=LookupBuffer(device, buffer)) == NULL)
696 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
698 if(!(values))
699 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
700 switch(param)
702 case AL_LOOP_POINTS_SOFT:
703 WriteLock(&albuf->lock);
704 if(ReadRef(&albuf->ref) != 0)
706 WriteUnlock(&albuf->lock);
707 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
709 if(values[0] >= values[1] || values[0] < 0 ||
710 values[1] > albuf->SampleLen)
712 WriteUnlock(&albuf->lock);
713 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
716 albuf->LoopStart = values[0];
717 albuf->LoopEnd = values[1];
718 WriteUnlock(&albuf->lock);
719 break;
721 default:
722 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
725 done:
726 UnlockBuffersRead(device);
727 ALCcontext_DecRef(context);
731 AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value)
733 ALCdevice *device;
734 ALCcontext *context;
735 ALbuffer *albuf;
737 context = GetContextRef();
738 if(!context) return;
740 device = context->Device;
741 LockBuffersRead(device);
742 if((albuf=LookupBuffer(device, buffer)) == NULL)
743 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
745 if(!(value))
746 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
747 switch(param)
749 case AL_SEC_LENGTH_SOFT:
750 ReadLock(&albuf->lock);
751 if(albuf->SampleLen != 0)
752 *value = albuf->SampleLen / (ALfloat)albuf->Frequency;
753 else
754 *value = 0.0f;
755 ReadUnlock(&albuf->lock);
756 break;
758 default:
759 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
762 done:
763 UnlockBuffersRead(device);
764 ALCcontext_DecRef(context);
768 AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
770 ALCdevice *device;
771 ALCcontext *context;
773 context = GetContextRef();
774 if(!context) return;
776 device = context->Device;
777 LockBuffersRead(device);
778 if(LookupBuffer(device, buffer) == NULL)
779 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
781 if(!(value1 && value2 && value3))
782 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
783 switch(param)
785 default:
786 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
789 done:
790 UnlockBuffersRead(device);
791 ALCcontext_DecRef(context);
795 AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values)
797 ALCdevice *device;
798 ALCcontext *context;
800 switch(param)
802 case AL_SEC_LENGTH_SOFT:
803 alGetBufferf(buffer, param, values);
804 return;
807 context = GetContextRef();
808 if(!context) return;
810 device = context->Device;
811 LockBuffersRead(device);
812 if(LookupBuffer(device, buffer) == NULL)
813 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
815 if(!(values))
816 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
817 switch(param)
819 default:
820 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
823 done:
824 UnlockBuffersRead(device);
825 ALCcontext_DecRef(context);
829 AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value)
831 ALCdevice *device;
832 ALCcontext *context;
833 ALbuffer *albuf;
835 context = GetContextRef();
836 if(!context) return;
838 device = context->Device;
839 LockBuffersRead(device);
840 if((albuf=LookupBuffer(device, buffer)) == NULL)
841 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
843 if(!(value))
844 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
845 switch(param)
847 case AL_FREQUENCY:
848 *value = albuf->Frequency;
849 break;
851 case AL_BITS:
852 *value = BytesFromFmt(albuf->FmtType) * 8;
853 break;
855 case AL_CHANNELS:
856 *value = ChannelsFromFmt(albuf->FmtChannels);
857 break;
859 case AL_SIZE:
860 ReadLock(&albuf->lock);
861 *value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels,
862 albuf->FmtType);
863 ReadUnlock(&albuf->lock);
864 break;
866 case AL_INTERNAL_FORMAT_SOFT:
867 *value = albuf->Format;
868 break;
870 case AL_BYTE_LENGTH_SOFT:
871 *value = albuf->OriginalSize;
872 break;
874 case AL_SAMPLE_LENGTH_SOFT:
875 *value = albuf->SampleLen;
876 break;
878 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
879 *value = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
880 break;
882 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
883 *value = ATOMIC_LOAD_SEQ(&albuf->PackAlign);
884 break;
886 default:
887 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
890 done:
891 UnlockBuffersRead(device);
892 ALCcontext_DecRef(context);
896 AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3)
898 ALCdevice *device;
899 ALCcontext *context;
901 context = GetContextRef();
902 if(!context) return;
904 device = context->Device;
905 LockBuffersRead(device);
906 if(LookupBuffer(device, buffer) == NULL)
907 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
909 if(!(value1 && value2 && value3))
910 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
911 switch(param)
913 default:
914 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
917 done:
918 UnlockBuffersRead(device);
919 ALCcontext_DecRef(context);
923 AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values)
925 ALCdevice *device;
926 ALCcontext *context;
927 ALbuffer *albuf;
929 switch(param)
931 case AL_FREQUENCY:
932 case AL_BITS:
933 case AL_CHANNELS:
934 case AL_SIZE:
935 case AL_INTERNAL_FORMAT_SOFT:
936 case AL_BYTE_LENGTH_SOFT:
937 case AL_SAMPLE_LENGTH_SOFT:
938 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
939 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
940 alGetBufferi(buffer, param, values);
941 return;
944 context = GetContextRef();
945 if(!context) return;
947 device = context->Device;
948 LockBuffersRead(device);
949 if((albuf=LookupBuffer(device, buffer)) == NULL)
950 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
952 if(!(values))
953 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
954 switch(param)
956 case AL_LOOP_POINTS_SOFT:
957 ReadLock(&albuf->lock);
958 values[0] = albuf->LoopStart;
959 values[1] = albuf->LoopEnd;
960 ReadUnlock(&albuf->lock);
961 break;
963 default:
964 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
967 done:
968 UnlockBuffersRead(device);
969 ALCcontext_DecRef(context);
974 * LoadData
976 * Loads the specified data into the buffer, using the specified formats.
977 * Currently, the new format must have the same channel configuration as the
978 * original format.
980 ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc)
982 enum FmtChannels DstChannels = FmtMono;
983 enum FmtType DstType = FmtByte;
984 ALuint NewChannels, NewBytes;
985 ALuint64 newsize;
987 if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE)
988 return AL_INVALID_ENUM;
989 if((long)SrcChannels != (long)DstChannels)
990 return AL_INVALID_ENUM;
992 NewChannels = ChannelsFromFmt(DstChannels);
993 NewBytes = BytesFromFmt(DstType);
995 newsize = frames;
996 newsize *= NewBytes;
997 newsize *= NewChannels;
998 if(newsize > INT_MAX)
999 return AL_OUT_OF_MEMORY;
1001 WriteLock(&ALBuf->lock);
1002 if(ReadRef(&ALBuf->ref) != 0)
1004 WriteUnlock(&ALBuf->lock);
1005 return AL_INVALID_OPERATION;
1008 /* Round up to the next 16-byte multiple. This could reallocate only when
1009 * increasing or the new size is less than half the current, but then the
1010 * buffer's AL_SIZE would not be very reliable for accounting buffer memory
1011 * usage, and reporting the real size could cause problems for apps that
1012 * use AL_SIZE to try to get the buffer's play length.
1014 newsize = (newsize+15) & ~0xf;
1015 if(newsize != ALBuf->BytesAlloc)
1017 void *temp = al_calloc(16, (size_t)newsize);
1018 if(!temp && newsize)
1020 WriteUnlock(&ALBuf->lock);
1021 return AL_OUT_OF_MEMORY;
1023 al_free(ALBuf->data);
1024 ALBuf->data = temp;
1025 ALBuf->BytesAlloc = (ALuint)newsize;
1028 if(data != NULL)
1029 ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align);
1031 if(storesrc)
1033 ALBuf->OriginalChannels = SrcChannels;
1034 ALBuf->OriginalType = SrcType;
1035 if(SrcType == UserFmtIMA4)
1037 ALsizei byte_align = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels);
1038 ALBuf->OriginalSize = frames / align * byte_align;
1039 ALBuf->OriginalAlign = align;
1041 else if(SrcType == UserFmtMSADPCM)
1043 ALsizei byte_align = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels);
1044 ALBuf->OriginalSize = frames / align * byte_align;
1045 ALBuf->OriginalAlign = align;
1047 else
1049 ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType);
1050 ALBuf->OriginalAlign = 1;
1053 else
1055 ALBuf->OriginalChannels = (enum UserFmtChannels)DstChannels;
1056 ALBuf->OriginalType = (enum UserFmtType)DstType;
1057 ALBuf->OriginalSize = frames * NewBytes * NewChannels;
1058 ALBuf->OriginalAlign = 1;
1061 ALBuf->Frequency = freq;
1062 ALBuf->FmtChannels = DstChannels;
1063 ALBuf->FmtType = DstType;
1064 ALBuf->Format = NewFormat;
1066 ALBuf->SampleLen = frames;
1067 ALBuf->LoopStart = 0;
1068 ALBuf->LoopEnd = ALBuf->SampleLen;
1070 WriteUnlock(&ALBuf->lock);
1071 return AL_NO_ERROR;
1075 ALsizei BytesFromUserFmt(enum UserFmtType type)
1077 switch(type)
1079 case UserFmtByte: return sizeof(ALbyte);
1080 case UserFmtUByte: return sizeof(ALubyte);
1081 case UserFmtShort: return sizeof(ALshort);
1082 case UserFmtUShort: return sizeof(ALushort);
1083 case UserFmtInt: return sizeof(ALint);
1084 case UserFmtUInt: return sizeof(ALuint);
1085 case UserFmtFloat: return sizeof(ALfloat);
1086 case UserFmtDouble: return sizeof(ALdouble);
1087 case UserFmtMulaw: return sizeof(ALubyte);
1088 case UserFmtAlaw: return sizeof(ALubyte);
1089 case UserFmtIMA4: break; /* not handled here */
1090 case UserFmtMSADPCM: break; /* not handled here */
1092 return 0;
1094 ALsizei ChannelsFromUserFmt(enum UserFmtChannels chans)
1096 switch(chans)
1098 case UserFmtMono: return 1;
1099 case UserFmtStereo: return 2;
1100 case UserFmtRear: return 2;
1101 case UserFmtQuad: return 4;
1102 case UserFmtX51: return 6;
1103 case UserFmtX61: return 7;
1104 case UserFmtX71: return 8;
1105 case UserFmtBFormat2D: return 3;
1106 case UserFmtBFormat3D: return 4;
1108 return 0;
1110 static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
1111 enum UserFmtType *type)
1113 static const struct {
1114 ALenum format;
1115 enum UserFmtChannels channels;
1116 enum UserFmtType type;
1117 } list[] = {
1118 { AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte },
1119 { AL_FORMAT_MONO16, UserFmtMono, UserFmtShort },
1120 { AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat },
1121 { AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble },
1122 { AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 },
1123 { AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM },
1124 { AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw },
1125 { AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw },
1127 { AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte },
1128 { AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort },
1129 { AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat },
1130 { AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble },
1131 { AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 },
1132 { AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM },
1133 { AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw },
1134 { AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw },
1136 { AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte },
1137 { AL_FORMAT_REAR16, UserFmtRear, UserFmtShort },
1138 { AL_FORMAT_REAR32, UserFmtRear, UserFmtFloat },
1139 { AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw },
1141 { AL_FORMAT_QUAD8_LOKI, UserFmtQuad, UserFmtUByte },
1142 { AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort },
1144 { AL_FORMAT_QUAD8, UserFmtQuad, UserFmtUByte },
1145 { AL_FORMAT_QUAD16, UserFmtQuad, UserFmtShort },
1146 { AL_FORMAT_QUAD32, UserFmtQuad, UserFmtFloat },
1147 { AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw },
1149 { AL_FORMAT_51CHN8, UserFmtX51, UserFmtUByte },
1150 { AL_FORMAT_51CHN16, UserFmtX51, UserFmtShort },
1151 { AL_FORMAT_51CHN32, UserFmtX51, UserFmtFloat },
1152 { AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw },
1154 { AL_FORMAT_61CHN8, UserFmtX61, UserFmtUByte },
1155 { AL_FORMAT_61CHN16, UserFmtX61, UserFmtShort },
1156 { AL_FORMAT_61CHN32, UserFmtX61, UserFmtFloat },
1157 { AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw },
1159 { AL_FORMAT_71CHN8, UserFmtX71, UserFmtUByte },
1160 { AL_FORMAT_71CHN16, UserFmtX71, UserFmtShort },
1161 { AL_FORMAT_71CHN32, UserFmtX71, UserFmtFloat },
1162 { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw },
1164 { AL_FORMAT_BFORMAT2D_8, UserFmtBFormat2D, UserFmtUByte },
1165 { AL_FORMAT_BFORMAT2D_16, UserFmtBFormat2D, UserFmtShort },
1166 { AL_FORMAT_BFORMAT2D_FLOAT32, UserFmtBFormat2D, UserFmtFloat },
1167 { AL_FORMAT_BFORMAT2D_MULAW, UserFmtBFormat2D, UserFmtMulaw },
1169 { AL_FORMAT_BFORMAT3D_8, UserFmtBFormat3D, UserFmtUByte },
1170 { AL_FORMAT_BFORMAT3D_16, UserFmtBFormat3D, UserFmtShort },
1171 { AL_FORMAT_BFORMAT3D_FLOAT32, UserFmtBFormat3D, UserFmtFloat },
1172 { AL_FORMAT_BFORMAT3D_MULAW, UserFmtBFormat3D, UserFmtMulaw },
1174 ALuint i;
1176 for(i = 0;i < COUNTOF(list);i++)
1178 if(list[i].format == format)
1180 *chans = list[i].channels;
1181 *type = list[i].type;
1182 return AL_TRUE;
1186 return AL_FALSE;
1189 ALsizei BytesFromFmt(enum FmtType type)
1191 switch(type)
1193 case FmtByte: return sizeof(ALbyte);
1194 case FmtShort: return sizeof(ALshort);
1195 case FmtFloat: return sizeof(ALfloat);
1197 return 0;
1199 ALsizei ChannelsFromFmt(enum FmtChannels chans)
1201 switch(chans)
1203 case FmtMono: return 1;
1204 case FmtStereo: return 2;
1205 case FmtRear: return 2;
1206 case FmtQuad: return 4;
1207 case FmtX51: return 6;
1208 case FmtX61: return 7;
1209 case FmtX71: return 8;
1210 case FmtBFormat2D: return 3;
1211 case FmtBFormat3D: return 4;
1213 return 0;
1215 static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type)
1217 static const struct {
1218 ALenum format;
1219 enum FmtChannels channels;
1220 enum FmtType type;
1221 } list[] = {
1222 { AL_MONO8_SOFT, FmtMono, FmtByte },
1223 { AL_MONO16_SOFT, FmtMono, FmtShort },
1224 { AL_MONO32F_SOFT, FmtMono, FmtFloat },
1226 { AL_STEREO8_SOFT, FmtStereo, FmtByte },
1227 { AL_STEREO16_SOFT, FmtStereo, FmtShort },
1228 { AL_STEREO32F_SOFT, FmtStereo, FmtFloat },
1230 { AL_REAR8_SOFT, FmtRear, FmtByte },
1231 { AL_REAR16_SOFT, FmtRear, FmtShort },
1232 { AL_REAR32F_SOFT, FmtRear, FmtFloat },
1234 { AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtByte },
1235 { AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort },
1237 { AL_QUAD8_SOFT, FmtQuad, FmtByte },
1238 { AL_QUAD16_SOFT, FmtQuad, FmtShort },
1239 { AL_QUAD32F_SOFT, FmtQuad, FmtFloat },
1241 { AL_5POINT1_8_SOFT, FmtX51, FmtByte },
1242 { AL_5POINT1_16_SOFT, FmtX51, FmtShort },
1243 { AL_5POINT1_32F_SOFT, FmtX51, FmtFloat },
1245 { AL_6POINT1_8_SOFT, FmtX61, FmtByte },
1246 { AL_6POINT1_16_SOFT, FmtX61, FmtShort },
1247 { AL_6POINT1_32F_SOFT, FmtX61, FmtFloat },
1249 { AL_7POINT1_8_SOFT, FmtX71, FmtByte },
1250 { AL_7POINT1_16_SOFT, FmtX71, FmtShort },
1251 { AL_7POINT1_32F_SOFT, FmtX71, FmtFloat },
1253 { AL_BFORMAT2D_8_SOFT, FmtBFormat2D, FmtByte },
1254 { AL_BFORMAT2D_16_SOFT, FmtBFormat2D, FmtShort },
1255 { AL_BFORMAT2D_32F_SOFT, FmtBFormat2D, FmtFloat },
1257 { AL_BFORMAT3D_8_SOFT, FmtBFormat3D, FmtByte },
1258 { AL_BFORMAT3D_16_SOFT, FmtBFormat3D, FmtShort },
1259 { AL_BFORMAT3D_32F_SOFT, FmtBFormat3D, FmtFloat },
1261 ALuint i;
1263 for(i = 0;i < COUNTOF(list);i++)
1265 if(list[i].format == format)
1267 *chans = list[i].channels;
1268 *type = list[i].type;
1269 return AL_TRUE;
1273 return AL_FALSE;
1276 static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align)
1278 if(*align < 0)
1279 return AL_FALSE;
1281 if(*align == 0)
1283 if(type == UserFmtIMA4)
1285 /* Here is where things vary:
1286 * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
1287 * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
1289 *align = 65;
1291 else if(type == UserFmtMSADPCM)
1292 *align = 64;
1293 else
1294 *align = 1;
1295 return AL_TRUE;
1298 if(type == UserFmtIMA4)
1300 /* IMA4 block alignment must be a multiple of 8, plus 1. */
1301 return ((*align)&7) == 1;
1303 if(type == UserFmtMSADPCM)
1305 /* MSADPCM block alignment must be a multiple of 2. */
1306 /* FIXME: Too strict? Might only require align*channels to be a
1307 * multiple of 2. */
1308 return ((*align)&1) == 0;
1311 return AL_TRUE;
1315 static ALboolean IsValidType(ALenum type)
1317 switch(type)
1319 case AL_BYTE_SOFT:
1320 case AL_UNSIGNED_BYTE_SOFT:
1321 case AL_SHORT_SOFT:
1322 case AL_UNSIGNED_SHORT_SOFT:
1323 case AL_INT_SOFT:
1324 case AL_UNSIGNED_INT_SOFT:
1325 case AL_FLOAT_SOFT:
1326 case AL_DOUBLE_SOFT:
1327 case AL_MULAW_SOFT:
1328 return AL_TRUE;
1330 return AL_FALSE;
1333 static ALboolean IsValidChannels(ALenum channels)
1335 switch(channels)
1337 case AL_MONO_SOFT:
1338 case AL_STEREO_SOFT:
1339 case AL_REAR_SOFT:
1340 case AL_QUAD_SOFT:
1341 case AL_5POINT1_SOFT:
1342 case AL_6POINT1_SOFT:
1343 case AL_7POINT1_SOFT:
1344 case AL_BFORMAT2D_SOFT:
1345 case AL_BFORMAT3D_SOFT:
1346 return AL_TRUE;
1348 return AL_FALSE;
1352 ALbuffer *NewBuffer(ALCcontext *context)
1354 ALCdevice *device = context->Device;
1355 ALbuffer *buffer;
1356 ALenum err;
1358 buffer = al_calloc(16, sizeof(ALbuffer));
1359 if(!buffer)
1360 SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
1361 RWLockInit(&buffer->lock);
1363 err = NewThunkEntry(&buffer->id);
1364 if(err == AL_NO_ERROR)
1365 err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer);
1366 if(err != AL_NO_ERROR)
1368 FreeThunkEntry(buffer->id);
1369 memset(buffer, 0, sizeof(ALbuffer));
1370 al_free(buffer);
1372 SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
1375 return buffer;
1378 void DeleteBuffer(ALCdevice *device, ALbuffer *buffer)
1380 RemoveBuffer(device, buffer->id);
1381 FreeThunkEntry(buffer->id);
1383 al_free(buffer->data);
1385 memset(buffer, 0, sizeof(*buffer));
1386 al_free(buffer);
1391 * ReleaseALBuffers()
1393 * INTERNAL: Called to destroy any buffers that still exist on the device
1395 ALvoid ReleaseALBuffers(ALCdevice *device)
1397 ALsizei i;
1398 for(i = 0;i < device->BufferMap.size;i++)
1400 ALbuffer *temp = device->BufferMap.values[i];
1401 device->BufferMap.values[i] = NULL;
1403 al_free(temp->data);
1405 FreeThunkEntry(temp->id);
1406 memset(temp, 0, sizeof(ALbuffer));
1407 al_free(temp);