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
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
)
60 context
= GetContextRef();
64 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
66 for(cur
= 0;cur
< n
;cur
++)
68 ALbuffer
*buffer
= NewBuffer(context
);
71 alDeleteBuffers(cur
, buffers
);
75 buffers
[cur
] = buffer
->id
;
79 ALCcontext_DecRef(context
);
82 AL_API ALvoid AL_APIENTRY
alDeleteBuffers(ALsizei n
, const ALuint
*buffers
)
89 context
= GetContextRef();
92 device
= context
->Device
;
94 LockBuffersWrite(device
);
96 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
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
);
112 if((ALBuf
=LookupBuffer(device
, buffers
[i
])) != NULL
)
113 DeleteBuffer(device
, ALBuf
);
117 UnlockBuffersWrite(device
);
118 ALCcontext_DecRef(context
);
121 AL_API ALboolean AL_APIENTRY
alIsBuffer(ALuint buffer
)
126 context
= GetContextRef();
127 if(!context
) return AL_FALSE
;
129 LockBuffersRead(context
->Device
);
130 ret
= ((!buffer
|| LookupBuffer(context
->Device
, buffer
)) ?
132 UnlockBuffersRead(context
->Device
);
134 ALCcontext_DecRef(context
);
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
;
147 ALenum newformat
= AL_NONE
;
152 context
= GetContextRef();
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
);
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
);
189 framesize
= FrameSizeFromUserFmt(srcchannels
, srctype
) * align
;
190 if((size
%framesize
) != 0)
191 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
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
);
213 framesize
= FrameSizeFromUserFmt(srcchannels
, srctype
) * align
;
214 if((size
%framesize
) != 0)
215 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
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
);
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
);
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
);
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
);
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
);
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
;
301 context
= GetContextRef();
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
);
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
);
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
)
381 context
= GetContextRef();
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
);
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
)
418 context
= GetContextRef();
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
);
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
)
473 context
= GetContextRef();
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
);
515 UnlockBuffersRead(device
);
516 ALCcontext_DecRef(context
);
519 AL_API ALboolean AL_APIENTRY
alIsBufferFormatSupportedSOFT(ALenum format
)
521 enum FmtChannels dstchannels
;
522 enum FmtType dsttype
;
526 context
= GetContextRef();
527 if(!context
) return AL_FALSE
;
529 ret
= DecomposeFormat(format
, &dstchannels
, &dsttype
);
531 ALCcontext_DecRef(context
);
537 AL_API
void AL_APIENTRY
alBufferf(ALuint buffer
, ALenum param
, ALfloat
UNUSED(value
))
542 context
= GetContextRef();
545 device
= context
->Device
;
546 LockBuffersRead(device
);
547 if(LookupBuffer(device
, buffer
) == NULL
)
548 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
553 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, 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
))
567 context
= GetContextRef();
570 device
= context
->Device
;
571 LockBuffersRead(device
);
572 if(LookupBuffer(device
, buffer
) == NULL
)
573 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
578 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
582 UnlockBuffersRead(device
);
583 ALCcontext_DecRef(context
);
587 AL_API
void AL_APIENTRY
alBufferfv(ALuint buffer
, ALenum param
, const ALfloat
*values
)
592 context
= GetContextRef();
595 device
= context
->Device
;
596 LockBuffersRead(device
);
597 if(LookupBuffer(device
, buffer
) == NULL
)
598 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
601 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
605 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
609 UnlockBuffersRead(device
);
610 ALCcontext_DecRef(context
);
614 AL_API
void AL_APIENTRY
alBufferi(ALuint buffer
, ALenum param
, ALint value
)
620 context
= GetContextRef();
623 device
= context
->Device
;
624 LockBuffersRead(device
);
625 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
626 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
630 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
632 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
633 ATOMIC_STORE(&albuf
->UnpackAlign
, value
);
636 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
638 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
639 ATOMIC_STORE(&albuf
->PackAlign
, value
);
643 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, 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
))
657 context
= GetContextRef();
660 device
= context
->Device
;
661 if(LookupBuffer(device
, buffer
) == NULL
)
662 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
667 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
671 ALCcontext_DecRef(context
);
675 AL_API
void AL_APIENTRY
alBufferiv(ALuint buffer
, ALenum param
, const ALint
*values
)
685 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
686 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
687 alBufferi(buffer
, param
, values
[0]);
692 context
= GetContextRef();
695 device
= context
->Device
;
696 LockBuffersRead(device
);
697 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
698 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
701 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
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
);
724 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
728 UnlockBuffersRead(device
);
729 ALCcontext_DecRef(context
);
733 AL_API ALvoid AL_APIENTRY
alGetBufferf(ALuint buffer
, ALenum param
, ALfloat
*value
)
739 context
= GetContextRef();
742 device
= context
->Device
;
743 LockBuffersRead(device
);
744 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
745 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
748 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
751 case AL_SEC_LENGTH_SOFT
:
752 ReadLock(&albuf
->lock
);
753 if(albuf
->SampleLen
!= 0)
754 *value
= albuf
->SampleLen
/ (ALfloat
)albuf
->Frequency
;
757 ReadUnlock(&albuf
->lock
);
761 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, 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
)
775 context
= GetContextRef();
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
);
788 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
792 UnlockBuffersRead(device
);
793 ALCcontext_DecRef(context
);
797 AL_API
void AL_APIENTRY
alGetBufferfv(ALuint buffer
, ALenum param
, ALfloat
*values
)
804 case AL_SEC_LENGTH_SOFT
:
805 alGetBufferf(buffer
, param
, values
);
809 context
= GetContextRef();
812 device
= context
->Device
;
813 LockBuffersRead(device
);
814 if(LookupBuffer(device
, buffer
) == NULL
)
815 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
818 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
822 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
826 UnlockBuffersRead(device
);
827 ALCcontext_DecRef(context
);
831 AL_API ALvoid AL_APIENTRY
alGetBufferi(ALuint buffer
, ALenum param
, ALint
*value
)
837 context
= GetContextRef();
840 device
= context
->Device
;
841 LockBuffersRead(device
);
842 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
843 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
846 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
850 *value
= albuf
->Frequency
;
854 *value
= BytesFromFmt(albuf
->FmtType
) * 8;
858 *value
= ChannelsFromFmt(albuf
->FmtChannels
);
862 ReadLock(&albuf
->lock
);
863 *value
= albuf
->SampleLen
* FrameSizeFromFmt(albuf
->FmtChannels
,
865 ReadUnlock(&albuf
->lock
);
868 case AL_INTERNAL_FORMAT_SOFT
:
869 *value
= albuf
->Format
;
872 case AL_BYTE_LENGTH_SOFT
:
873 *value
= albuf
->OriginalSize
;
876 case AL_SAMPLE_LENGTH_SOFT
:
877 *value
= albuf
->SampleLen
;
880 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
881 *value
= ATOMIC_LOAD(&albuf
->UnpackAlign
);
884 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
885 *value
= ATOMIC_LOAD(&albuf
->PackAlign
);
889 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, 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
)
903 context
= GetContextRef();
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
);
916 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
920 UnlockBuffersRead(device
);
921 ALCcontext_DecRef(context
);
925 AL_API
void AL_APIENTRY
alGetBufferiv(ALuint buffer
, ALenum param
, ALint
*values
)
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
);
946 context
= GetContextRef();
949 device
= context
->Device
;
950 LockBuffersRead(device
);
951 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
952 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
955 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
958 case AL_LOOP_POINTS_SOFT
:
959 ReadLock(&albuf
->lock
);
960 values
[0] = albuf
->LoopStart
;
961 values
[1] = albuf
->LoopEnd
;
962 ReadUnlock(&albuf
->lock
);
966 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
970 UnlockBuffersRead(device
);
971 ALCcontext_DecRef(context
);
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
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
;
989 if(DecomposeFormat(NewFormat
, &DstChannels
, &DstType
) == AL_FALSE
||
990 (long)SrcChannels
!= (long)DstChannels
)
991 return AL_INVALID_ENUM
;
993 NewChannels
= ChannelsFromFmt(DstChannels
);
994 NewBytes
= BytesFromFmt(DstType
);
998 newsize
*= NewChannels
;
999 if(newsize
> INT_MAX
)
1000 return AL_OUT_OF_MEMORY
;
1002 WriteLock(&ALBuf
->lock
);
1003 if(ReadRef(&ALBuf
->ref
) != 0)
1005 WriteUnlock(&ALBuf
->lock
);
1006 return AL_INVALID_OPERATION
;
1009 /* Round up to the next 16-byte multiple. This could reallocate only when
1010 * increasing or the new size is less than half the current, but then the
1011 * buffer's AL_SIZE would not be very reliable for accounting buffer memory
1012 * usage, and reporting the real size could cause problems for apps that
1013 * use AL_SIZE to try to get the buffer's play length.
1015 newsize
= (newsize
+15) & ~0xf;
1016 if(newsize
!= ALBuf
->BytesAlloc
)
1018 void *temp
= al_calloc(16, (size_t)newsize
);
1019 if(!temp
&& newsize
)
1021 WriteUnlock(&ALBuf
->lock
);
1022 return AL_OUT_OF_MEMORY
;
1024 al_free(ALBuf
->data
);
1026 ALBuf
->BytesAlloc
= (ALuint
)newsize
;
1030 ConvertData(ALBuf
->data
, (enum UserFmtType
)DstType
, data
, SrcType
, NewChannels
, frames
, align
);
1034 ALBuf
->OriginalChannels
= SrcChannels
;
1035 ALBuf
->OriginalType
= SrcType
;
1036 if(SrcType
== UserFmtIMA4
)
1038 ALsizei byte_align
= ((align
-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels
);
1039 ALBuf
->OriginalSize
= frames
/ align
* byte_align
;
1040 ALBuf
->OriginalAlign
= align
;
1042 else if(SrcType
== UserFmtMSADPCM
)
1044 ALsizei byte_align
= ((align
-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels
);
1045 ALBuf
->OriginalSize
= frames
/ align
* byte_align
;
1046 ALBuf
->OriginalAlign
= align
;
1050 ALBuf
->OriginalSize
= frames
* FrameSizeFromUserFmt(SrcChannels
, SrcType
);
1051 ALBuf
->OriginalAlign
= 1;
1056 ALBuf
->OriginalChannels
= (enum UserFmtChannels
)DstChannels
;
1057 ALBuf
->OriginalType
= (enum UserFmtType
)DstType
;
1058 ALBuf
->OriginalSize
= frames
* NewBytes
* NewChannels
;
1059 ALBuf
->OriginalAlign
= 1;
1062 ALBuf
->Frequency
= freq
;
1063 ALBuf
->FmtChannels
= DstChannels
;
1064 ALBuf
->FmtType
= DstType
;
1065 ALBuf
->Format
= NewFormat
;
1067 ALBuf
->SampleLen
= frames
;
1068 ALBuf
->LoopStart
= 0;
1069 ALBuf
->LoopEnd
= ALBuf
->SampleLen
;
1071 WriteUnlock(&ALBuf
->lock
);
1076 ALuint
BytesFromUserFmt(enum UserFmtType type
)
1080 case UserFmtByte
: return sizeof(ALbyte
);
1081 case UserFmtUByte
: return sizeof(ALubyte
);
1082 case UserFmtShort
: return sizeof(ALshort
);
1083 case UserFmtUShort
: return sizeof(ALushort
);
1084 case UserFmtInt
: return sizeof(ALint
);
1085 case UserFmtUInt
: return sizeof(ALuint
);
1086 case UserFmtFloat
: return sizeof(ALfloat
);
1087 case UserFmtDouble
: return sizeof(ALdouble
);
1088 case UserFmtByte3
: return sizeof(ALbyte
[3]);
1089 case UserFmtUByte3
: return sizeof(ALubyte
[3]);
1090 case UserFmtMulaw
: return sizeof(ALubyte
);
1091 case UserFmtAlaw
: return sizeof(ALubyte
);
1092 case UserFmtIMA4
: break; /* not handled here */
1093 case UserFmtMSADPCM
: break; /* not handled here */
1097 ALuint
ChannelsFromUserFmt(enum UserFmtChannels chans
)
1101 case UserFmtMono
: return 1;
1102 case UserFmtStereo
: return 2;
1103 case UserFmtRear
: return 2;
1104 case UserFmtQuad
: return 4;
1105 case UserFmtX51
: return 6;
1106 case UserFmtX61
: return 7;
1107 case UserFmtX71
: return 8;
1108 case UserFmtBFormat2D
: return 3;
1109 case UserFmtBFormat3D
: return 4;
1113 static ALboolean
DecomposeUserFormat(ALenum format
, enum UserFmtChannels
*chans
,
1114 enum UserFmtType
*type
)
1116 static const struct {
1118 enum UserFmtChannels channels
;
1119 enum UserFmtType type
;
1121 { AL_FORMAT_MONO8
, UserFmtMono
, UserFmtUByte
},
1122 { AL_FORMAT_MONO16
, UserFmtMono
, UserFmtShort
},
1123 { AL_FORMAT_MONO_FLOAT32
, UserFmtMono
, UserFmtFloat
},
1124 { AL_FORMAT_MONO_DOUBLE_EXT
, UserFmtMono
, UserFmtDouble
},
1125 { AL_FORMAT_MONO_IMA4
, UserFmtMono
, UserFmtIMA4
},
1126 { AL_FORMAT_MONO_MSADPCM_SOFT
, UserFmtMono
, UserFmtMSADPCM
},
1127 { AL_FORMAT_MONO_MULAW
, UserFmtMono
, UserFmtMulaw
},
1128 { AL_FORMAT_MONO_ALAW_EXT
, UserFmtMono
, UserFmtAlaw
},
1130 { AL_FORMAT_STEREO8
, UserFmtStereo
, UserFmtUByte
},
1131 { AL_FORMAT_STEREO16
, UserFmtStereo
, UserFmtShort
},
1132 { AL_FORMAT_STEREO_FLOAT32
, UserFmtStereo
, UserFmtFloat
},
1133 { AL_FORMAT_STEREO_DOUBLE_EXT
, UserFmtStereo
, UserFmtDouble
},
1134 { AL_FORMAT_STEREO_IMA4
, UserFmtStereo
, UserFmtIMA4
},
1135 { AL_FORMAT_STEREO_MSADPCM_SOFT
, UserFmtStereo
, UserFmtMSADPCM
},
1136 { AL_FORMAT_STEREO_MULAW
, UserFmtStereo
, UserFmtMulaw
},
1137 { AL_FORMAT_STEREO_ALAW_EXT
, UserFmtStereo
, UserFmtAlaw
},
1139 { AL_FORMAT_REAR8
, UserFmtRear
, UserFmtUByte
},
1140 { AL_FORMAT_REAR16
, UserFmtRear
, UserFmtShort
},
1141 { AL_FORMAT_REAR32
, UserFmtRear
, UserFmtFloat
},
1142 { AL_FORMAT_REAR_MULAW
, UserFmtRear
, UserFmtMulaw
},
1144 { AL_FORMAT_QUAD8_LOKI
, UserFmtQuad
, UserFmtUByte
},
1145 { AL_FORMAT_QUAD16_LOKI
, UserFmtQuad
, UserFmtShort
},
1147 { AL_FORMAT_QUAD8
, UserFmtQuad
, UserFmtUByte
},
1148 { AL_FORMAT_QUAD16
, UserFmtQuad
, UserFmtShort
},
1149 { AL_FORMAT_QUAD32
, UserFmtQuad
, UserFmtFloat
},
1150 { AL_FORMAT_QUAD_MULAW
, UserFmtQuad
, UserFmtMulaw
},
1152 { AL_FORMAT_51CHN8
, UserFmtX51
, UserFmtUByte
},
1153 { AL_FORMAT_51CHN16
, UserFmtX51
, UserFmtShort
},
1154 { AL_FORMAT_51CHN32
, UserFmtX51
, UserFmtFloat
},
1155 { AL_FORMAT_51CHN_MULAW
, UserFmtX51
, UserFmtMulaw
},
1157 { AL_FORMAT_61CHN8
, UserFmtX61
, UserFmtUByte
},
1158 { AL_FORMAT_61CHN16
, UserFmtX61
, UserFmtShort
},
1159 { AL_FORMAT_61CHN32
, UserFmtX61
, UserFmtFloat
},
1160 { AL_FORMAT_61CHN_MULAW
, UserFmtX61
, UserFmtMulaw
},
1162 { AL_FORMAT_71CHN8
, UserFmtX71
, UserFmtUByte
},
1163 { AL_FORMAT_71CHN16
, UserFmtX71
, UserFmtShort
},
1164 { AL_FORMAT_71CHN32
, UserFmtX71
, UserFmtFloat
},
1165 { AL_FORMAT_71CHN_MULAW
, UserFmtX71
, UserFmtMulaw
},
1167 { AL_FORMAT_BFORMAT2D_8
, UserFmtBFormat2D
, UserFmtUByte
},
1168 { AL_FORMAT_BFORMAT2D_16
, UserFmtBFormat2D
, UserFmtShort
},
1169 { AL_FORMAT_BFORMAT2D_FLOAT32
, UserFmtBFormat2D
, UserFmtFloat
},
1170 { AL_FORMAT_BFORMAT2D_MULAW
, UserFmtBFormat2D
, UserFmtMulaw
},
1172 { AL_FORMAT_BFORMAT3D_8
, UserFmtBFormat3D
, UserFmtUByte
},
1173 { AL_FORMAT_BFORMAT3D_16
, UserFmtBFormat3D
, UserFmtShort
},
1174 { AL_FORMAT_BFORMAT3D_FLOAT32
, UserFmtBFormat3D
, UserFmtFloat
},
1175 { AL_FORMAT_BFORMAT3D_MULAW
, UserFmtBFormat3D
, UserFmtMulaw
},
1179 for(i
= 0;i
< COUNTOF(list
);i
++)
1181 if(list
[i
].format
== format
)
1183 *chans
= list
[i
].channels
;
1184 *type
= list
[i
].type
;
1192 ALuint
BytesFromFmt(enum FmtType type
)
1196 case FmtByte
: return sizeof(ALbyte
);
1197 case FmtShort
: return sizeof(ALshort
);
1198 case FmtFloat
: return sizeof(ALfloat
);
1202 ALuint
ChannelsFromFmt(enum FmtChannels chans
)
1206 case FmtMono
: return 1;
1207 case FmtStereo
: return 2;
1208 case FmtRear
: return 2;
1209 case FmtQuad
: return 4;
1210 case FmtX51
: return 6;
1211 case FmtX61
: return 7;
1212 case FmtX71
: return 8;
1213 case FmtBFormat2D
: return 3;
1214 case FmtBFormat3D
: return 4;
1218 static ALboolean
DecomposeFormat(ALenum format
, enum FmtChannels
*chans
, enum FmtType
*type
)
1220 static const struct {
1222 enum FmtChannels channels
;
1225 { AL_MONO8_SOFT
, FmtMono
, FmtByte
},
1226 { AL_MONO16_SOFT
, FmtMono
, FmtShort
},
1227 { AL_MONO32F_SOFT
, FmtMono
, FmtFloat
},
1229 { AL_STEREO8_SOFT
, FmtStereo
, FmtByte
},
1230 { AL_STEREO16_SOFT
, FmtStereo
, FmtShort
},
1231 { AL_STEREO32F_SOFT
, FmtStereo
, FmtFloat
},
1233 { AL_REAR8_SOFT
, FmtRear
, FmtByte
},
1234 { AL_REAR16_SOFT
, FmtRear
, FmtShort
},
1235 { AL_REAR32F_SOFT
, FmtRear
, FmtFloat
},
1237 { AL_FORMAT_QUAD8_LOKI
, FmtQuad
, FmtByte
},
1238 { AL_FORMAT_QUAD16_LOKI
, FmtQuad
, FmtShort
},
1240 { AL_QUAD8_SOFT
, FmtQuad
, FmtByte
},
1241 { AL_QUAD16_SOFT
, FmtQuad
, FmtShort
},
1242 { AL_QUAD32F_SOFT
, FmtQuad
, FmtFloat
},
1244 { AL_5POINT1_8_SOFT
, FmtX51
, FmtByte
},
1245 { AL_5POINT1_16_SOFT
, FmtX51
, FmtShort
},
1246 { AL_5POINT1_32F_SOFT
, FmtX51
, FmtFloat
},
1248 { AL_6POINT1_8_SOFT
, FmtX61
, FmtByte
},
1249 { AL_6POINT1_16_SOFT
, FmtX61
, FmtShort
},
1250 { AL_6POINT1_32F_SOFT
, FmtX61
, FmtFloat
},
1252 { AL_7POINT1_8_SOFT
, FmtX71
, FmtByte
},
1253 { AL_7POINT1_16_SOFT
, FmtX71
, FmtShort
},
1254 { AL_7POINT1_32F_SOFT
, FmtX71
, FmtFloat
},
1256 { AL_BFORMAT2D_8_SOFT
, FmtBFormat2D
, FmtByte
},
1257 { AL_BFORMAT2D_16_SOFT
, FmtBFormat2D
, FmtShort
},
1258 { AL_BFORMAT2D_32F_SOFT
, FmtBFormat2D
, FmtFloat
},
1260 { AL_BFORMAT3D_8_SOFT
, FmtBFormat3D
, FmtByte
},
1261 { AL_BFORMAT3D_16_SOFT
, FmtBFormat3D
, FmtShort
},
1262 { AL_BFORMAT3D_32F_SOFT
, FmtBFormat3D
, FmtFloat
},
1266 for(i
= 0;i
< COUNTOF(list
);i
++)
1268 if(list
[i
].format
== format
)
1270 *chans
= list
[i
].channels
;
1271 *type
= list
[i
].type
;
1279 static ALboolean
SanitizeAlignment(enum UserFmtType type
, ALsizei
*align
)
1286 if(type
== UserFmtIMA4
)
1288 /* Here is where things vary:
1289 * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
1290 * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
1294 else if(type
== UserFmtMSADPCM
)
1301 if(type
== UserFmtIMA4
)
1303 /* IMA4 block alignment must be a multiple of 8, plus 1. */
1304 return ((*align
)&7) == 1;
1306 if(type
== UserFmtMSADPCM
)
1308 /* MSADPCM block alignment must be a multiple of 2. */
1309 /* FIXME: Too strict? Might only require align*channels to be a
1311 return ((*align
)&1) == 0;
1318 static ALboolean
IsValidType(ALenum type
)
1323 case AL_UNSIGNED_BYTE_SOFT
:
1325 case AL_UNSIGNED_SHORT_SOFT
:
1327 case AL_UNSIGNED_INT_SOFT
:
1329 case AL_DOUBLE_SOFT
:
1331 case AL_UNSIGNED_BYTE3_SOFT
:
1338 static ALboolean
IsValidChannels(ALenum channels
)
1343 case AL_STEREO_SOFT
:
1346 case AL_5POINT1_SOFT
:
1347 case AL_6POINT1_SOFT
:
1348 case AL_7POINT1_SOFT
:
1349 case AL_BFORMAT2D_SOFT
:
1350 case AL_BFORMAT3D_SOFT
:
1357 ALbuffer
*NewBuffer(ALCcontext
*context
)
1359 ALCdevice
*device
= context
->Device
;
1363 buffer
= al_calloc(16, sizeof(ALbuffer
));
1365 SET_ERROR_AND_RETURN_VALUE(context
, AL_OUT_OF_MEMORY
, NULL
);
1366 RWLockInit(&buffer
->lock
);
1368 err
= NewThunkEntry(&buffer
->id
);
1369 if(err
== AL_NO_ERROR
)
1370 err
= InsertUIntMapEntry(&device
->BufferMap
, buffer
->id
, buffer
);
1371 if(err
!= AL_NO_ERROR
)
1373 FreeThunkEntry(buffer
->id
);
1374 memset(buffer
, 0, sizeof(ALbuffer
));
1377 SET_ERROR_AND_RETURN_VALUE(context
, err
, NULL
);
1383 void DeleteBuffer(ALCdevice
*device
, ALbuffer
*buffer
)
1385 RemoveBuffer(device
, buffer
->id
);
1386 FreeThunkEntry(buffer
->id
);
1388 al_free(buffer
->data
);
1390 memset(buffer
, 0, sizeof(*buffer
));
1396 * ReleaseALBuffers()
1398 * INTERNAL: Called to destroy any buffers that still exist on the device
1400 ALvoid
ReleaseALBuffers(ALCdevice
*device
)
1403 for(i
= 0;i
< device
->BufferMap
.size
;i
++)
1405 ALbuffer
*temp
= device
->BufferMap
.array
[i
].value
;
1406 device
->BufferMap
.array
[i
].value
= NULL
;
1408 al_free(temp
->data
);
1410 FreeThunkEntry(temp
->id
);
1411 memset(temp
, 0, sizeof(ALbuffer
));