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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
36 #include "sample_cvt.h"
39 extern inline struct ALbuffer
*LookupBuffer(ALCdevice
*device
, ALuint id
);
40 extern inline struct ALbuffer
*RemoveBuffer(ALCdevice
*device
, ALuint id
);
41 extern inline ALuint
FrameSizeFromUserFmt(enum UserFmtChannels chans
, enum UserFmtType type
);
42 extern inline ALuint
FrameSizeFromFmt(enum FmtChannels chans
, enum FmtType type
);
44 static ALenum
LoadData(ALbuffer
*ALBuf
, ALuint freq
, ALenum NewFormat
, ALsizei frames
, enum UserFmtChannels chans
, enum UserFmtType type
, const ALvoid
*data
, ALsizei align
, ALboolean storesrc
);
45 static ALboolean
IsValidType(ALenum type
) DECL_CONST
;
46 static ALboolean
IsValidChannels(ALenum channels
) DECL_CONST
;
47 static ALboolean
DecomposeUserFormat(ALenum format
, enum UserFmtChannels
*chans
, enum UserFmtType
*type
) DECL_CONST
;
48 static ALboolean
DecomposeFormat(ALenum format
, enum FmtChannels
*chans
, enum FmtType
*type
) DECL_CONST
;
49 static ALboolean
SanitizeAlignment(enum UserFmtType type
, ALsizei
*align
);
52 AL_API ALvoid AL_APIENTRY
alGenBuffers(ALsizei n
, ALuint
*buffers
)
59 context
= GetContextRef();
63 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
65 device
= context
->Device
;
66 for(cur
= 0;cur
< n
;cur
++)
68 ALbuffer
*buffer
= calloc(1, sizeof(ALbuffer
));
71 alDeleteBuffers(cur
, buffers
);
72 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
74 RWLockInit(&buffer
->lock
);
76 err
= NewThunkEntry(&buffer
->id
);
77 if(err
== AL_NO_ERROR
)
78 err
= InsertUIntMapEntry(&device
->BufferMap
, buffer
->id
, buffer
);
79 if(err
!= AL_NO_ERROR
)
81 FreeThunkEntry(buffer
->id
);
82 memset(buffer
, 0, sizeof(ALbuffer
));
85 alDeleteBuffers(cur
, buffers
);
86 SET_ERROR_AND_GOTO(context
, err
, done
);
89 buffers
[cur
] = buffer
->id
;
93 ALCcontext_DecRef(context
);
96 AL_API ALvoid AL_APIENTRY
alDeleteBuffers(ALsizei n
, const ALuint
*buffers
)
103 context
= GetContextRef();
107 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
109 device
= context
->Device
;
115 /* Check for valid Buffer ID */
116 if((ALBuf
=LookupBuffer(device
, buffers
[i
])) == NULL
)
117 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
118 if(ReadRef(&ALBuf
->ref
) != 0)
119 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
124 if((ALBuf
=RemoveBuffer(device
, buffers
[i
])) == NULL
)
126 FreeThunkEntry(ALBuf
->id
);
130 memset(ALBuf
, 0, sizeof(*ALBuf
));
135 ALCcontext_DecRef(context
);
138 AL_API ALboolean AL_APIENTRY
alIsBuffer(ALuint buffer
)
143 context
= GetContextRef();
144 if(!context
) return AL_FALSE
;
146 ret
= ((!buffer
|| LookupBuffer(context
->Device
, buffer
)) ?
149 ALCcontext_DecRef(context
);
155 AL_API ALvoid AL_APIENTRY
alBufferData(ALuint buffer
, ALenum format
, const ALvoid
*data
, ALsizei size
, ALsizei freq
)
157 enum UserFmtChannels srcchannels
;
158 enum UserFmtType srctype
;
162 ALenum newformat
= AL_NONE
;
167 context
= GetContextRef();
170 device
= context
->Device
;
171 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
172 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
173 if(!(size
>= 0 && freq
> 0))
174 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
175 if(DecomposeUserFormat(format
, &srcchannels
, &srctype
) == AL_FALSE
)
176 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
178 align
= albuf
->UnpackAlign
;
179 if(SanitizeAlignment(srctype
, &align
) == AL_FALSE
)
180 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
188 framesize
= FrameSizeFromUserFmt(srcchannels
, srctype
) * align
;
189 if((size
%framesize
) != 0)
190 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
192 err
= LoadData(albuf
, freq
, format
, size
/framesize
*align
,
193 srcchannels
, srctype
, data
, align
, AL_TRUE
);
194 if(err
!= AL_NO_ERROR
)
195 SET_ERROR_AND_GOTO(context
, err
, done
);
203 framesize
= FrameSizeFromUserFmt(srcchannels
, srctype
) * align
;
204 if((size
%framesize
) != 0)
205 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
209 case UserFmtMono
: newformat
= AL_FORMAT_MONO_FLOAT32
; break;
210 case UserFmtStereo
: newformat
= AL_FORMAT_STEREO_FLOAT32
; break;
211 case UserFmtRear
: newformat
= AL_FORMAT_REAR32
; break;
212 case UserFmtQuad
: newformat
= AL_FORMAT_QUAD32
; break;
213 case UserFmtX51
: newformat
= AL_FORMAT_51CHN32
; break;
214 case UserFmtX61
: newformat
= AL_FORMAT_61CHN32
; break;
215 case UserFmtX71
: newformat
= AL_FORMAT_71CHN32
; break;
217 err
= LoadData(albuf
, freq
, newformat
, size
/framesize
*align
,
218 srcchannels
, srctype
, data
, align
, AL_TRUE
);
219 if(err
!= AL_NO_ERROR
)
220 SET_ERROR_AND_GOTO(context
, err
, done
);
225 framesize
= FrameSizeFromUserFmt(srcchannels
, srctype
) * align
;
226 if((size
%framesize
) != 0)
227 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
231 case UserFmtMono
: newformat
= AL_FORMAT_MONO16
; break;
232 case UserFmtStereo
: newformat
= AL_FORMAT_STEREO16
; break;
233 case UserFmtRear
: newformat
= AL_FORMAT_REAR16
; break;
234 case UserFmtQuad
: newformat
= AL_FORMAT_QUAD16
; break;
235 case UserFmtX51
: newformat
= AL_FORMAT_51CHN16
; break;
236 case UserFmtX61
: newformat
= AL_FORMAT_61CHN16
; break;
237 case UserFmtX71
: newformat
= AL_FORMAT_71CHN16
; break;
239 err
= LoadData(albuf
, freq
, newformat
, size
/framesize
*align
,
240 srcchannels
, srctype
, data
, align
, AL_TRUE
);
241 if(err
!= AL_NO_ERROR
)
242 SET_ERROR_AND_GOTO(context
, err
, done
);
246 framesize
= (align
-1)/2 + 4;
247 framesize
*= ChannelsFromUserFmt(srcchannels
);
248 if((size
%framesize
) != 0)
249 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
253 case UserFmtMono
: newformat
= AL_FORMAT_MONO16
; break;
254 case UserFmtStereo
: newformat
= AL_FORMAT_STEREO16
; break;
255 case UserFmtRear
: newformat
= AL_FORMAT_REAR16
; break;
256 case UserFmtQuad
: newformat
= AL_FORMAT_QUAD16
; break;
257 case UserFmtX51
: newformat
= AL_FORMAT_51CHN16
; break;
258 case UserFmtX61
: newformat
= AL_FORMAT_61CHN16
; break;
259 case UserFmtX71
: newformat
= AL_FORMAT_71CHN16
; break;
261 err
= LoadData(albuf
, freq
, newformat
, size
/framesize
*align
,
262 srcchannels
, srctype
, data
, align
, AL_TRUE
);
263 if(err
!= AL_NO_ERROR
)
264 SET_ERROR_AND_GOTO(context
, err
, done
);
268 framesize
= (align
-2)/2 + 7;
269 framesize
*= ChannelsFromUserFmt(srcchannels
);
270 if((size
%framesize
) != 0)
271 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
275 case UserFmtMono
: newformat
= AL_FORMAT_MONO16
; break;
276 case UserFmtStereo
: newformat
= AL_FORMAT_STEREO16
; break;
277 case UserFmtRear
: newformat
= AL_FORMAT_REAR16
; break;
278 case UserFmtQuad
: newformat
= AL_FORMAT_QUAD16
; break;
279 case UserFmtX51
: newformat
= AL_FORMAT_51CHN16
; break;
280 case UserFmtX61
: newformat
= AL_FORMAT_61CHN16
; break;
281 case UserFmtX71
: newformat
= AL_FORMAT_71CHN16
; break;
283 err
= LoadData(albuf
, freq
, newformat
, size
/framesize
*align
,
284 srcchannels
, srctype
, data
, align
, AL_TRUE
);
285 if(err
!= AL_NO_ERROR
)
286 SET_ERROR_AND_GOTO(context
, err
, done
);
291 ALCcontext_DecRef(context
);
294 AL_API ALvoid AL_APIENTRY
alBufferSubDataSOFT(ALuint buffer
, ALenum format
, const ALvoid
*data
, ALsizei offset
, ALsizei length
)
296 enum UserFmtChannels srcchannels
;
297 enum UserFmtType srctype
;
306 context
= GetContextRef();
309 device
= context
->Device
;
310 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
311 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
312 if(!(length
>= 0 && offset
>= 0))
313 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
314 if(DecomposeUserFormat(format
, &srcchannels
, &srctype
) == AL_FALSE
)
315 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
317 WriteLock(&albuf
->lock
);
318 align
= albuf
->UnpackAlign
;
319 if(SanitizeAlignment(srctype
, &align
) == AL_FALSE
)
321 WriteUnlock(&albuf
->lock
);
322 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
324 if(srcchannels
!= albuf
->OriginalChannels
|| srctype
!= albuf
->OriginalType
)
326 WriteUnlock(&albuf
->lock
);
327 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
329 if(align
!= albuf
->OriginalAlign
)
331 WriteUnlock(&albuf
->lock
);
332 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
335 if(albuf
->OriginalType
== UserFmtIMA4
)
337 byte_align
= (albuf
->OriginalAlign
-1)/2 + 4;
338 byte_align
*= ChannelsFromUserFmt(albuf
->OriginalChannels
);
340 else if(albuf
->OriginalType
== UserFmtMSADPCM
)
342 byte_align
= (albuf
->OriginalAlign
-2)/2 + 7;
343 byte_align
*= ChannelsFromUserFmt(albuf
->OriginalChannels
);
347 byte_align
= albuf
->OriginalAlign
;
348 byte_align
*= FrameSizeFromUserFmt(albuf
->OriginalChannels
,
349 albuf
->OriginalType
);
352 if(offset
> albuf
->OriginalSize
|| length
> albuf
->OriginalSize
-offset
||
353 (offset
%byte_align
) != 0 || (length
%byte_align
) != 0)
355 WriteUnlock(&albuf
->lock
);
356 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
359 channels
= ChannelsFromFmt(albuf
->FmtChannels
);
360 bytes
= BytesFromFmt(albuf
->FmtType
);
361 /* offset -> byte offset, length -> sample count */
362 offset
= offset
/byte_align
* channels
*bytes
;
363 length
= length
/byte_align
* albuf
->OriginalAlign
;
365 ConvertData((char*)albuf
->data
+offset
, (enum UserFmtType
)albuf
->FmtType
,
366 data
, srctype
, channels
, length
, align
);
367 WriteUnlock(&albuf
->lock
);
370 ALCcontext_DecRef(context
);
374 AL_API
void AL_APIENTRY
alBufferSamplesSOFT(ALuint buffer
,
375 ALuint samplerate
, ALenum internalformat
, ALsizei samples
,
376 ALenum channels
, ALenum type
, const ALvoid
*data
)
384 context
= GetContextRef();
387 device
= context
->Device
;
388 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
389 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
390 if(!(samples
>= 0 && samplerate
!= 0))
391 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
392 if(IsValidType(type
) == AL_FALSE
|| IsValidChannels(channels
) == AL_FALSE
)
393 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
395 align
= albuf
->UnpackAlign
;
396 if(SanitizeAlignment(type
, &align
) == AL_FALSE
)
397 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
398 if((samples
%align
) != 0)
399 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
401 err
= LoadData(albuf
, samplerate
, internalformat
, samples
,
402 channels
, type
, data
, align
, AL_FALSE
);
403 if(err
!= AL_NO_ERROR
)
404 SET_ERROR_AND_GOTO(context
, err
, done
);
407 ALCcontext_DecRef(context
);
410 AL_API
void AL_APIENTRY
alBufferSubSamplesSOFT(ALuint buffer
,
411 ALsizei offset
, ALsizei samples
,
412 ALenum channels
, ALenum type
, const ALvoid
*data
)
419 context
= GetContextRef();
422 device
= context
->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
= 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 ALCcontext_DecRef(context
);
463 AL_API
void AL_APIENTRY
alGetBufferSamplesSOFT(ALuint buffer
,
464 ALsizei offset
, ALsizei samples
,
465 ALenum channels
, ALenum type
, ALvoid
*data
)
472 context
= GetContextRef();
475 device
= context
->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
= 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
);
513 ALCcontext_DecRef(context
);
516 AL_API ALboolean AL_APIENTRY
alIsBufferFormatSupportedSOFT(ALenum format
)
518 enum FmtChannels dstchannels
;
519 enum FmtType dsttype
;
523 context
= GetContextRef();
524 if(!context
) return AL_FALSE
;
526 ret
= DecomposeFormat(format
, &dstchannels
, &dsttype
);
528 ALCcontext_DecRef(context
);
534 AL_API
void AL_APIENTRY
alBufferf(ALuint buffer
, ALenum param
, ALfloat
UNUSED(value
))
539 context
= GetContextRef();
542 device
= context
->Device
;
543 if(LookupBuffer(device
, buffer
) == NULL
)
544 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
549 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
553 ALCcontext_DecRef(context
);
557 AL_API
void AL_APIENTRY
alBuffer3f(ALuint buffer
, ALenum param
, ALfloat
UNUSED(value1
), ALfloat
UNUSED(value2
), ALfloat
UNUSED(value3
))
562 context
= GetContextRef();
565 device
= context
->Device
;
566 if(LookupBuffer(device
, buffer
) == NULL
)
567 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
572 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
576 ALCcontext_DecRef(context
);
580 AL_API
void AL_APIENTRY
alBufferfv(ALuint buffer
, ALenum param
, const ALfloat
*values
)
585 context
= GetContextRef();
588 device
= context
->Device
;
589 if(LookupBuffer(device
, buffer
) == NULL
)
590 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
593 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
597 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
601 ALCcontext_DecRef(context
);
605 AL_API
void AL_APIENTRY
alBufferi(ALuint buffer
, ALenum param
, ALint value
)
611 context
= GetContextRef();
614 device
= context
->Device
;
615 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
616 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
620 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
622 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
623 ExchangeInt(&albuf
->UnpackAlign
, value
);
626 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
628 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
629 ExchangeInt(&albuf
->PackAlign
, value
);
633 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
637 ALCcontext_DecRef(context
);
641 AL_API
void AL_APIENTRY
alBuffer3i(ALuint buffer
, ALenum param
, ALint
UNUSED(value1
), ALint
UNUSED(value2
), ALint
UNUSED(value3
))
646 context
= GetContextRef();
649 device
= context
->Device
;
650 if(LookupBuffer(device
, buffer
) == NULL
)
651 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
656 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
660 ALCcontext_DecRef(context
);
664 AL_API
void AL_APIENTRY
alBufferiv(ALuint buffer
, ALenum param
, const ALint
*values
)
674 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
675 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
676 alBufferi(buffer
, param
, values
[0]);
681 context
= GetContextRef();
684 device
= context
->Device
;
685 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
686 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
689 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
692 case AL_LOOP_POINTS_SOFT
:
693 WriteLock(&albuf
->lock
);
694 if(ReadRef(&albuf
->ref
) != 0)
696 WriteUnlock(&albuf
->lock
);
697 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
699 if(values
[0] >= values
[1] || values
[0] < 0 ||
700 values
[1] > albuf
->SampleLen
)
702 WriteUnlock(&albuf
->lock
);
703 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
706 albuf
->LoopStart
= values
[0];
707 albuf
->LoopEnd
= values
[1];
708 WriteUnlock(&albuf
->lock
);
712 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
716 ALCcontext_DecRef(context
);
720 AL_API ALvoid AL_APIENTRY
alGetBufferf(ALuint buffer
, ALenum param
, ALfloat
*value
)
726 context
= GetContextRef();
729 device
= context
->Device
;
730 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
731 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
734 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
737 case AL_SEC_LENGTH_SOFT
:
738 ReadLock(&albuf
->lock
);
739 if(albuf
->SampleLen
!= 0)
740 *value
= albuf
->SampleLen
/ (ALfloat
)albuf
->Frequency
;
743 ReadUnlock(&albuf
->lock
);
747 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
751 ALCcontext_DecRef(context
);
755 AL_API
void AL_APIENTRY
alGetBuffer3f(ALuint buffer
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
760 context
= GetContextRef();
763 device
= context
->Device
;
764 if(LookupBuffer(device
, buffer
) == NULL
)
765 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
767 if(!(value1
&& value2
&& value3
))
768 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
772 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
776 ALCcontext_DecRef(context
);
780 AL_API
void AL_APIENTRY
alGetBufferfv(ALuint buffer
, ALenum param
, ALfloat
*values
)
787 case AL_SEC_LENGTH_SOFT
:
788 alGetBufferf(buffer
, param
, values
);
792 context
= GetContextRef();
795 device
= context
->Device
;
796 if(LookupBuffer(device
, buffer
) == NULL
)
797 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
800 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
804 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
808 ALCcontext_DecRef(context
);
812 AL_API ALvoid AL_APIENTRY
alGetBufferi(ALuint buffer
, ALenum param
, ALint
*value
)
818 context
= GetContextRef();
821 device
= context
->Device
;
822 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
823 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
826 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
830 *value
= albuf
->Frequency
;
834 *value
= BytesFromFmt(albuf
->FmtType
) * 8;
838 *value
= ChannelsFromFmt(albuf
->FmtChannels
);
842 ReadLock(&albuf
->lock
);
843 *value
= albuf
->SampleLen
* FrameSizeFromFmt(albuf
->FmtChannels
,
845 ReadUnlock(&albuf
->lock
);
848 case AL_INTERNAL_FORMAT_SOFT
:
849 *value
= albuf
->Format
;
852 case AL_BYTE_LENGTH_SOFT
:
853 *value
= albuf
->OriginalSize
;
856 case AL_SAMPLE_LENGTH_SOFT
:
857 *value
= albuf
->SampleLen
;
860 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
861 *value
= albuf
->UnpackAlign
;
864 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
865 *value
= albuf
->PackAlign
;
869 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
873 ALCcontext_DecRef(context
);
877 AL_API
void AL_APIENTRY
alGetBuffer3i(ALuint buffer
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
882 context
= GetContextRef();
885 device
= context
->Device
;
886 if(LookupBuffer(device
, buffer
) == NULL
)
887 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
889 if(!(value1
&& value2
&& value3
))
890 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
894 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
898 ALCcontext_DecRef(context
);
902 AL_API
void AL_APIENTRY
alGetBufferiv(ALuint buffer
, ALenum param
, ALint
*values
)
914 case AL_INTERNAL_FORMAT_SOFT
:
915 case AL_BYTE_LENGTH_SOFT
:
916 case AL_SAMPLE_LENGTH_SOFT
:
917 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
918 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
919 alGetBufferi(buffer
, param
, values
);
923 context
= GetContextRef();
926 device
= context
->Device
;
927 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
928 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
931 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
934 case AL_LOOP_POINTS_SOFT
:
935 ReadLock(&albuf
->lock
);
936 values
[0] = albuf
->LoopStart
;
937 values
[1] = albuf
->LoopEnd
;
938 ReadUnlock(&albuf
->lock
);
942 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
946 ALCcontext_DecRef(context
);
953 * Loads the specified data into the buffer, using the specified formats.
954 * Currently, the new format must have the same channel configuration as the
957 static ALenum
LoadData(ALbuffer
*ALBuf
, ALuint freq
, ALenum NewFormat
, ALsizei frames
, enum UserFmtChannels SrcChannels
, enum UserFmtType SrcType
, const ALvoid
*data
, ALsizei align
, ALboolean storesrc
)
959 ALuint NewChannels
, NewBytes
;
960 enum FmtChannels DstChannels
;
961 enum FmtType DstType
;
965 if(DecomposeFormat(NewFormat
, &DstChannels
, &DstType
) == AL_FALSE
||
966 (long)SrcChannels
!= (long)DstChannels
)
967 return AL_INVALID_ENUM
;
969 NewChannels
= ChannelsFromFmt(DstChannels
);
970 NewBytes
= BytesFromFmt(DstType
);
974 newsize
*= NewChannels
;
975 if(newsize
> INT_MAX
)
976 return AL_OUT_OF_MEMORY
;
978 WriteLock(&ALBuf
->lock
);
979 if(ReadRef(&ALBuf
->ref
) != 0)
981 WriteUnlock(&ALBuf
->lock
);
982 return AL_INVALID_OPERATION
;
985 temp
= realloc(ALBuf
->data
, (size_t)newsize
);
988 WriteUnlock(&ALBuf
->lock
);
989 return AL_OUT_OF_MEMORY
;
994 ConvertData(ALBuf
->data
, (enum UserFmtType
)DstType
, data
, SrcType
, NewChannels
, frames
, align
);
998 ALBuf
->OriginalChannels
= SrcChannels
;
999 ALBuf
->OriginalType
= SrcType
;
1000 if(SrcType
== UserFmtIMA4
)
1002 ALsizei byte_align
= ((align
-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels
);
1003 ALBuf
->OriginalSize
= frames
/ align
* byte_align
;
1004 ALBuf
->OriginalAlign
= align
;
1006 else if(SrcType
== UserFmtMSADPCM
)
1008 ALsizei byte_align
= ((align
-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels
);
1009 ALBuf
->OriginalSize
= frames
/ align
* byte_align
;
1010 ALBuf
->OriginalAlign
= align
;
1014 ALBuf
->OriginalSize
= frames
* FrameSizeFromUserFmt(SrcChannels
, SrcType
);
1015 ALBuf
->OriginalAlign
= 1;
1020 ALBuf
->OriginalChannels
= (enum UserFmtChannels
)DstChannels
;
1021 ALBuf
->OriginalType
= (enum UserFmtType
)DstType
;
1022 ALBuf
->OriginalSize
= frames
* NewBytes
* NewChannels
;
1023 ALBuf
->OriginalAlign
= 1;
1026 ALBuf
->Frequency
= freq
;
1027 ALBuf
->FmtChannels
= DstChannels
;
1028 ALBuf
->FmtType
= DstType
;
1029 ALBuf
->Format
= NewFormat
;
1031 ALBuf
->SampleLen
= frames
;
1032 ALBuf
->LoopStart
= 0;
1033 ALBuf
->LoopEnd
= ALBuf
->SampleLen
;
1035 WriteUnlock(&ALBuf
->lock
);
1040 ALuint
BytesFromUserFmt(enum UserFmtType type
)
1044 case UserFmtByte
: return sizeof(ALbyte
);
1045 case UserFmtUByte
: return sizeof(ALubyte
);
1046 case UserFmtShort
: return sizeof(ALshort
);
1047 case UserFmtUShort
: return sizeof(ALushort
);
1048 case UserFmtInt
: return sizeof(ALint
);
1049 case UserFmtUInt
: return sizeof(ALuint
);
1050 case UserFmtFloat
: return sizeof(ALfloat
);
1051 case UserFmtDouble
: return sizeof(ALdouble
);
1052 case UserFmtByte3
: return sizeof(ALbyte
[3]);
1053 case UserFmtUByte3
: return sizeof(ALubyte
[3]);
1054 case UserFmtMulaw
: return sizeof(ALubyte
);
1055 case UserFmtAlaw
: return sizeof(ALubyte
);
1056 case UserFmtIMA4
: break; /* not handled here */
1057 case UserFmtMSADPCM
: break; /* not handled here */
1061 ALuint
ChannelsFromUserFmt(enum UserFmtChannels chans
)
1065 case UserFmtMono
: return 1;
1066 case UserFmtStereo
: return 2;
1067 case UserFmtRear
: return 2;
1068 case UserFmtQuad
: return 4;
1069 case UserFmtX51
: return 6;
1070 case UserFmtX61
: return 7;
1071 case UserFmtX71
: return 8;
1075 static ALboolean
DecomposeUserFormat(ALenum format
, enum UserFmtChannels
*chans
,
1076 enum UserFmtType
*type
)
1078 static const struct {
1080 enum UserFmtChannels channels
;
1081 enum UserFmtType type
;
1083 { AL_FORMAT_MONO8
, UserFmtMono
, UserFmtUByte
},
1084 { AL_FORMAT_MONO16
, UserFmtMono
, UserFmtShort
},
1085 { AL_FORMAT_MONO_FLOAT32
, UserFmtMono
, UserFmtFloat
},
1086 { AL_FORMAT_MONO_DOUBLE_EXT
, UserFmtMono
, UserFmtDouble
},
1087 { AL_FORMAT_MONO_IMA4
, UserFmtMono
, UserFmtIMA4
},
1088 { AL_FORMAT_MONO_MSADPCM_SOFT
, UserFmtMono
, UserFmtMSADPCM
},
1089 { AL_FORMAT_MONO_MULAW
, UserFmtMono
, UserFmtMulaw
},
1090 { AL_FORMAT_MONO_ALAW_EXT
, UserFmtMono
, UserFmtAlaw
},
1092 { AL_FORMAT_STEREO8
, UserFmtStereo
, UserFmtUByte
},
1093 { AL_FORMAT_STEREO16
, UserFmtStereo
, UserFmtShort
},
1094 { AL_FORMAT_STEREO_FLOAT32
, UserFmtStereo
, UserFmtFloat
},
1095 { AL_FORMAT_STEREO_DOUBLE_EXT
, UserFmtStereo
, UserFmtDouble
},
1096 { AL_FORMAT_STEREO_IMA4
, UserFmtStereo
, UserFmtIMA4
},
1097 { AL_FORMAT_STEREO_MSADPCM_SOFT
, UserFmtStereo
, UserFmtMSADPCM
},
1098 { AL_FORMAT_STEREO_MULAW
, UserFmtStereo
, UserFmtMulaw
},
1099 { AL_FORMAT_STEREO_ALAW_EXT
, UserFmtStereo
, UserFmtAlaw
},
1101 { AL_FORMAT_REAR8
, UserFmtRear
, UserFmtUByte
},
1102 { AL_FORMAT_REAR16
, UserFmtRear
, UserFmtShort
},
1103 { AL_FORMAT_REAR32
, UserFmtRear
, UserFmtFloat
},
1104 { AL_FORMAT_REAR_MULAW
, UserFmtRear
, UserFmtMulaw
},
1106 { AL_FORMAT_QUAD8_LOKI
, UserFmtQuad
, UserFmtUByte
},
1107 { AL_FORMAT_QUAD16_LOKI
, UserFmtQuad
, UserFmtShort
},
1109 { AL_FORMAT_QUAD8
, UserFmtQuad
, UserFmtUByte
},
1110 { AL_FORMAT_QUAD16
, UserFmtQuad
, UserFmtShort
},
1111 { AL_FORMAT_QUAD32
, UserFmtQuad
, UserFmtFloat
},
1112 { AL_FORMAT_QUAD_MULAW
, UserFmtQuad
, UserFmtMulaw
},
1114 { AL_FORMAT_51CHN8
, UserFmtX51
, UserFmtUByte
},
1115 { AL_FORMAT_51CHN16
, UserFmtX51
, UserFmtShort
},
1116 { AL_FORMAT_51CHN32
, UserFmtX51
, UserFmtFloat
},
1117 { AL_FORMAT_51CHN_MULAW
, UserFmtX51
, UserFmtMulaw
},
1119 { AL_FORMAT_61CHN8
, UserFmtX61
, UserFmtUByte
},
1120 { AL_FORMAT_61CHN16
, UserFmtX61
, UserFmtShort
},
1121 { AL_FORMAT_61CHN32
, UserFmtX61
, UserFmtFloat
},
1122 { AL_FORMAT_61CHN_MULAW
, UserFmtX61
, UserFmtMulaw
},
1124 { AL_FORMAT_71CHN8
, UserFmtX71
, UserFmtUByte
},
1125 { AL_FORMAT_71CHN16
, UserFmtX71
, UserFmtShort
},
1126 { AL_FORMAT_71CHN32
, UserFmtX71
, UserFmtFloat
},
1127 { AL_FORMAT_71CHN_MULAW
, UserFmtX71
, UserFmtMulaw
},
1131 for(i
= 0;i
< COUNTOF(list
);i
++)
1133 if(list
[i
].format
== format
)
1135 *chans
= list
[i
].channels
;
1136 *type
= list
[i
].type
;
1144 ALuint
BytesFromFmt(enum FmtType type
)
1148 case FmtByte
: return sizeof(ALbyte
);
1149 case FmtShort
: return sizeof(ALshort
);
1150 case FmtFloat
: return sizeof(ALfloat
);
1154 ALuint
ChannelsFromFmt(enum FmtChannels chans
)
1158 case FmtMono
: return 1;
1159 case FmtStereo
: return 2;
1160 case FmtRear
: return 2;
1161 case FmtQuad
: return 4;
1162 case FmtX51
: return 6;
1163 case FmtX61
: return 7;
1164 case FmtX71
: return 8;
1168 static ALboolean
DecomposeFormat(ALenum format
, enum FmtChannels
*chans
, enum FmtType
*type
)
1170 static const struct {
1172 enum FmtChannels channels
;
1175 { AL_MONO8_SOFT
, FmtMono
, FmtByte
},
1176 { AL_MONO16_SOFT
, FmtMono
, FmtShort
},
1177 { AL_MONO32F_SOFT
, FmtMono
, FmtFloat
},
1179 { AL_STEREO8_SOFT
, FmtStereo
, FmtByte
},
1180 { AL_STEREO16_SOFT
, FmtStereo
, FmtShort
},
1181 { AL_STEREO32F_SOFT
, FmtStereo
, FmtFloat
},
1183 { AL_REAR8_SOFT
, FmtRear
, FmtByte
},
1184 { AL_REAR16_SOFT
, FmtRear
, FmtShort
},
1185 { AL_REAR32F_SOFT
, FmtRear
, FmtFloat
},
1187 { AL_FORMAT_QUAD8_LOKI
, FmtQuad
, FmtByte
},
1188 { AL_FORMAT_QUAD16_LOKI
, FmtQuad
, FmtShort
},
1190 { AL_QUAD8_SOFT
, FmtQuad
, FmtByte
},
1191 { AL_QUAD16_SOFT
, FmtQuad
, FmtShort
},
1192 { AL_QUAD32F_SOFT
, FmtQuad
, FmtFloat
},
1194 { AL_5POINT1_8_SOFT
, FmtX51
, FmtByte
},
1195 { AL_5POINT1_16_SOFT
, FmtX51
, FmtShort
},
1196 { AL_5POINT1_32F_SOFT
, FmtX51
, FmtFloat
},
1198 { AL_6POINT1_8_SOFT
, FmtX61
, FmtByte
},
1199 { AL_6POINT1_16_SOFT
, FmtX61
, FmtShort
},
1200 { AL_6POINT1_32F_SOFT
, FmtX61
, FmtFloat
},
1202 { AL_7POINT1_8_SOFT
, FmtX71
, FmtByte
},
1203 { AL_7POINT1_16_SOFT
, FmtX71
, FmtShort
},
1204 { AL_7POINT1_32F_SOFT
, FmtX71
, FmtFloat
},
1208 for(i
= 0;i
< COUNTOF(list
);i
++)
1210 if(list
[i
].format
== format
)
1212 *chans
= list
[i
].channels
;
1213 *type
= list
[i
].type
;
1221 static ALboolean
SanitizeAlignment(enum UserFmtType type
, ALsizei
*align
)
1228 if(type
== UserFmtIMA4
)
1230 /* Here is where things vary:
1231 * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
1232 * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
1236 else if(type
== UserFmtMSADPCM
)
1243 if(type
== UserFmtIMA4
)
1245 /* IMA4 block alignment must be a multiple of 8, plus 1. */
1246 return ((*align
)&7) == 1;
1248 if(type
== UserFmtMSADPCM
)
1250 /* MSADPCM block alignment must be a multiple of 2. */
1251 /* FIXME: Too strict? Might only require align*channels to be a
1253 return ((*align
)&1) == 0;
1260 static ALboolean
IsValidType(ALenum type
)
1265 case AL_UNSIGNED_BYTE_SOFT
:
1267 case AL_UNSIGNED_SHORT_SOFT
:
1269 case AL_UNSIGNED_INT_SOFT
:
1271 case AL_DOUBLE_SOFT
:
1273 case AL_UNSIGNED_BYTE3_SOFT
:
1279 static ALboolean
IsValidChannels(ALenum channels
)
1284 case AL_STEREO_SOFT
:
1287 case AL_5POINT1_SOFT
:
1288 case AL_6POINT1_SOFT
:
1289 case AL_7POINT1_SOFT
:
1297 * ReleaseALBuffers()
1299 * INTERNAL: Called to destroy any buffers that still exist on the device
1301 ALvoid
ReleaseALBuffers(ALCdevice
*device
)
1304 for(i
= 0;i
< device
->BufferMap
.size
;i
++)
1306 ALbuffer
*temp
= device
->BufferMap
.array
[i
].value
;
1307 device
->BufferMap
.array
[i
].value
= NULL
;
1311 FreeThunkEntry(temp
->id
);
1312 memset(temp
, 0, sizeof(ALbuffer
));