Use separate macros for atomics that don't take a memory order
[openal-soft.git] / OpenAL32 / alBuffer.c
blob24470d64a9cfb2fe33684f3b24d3b7a7c9ffeac3
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);
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 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_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 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 = UserFmtMono;
292 enum UserFmtType srctype = UserFmtByte;
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_SEQ(&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_SEQ(&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_SEQ(&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_SEQ(&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_SEQ(&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_SEQ(&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_SEQ(&albuf->UnpackAlign);
882 break;
884 case AL_PACK_BLOCK_ALIGNMENT_SOFT:
885 *value = ATOMIC_LOAD_SEQ(&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 enum FmtChannels DstChannels = FmtMono;
985 enum FmtType DstType = FmtByte;
986 ALuint NewChannels, NewBytes;
987 ALuint64 newsize;
989 if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE)
990 return AL_INVALID_ENUM;
991 if((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 /* Round up to the next 16-byte multiple. This could reallocate only when
1011 * increasing or the new size is less than half the current, but then the
1012 * buffer's AL_SIZE would not be very reliable for accounting buffer memory
1013 * usage, and reporting the real size could cause problems for apps that
1014 * use AL_SIZE to try to get the buffer's play length.
1016 newsize = (newsize+15) & ~0xf;
1017 if(newsize != ALBuf->BytesAlloc)
1019 void *temp = al_calloc(16, (size_t)newsize);
1020 if(!temp && newsize)
1022 WriteUnlock(&ALBuf->lock);
1023 return AL_OUT_OF_MEMORY;
1025 al_free(ALBuf->data);
1026 ALBuf->data = temp;
1027 ALBuf->BytesAlloc = (ALuint)newsize;
1030 if(data != NULL)
1031 ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align);
1033 if(storesrc)
1035 ALBuf->OriginalChannels = SrcChannels;
1036 ALBuf->OriginalType = SrcType;
1037 if(SrcType == UserFmtIMA4)
1039 ALsizei byte_align = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels);
1040 ALBuf->OriginalSize = frames / align * byte_align;
1041 ALBuf->OriginalAlign = align;
1043 else if(SrcType == UserFmtMSADPCM)
1045 ALsizei byte_align = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels);
1046 ALBuf->OriginalSize = frames / align * byte_align;
1047 ALBuf->OriginalAlign = align;
1049 else
1051 ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType);
1052 ALBuf->OriginalAlign = 1;
1055 else
1057 ALBuf->OriginalChannels = (enum UserFmtChannels)DstChannels;
1058 ALBuf->OriginalType = (enum UserFmtType)DstType;
1059 ALBuf->OriginalSize = frames * NewBytes * NewChannels;
1060 ALBuf->OriginalAlign = 1;
1063 ALBuf->Frequency = freq;
1064 ALBuf->FmtChannels = DstChannels;
1065 ALBuf->FmtType = DstType;
1066 ALBuf->Format = NewFormat;
1068 ALBuf->SampleLen = frames;
1069 ALBuf->LoopStart = 0;
1070 ALBuf->LoopEnd = ALBuf->SampleLen;
1072 WriteUnlock(&ALBuf->lock);
1073 return AL_NO_ERROR;
1077 ALuint BytesFromUserFmt(enum UserFmtType type)
1079 switch(type)
1081 case UserFmtByte: return sizeof(ALbyte);
1082 case UserFmtUByte: return sizeof(ALubyte);
1083 case UserFmtShort: return sizeof(ALshort);
1084 case UserFmtUShort: return sizeof(ALushort);
1085 case UserFmtInt: return sizeof(ALint);
1086 case UserFmtUInt: return sizeof(ALuint);
1087 case UserFmtFloat: return sizeof(ALfloat);
1088 case UserFmtDouble: return sizeof(ALdouble);
1089 case UserFmtByte3: return sizeof(ALbyte[3]);
1090 case UserFmtUByte3: return sizeof(ALubyte[3]);
1091 case UserFmtMulaw: return sizeof(ALubyte);
1092 case UserFmtAlaw: return sizeof(ALubyte);
1093 case UserFmtIMA4: break; /* not handled here */
1094 case UserFmtMSADPCM: break; /* not handled here */
1096 return 0;
1098 ALuint ChannelsFromUserFmt(enum UserFmtChannels chans)
1100 switch(chans)
1102 case UserFmtMono: return 1;
1103 case UserFmtStereo: return 2;
1104 case UserFmtRear: return 2;
1105 case UserFmtQuad: return 4;
1106 case UserFmtX51: return 6;
1107 case UserFmtX61: return 7;
1108 case UserFmtX71: return 8;
1109 case UserFmtBFormat2D: return 3;
1110 case UserFmtBFormat3D: return 4;
1112 return 0;
1114 static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
1115 enum UserFmtType *type)
1117 static const struct {
1118 ALenum format;
1119 enum UserFmtChannels channels;
1120 enum UserFmtType type;
1121 } list[] = {
1122 { AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte },
1123 { AL_FORMAT_MONO16, UserFmtMono, UserFmtShort },
1124 { AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat },
1125 { AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble },
1126 { AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 },
1127 { AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM },
1128 { AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw },
1129 { AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw },
1131 { AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte },
1132 { AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort },
1133 { AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat },
1134 { AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble },
1135 { AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 },
1136 { AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM },
1137 { AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw },
1138 { AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw },
1140 { AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte },
1141 { AL_FORMAT_REAR16, UserFmtRear, UserFmtShort },
1142 { AL_FORMAT_REAR32, UserFmtRear, UserFmtFloat },
1143 { AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw },
1145 { AL_FORMAT_QUAD8_LOKI, UserFmtQuad, UserFmtUByte },
1146 { AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort },
1148 { AL_FORMAT_QUAD8, UserFmtQuad, UserFmtUByte },
1149 { AL_FORMAT_QUAD16, UserFmtQuad, UserFmtShort },
1150 { AL_FORMAT_QUAD32, UserFmtQuad, UserFmtFloat },
1151 { AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw },
1153 { AL_FORMAT_51CHN8, UserFmtX51, UserFmtUByte },
1154 { AL_FORMAT_51CHN16, UserFmtX51, UserFmtShort },
1155 { AL_FORMAT_51CHN32, UserFmtX51, UserFmtFloat },
1156 { AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw },
1158 { AL_FORMAT_61CHN8, UserFmtX61, UserFmtUByte },
1159 { AL_FORMAT_61CHN16, UserFmtX61, UserFmtShort },
1160 { AL_FORMAT_61CHN32, UserFmtX61, UserFmtFloat },
1161 { AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw },
1163 { AL_FORMAT_71CHN8, UserFmtX71, UserFmtUByte },
1164 { AL_FORMAT_71CHN16, UserFmtX71, UserFmtShort },
1165 { AL_FORMAT_71CHN32, UserFmtX71, UserFmtFloat },
1166 { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw },
1168 { AL_FORMAT_BFORMAT2D_8, UserFmtBFormat2D, UserFmtUByte },
1169 { AL_FORMAT_BFORMAT2D_16, UserFmtBFormat2D, UserFmtShort },
1170 { AL_FORMAT_BFORMAT2D_FLOAT32, UserFmtBFormat2D, UserFmtFloat },
1171 { AL_FORMAT_BFORMAT2D_MULAW, UserFmtBFormat2D, UserFmtMulaw },
1173 { AL_FORMAT_BFORMAT3D_8, UserFmtBFormat3D, UserFmtUByte },
1174 { AL_FORMAT_BFORMAT3D_16, UserFmtBFormat3D, UserFmtShort },
1175 { AL_FORMAT_BFORMAT3D_FLOAT32, UserFmtBFormat3D, UserFmtFloat },
1176 { AL_FORMAT_BFORMAT3D_MULAW, UserFmtBFormat3D, UserFmtMulaw },
1178 ALuint i;
1180 for(i = 0;i < COUNTOF(list);i++)
1182 if(list[i].format == format)
1184 *chans = list[i].channels;
1185 *type = list[i].type;
1186 return AL_TRUE;
1190 return AL_FALSE;
1193 ALuint BytesFromFmt(enum FmtType type)
1195 switch(type)
1197 case FmtByte: return sizeof(ALbyte);
1198 case FmtShort: return sizeof(ALshort);
1199 case FmtFloat: return sizeof(ALfloat);
1201 return 0;
1203 ALuint ChannelsFromFmt(enum FmtChannels chans)
1205 switch(chans)
1207 case FmtMono: return 1;
1208 case FmtStereo: return 2;
1209 case FmtRear: return 2;
1210 case FmtQuad: return 4;
1211 case FmtX51: return 6;
1212 case FmtX61: return 7;
1213 case FmtX71: return 8;
1214 case FmtBFormat2D: return 3;
1215 case FmtBFormat3D: return 4;
1217 return 0;
1219 static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type)
1221 static const struct {
1222 ALenum format;
1223 enum FmtChannels channels;
1224 enum FmtType type;
1225 } list[] = {
1226 { AL_MONO8_SOFT, FmtMono, FmtByte },
1227 { AL_MONO16_SOFT, FmtMono, FmtShort },
1228 { AL_MONO32F_SOFT, FmtMono, FmtFloat },
1230 { AL_STEREO8_SOFT, FmtStereo, FmtByte },
1231 { AL_STEREO16_SOFT, FmtStereo, FmtShort },
1232 { AL_STEREO32F_SOFT, FmtStereo, FmtFloat },
1234 { AL_REAR8_SOFT, FmtRear, FmtByte },
1235 { AL_REAR16_SOFT, FmtRear, FmtShort },
1236 { AL_REAR32F_SOFT, FmtRear, FmtFloat },
1238 { AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtByte },
1239 { AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort },
1241 { AL_QUAD8_SOFT, FmtQuad, FmtByte },
1242 { AL_QUAD16_SOFT, FmtQuad, FmtShort },
1243 { AL_QUAD32F_SOFT, FmtQuad, FmtFloat },
1245 { AL_5POINT1_8_SOFT, FmtX51, FmtByte },
1246 { AL_5POINT1_16_SOFT, FmtX51, FmtShort },
1247 { AL_5POINT1_32F_SOFT, FmtX51, FmtFloat },
1249 { AL_6POINT1_8_SOFT, FmtX61, FmtByte },
1250 { AL_6POINT1_16_SOFT, FmtX61, FmtShort },
1251 { AL_6POINT1_32F_SOFT, FmtX61, FmtFloat },
1253 { AL_7POINT1_8_SOFT, FmtX71, FmtByte },
1254 { AL_7POINT1_16_SOFT, FmtX71, FmtShort },
1255 { AL_7POINT1_32F_SOFT, FmtX71, FmtFloat },
1257 { AL_BFORMAT2D_8_SOFT, FmtBFormat2D, FmtByte },
1258 { AL_BFORMAT2D_16_SOFT, FmtBFormat2D, FmtShort },
1259 { AL_BFORMAT2D_32F_SOFT, FmtBFormat2D, FmtFloat },
1261 { AL_BFORMAT3D_8_SOFT, FmtBFormat3D, FmtByte },
1262 { AL_BFORMAT3D_16_SOFT, FmtBFormat3D, FmtShort },
1263 { AL_BFORMAT3D_32F_SOFT, FmtBFormat3D, FmtFloat },
1265 ALuint i;
1267 for(i = 0;i < COUNTOF(list);i++)
1269 if(list[i].format == format)
1271 *chans = list[i].channels;
1272 *type = list[i].type;
1273 return AL_TRUE;
1277 return AL_FALSE;
1280 static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align)
1282 if(*align < 0)
1283 return AL_FALSE;
1285 if(*align == 0)
1287 if(type == UserFmtIMA4)
1289 /* Here is where things vary:
1290 * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
1291 * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
1293 *align = 65;
1295 else if(type == UserFmtMSADPCM)
1296 *align = 64;
1297 else
1298 *align = 1;
1299 return AL_TRUE;
1302 if(type == UserFmtIMA4)
1304 /* IMA4 block alignment must be a multiple of 8, plus 1. */
1305 return ((*align)&7) == 1;
1307 if(type == UserFmtMSADPCM)
1309 /* MSADPCM block alignment must be a multiple of 2. */
1310 /* FIXME: Too strict? Might only require align*channels to be a
1311 * multiple of 2. */
1312 return ((*align)&1) == 0;
1315 return AL_TRUE;
1319 static ALboolean IsValidType(ALenum type)
1321 switch(type)
1323 case AL_BYTE_SOFT:
1324 case AL_UNSIGNED_BYTE_SOFT:
1325 case AL_SHORT_SOFT:
1326 case AL_UNSIGNED_SHORT_SOFT:
1327 case AL_INT_SOFT:
1328 case AL_UNSIGNED_INT_SOFT:
1329 case AL_FLOAT_SOFT:
1330 case AL_DOUBLE_SOFT:
1331 case AL_BYTE3_SOFT:
1332 case AL_UNSIGNED_BYTE3_SOFT:
1333 case AL_MULAW_SOFT:
1334 return AL_TRUE;
1336 return AL_FALSE;
1339 static ALboolean IsValidChannels(ALenum channels)
1341 switch(channels)
1343 case AL_MONO_SOFT:
1344 case AL_STEREO_SOFT:
1345 case AL_REAR_SOFT:
1346 case AL_QUAD_SOFT:
1347 case AL_5POINT1_SOFT:
1348 case AL_6POINT1_SOFT:
1349 case AL_7POINT1_SOFT:
1350 case AL_BFORMAT2D_SOFT:
1351 case AL_BFORMAT3D_SOFT:
1352 return AL_TRUE;
1354 return AL_FALSE;
1358 ALbuffer *NewBuffer(ALCcontext *context)
1360 ALCdevice *device = context->Device;
1361 ALbuffer *buffer;
1362 ALenum err;
1364 buffer = al_calloc(16, sizeof(ALbuffer));
1365 if(!buffer)
1366 SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
1367 RWLockInit(&buffer->lock);
1369 err = NewThunkEntry(&buffer->id);
1370 if(err == AL_NO_ERROR)
1371 err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer);
1372 if(err != AL_NO_ERROR)
1374 FreeThunkEntry(buffer->id);
1375 memset(buffer, 0, sizeof(ALbuffer));
1376 al_free(buffer);
1378 SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
1381 return buffer;
1384 void DeleteBuffer(ALCdevice *device, ALbuffer *buffer)
1386 RemoveBuffer(device, buffer->id);
1387 FreeThunkEntry(buffer->id);
1389 al_free(buffer->data);
1391 memset(buffer, 0, sizeof(*buffer));
1392 al_free(buffer);
1397 * ReleaseALBuffers()
1399 * INTERNAL: Called to destroy any buffers that still exist on the device
1401 ALvoid ReleaseALBuffers(ALCdevice *device)
1403 ALsizei i;
1404 for(i = 0;i < device->BufferMap.size;i++)
1406 ALbuffer *temp = device->BufferMap.values[i];
1407 device->BufferMap.values[i] = NULL;
1409 al_free(temp->data);
1411 FreeThunkEntry(temp->id);
1412 memset(temp, 0, sizeof(ALbuffer));
1413 al_free(temp);