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 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
)
56 context
= GetContextRef();
60 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
62 for(cur
= 0;cur
< n
;cur
++)
64 ALbuffer
*buffer
= NewBuffer(context
);
67 alDeleteBuffers(cur
, buffers
);
71 buffers
[cur
] = buffer
->id
;
75 ALCcontext_DecRef(context
);
78 AL_API ALvoid AL_APIENTRY
alDeleteBuffers(ALsizei n
, const ALuint
*buffers
)
85 context
= GetContextRef();
89 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
91 device
= context
->Device
;
97 /* Check for valid Buffer ID */
98 if((ALBuf
=LookupBuffer(device
, buffers
[i
])) == NULL
)
99 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
100 if(ReadRef(&ALBuf
->ref
) != 0)
101 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
106 if((ALBuf
=LookupBuffer(device
, buffers
[i
])) != NULL
)
107 DeleteBuffer(device
, ALBuf
);
111 ALCcontext_DecRef(context
);
114 AL_API ALboolean AL_APIENTRY
alIsBuffer(ALuint buffer
)
119 context
= GetContextRef();
120 if(!context
) return AL_FALSE
;
122 ret
= ((!buffer
|| LookupBuffer(context
->Device
, buffer
)) ?
125 ALCcontext_DecRef(context
);
131 AL_API ALvoid AL_APIENTRY
alBufferData(ALuint buffer
, ALenum format
, const ALvoid
*data
, ALsizei size
, ALsizei freq
)
133 enum UserFmtChannels srcchannels
;
134 enum UserFmtType srctype
;
138 ALenum newformat
= AL_NONE
;
143 context
= GetContextRef();
146 device
= context
->Device
;
147 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
148 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
149 if(!(size
>= 0 && freq
> 0))
150 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
151 if(DecomposeUserFormat(format
, &srcchannels
, &srctype
) == AL_FALSE
)
152 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
154 align
= ATOMIC_LOAD(&albuf
->UnpackAlign
);
155 if(SanitizeAlignment(srctype
, &align
) == AL_FALSE
)
156 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
164 framesize
= FrameSizeFromUserFmt(srcchannels
, srctype
) * align
;
165 if((size
%framesize
) != 0)
166 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
168 err
= LoadData(albuf
, freq
, format
, size
/framesize
*align
,
169 srcchannels
, srctype
, data
, align
, AL_TRUE
);
170 if(err
!= AL_NO_ERROR
)
171 SET_ERROR_AND_GOTO(context
, err
, done
);
179 framesize
= FrameSizeFromUserFmt(srcchannels
, srctype
) * align
;
180 if((size
%framesize
) != 0)
181 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
185 case UserFmtMono
: newformat
= AL_FORMAT_MONO_FLOAT32
; break;
186 case UserFmtStereo
: newformat
= AL_FORMAT_STEREO_FLOAT32
; break;
187 case UserFmtRear
: newformat
= AL_FORMAT_REAR32
; break;
188 case UserFmtQuad
: newformat
= AL_FORMAT_QUAD32
; break;
189 case UserFmtX51
: newformat
= AL_FORMAT_51CHN32
; break;
190 case UserFmtX61
: newformat
= AL_FORMAT_61CHN32
; break;
191 case UserFmtX71
: newformat
= AL_FORMAT_71CHN32
; break;
192 case UserFmtBFormat2D
: newformat
= AL_FORMAT_BFORMAT2D_FLOAT32
; break;
193 case UserFmtBFormat3D
: newformat
= AL_FORMAT_BFORMAT3D_FLOAT32
; 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;
216 case UserFmtBFormat2D
: newformat
= AL_FORMAT_BFORMAT2D_16
; break;
217 case UserFmtBFormat3D
: newformat
= AL_FORMAT_BFORMAT3D_16
; break;
219 err
= LoadData(albuf
, freq
, newformat
, size
/framesize
*align
,
220 srcchannels
, srctype
, data
, align
, AL_TRUE
);
221 if(err
!= AL_NO_ERROR
)
222 SET_ERROR_AND_GOTO(context
, err
, done
);
226 framesize
= (align
-1)/2 + 4;
227 framesize
*= ChannelsFromUserFmt(srcchannels
);
228 if((size
%framesize
) != 0)
229 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
233 case UserFmtMono
: newformat
= AL_FORMAT_MONO16
; break;
234 case UserFmtStereo
: newformat
= AL_FORMAT_STEREO16
; break;
235 case UserFmtRear
: newformat
= AL_FORMAT_REAR16
; break;
236 case UserFmtQuad
: newformat
= AL_FORMAT_QUAD16
; break;
237 case UserFmtX51
: newformat
= AL_FORMAT_51CHN16
; break;
238 case UserFmtX61
: newformat
= AL_FORMAT_61CHN16
; break;
239 case UserFmtX71
: newformat
= AL_FORMAT_71CHN16
; break;
240 case UserFmtBFormat2D
: newformat
= AL_FORMAT_BFORMAT2D_16
; break;
241 case UserFmtBFormat3D
: newformat
= AL_FORMAT_BFORMAT3D_16
; break;
243 err
= LoadData(albuf
, freq
, newformat
, size
/framesize
*align
,
244 srcchannels
, srctype
, data
, align
, AL_TRUE
);
245 if(err
!= AL_NO_ERROR
)
246 SET_ERROR_AND_GOTO(context
, err
, done
);
250 framesize
= (align
-2)/2 + 7;
251 framesize
*= ChannelsFromUserFmt(srcchannels
);
252 if((size
%framesize
) != 0)
253 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
257 case UserFmtMono
: newformat
= AL_FORMAT_MONO16
; break;
258 case UserFmtStereo
: newformat
= AL_FORMAT_STEREO16
; break;
259 case UserFmtRear
: newformat
= AL_FORMAT_REAR16
; break;
260 case UserFmtQuad
: newformat
= AL_FORMAT_QUAD16
; break;
261 case UserFmtX51
: newformat
= AL_FORMAT_51CHN16
; break;
262 case UserFmtX61
: newformat
= AL_FORMAT_61CHN16
; break;
263 case UserFmtX71
: newformat
= AL_FORMAT_71CHN16
; break;
264 case UserFmtBFormat2D
: newformat
= AL_FORMAT_BFORMAT2D_16
; break;
265 case UserFmtBFormat3D
: newformat
= AL_FORMAT_BFORMAT3D_16
; break;
267 err
= LoadData(albuf
, freq
, newformat
, size
/framesize
*align
,
268 srcchannels
, srctype
, data
, align
, AL_TRUE
);
269 if(err
!= AL_NO_ERROR
)
270 SET_ERROR_AND_GOTO(context
, err
, done
);
275 ALCcontext_DecRef(context
);
278 AL_API ALvoid AL_APIENTRY
alBufferSubDataSOFT(ALuint buffer
, ALenum format
, const ALvoid
*data
, ALsizei offset
, ALsizei length
)
280 enum UserFmtChannels srcchannels
;
281 enum UserFmtType srctype
;
290 context
= GetContextRef();
293 device
= context
->Device
;
294 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
295 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
296 if(!(length
>= 0 && offset
>= 0))
297 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
298 if(DecomposeUserFormat(format
, &srcchannels
, &srctype
) == AL_FALSE
)
299 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
301 WriteLock(&albuf
->lock
);
302 align
= ATOMIC_LOAD(&albuf
->UnpackAlign
);
303 if(SanitizeAlignment(srctype
, &align
) == AL_FALSE
)
305 WriteUnlock(&albuf
->lock
);
306 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
308 if(srcchannels
!= albuf
->OriginalChannels
|| srctype
!= albuf
->OriginalType
)
310 WriteUnlock(&albuf
->lock
);
311 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
313 if(align
!= albuf
->OriginalAlign
)
315 WriteUnlock(&albuf
->lock
);
316 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
319 if(albuf
->OriginalType
== UserFmtIMA4
)
321 byte_align
= (albuf
->OriginalAlign
-1)/2 + 4;
322 byte_align
*= ChannelsFromUserFmt(albuf
->OriginalChannels
);
324 else if(albuf
->OriginalType
== UserFmtMSADPCM
)
326 byte_align
= (albuf
->OriginalAlign
-2)/2 + 7;
327 byte_align
*= ChannelsFromUserFmt(albuf
->OriginalChannels
);
331 byte_align
= albuf
->OriginalAlign
;
332 byte_align
*= FrameSizeFromUserFmt(albuf
->OriginalChannels
,
333 albuf
->OriginalType
);
336 if(offset
> albuf
->OriginalSize
|| length
> albuf
->OriginalSize
-offset
||
337 (offset
%byte_align
) != 0 || (length
%byte_align
) != 0)
339 WriteUnlock(&albuf
->lock
);
340 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
343 channels
= ChannelsFromFmt(albuf
->FmtChannels
);
344 bytes
= BytesFromFmt(albuf
->FmtType
);
345 /* offset -> byte offset, length -> sample count */
346 offset
= offset
/byte_align
* channels
*bytes
;
347 length
= length
/byte_align
* albuf
->OriginalAlign
;
349 ConvertData((char*)albuf
->data
+offset
, (enum UserFmtType
)albuf
->FmtType
,
350 data
, srctype
, channels
, length
, align
);
351 WriteUnlock(&albuf
->lock
);
354 ALCcontext_DecRef(context
);
358 AL_API
void AL_APIENTRY
alBufferSamplesSOFT(ALuint buffer
,
359 ALuint samplerate
, ALenum internalformat
, ALsizei samples
,
360 ALenum channels
, ALenum type
, const ALvoid
*data
)
368 context
= GetContextRef();
371 device
= context
->Device
;
372 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
373 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
374 if(!(samples
>= 0 && samplerate
!= 0))
375 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
376 if(IsValidType(type
) == AL_FALSE
|| IsValidChannels(channels
) == AL_FALSE
)
377 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
379 align
= ATOMIC_LOAD(&albuf
->UnpackAlign
);
380 if(SanitizeAlignment(type
, &align
) == AL_FALSE
)
381 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
382 if((samples
%align
) != 0)
383 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
385 err
= LoadData(albuf
, samplerate
, internalformat
, samples
,
386 channels
, type
, data
, align
, AL_FALSE
);
387 if(err
!= AL_NO_ERROR
)
388 SET_ERROR_AND_GOTO(context
, err
, done
);
391 ALCcontext_DecRef(context
);
394 AL_API
void AL_APIENTRY
alBufferSubSamplesSOFT(ALuint buffer
,
395 ALsizei offset
, ALsizei samples
,
396 ALenum channels
, ALenum type
, const ALvoid
*data
)
403 context
= GetContextRef();
406 device
= context
->Device
;
407 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
408 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
409 if(!(samples
>= 0 && offset
>= 0))
410 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
411 if(IsValidType(type
) == AL_FALSE
)
412 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
414 WriteLock(&albuf
->lock
);
415 align
= ATOMIC_LOAD(&albuf
->UnpackAlign
);
416 if(SanitizeAlignment(type
, &align
) == AL_FALSE
)
418 WriteUnlock(&albuf
->lock
);
419 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
421 if(channels
!= (ALenum
)albuf
->FmtChannels
)
423 WriteUnlock(&albuf
->lock
);
424 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
426 if(offset
> albuf
->SampleLen
|| samples
> albuf
->SampleLen
-offset
)
428 WriteUnlock(&albuf
->lock
);
429 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
431 if((samples
%align
) != 0)
433 WriteUnlock(&albuf
->lock
);
434 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
437 /* offset -> byte offset */
438 offset
*= FrameSizeFromFmt(albuf
->FmtChannels
, albuf
->FmtType
);
439 ConvertData((char*)albuf
->data
+offset
, (enum UserFmtType
)albuf
->FmtType
,
440 data
, type
, ChannelsFromFmt(albuf
->FmtChannels
), samples
, align
);
441 WriteUnlock(&albuf
->lock
);
444 ALCcontext_DecRef(context
);
447 AL_API
void AL_APIENTRY
alGetBufferSamplesSOFT(ALuint buffer
,
448 ALsizei offset
, ALsizei samples
,
449 ALenum channels
, ALenum type
, ALvoid
*data
)
456 context
= GetContextRef();
459 device
= context
->Device
;
460 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
461 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
462 if(!(samples
>= 0 && offset
>= 0))
463 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
464 if(IsValidType(type
) == AL_FALSE
)
465 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
467 ReadLock(&albuf
->lock
);
468 align
= ATOMIC_LOAD(&albuf
->PackAlign
);
469 if(SanitizeAlignment(type
, &align
) == AL_FALSE
)
471 ReadUnlock(&albuf
->lock
);
472 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
474 if(channels
!= (ALenum
)albuf
->FmtChannels
)
476 ReadUnlock(&albuf
->lock
);
477 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
479 if(offset
> albuf
->SampleLen
|| samples
> albuf
->SampleLen
-offset
)
481 ReadUnlock(&albuf
->lock
);
482 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
484 if((samples
%align
) != 0)
486 ReadUnlock(&albuf
->lock
);
487 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
490 /* offset -> byte offset */
491 offset
*= FrameSizeFromFmt(albuf
->FmtChannels
, albuf
->FmtType
);
492 ConvertData(data
, type
, (char*)albuf
->data
+offset
, (enum UserFmtType
)albuf
->FmtType
,
493 ChannelsFromFmt(albuf
->FmtChannels
), samples
, align
);
494 ReadUnlock(&albuf
->lock
);
497 ALCcontext_DecRef(context
);
500 AL_API ALboolean AL_APIENTRY
alIsBufferFormatSupportedSOFT(ALenum format
)
502 enum FmtChannels dstchannels
;
503 enum FmtType dsttype
;
507 context
= GetContextRef();
508 if(!context
) return AL_FALSE
;
510 ret
= DecomposeFormat(format
, &dstchannels
, &dsttype
);
512 ALCcontext_DecRef(context
);
518 AL_API
void AL_APIENTRY
alBufferf(ALuint buffer
, ALenum param
, ALfloat
UNUSED(value
))
523 context
= GetContextRef();
526 device
= context
->Device
;
527 if(LookupBuffer(device
, buffer
) == NULL
)
528 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
533 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
537 ALCcontext_DecRef(context
);
541 AL_API
void AL_APIENTRY
alBuffer3f(ALuint buffer
, ALenum param
, ALfloat
UNUSED(value1
), ALfloat
UNUSED(value2
), ALfloat
UNUSED(value3
))
546 context
= GetContextRef();
549 device
= context
->Device
;
550 if(LookupBuffer(device
, buffer
) == NULL
)
551 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
556 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
560 ALCcontext_DecRef(context
);
564 AL_API
void AL_APIENTRY
alBufferfv(ALuint buffer
, ALenum param
, const ALfloat
*values
)
569 context
= GetContextRef();
572 device
= context
->Device
;
573 if(LookupBuffer(device
, buffer
) == NULL
)
574 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
577 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
581 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
585 ALCcontext_DecRef(context
);
589 AL_API
void AL_APIENTRY
alBufferi(ALuint buffer
, ALenum param
, ALint value
)
595 context
= GetContextRef();
598 device
= context
->Device
;
599 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
600 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
604 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
606 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
607 ATOMIC_STORE(&albuf
->UnpackAlign
, value
);
610 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
612 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
613 ATOMIC_STORE(&albuf
->PackAlign
, value
);
617 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
621 ALCcontext_DecRef(context
);
625 AL_API
void AL_APIENTRY
alBuffer3i(ALuint buffer
, ALenum param
, ALint
UNUSED(value1
), ALint
UNUSED(value2
), ALint
UNUSED(value3
))
630 context
= GetContextRef();
633 device
= context
->Device
;
634 if(LookupBuffer(device
, buffer
) == NULL
)
635 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
640 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
644 ALCcontext_DecRef(context
);
648 AL_API
void AL_APIENTRY
alBufferiv(ALuint buffer
, ALenum param
, const ALint
*values
)
658 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
659 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
660 alBufferi(buffer
, param
, values
[0]);
665 context
= GetContextRef();
668 device
= context
->Device
;
669 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
670 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
673 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
676 case AL_LOOP_POINTS_SOFT
:
677 WriteLock(&albuf
->lock
);
678 if(ReadRef(&albuf
->ref
) != 0)
680 WriteUnlock(&albuf
->lock
);
681 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
683 if(values
[0] >= values
[1] || values
[0] < 0 ||
684 values
[1] > albuf
->SampleLen
)
686 WriteUnlock(&albuf
->lock
);
687 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
690 albuf
->LoopStart
= values
[0];
691 albuf
->LoopEnd
= values
[1];
692 WriteUnlock(&albuf
->lock
);
696 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
700 ALCcontext_DecRef(context
);
704 AL_API ALvoid AL_APIENTRY
alGetBufferf(ALuint buffer
, ALenum param
, ALfloat
*value
)
710 context
= GetContextRef();
713 device
= context
->Device
;
714 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
715 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
718 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
721 case AL_SEC_LENGTH_SOFT
:
722 ReadLock(&albuf
->lock
);
723 if(albuf
->SampleLen
!= 0)
724 *value
= albuf
->SampleLen
/ (ALfloat
)albuf
->Frequency
;
727 ReadUnlock(&albuf
->lock
);
731 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
735 ALCcontext_DecRef(context
);
739 AL_API
void AL_APIENTRY
alGetBuffer3f(ALuint buffer
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
744 context
= GetContextRef();
747 device
= context
->Device
;
748 if(LookupBuffer(device
, buffer
) == NULL
)
749 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
751 if(!(value1
&& value2
&& value3
))
752 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
756 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
760 ALCcontext_DecRef(context
);
764 AL_API
void AL_APIENTRY
alGetBufferfv(ALuint buffer
, ALenum param
, ALfloat
*values
)
771 case AL_SEC_LENGTH_SOFT
:
772 alGetBufferf(buffer
, param
, values
);
776 context
= GetContextRef();
779 device
= context
->Device
;
780 if(LookupBuffer(device
, buffer
) == NULL
)
781 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
784 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
788 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
792 ALCcontext_DecRef(context
);
796 AL_API ALvoid AL_APIENTRY
alGetBufferi(ALuint buffer
, ALenum param
, ALint
*value
)
802 context
= GetContextRef();
805 device
= context
->Device
;
806 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
807 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
810 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
814 *value
= albuf
->Frequency
;
818 *value
= BytesFromFmt(albuf
->FmtType
) * 8;
822 *value
= ChannelsFromFmt(albuf
->FmtChannels
);
826 ReadLock(&albuf
->lock
);
827 *value
= albuf
->SampleLen
* FrameSizeFromFmt(albuf
->FmtChannels
,
829 ReadUnlock(&albuf
->lock
);
832 case AL_INTERNAL_FORMAT_SOFT
:
833 *value
= albuf
->Format
;
836 case AL_BYTE_LENGTH_SOFT
:
837 *value
= albuf
->OriginalSize
;
840 case AL_SAMPLE_LENGTH_SOFT
:
841 *value
= albuf
->SampleLen
;
844 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
845 *value
= ATOMIC_LOAD(&albuf
->UnpackAlign
);
848 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
849 *value
= ATOMIC_LOAD(&albuf
->PackAlign
);
853 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
857 ALCcontext_DecRef(context
);
861 AL_API
void AL_APIENTRY
alGetBuffer3i(ALuint buffer
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
866 context
= GetContextRef();
869 device
= context
->Device
;
870 if(LookupBuffer(device
, buffer
) == NULL
)
871 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
873 if(!(value1
&& value2
&& value3
))
874 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
878 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
882 ALCcontext_DecRef(context
);
886 AL_API
void AL_APIENTRY
alGetBufferiv(ALuint buffer
, ALenum param
, ALint
*values
)
898 case AL_INTERNAL_FORMAT_SOFT
:
899 case AL_BYTE_LENGTH_SOFT
:
900 case AL_SAMPLE_LENGTH_SOFT
:
901 case AL_UNPACK_BLOCK_ALIGNMENT_SOFT
:
902 case AL_PACK_BLOCK_ALIGNMENT_SOFT
:
903 alGetBufferi(buffer
, param
, values
);
907 context
= GetContextRef();
910 device
= context
->Device
;
911 if((albuf
=LookupBuffer(device
, buffer
)) == NULL
)
912 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
915 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
918 case AL_LOOP_POINTS_SOFT
:
919 ReadLock(&albuf
->lock
);
920 values
[0] = albuf
->LoopStart
;
921 values
[1] = albuf
->LoopEnd
;
922 ReadUnlock(&albuf
->lock
);
926 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
930 ALCcontext_DecRef(context
);
937 * Loads the specified data into the buffer, using the specified formats.
938 * Currently, the new format must have the same channel configuration as the
941 ALenum
LoadData(ALbuffer
*ALBuf
, ALuint freq
, ALenum NewFormat
, ALsizei frames
, enum UserFmtChannels SrcChannels
, enum UserFmtType SrcType
, const ALvoid
*data
, ALsizei align
, ALboolean storesrc
)
943 ALuint NewChannels
, NewBytes
;
944 enum FmtChannels DstChannels
;
945 enum FmtType DstType
;
949 if(DecomposeFormat(NewFormat
, &DstChannels
, &DstType
) == AL_FALSE
||
950 (long)SrcChannels
!= (long)DstChannels
)
951 return AL_INVALID_ENUM
;
953 NewChannels
= ChannelsFromFmt(DstChannels
);
954 NewBytes
= BytesFromFmt(DstType
);
958 newsize
*= NewChannels
;
959 if(newsize
> INT_MAX
)
960 return AL_OUT_OF_MEMORY
;
962 WriteLock(&ALBuf
->lock
);
963 if(ReadRef(&ALBuf
->ref
) != 0)
965 WriteUnlock(&ALBuf
->lock
);
966 return AL_INVALID_OPERATION
;
969 temp
= realloc(ALBuf
->data
, (size_t)newsize
);
972 WriteUnlock(&ALBuf
->lock
);
973 return AL_OUT_OF_MEMORY
;
978 ConvertData(ALBuf
->data
, (enum UserFmtType
)DstType
, data
, SrcType
, NewChannels
, frames
, align
);
982 ALBuf
->OriginalChannels
= SrcChannels
;
983 ALBuf
->OriginalType
= SrcType
;
984 if(SrcType
== UserFmtIMA4
)
986 ALsizei byte_align
= ((align
-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels
);
987 ALBuf
->OriginalSize
= frames
/ align
* byte_align
;
988 ALBuf
->OriginalAlign
= align
;
990 else if(SrcType
== UserFmtMSADPCM
)
992 ALsizei byte_align
= ((align
-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels
);
993 ALBuf
->OriginalSize
= frames
/ align
* byte_align
;
994 ALBuf
->OriginalAlign
= align
;
998 ALBuf
->OriginalSize
= frames
* FrameSizeFromUserFmt(SrcChannels
, SrcType
);
999 ALBuf
->OriginalAlign
= 1;
1004 ALBuf
->OriginalChannels
= (enum UserFmtChannels
)DstChannels
;
1005 ALBuf
->OriginalType
= (enum UserFmtType
)DstType
;
1006 ALBuf
->OriginalSize
= frames
* NewBytes
* NewChannels
;
1007 ALBuf
->OriginalAlign
= 1;
1010 ALBuf
->Frequency
= freq
;
1011 ALBuf
->FmtChannels
= DstChannels
;
1012 ALBuf
->FmtType
= DstType
;
1013 ALBuf
->Format
= NewFormat
;
1015 ALBuf
->SampleLen
= frames
;
1016 ALBuf
->LoopStart
= 0;
1017 ALBuf
->LoopEnd
= ALBuf
->SampleLen
;
1019 WriteUnlock(&ALBuf
->lock
);
1024 ALuint
BytesFromUserFmt(enum UserFmtType type
)
1028 case UserFmtByte
: return sizeof(ALbyte
);
1029 case UserFmtUByte
: return sizeof(ALubyte
);
1030 case UserFmtShort
: return sizeof(ALshort
);
1031 case UserFmtUShort
: return sizeof(ALushort
);
1032 case UserFmtInt
: return sizeof(ALint
);
1033 case UserFmtUInt
: return sizeof(ALuint
);
1034 case UserFmtFloat
: return sizeof(ALfloat
);
1035 case UserFmtDouble
: return sizeof(ALdouble
);
1036 case UserFmtByte3
: return sizeof(ALbyte
[3]);
1037 case UserFmtUByte3
: return sizeof(ALubyte
[3]);
1038 case UserFmtMulaw
: return sizeof(ALubyte
);
1039 case UserFmtAlaw
: return sizeof(ALubyte
);
1040 case UserFmtIMA4
: break; /* not handled here */
1041 case UserFmtMSADPCM
: break; /* not handled here */
1045 ALuint
ChannelsFromUserFmt(enum UserFmtChannels chans
)
1049 case UserFmtMono
: return 1;
1050 case UserFmtStereo
: return 2;
1051 case UserFmtRear
: return 2;
1052 case UserFmtQuad
: return 4;
1053 case UserFmtX51
: return 6;
1054 case UserFmtX61
: return 7;
1055 case UserFmtX71
: return 8;
1056 case UserFmtBFormat2D
: return 3;
1057 case UserFmtBFormat3D
: return 4;
1061 static ALboolean
DecomposeUserFormat(ALenum format
, enum UserFmtChannels
*chans
,
1062 enum UserFmtType
*type
)
1064 static const struct {
1066 enum UserFmtChannels channels
;
1067 enum UserFmtType type
;
1069 { AL_FORMAT_MONO8
, UserFmtMono
, UserFmtUByte
},
1070 { AL_FORMAT_MONO16
, UserFmtMono
, UserFmtShort
},
1071 { AL_FORMAT_MONO_FLOAT32
, UserFmtMono
, UserFmtFloat
},
1072 { AL_FORMAT_MONO_DOUBLE_EXT
, UserFmtMono
, UserFmtDouble
},
1073 { AL_FORMAT_MONO_IMA4
, UserFmtMono
, UserFmtIMA4
},
1074 { AL_FORMAT_MONO_MSADPCM_SOFT
, UserFmtMono
, UserFmtMSADPCM
},
1075 { AL_FORMAT_MONO_MULAW
, UserFmtMono
, UserFmtMulaw
},
1076 { AL_FORMAT_MONO_ALAW_EXT
, UserFmtMono
, UserFmtAlaw
},
1078 { AL_FORMAT_STEREO8
, UserFmtStereo
, UserFmtUByte
},
1079 { AL_FORMAT_STEREO16
, UserFmtStereo
, UserFmtShort
},
1080 { AL_FORMAT_STEREO_FLOAT32
, UserFmtStereo
, UserFmtFloat
},
1081 { AL_FORMAT_STEREO_DOUBLE_EXT
, UserFmtStereo
, UserFmtDouble
},
1082 { AL_FORMAT_STEREO_IMA4
, UserFmtStereo
, UserFmtIMA4
},
1083 { AL_FORMAT_STEREO_MSADPCM_SOFT
, UserFmtStereo
, UserFmtMSADPCM
},
1084 { AL_FORMAT_STEREO_MULAW
, UserFmtStereo
, UserFmtMulaw
},
1085 { AL_FORMAT_STEREO_ALAW_EXT
, UserFmtStereo
, UserFmtAlaw
},
1087 { AL_FORMAT_REAR8
, UserFmtRear
, UserFmtUByte
},
1088 { AL_FORMAT_REAR16
, UserFmtRear
, UserFmtShort
},
1089 { AL_FORMAT_REAR32
, UserFmtRear
, UserFmtFloat
},
1090 { AL_FORMAT_REAR_MULAW
, UserFmtRear
, UserFmtMulaw
},
1092 { AL_FORMAT_QUAD8_LOKI
, UserFmtQuad
, UserFmtUByte
},
1093 { AL_FORMAT_QUAD16_LOKI
, UserFmtQuad
, UserFmtShort
},
1095 { AL_FORMAT_QUAD8
, UserFmtQuad
, UserFmtUByte
},
1096 { AL_FORMAT_QUAD16
, UserFmtQuad
, UserFmtShort
},
1097 { AL_FORMAT_QUAD32
, UserFmtQuad
, UserFmtFloat
},
1098 { AL_FORMAT_QUAD_MULAW
, UserFmtQuad
, UserFmtMulaw
},
1100 { AL_FORMAT_51CHN8
, UserFmtX51
, UserFmtUByte
},
1101 { AL_FORMAT_51CHN16
, UserFmtX51
, UserFmtShort
},
1102 { AL_FORMAT_51CHN32
, UserFmtX51
, UserFmtFloat
},
1103 { AL_FORMAT_51CHN_MULAW
, UserFmtX51
, UserFmtMulaw
},
1105 { AL_FORMAT_61CHN8
, UserFmtX61
, UserFmtUByte
},
1106 { AL_FORMAT_61CHN16
, UserFmtX61
, UserFmtShort
},
1107 { AL_FORMAT_61CHN32
, UserFmtX61
, UserFmtFloat
},
1108 { AL_FORMAT_61CHN_MULAW
, UserFmtX61
, UserFmtMulaw
},
1110 { AL_FORMAT_71CHN8
, UserFmtX71
, UserFmtUByte
},
1111 { AL_FORMAT_71CHN16
, UserFmtX71
, UserFmtShort
},
1112 { AL_FORMAT_71CHN32
, UserFmtX71
, UserFmtFloat
},
1113 { AL_FORMAT_71CHN_MULAW
, UserFmtX71
, UserFmtMulaw
},
1115 { AL_FORMAT_BFORMAT2D_8
, UserFmtBFormat2D
, UserFmtUByte
},
1116 { AL_FORMAT_BFORMAT2D_16
, UserFmtBFormat2D
, UserFmtShort
},
1117 { AL_FORMAT_BFORMAT2D_FLOAT32
, UserFmtBFormat2D
, UserFmtFloat
},
1118 { AL_FORMAT_BFORMAT2D_MULAW
, UserFmtBFormat2D
, UserFmtMulaw
},
1120 { AL_FORMAT_BFORMAT3D_8
, UserFmtBFormat3D
, UserFmtUByte
},
1121 { AL_FORMAT_BFORMAT3D_16
, UserFmtBFormat3D
, UserFmtShort
},
1122 { AL_FORMAT_BFORMAT3D_FLOAT32
, UserFmtBFormat3D
, UserFmtFloat
},
1123 { AL_FORMAT_BFORMAT3D_MULAW
, UserFmtBFormat3D
, UserFmtMulaw
},
1127 for(i
= 0;i
< COUNTOF(list
);i
++)
1129 if(list
[i
].format
== format
)
1131 *chans
= list
[i
].channels
;
1132 *type
= list
[i
].type
;
1140 ALuint
BytesFromFmt(enum FmtType type
)
1144 case FmtByte
: return sizeof(ALbyte
);
1145 case FmtShort
: return sizeof(ALshort
);
1146 case FmtFloat
: return sizeof(ALfloat
);
1150 ALuint
ChannelsFromFmt(enum FmtChannels chans
)
1154 case FmtMono
: return 1;
1155 case FmtStereo
: return 2;
1156 case FmtRear
: return 2;
1157 case FmtQuad
: return 4;
1158 case FmtX51
: return 6;
1159 case FmtX61
: return 7;
1160 case FmtX71
: return 8;
1161 case FmtBFormat2D
: return 3;
1162 case FmtBFormat3D
: return 4;
1166 static ALboolean
DecomposeFormat(ALenum format
, enum FmtChannels
*chans
, enum FmtType
*type
)
1168 static const struct {
1170 enum FmtChannels channels
;
1173 { AL_MONO8_SOFT
, FmtMono
, FmtByte
},
1174 { AL_MONO16_SOFT
, FmtMono
, FmtShort
},
1175 { AL_MONO32F_SOFT
, FmtMono
, FmtFloat
},
1177 { AL_STEREO8_SOFT
, FmtStereo
, FmtByte
},
1178 { AL_STEREO16_SOFT
, FmtStereo
, FmtShort
},
1179 { AL_STEREO32F_SOFT
, FmtStereo
, FmtFloat
},
1181 { AL_REAR8_SOFT
, FmtRear
, FmtByte
},
1182 { AL_REAR16_SOFT
, FmtRear
, FmtShort
},
1183 { AL_REAR32F_SOFT
, FmtRear
, FmtFloat
},
1185 { AL_FORMAT_QUAD8_LOKI
, FmtQuad
, FmtByte
},
1186 { AL_FORMAT_QUAD16_LOKI
, FmtQuad
, FmtShort
},
1188 { AL_QUAD8_SOFT
, FmtQuad
, FmtByte
},
1189 { AL_QUAD16_SOFT
, FmtQuad
, FmtShort
},
1190 { AL_QUAD32F_SOFT
, FmtQuad
, FmtFloat
},
1192 { AL_5POINT1_8_SOFT
, FmtX51
, FmtByte
},
1193 { AL_5POINT1_16_SOFT
, FmtX51
, FmtShort
},
1194 { AL_5POINT1_32F_SOFT
, FmtX51
, FmtFloat
},
1196 { AL_6POINT1_8_SOFT
, FmtX61
, FmtByte
},
1197 { AL_6POINT1_16_SOFT
, FmtX61
, FmtShort
},
1198 { AL_6POINT1_32F_SOFT
, FmtX61
, FmtFloat
},
1200 { AL_7POINT1_8_SOFT
, FmtX71
, FmtByte
},
1201 { AL_7POINT1_16_SOFT
, FmtX71
, FmtShort
},
1202 { AL_7POINT1_32F_SOFT
, FmtX71
, FmtFloat
},
1204 { AL_FORMAT_BFORMAT2D_8
, FmtBFormat2D
, FmtByte
},
1205 { AL_FORMAT_BFORMAT2D_16
, FmtBFormat2D
, FmtShort
},
1206 { AL_FORMAT_BFORMAT2D_FLOAT32
, FmtBFormat2D
, FmtFloat
},
1208 { AL_FORMAT_BFORMAT3D_8
, FmtBFormat3D
, FmtByte
},
1209 { AL_FORMAT_BFORMAT3D_16
, FmtBFormat3D
, FmtShort
},
1210 { AL_FORMAT_BFORMAT3D_FLOAT32
, FmtBFormat3D
, FmtFloat
},
1214 for(i
= 0;i
< COUNTOF(list
);i
++)
1216 if(list
[i
].format
== format
)
1218 *chans
= list
[i
].channels
;
1219 *type
= list
[i
].type
;
1227 static ALboolean
SanitizeAlignment(enum UserFmtType type
, ALsizei
*align
)
1234 if(type
== UserFmtIMA4
)
1236 /* Here is where things vary:
1237 * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
1238 * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
1242 else if(type
== UserFmtMSADPCM
)
1249 if(type
== UserFmtIMA4
)
1251 /* IMA4 block alignment must be a multiple of 8, plus 1. */
1252 return ((*align
)&7) == 1;
1254 if(type
== UserFmtMSADPCM
)
1256 /* MSADPCM block alignment must be a multiple of 2. */
1257 /* FIXME: Too strict? Might only require align*channels to be a
1259 return ((*align
)&1) == 0;
1266 static ALboolean
IsValidType(ALenum type
)
1271 case AL_UNSIGNED_BYTE_SOFT
:
1273 case AL_UNSIGNED_SHORT_SOFT
:
1275 case AL_UNSIGNED_INT_SOFT
:
1277 case AL_DOUBLE_SOFT
:
1279 case AL_UNSIGNED_BYTE3_SOFT
:
1285 static ALboolean
IsValidChannels(ALenum channels
)
1290 case AL_STEREO_SOFT
:
1293 case AL_5POINT1_SOFT
:
1294 case AL_6POINT1_SOFT
:
1295 case AL_7POINT1_SOFT
:
1302 ALbuffer
*NewBuffer(ALCcontext
*context
)
1304 ALCdevice
*device
= context
->Device
;
1308 buffer
= calloc(1, sizeof(ALbuffer
));
1310 SET_ERROR_AND_RETURN_VALUE(context
, AL_OUT_OF_MEMORY
, NULL
);
1311 RWLockInit(&buffer
->lock
);
1313 err
= NewThunkEntry(&buffer
->id
);
1314 if(err
== AL_NO_ERROR
)
1315 err
= InsertUIntMapEntry(&device
->BufferMap
, buffer
->id
, buffer
);
1316 if(err
!= AL_NO_ERROR
)
1318 FreeThunkEntry(buffer
->id
);
1319 memset(buffer
, 0, sizeof(ALbuffer
));
1322 SET_ERROR_AND_RETURN_VALUE(context
, err
, NULL
);
1328 void DeleteBuffer(ALCdevice
*device
, ALbuffer
*buffer
)
1330 RemoveBuffer(device
, buffer
->id
);
1331 FreeThunkEntry(buffer
->id
);
1335 memset(buffer
, 0, sizeof(*buffer
));
1341 * ReleaseALBuffers()
1343 * INTERNAL: Called to destroy any buffers that still exist on the device
1345 ALvoid
ReleaseALBuffers(ALCdevice
*device
)
1348 for(i
= 0;i
< device
->BufferMap
.size
;i
++)
1350 ALbuffer
*temp
= device
->BufferMap
.array
[i
].value
;
1351 device
->BufferMap
.array
[i
].value
= NULL
;
1355 FreeThunkEntry(temp
->id
);
1356 memset(temp
, 0, sizeof(ALbuffer
));