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 ALboolean
IsValidType(ALenum type
) DECL_CONST
;
45 static ALboolean
IsValidChannels(ALenum channels
) DECL_CONST
;
46 static ALboolean
DecomposeUserFormat(ALenum format
, enum UserFmtChannels
*chans
, enum UserFmtType
*type
) DECL_CONST
;
47 static ALboolean
DecomposeFormat(ALenum format
, enum FmtChannels
*chans
, enum FmtType
*type
) DECL_CONST
;
48 static ALboolean
SanitizeAlignment(enum UserFmtType type
, ALsizei
*align
);
51 AL_API ALvoid AL_APIENTRY
alGenBuffers(ALsizei n
, ALuint
*buffers
)
57 context
= GetContextRef();
61 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
63 device
= context
->Device
;
64 for(cur
= 0;cur
< n
;cur
++)
66 ALbuffer
*buffer
= NewBuffer(context
);
69 alDeleteBuffers(cur
, buffers
);
73 buffers
[cur
] = buffer
->id
;
77 ALCcontext_DecRef(context
);
80 AL_API ALvoid AL_APIENTRY
alDeleteBuffers(ALsizei n
, const ALuint
*buffers
)
87 context
= GetContextRef();
91 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
93 device
= context
->Device
;
99 /* Check for valid Buffer ID */
100 if((ALBuf
=LookupBuffer(device
, buffers
[i
])) == NULL
)
101 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
102 if(ReadRef(&ALBuf
->ref
) != 0)
103 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
108 if((ALBuf
=LookupBuffer(device
, buffers
[i
])) != NULL
)
109 DeleteBuffer(device
, ALBuf
);
113 ALCcontext_DecRef(context
);
116 AL_API ALboolean AL_APIENTRY
alIsBuffer(ALuint buffer
)
121 context
= GetContextRef();
122 if(!context
) return AL_FALSE
;
124 ret
= ((!buffer
|| LookupBuffer(context
->Device
, buffer
)) ?
127 ALCcontext_DecRef(context
);
133 AL_API ALvoid AL_APIENTRY
alBufferData(ALuint buffer
, ALenum format
, const ALvoid
*data
, ALsizei size
, ALsizei freq
)
135 enum UserFmtChannels srcchannels
;
136 enum UserFmtType srctype
;
140 ALenum newformat
= AL_NONE
;
145 context
= GetContextRef();
148 device
= context
->Device
;
149 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
150 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
151 if(!(size
>= 0 && freq
> 0))
152 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
153 if(DecomposeUserFormat(format
, &srcchannels
, &srctype
) == AL_FALSE
)
154 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
156 align
= albuf
->UnpackAlign
;
157 if(SanitizeAlignment(srctype
, &align
) == AL_FALSE
)
158 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
166 framesize
= FrameSizeFromUserFmt(srcchannels
, srctype
) * align
;
167 if((size
%framesize
) != 0)
168 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
170 err
= LoadData(albuf
, freq
, format
, size
/framesize
*align
,
171 srcchannels
, srctype
, data
, align
, AL_TRUE
);
172 if(err
!= AL_NO_ERROR
)
173 SET_ERROR_AND_GOTO(context
, err
, done
);
181 framesize
= FrameSizeFromUserFmt(srcchannels
, srctype
) * align
;
182 if((size
%framesize
) != 0)
183 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
187 case UserFmtMono
: newformat
= AL_FORMAT_MONO_FLOAT32
; break;
188 case UserFmtStereo
: newformat
= AL_FORMAT_STEREO_FLOAT32
; break;
189 case UserFmtRear
: newformat
= AL_FORMAT_REAR32
; break;
190 case UserFmtQuad
: newformat
= AL_FORMAT_QUAD32
; break;
191 case UserFmtX51
: newformat
= AL_FORMAT_51CHN32
; break;
192 case UserFmtX61
: newformat
= AL_FORMAT_61CHN32
; break;
193 case UserFmtX71
: newformat
= AL_FORMAT_71CHN32
; break;
195 err
= LoadData(albuf
, freq
, newformat
, size
/framesize
*align
,
196 srcchannels
, srctype
, data
, align
, AL_TRUE
);
197 if(err
!= AL_NO_ERROR
)
198 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_MONO16
; break;
210 case UserFmtStereo
: newformat
= AL_FORMAT_STEREO16
; break;
211 case UserFmtRear
: newformat
= AL_FORMAT_REAR16
; break;
212 case UserFmtQuad
: newformat
= AL_FORMAT_QUAD16
; break;
213 case UserFmtX51
: newformat
= AL_FORMAT_51CHN16
; break;
214 case UserFmtX61
: newformat
= AL_FORMAT_61CHN16
; break;
215 case UserFmtX71
: newformat
= AL_FORMAT_71CHN16
; 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
);
224 framesize
= (align
-1)/2 + 4;
225 framesize
*= ChannelsFromUserFmt(srcchannels
);
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
-2)/2 + 7;
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
);
269 ALCcontext_DecRef(context
);
272 AL_API ALvoid AL_APIENTRY
alBufferSubDataSOFT(ALuint buffer
, ALenum format
, const ALvoid
*data
, ALsizei offset
, ALsizei length
)
274 enum UserFmtChannels srcchannels
;
275 enum UserFmtType srctype
;
284 context
= GetContextRef();
287 device
= context
->Device
;
288 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
289 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
290 if(!(length
>= 0 && offset
>= 0))
291 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
292 if(DecomposeUserFormat(format
, &srcchannels
, &srctype
) == AL_FALSE
)
293 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
295 WriteLock(&albuf
->lock
);
296 align
= albuf
->UnpackAlign
;
297 if(SanitizeAlignment(srctype
, &align
) == AL_FALSE
)
299 WriteUnlock(&albuf
->lock
);
300 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
302 if(srcchannels
!= albuf
->OriginalChannels
|| srctype
!= albuf
->OriginalType
)
304 WriteUnlock(&albuf
->lock
);
305 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
307 if(align
!= albuf
->OriginalAlign
)
309 WriteUnlock(&albuf
->lock
);
310 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
313 if(albuf
->OriginalType
== UserFmtIMA4
)
315 byte_align
= (albuf
->OriginalAlign
-1)/2 + 4;
316 byte_align
*= ChannelsFromUserFmt(albuf
->OriginalChannels
);
318 else if(albuf
->OriginalType
== UserFmtMSADPCM
)
320 byte_align
= (albuf
->OriginalAlign
-2)/2 + 7;
321 byte_align
*= ChannelsFromUserFmt(albuf
->OriginalChannels
);
325 byte_align
= albuf
->OriginalAlign
;
326 byte_align
*= FrameSizeFromUserFmt(albuf
->OriginalChannels
,
327 albuf
->OriginalType
);
330 if(offset
> albuf
->OriginalSize
|| length
> albuf
->OriginalSize
-offset
||
331 (offset
%byte_align
) != 0 || (length
%byte_align
) != 0)
333 WriteUnlock(&albuf
->lock
);
334 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
337 channels
= ChannelsFromFmt(albuf
->FmtChannels
);
338 bytes
= BytesFromFmt(albuf
->FmtType
);
339 /* offset -> byte offset, length -> sample count */
340 offset
= offset
/byte_align
* channels
*bytes
;
341 length
= length
/byte_align
* albuf
->OriginalAlign
;
343 ConvertData((char*)albuf
->data
+offset
, (enum UserFmtType
)albuf
->FmtType
,
344 data
, srctype
, channels
, length
, align
);
345 WriteUnlock(&albuf
->lock
);
348 ALCcontext_DecRef(context
);
352 AL_API
void AL_APIENTRY
alBufferSamplesSOFT(ALuint buffer
,
353 ALuint samplerate
, ALenum internalformat
, ALsizei samples
,
354 ALenum channels
, ALenum type
, const ALvoid
*data
)
362 context
= GetContextRef();
365 device
= context
->Device
;
366 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
367 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
368 if(!(samples
>= 0 && samplerate
!= 0))
369 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
370 if(IsValidType(type
) == AL_FALSE
|| IsValidChannels(channels
) == AL_FALSE
)
371 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
373 align
= albuf
->UnpackAlign
;
374 if(SanitizeAlignment(type
, &align
) == AL_FALSE
)
375 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
376 if((samples
%align
) != 0)
377 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
379 err
= LoadData(albuf
, samplerate
, internalformat
, samples
,
380 channels
, type
, data
, align
, AL_FALSE
);
381 if(err
!= AL_NO_ERROR
)
382 SET_ERROR_AND_GOTO(context
, err
, done
);
385 ALCcontext_DecRef(context
);
388 AL_API
void AL_APIENTRY
alBufferSubSamplesSOFT(ALuint buffer
,
389 ALsizei offset
, ALsizei samples
,
390 ALenum channels
, ALenum type
, const ALvoid
*data
)
397 context
= GetContextRef();
400 device
= context
->Device
;
401 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
402 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
403 if(!(samples
>= 0 && offset
>= 0))
404 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
405 if(IsValidType(type
) == AL_FALSE
)
406 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
408 WriteLock(&albuf
->lock
);
409 align
= albuf
->UnpackAlign
;
410 if(SanitizeAlignment(type
, &align
) == AL_FALSE
)
412 WriteUnlock(&albuf
->lock
);
413 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
415 if(channels
!= (ALenum
)albuf
->FmtChannels
)
417 WriteUnlock(&albuf
->lock
);
418 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
420 if(offset
> albuf
->SampleLen
|| samples
> albuf
->SampleLen
-offset
)
422 WriteUnlock(&albuf
->lock
);
423 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
425 if((samples
%align
) != 0)
427 WriteUnlock(&albuf
->lock
);
428 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
431 /* offset -> byte offset */
432 offset
*= FrameSizeFromFmt(albuf
->FmtChannels
, albuf
->FmtType
);
433 ConvertData((char*)albuf
->data
+offset
, (enum UserFmtType
)albuf
->FmtType
,
434 data
, type
, ChannelsFromFmt(albuf
->FmtChannels
), samples
, align
);
435 WriteUnlock(&albuf
->lock
);
438 ALCcontext_DecRef(context
);
441 AL_API
void AL_APIENTRY
alGetBufferSamplesSOFT(ALuint buffer
,
442 ALsizei offset
, ALsizei samples
,
443 ALenum channels
, ALenum type
, ALvoid
*data
)
450 context
= GetContextRef();
453 device
= context
->Device
;
454 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
455 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
456 if(!(samples
>= 0 && offset
>= 0))
457 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
458 if(IsValidType(type
) == AL_FALSE
)
459 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
461 ReadLock(&albuf
->lock
);
462 align
= albuf
->PackAlign
;
463 if(SanitizeAlignment(type
, &align
) == AL_FALSE
)
465 ReadUnlock(&albuf
->lock
);
466 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
468 if(channels
!= (ALenum
)albuf
->FmtChannels
)
470 ReadUnlock(&albuf
->lock
);
471 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
473 if(offset
> albuf
->SampleLen
|| samples
> albuf
->SampleLen
-offset
)
475 ReadUnlock(&albuf
->lock
);
476 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
478 if((samples
%align
) != 0)
480 ReadUnlock(&albuf
->lock
);
481 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
484 /* offset -> byte offset */
485 offset
*= FrameSizeFromFmt(albuf
->FmtChannels
, albuf
->FmtType
);
486 ConvertData(data
, type
, (char*)albuf
->data
+offset
, (enum UserFmtType
)albuf
->FmtType
,
487 ChannelsFromFmt(albuf
->FmtChannels
), samples
, align
);
488 ReadUnlock(&albuf
->lock
);
491 ALCcontext_DecRef(context
);
494 AL_API ALboolean AL_APIENTRY
alIsBufferFormatSupportedSOFT(ALenum format
)
496 enum FmtChannels dstchannels
;
497 enum FmtType dsttype
;
501 context
= GetContextRef();
502 if(!context
) return AL_FALSE
;
504 ret
= DecomposeFormat(format
, &dstchannels
, &dsttype
);
506 ALCcontext_DecRef(context
);
512 AL_API
void AL_APIENTRY
alBufferf(ALuint buffer
, ALenum param
, ALfloat
UNUSED(value
))
517 context
= GetContextRef();
520 device
= context
->Device
;
521 if(LookupBuffer(device
, buffer
) == NULL
)
522 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
527 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
531 ALCcontext_DecRef(context
);
535 AL_API
void AL_APIENTRY
alBuffer3f(ALuint buffer
, ALenum param
, ALfloat
UNUSED(value1
), ALfloat
UNUSED(value2
), ALfloat
UNUSED(value3
))
540 context
= GetContextRef();
543 device
= context
->Device
;
544 if(LookupBuffer(device
, buffer
) == NULL
)
545 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
550 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
554 ALCcontext_DecRef(context
);
558 AL_API
void AL_APIENTRY
alBufferfv(ALuint buffer
, ALenum param
, const ALfloat
*values
)
563 context
= GetContextRef();
566 device
= context
->Device
;
567 if(LookupBuffer(device
, buffer
) == NULL
)
568 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
571 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
575 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
579 ALCcontext_DecRef(context
);
583 AL_API
void AL_APIENTRY
alBufferi(ALuint buffer
, ALenum param
, ALint value
)
589 context
= GetContextRef();
592 device
= context
->Device
;
593 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
594 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
598 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
600 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
601 ExchangeInt(&albuf
->UnpackAlign
, value
);
604 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
606 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
607 ExchangeInt(&albuf
->PackAlign
, value
);
611 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
615 ALCcontext_DecRef(context
);
619 AL_API
void AL_APIENTRY
alBuffer3i(ALuint buffer
, ALenum param
, ALint
UNUSED(value1
), ALint
UNUSED(value2
), ALint
UNUSED(value3
))
624 context
= GetContextRef();
627 device
= context
->Device
;
628 if(LookupBuffer(device
, buffer
) == NULL
)
629 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
634 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
638 ALCcontext_DecRef(context
);
642 AL_API
void AL_APIENTRY
alBufferiv(ALuint buffer
, ALenum param
, const ALint
*values
)
652 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
653 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
654 alBufferi(buffer
, param
, values
[0]);
659 context
= GetContextRef();
662 device
= context
->Device
;
663 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
664 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
667 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
670 case AL_LOOP_POINTS_SOFT
:
671 WriteLock(&albuf
->lock
);
672 if(ReadRef(&albuf
->ref
) != 0)
674 WriteUnlock(&albuf
->lock
);
675 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
677 if(values
[0] >= values
[1] || values
[0] < 0 ||
678 values
[1] > albuf
->SampleLen
)
680 WriteUnlock(&albuf
->lock
);
681 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
684 albuf
->LoopStart
= values
[0];
685 albuf
->LoopEnd
= values
[1];
686 WriteUnlock(&albuf
->lock
);
690 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
694 ALCcontext_DecRef(context
);
698 AL_API ALvoid AL_APIENTRY
alGetBufferf(ALuint buffer
, ALenum param
, ALfloat
*value
)
704 context
= GetContextRef();
707 device
= context
->Device
;
708 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
709 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
712 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
715 case AL_SEC_LENGTH_SOFT
:
716 ReadLock(&albuf
->lock
);
717 if(albuf
->SampleLen
!= 0)
718 *value
= albuf
->SampleLen
/ (ALfloat
)albuf
->Frequency
;
721 ReadUnlock(&albuf
->lock
);
725 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
729 ALCcontext_DecRef(context
);
733 AL_API
void AL_APIENTRY
alGetBuffer3f(ALuint buffer
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
738 context
= GetContextRef();
741 device
= context
->Device
;
742 if(LookupBuffer(device
, buffer
) == NULL
)
743 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
745 if(!(value1
&& value2
&& value3
))
746 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
750 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
754 ALCcontext_DecRef(context
);
758 AL_API
void AL_APIENTRY
alGetBufferfv(ALuint buffer
, ALenum param
, ALfloat
*values
)
765 case AL_SEC_LENGTH_SOFT
:
766 alGetBufferf(buffer
, param
, values
);
770 context
= GetContextRef();
773 device
= context
->Device
;
774 if(LookupBuffer(device
, buffer
) == NULL
)
775 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
778 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
782 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
786 ALCcontext_DecRef(context
);
790 AL_API ALvoid AL_APIENTRY
alGetBufferi(ALuint buffer
, ALenum param
, ALint
*value
)
796 context
= GetContextRef();
799 device
= context
->Device
;
800 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
801 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
804 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
808 *value
= albuf
->Frequency
;
812 *value
= BytesFromFmt(albuf
->FmtType
) * 8;
816 *value
= ChannelsFromFmt(albuf
->FmtChannels
);
820 ReadLock(&albuf
->lock
);
821 *value
= albuf
->SampleLen
* FrameSizeFromFmt(albuf
->FmtChannels
,
823 ReadUnlock(&albuf
->lock
);
826 case AL_INTERNAL_FORMAT_SOFT
:
827 *value
= albuf
->Format
;
830 case AL_BYTE_LENGTH_SOFT
:
831 *value
= albuf
->OriginalSize
;
834 case AL_SAMPLE_LENGTH_SOFT
:
835 *value
= albuf
->SampleLen
;
838 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
839 *value
= albuf
->UnpackAlign
;
842 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
843 *value
= albuf
->PackAlign
;
847 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
851 ALCcontext_DecRef(context
);
855 AL_API
void AL_APIENTRY
alGetBuffer3i(ALuint buffer
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
860 context
= GetContextRef();
863 device
= context
->Device
;
864 if(LookupBuffer(device
, buffer
) == NULL
)
865 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
867 if(!(value1
&& value2
&& value3
))
868 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
872 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
876 ALCcontext_DecRef(context
);
880 AL_API
void AL_APIENTRY
alGetBufferiv(ALuint buffer
, ALenum param
, ALint
*values
)
892 case AL_INTERNAL_FORMAT_SOFT
:
893 case AL_BYTE_LENGTH_SOFT
:
894 case AL_SAMPLE_LENGTH_SOFT
:
895 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
896 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
897 alGetBufferi(buffer
, param
, values
);
901 context
= GetContextRef();
904 device
= context
->Device
;
905 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
906 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
909 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
912 case AL_LOOP_POINTS_SOFT
:
913 ReadLock(&albuf
->lock
);
914 values
[0] = albuf
->LoopStart
;
915 values
[1] = albuf
->LoopEnd
;
916 ReadUnlock(&albuf
->lock
);
920 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
924 ALCcontext_DecRef(context
);
931 * Loads the specified data into the buffer, using the specified formats.
932 * Currently, the new format must have the same channel configuration as the
935 ALenum
LoadData(ALbuffer
*ALBuf
, ALuint freq
, ALenum NewFormat
, ALsizei frames
, enum UserFmtChannels SrcChannels
, enum UserFmtType SrcType
, const ALvoid
*data
, ALsizei align
, ALboolean storesrc
)
937 ALuint NewChannels
, NewBytes
;
938 enum FmtChannels DstChannels
;
939 enum FmtType DstType
;
943 if(DecomposeFormat(NewFormat
, &DstChannels
, &DstType
) == AL_FALSE
||
944 (long)SrcChannels
!= (long)DstChannels
)
945 return AL_INVALID_ENUM
;
947 NewChannels
= ChannelsFromFmt(DstChannels
);
948 NewBytes
= BytesFromFmt(DstType
);
952 newsize
*= NewChannels
;
953 if(newsize
> INT_MAX
)
954 return AL_OUT_OF_MEMORY
;
956 WriteLock(&ALBuf
->lock
);
957 if(ReadRef(&ALBuf
->ref
) != 0)
959 WriteUnlock(&ALBuf
->lock
);
960 return AL_INVALID_OPERATION
;
963 temp
= realloc(ALBuf
->data
, (size_t)newsize
);
966 WriteUnlock(&ALBuf
->lock
);
967 return AL_OUT_OF_MEMORY
;
972 ConvertData(ALBuf
->data
, (enum UserFmtType
)DstType
, data
, SrcType
, NewChannels
, frames
, align
);
976 ALBuf
->OriginalChannels
= SrcChannels
;
977 ALBuf
->OriginalType
= SrcType
;
978 if(SrcType
== UserFmtIMA4
)
980 ALsizei byte_align
= ((align
-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels
);
981 ALBuf
->OriginalSize
= frames
/ align
* byte_align
;
982 ALBuf
->OriginalAlign
= align
;
984 else if(SrcType
== UserFmtMSADPCM
)
986 ALsizei byte_align
= ((align
-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels
);
987 ALBuf
->OriginalSize
= frames
/ align
* byte_align
;
988 ALBuf
->OriginalAlign
= align
;
992 ALBuf
->OriginalSize
= frames
* FrameSizeFromUserFmt(SrcChannels
, SrcType
);
993 ALBuf
->OriginalAlign
= 1;
998 ALBuf
->OriginalChannels
= (enum UserFmtChannels
)DstChannels
;
999 ALBuf
->OriginalType
= (enum UserFmtType
)DstType
;
1000 ALBuf
->OriginalSize
= frames
* NewBytes
* NewChannels
;
1001 ALBuf
->OriginalAlign
= 1;
1004 ALBuf
->Frequency
= freq
;
1005 ALBuf
->FmtChannels
= DstChannels
;
1006 ALBuf
->FmtType
= DstType
;
1007 ALBuf
->Format
= NewFormat
;
1009 ALBuf
->SampleLen
= frames
;
1010 ALBuf
->LoopStart
= 0;
1011 ALBuf
->LoopEnd
= ALBuf
->SampleLen
;
1013 WriteUnlock(&ALBuf
->lock
);
1018 ALuint
BytesFromUserFmt(enum UserFmtType type
)
1022 case UserFmtByte
: return sizeof(ALbyte
);
1023 case UserFmtUByte
: return sizeof(ALubyte
);
1024 case UserFmtShort
: return sizeof(ALshort
);
1025 case UserFmtUShort
: return sizeof(ALushort
);
1026 case UserFmtInt
: return sizeof(ALint
);
1027 case UserFmtUInt
: return sizeof(ALuint
);
1028 case UserFmtFloat
: return sizeof(ALfloat
);
1029 case UserFmtDouble
: return sizeof(ALdouble
);
1030 case UserFmtByte3
: return sizeof(ALbyte
[3]);
1031 case UserFmtUByte3
: return sizeof(ALubyte
[3]);
1032 case UserFmtMulaw
: return sizeof(ALubyte
);
1033 case UserFmtAlaw
: return sizeof(ALubyte
);
1034 case UserFmtIMA4
: break; /* not handled here */
1035 case UserFmtMSADPCM
: break; /* not handled here */
1039 ALuint
ChannelsFromUserFmt(enum UserFmtChannels chans
)
1043 case UserFmtMono
: return 1;
1044 case UserFmtStereo
: return 2;
1045 case UserFmtRear
: return 2;
1046 case UserFmtQuad
: return 4;
1047 case UserFmtX51
: return 6;
1048 case UserFmtX61
: return 7;
1049 case UserFmtX71
: return 8;
1053 static ALboolean
DecomposeUserFormat(ALenum format
, enum UserFmtChannels
*chans
,
1054 enum UserFmtType
*type
)
1056 static const struct {
1058 enum UserFmtChannels channels
;
1059 enum UserFmtType type
;
1061 { AL_FORMAT_MONO8
, UserFmtMono
, UserFmtUByte
},
1062 { AL_FORMAT_MONO16
, UserFmtMono
, UserFmtShort
},
1063 { AL_FORMAT_MONO_FLOAT32
, UserFmtMono
, UserFmtFloat
},
1064 { AL_FORMAT_MONO_DOUBLE_EXT
, UserFmtMono
, UserFmtDouble
},
1065 { AL_FORMAT_MONO_IMA4
, UserFmtMono
, UserFmtIMA4
},
1066 { AL_FORMAT_MONO_MSADPCM_SOFT
, UserFmtMono
, UserFmtMSADPCM
},
1067 { AL_FORMAT_MONO_MULAW
, UserFmtMono
, UserFmtMulaw
},
1068 { AL_FORMAT_MONO_ALAW_EXT
, UserFmtMono
, UserFmtAlaw
},
1070 { AL_FORMAT_STEREO8
, UserFmtStereo
, UserFmtUByte
},
1071 { AL_FORMAT_STEREO16
, UserFmtStereo
, UserFmtShort
},
1072 { AL_FORMAT_STEREO_FLOAT32
, UserFmtStereo
, UserFmtFloat
},
1073 { AL_FORMAT_STEREO_DOUBLE_EXT
, UserFmtStereo
, UserFmtDouble
},
1074 { AL_FORMAT_STEREO_IMA4
, UserFmtStereo
, UserFmtIMA4
},
1075 { AL_FORMAT_STEREO_MSADPCM_SOFT
, UserFmtStereo
, UserFmtMSADPCM
},
1076 { AL_FORMAT_STEREO_MULAW
, UserFmtStereo
, UserFmtMulaw
},
1077 { AL_FORMAT_STEREO_ALAW_EXT
, UserFmtStereo
, UserFmtAlaw
},
1079 { AL_FORMAT_REAR8
, UserFmtRear
, UserFmtUByte
},
1080 { AL_FORMAT_REAR16
, UserFmtRear
, UserFmtShort
},
1081 { AL_FORMAT_REAR32
, UserFmtRear
, UserFmtFloat
},
1082 { AL_FORMAT_REAR_MULAW
, UserFmtRear
, UserFmtMulaw
},
1084 { AL_FORMAT_QUAD8_LOKI
, UserFmtQuad
, UserFmtUByte
},
1085 { AL_FORMAT_QUAD16_LOKI
, UserFmtQuad
, UserFmtShort
},
1087 { AL_FORMAT_QUAD8
, UserFmtQuad
, UserFmtUByte
},
1088 { AL_FORMAT_QUAD16
, UserFmtQuad
, UserFmtShort
},
1089 { AL_FORMAT_QUAD32
, UserFmtQuad
, UserFmtFloat
},
1090 { AL_FORMAT_QUAD_MULAW
, UserFmtQuad
, UserFmtMulaw
},
1092 { AL_FORMAT_51CHN8
, UserFmtX51
, UserFmtUByte
},
1093 { AL_FORMAT_51CHN16
, UserFmtX51
, UserFmtShort
},
1094 { AL_FORMAT_51CHN32
, UserFmtX51
, UserFmtFloat
},
1095 { AL_FORMAT_51CHN_MULAW
, UserFmtX51
, UserFmtMulaw
},
1097 { AL_FORMAT_61CHN8
, UserFmtX61
, UserFmtUByte
},
1098 { AL_FORMAT_61CHN16
, UserFmtX61
, UserFmtShort
},
1099 { AL_FORMAT_61CHN32
, UserFmtX61
, UserFmtFloat
},
1100 { AL_FORMAT_61CHN_MULAW
, UserFmtX61
, UserFmtMulaw
},
1102 { AL_FORMAT_71CHN8
, UserFmtX71
, UserFmtUByte
},
1103 { AL_FORMAT_71CHN16
, UserFmtX71
, UserFmtShort
},
1104 { AL_FORMAT_71CHN32
, UserFmtX71
, UserFmtFloat
},
1105 { AL_FORMAT_71CHN_MULAW
, UserFmtX71
, UserFmtMulaw
},
1109 for(i
= 0;i
< COUNTOF(list
);i
++)
1111 if(list
[i
].format
== format
)
1113 *chans
= list
[i
].channels
;
1114 *type
= list
[i
].type
;
1122 ALuint
BytesFromFmt(enum FmtType type
)
1126 case FmtByte
: return sizeof(ALbyte
);
1127 case FmtShort
: return sizeof(ALshort
);
1128 case FmtFloat
: return sizeof(ALfloat
);
1132 ALuint
ChannelsFromFmt(enum FmtChannels chans
)
1136 case FmtMono
: return 1;
1137 case FmtStereo
: return 2;
1138 case FmtRear
: return 2;
1139 case FmtQuad
: return 4;
1140 case FmtX51
: return 6;
1141 case FmtX61
: return 7;
1142 case FmtX71
: return 8;
1146 static ALboolean
DecomposeFormat(ALenum format
, enum FmtChannels
*chans
, enum FmtType
*type
)
1148 static const struct {
1150 enum FmtChannels channels
;
1153 { AL_MONO8_SOFT
, FmtMono
, FmtByte
},
1154 { AL_MONO16_SOFT
, FmtMono
, FmtShort
},
1155 { AL_MONO32F_SOFT
, FmtMono
, FmtFloat
},
1157 { AL_STEREO8_SOFT
, FmtStereo
, FmtByte
},
1158 { AL_STEREO16_SOFT
, FmtStereo
, FmtShort
},
1159 { AL_STEREO32F_SOFT
, FmtStereo
, FmtFloat
},
1161 { AL_REAR8_SOFT
, FmtRear
, FmtByte
},
1162 { AL_REAR16_SOFT
, FmtRear
, FmtShort
},
1163 { AL_REAR32F_SOFT
, FmtRear
, FmtFloat
},
1165 { AL_FORMAT_QUAD8_LOKI
, FmtQuad
, FmtByte
},
1166 { AL_FORMAT_QUAD16_LOKI
, FmtQuad
, FmtShort
},
1168 { AL_QUAD8_SOFT
, FmtQuad
, FmtByte
},
1169 { AL_QUAD16_SOFT
, FmtQuad
, FmtShort
},
1170 { AL_QUAD32F_SOFT
, FmtQuad
, FmtFloat
},
1172 { AL_5POINT1_8_SOFT
, FmtX51
, FmtByte
},
1173 { AL_5POINT1_16_SOFT
, FmtX51
, FmtShort
},
1174 { AL_5POINT1_32F_SOFT
, FmtX51
, FmtFloat
},
1176 { AL_6POINT1_8_SOFT
, FmtX61
, FmtByte
},
1177 { AL_6POINT1_16_SOFT
, FmtX61
, FmtShort
},
1178 { AL_6POINT1_32F_SOFT
, FmtX61
, FmtFloat
},
1180 { AL_7POINT1_8_SOFT
, FmtX71
, FmtByte
},
1181 { AL_7POINT1_16_SOFT
, FmtX71
, FmtShort
},
1182 { AL_7POINT1_32F_SOFT
, FmtX71
, FmtFloat
},
1186 for(i
= 0;i
< COUNTOF(list
);i
++)
1188 if(list
[i
].format
== format
)
1190 *chans
= list
[i
].channels
;
1191 *type
= list
[i
].type
;
1199 static ALboolean
SanitizeAlignment(enum UserFmtType type
, ALsizei
*align
)
1206 if(type
== UserFmtIMA4
)
1208 /* Here is where things vary:
1209 * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
1210 * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
1214 else if(type
== UserFmtMSADPCM
)
1221 if(type
== UserFmtIMA4
)
1223 /* IMA4 block alignment must be a multiple of 8, plus 1. */
1224 return ((*align
)&7) == 1;
1226 if(type
== UserFmtMSADPCM
)
1228 /* MSADPCM block alignment must be a multiple of 2. */
1229 /* FIXME: Too strict? Might only require align*channels to be a
1231 return ((*align
)&1) == 0;
1238 static ALboolean
IsValidType(ALenum type
)
1243 case AL_UNSIGNED_BYTE_SOFT
:
1245 case AL_UNSIGNED_SHORT_SOFT
:
1247 case AL_UNSIGNED_INT_SOFT
:
1249 case AL_DOUBLE_SOFT
:
1251 case AL_UNSIGNED_BYTE3_SOFT
:
1257 static ALboolean
IsValidChannels(ALenum channels
)
1262 case AL_STEREO_SOFT
:
1265 case AL_5POINT1_SOFT
:
1266 case AL_6POINT1_SOFT
:
1267 case AL_7POINT1_SOFT
:
1274 ALbuffer
*NewBuffer(ALCcontext
*context
)
1276 ALCdevice
*device
= context
->Device
;
1280 buffer
= calloc(1, sizeof(ALbuffer
));
1282 SET_ERROR_AND_RETURN_VALUE(context
, AL_OUT_OF_MEMORY
, NULL
);
1283 RWLockInit(&buffer
->lock
);
1285 err
= NewThunkEntry(&buffer
->id
);
1286 if(err
== AL_NO_ERROR
)
1287 err
= InsertUIntMapEntry(&device
->BufferMap
, buffer
->id
, buffer
);
1288 if(err
!= AL_NO_ERROR
)
1290 FreeThunkEntry(buffer
->id
);
1291 memset(buffer
, 0, sizeof(ALbuffer
));
1294 SET_ERROR_AND_RETURN_VALUE(context
, err
, NULL
);
1300 void DeleteBuffer(ALCdevice
*device
, ALbuffer
*buffer
)
1302 RemoveBuffer(device
, buffer
->id
);
1303 FreeThunkEntry(buffer
->id
);
1307 memset(buffer
, 0, sizeof(*buffer
));
1313 * ReleaseALBuffers()
1315 * INTERNAL: Called to destroy any buffers that still exist on the device
1317 ALvoid
ReleaseALBuffers(ALCdevice
*device
)
1320 for(i
= 0;i
< device
->BufferMap
.size
;i
++)
1322 ALbuffer
*temp
= device
->BufferMap
.array
[i
].value
;
1323 device
->BufferMap
.array
[i
].value
= NULL
;
1327 FreeThunkEntry(temp
->id
);
1328 memset(temp
, 0, sizeof(ALbuffer
));