Add base support for ALC_EXT_disconnect
[openal-soft.git] / OpenAL32 / alBuffer.c
blob09f692dcef80d9a1f1a124ddfef7ae0e0787fd5b
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <assert.h>
26 #include "alMain.h"
27 #include "AL/al.h"
28 #include "AL/alc.h"
29 #include "alError.h"
30 #include "alBuffer.h"
31 #include "alDatabuffer.h"
32 #include "alThunk.h"
35 static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint freq, ALenum OrigFormat, ALenum NewFormat);
36 static void ConvertData(ALshort *dst, const ALvoid *src, ALint origBytes, ALsizei len);
37 static void ConvertDataRear(ALshort *dst, const ALvoid *src, ALint origBytes, ALsizei len);
38 static void ConvertDataIMA4(ALshort *dst, const ALvoid *src, ALint origChans, ALsizei len);
41 * AL Buffer Functions
43 * AL Buffers are shared amoung Contexts, so we store the list of generated Buffers
44 * as a global variable in this module. (A valid context is not required to make
45 * AL Buffer function calls
50 * Global Variables
53 static const long g_IMAStep_size[89]={ // IMA ADPCM Stepsize table
54 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
55 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
56 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
57 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
58 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493,10442,11487,12635,13899,
59 15289,16818,18500,20350,22358,24633,27086,29794,32767
62 static const long g_IMACodeword_4[16]={ // IMA4 ADPCM Codeword decode table
63 1, 3, 5, 7, 9, 11, 13, 15,
64 -1,-3,-5,-7,-9,-11,-13,-15,
67 static const long g_IMAIndex_adjust_4[16]={ // IMA4 ADPCM Step index adjust decode table
68 -1,-1,-1,-1, 2, 4, 6, 8,
69 -1,-1,-1,-1, 2, 4, 6, 8
73 * alGenBuffers(ALsizei n, ALuint *puiBuffers)
75 * Generates n AL Buffers, and stores the Buffers Names in the array pointed to by puiBuffers
77 ALAPI ALvoid ALAPIENTRY alGenBuffers(ALsizei n,ALuint *puiBuffers)
79 ALCcontext *Context;
80 ALsizei i=0;
82 Context = GetContextSuspended();
83 if(!Context) return;
85 // Check that we are actually generation some Buffers
86 if (n > 0)
88 ALCdevice *device = Context->Device;
90 // Check the pointer is valid (and points to enough memory to store Buffer Names)
91 if (!IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
93 ALbuffer **list = &device->Buffers;
94 while(*list)
95 list = &(*list)->next;
97 // Create all the new Buffers
98 while(i < n)
100 *list = calloc(1, sizeof(ALbuffer));
101 if(!(*list))
103 alDeleteBuffers(i, puiBuffers);
104 alSetError(AL_OUT_OF_MEMORY);
105 break;
108 puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
109 (*list)->state = UNUSED;
110 device->BufferCount++;
111 i++;
113 list = &(*list)->next;
116 else
118 // Pointer does not point to enough memory to write Buffer names
119 alSetError(AL_INVALID_VALUE);
123 ProcessContext(Context);
125 return;
129 * alDeleteBuffers(ALsizei n, ALuint *puiBuffers)
131 * Deletes the n AL Buffers pointed to by puiBuffers
133 ALAPI ALvoid ALAPIENTRY alDeleteBuffers(ALsizei n, const ALuint *puiBuffers)
135 ALCcontext *Context;
136 ALbuffer *ALBuf;
137 ALsizei i;
138 ALboolean bFailed = AL_FALSE;
140 Context = GetContextSuspended();
141 if(!Context) return;
143 // Check we are actually Deleting some Buffers
144 if (n >= 0)
146 ALCdevice *device = Context->Device;
148 // Check that all the buffers are valid and can actually be deleted
149 for (i = 0; i < n; i++)
151 // Check for valid Buffer ID (can be NULL buffer)
152 if (alIsBuffer(puiBuffers[i]))
154 // If not the NULL buffer, check that the reference count is 0
155 ALBuf = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
156 if (ALBuf)
158 if (ALBuf->refcount != 0)
160 // Buffer still in use, cannot be deleted
161 alSetError(AL_INVALID_OPERATION);
162 bFailed = AL_TRUE;
166 else
168 // Invalid Buffer
169 alSetError(AL_INVALID_NAME);
170 bFailed = AL_TRUE;
174 // If all the Buffers were valid (and have Reference Counts of 0), then we can delete them
175 if (!bFailed)
177 for (i = 0; i < n; i++)
179 if (puiBuffers[i] && alIsBuffer(puiBuffers[i]))
181 ALbuffer **list = &device->Buffers;
183 ALBuf=((ALbuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
184 while(*list && *list != ALBuf)
185 list = &(*list)->next;
187 if(*list)
188 *list = (*list)->next;
190 // Release the memory used to store audio data
191 free(ALBuf->data);
193 // Release buffer structure
194 ALTHUNK_REMOVEENTRY(puiBuffers[i]);
195 memset(ALBuf, 0, sizeof(ALbuffer));
196 device->BufferCount--;
197 free(ALBuf);
202 else
203 alSetError(AL_INVALID_VALUE);
205 ProcessContext(Context);
207 return;
212 * alIsBuffer(ALuint uiBuffer)
214 * Checks if ulBuffer is a valid Buffer Name
216 ALAPI ALboolean ALAPIENTRY alIsBuffer(ALuint uiBuffer)
218 ALCcontext *Context;
219 ALboolean result=AL_FALSE;
220 ALbuffer *ALBuf;
221 ALbuffer *TgtALBuf;
223 Context = GetContextSuspended();
224 if(!Context) return AL_FALSE;
226 if (uiBuffer)
228 ALCdevice *device = Context->Device;
230 TgtALBuf = (ALbuffer *)ALTHUNK_LOOKUPENTRY(uiBuffer);
232 // Check through list of generated buffers for uiBuffer
233 ALBuf = device->Buffers;
234 while (ALBuf)
236 if (ALBuf == TgtALBuf)
238 result = AL_TRUE;
239 break;
242 ALBuf = ALBuf->next;
245 else
247 result = AL_TRUE;
251 ProcessContext(Context);
253 return result;
257 * alBufferData(ALuint buffer,ALenum format,ALvoid *data,ALsizei size,ALsizei freq)
259 * Fill buffer with audio data
261 ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *data,ALsizei size,ALsizei freq)
263 ALCcontext *Context;
264 ALsizei padding = 2;
265 ALbuffer *ALBuf;
266 ALvoid *temp;
268 Context = GetContextSuspended();
269 if(!Context) return;
271 if (alIsBuffer(buffer) && (buffer != 0))
273 ALBuf=((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
275 if(Context->SampleSource)
277 ALuint offset;
279 if(Context->SampleSource->state == MAPPED)
281 alSetError(AL_INVALID_OPERATION);
282 ProcessContext(Context);
283 return;
286 offset = (ALuint)data;
287 data = Context->SampleSource->data + offset;
290 if ((ALBuf->refcount==0)&&(data))
292 switch(format)
294 case AL_FORMAT_MONO8:
295 case AL_FORMAT_MONO16:
296 case AL_FORMAT_MONO_FLOAT32:
297 LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO16);
298 break;
300 case AL_FORMAT_STEREO8:
301 case AL_FORMAT_STEREO16:
302 case AL_FORMAT_STEREO_FLOAT32:
303 LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16);
304 break;
306 case AL_FORMAT_REAR8:
307 case AL_FORMAT_REAR16:
308 case AL_FORMAT_REAR32: {
309 ALuint NewFormat = AL_FORMAT_QUAD16;
310 ALuint NewChannels = aluChannelsFromFormat(NewFormat);
311 ALuint OrigBytes = ((format==AL_FORMAT_REAR8) ? 1 :
312 ((format==AL_FORMAT_REAR16) ? 2 :
313 4));
315 assert(aluBytesFromFormat(NewFormat) == 2);
317 if((size%(OrigBytes*2)) != 0)
319 alSetError(AL_INVALID_VALUE);
320 break;
323 size /= OrigBytes;
324 size *= 2;
326 // Samples are converted to 16 bit here
327 temp = realloc(ALBuf->data, (padding*NewChannels + size) * sizeof(ALshort));
328 if(temp)
330 ALBuf->data = temp;
331 ConvertDataRear(ALBuf->data, data, OrigBytes, size);
333 memset(&(ALBuf->data[size]), 0, padding*NewChannels*sizeof(ALshort));
335 ALBuf->format = NewFormat;
336 ALBuf->eOriginalFormat = format;
337 ALBuf->size = size*sizeof(ALshort);
338 ALBuf->frequency = freq;
339 ALBuf->padding = padding;
341 else
342 alSetError(AL_OUT_OF_MEMORY);
343 } break;
345 case AL_FORMAT_QUAD8_LOKI:
346 case AL_FORMAT_QUAD16_LOKI:
347 case AL_FORMAT_QUAD8:
348 case AL_FORMAT_QUAD16:
349 case AL_FORMAT_QUAD32:
350 LoadData(ALBuf, data, size, freq, format, AL_FORMAT_QUAD16);
351 break;
353 case AL_FORMAT_51CHN8:
354 case AL_FORMAT_51CHN16:
355 case AL_FORMAT_51CHN32:
356 LoadData(ALBuf, data, size, freq, format, AL_FORMAT_51CHN16);
357 break;
359 case AL_FORMAT_61CHN8:
360 case AL_FORMAT_61CHN16:
361 case AL_FORMAT_61CHN32:
362 LoadData(ALBuf, data, size, freq, format, AL_FORMAT_61CHN16);
363 break;
365 case AL_FORMAT_71CHN8:
366 case AL_FORMAT_71CHN16:
367 case AL_FORMAT_71CHN32:
368 LoadData(ALBuf, data, size, freq, format, AL_FORMAT_71CHN16);
369 break;
371 case AL_FORMAT_MONO_IMA4:
372 case AL_FORMAT_STEREO_IMA4: {
373 int OrigChans = ((format==AL_FORMAT_MONO_IMA4) ? 1 : 2);
375 // Here is where things vary:
376 // nVidia and Apple use 64+1 samples per channel per block => block_size=36*chans bytes
377 // Most PC sound software uses 2040+1 samples per channel per block -> block_size=1024*chans bytes
378 if((size%(36*OrigChans)) != 0)
380 alSetError(AL_INVALID_VALUE);
381 break;
384 size /= 36;
385 size *= 65;
387 // Allocate extra padding samples
388 temp = realloc(ALBuf->data, (padding*OrigChans + size)*sizeof(ALshort));
389 if(temp)
391 ALBuf->data = temp;
392 ConvertDataIMA4(ALBuf->data, data, OrigChans, size/65);
394 memset(&(ALBuf->data[size]), 0, padding*sizeof(ALshort)*OrigChans);
396 ALBuf->format = ((OrigChans==1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16);
397 ALBuf->eOriginalFormat = format;
398 ALBuf->size = size*sizeof(ALshort);
399 ALBuf->frequency = freq;
400 ALBuf->padding = padding;
402 else
403 alSetError(AL_OUT_OF_MEMORY);
404 } break;
406 default:
407 alSetError(AL_INVALID_ENUM);
408 break;
411 else
413 // Buffer is in use, or data is a NULL pointer
414 alSetError(AL_INVALID_VALUE);
417 else
419 // Invalid Buffer Name
420 alSetError(AL_INVALID_NAME);
423 ProcessContext(Context);
427 * alBufferSubDataEXT(ALuint buffer,ALenum format,ALvoid *data,ALsizei offset,ALsizei length)
429 * Fill buffer with audio data
431 ALvoid ALAPIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length)
433 ALCcontext *Context;
434 ALbuffer *ALBuf;
436 Context = GetContextSuspended();
437 if(!Context) return;
439 if(alIsBuffer(buffer) && buffer != 0)
441 ALBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(buffer);
443 if(Context->SampleSource)
445 ALuint offset;
447 if(Context->SampleSource->state == MAPPED)
449 alSetError(AL_INVALID_OPERATION);
450 ProcessContext(Context);
451 return;
454 offset = (ALuint)data;
455 data = Context->SampleSource->data + offset;
458 if(ALBuf->data == NULL)
460 // buffer does not have any data
461 alSetError(AL_INVALID_NAME);
463 else if(length < 0 || offset < 0 || (length > 0 && data == NULL))
465 // data is NULL or offset/length is negative
466 alSetError(AL_INVALID_VALUE);
468 else
470 switch(format)
472 case AL_FORMAT_REAR8:
473 case AL_FORMAT_REAR16:
474 case AL_FORMAT_REAR32: {
475 ALuint OrigBytes = ((format==AL_FORMAT_REAR8) ? 1 :
476 ((format==AL_FORMAT_REAR16) ? 2 :
477 4));
479 if(ALBuf->eOriginalFormat != AL_FORMAT_REAR8 &&
480 ALBuf->eOriginalFormat != AL_FORMAT_REAR16 &&
481 ALBuf->eOriginalFormat != AL_FORMAT_REAR32)
483 alSetError(AL_INVALID_ENUM);
484 break;
487 if(ALBuf->size/4/sizeof(ALshort) < (ALuint)offset+length)
489 alSetError(AL_INVALID_VALUE);
490 break;
493 ConvertDataRear(&ALBuf->data[offset*4], data, OrigBytes, length*2);
494 } break;
496 case AL_FORMAT_MONO_IMA4:
497 case AL_FORMAT_STEREO_IMA4: {
498 int Channels = aluChannelsFromFormat(ALBuf->format);
500 if(ALBuf->eOriginalFormat != format)
502 alSetError(AL_INVALID_ENUM);
503 break;
506 if((offset%65) != 0 || (length%65) != 0 ||
507 ALBuf->size/Channels/sizeof(ALshort) < (ALuint)offset+length)
509 alSetError(AL_INVALID_VALUE);
510 break;
513 ConvertDataIMA4(&ALBuf->data[offset*Channels], data, Channels, length/65*Channels);
514 } break;
516 default: {
517 ALuint Channels = aluChannelsFromFormat(format);
518 ALuint Bytes = aluBytesFromFormat(format);
520 if(Channels != aluChannelsFromFormat(ALBuf->format))
522 alSetError(AL_INVALID_ENUM);
523 break;
526 if(ALBuf->size/Channels/sizeof(ALshort) < (ALuint)offset+length)
528 alSetError(AL_INVALID_VALUE);
529 break;
532 ConvertData(&ALBuf->data[offset*Channels], data, Bytes, length*Channels);
533 } break;
537 else
539 // Invalid Buffer Name
540 alSetError(AL_INVALID_NAME);
543 ProcessContext(Context);
547 ALAPI void ALAPIENTRY alBufferf(ALuint buffer, ALenum eParam, ALfloat flValue)
549 ALCcontext *pContext;
551 (void)flValue;
553 pContext = GetContextSuspended();
554 if(!pContext) return;
556 if (alIsBuffer(buffer) && (buffer != 0))
558 switch(eParam)
560 default:
561 alSetError(AL_INVALID_ENUM);
562 break;
565 else
567 alSetError(AL_INVALID_NAME);
570 ProcessContext(pContext);
574 ALAPI void ALAPIENTRY alBuffer3f(ALuint buffer, ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3)
576 ALCcontext *pContext;
578 (void)flValue1;
579 (void)flValue2;
580 (void)flValue3;
582 pContext = GetContextSuspended();
583 if(!pContext) return;
585 if (alIsBuffer(buffer) && (buffer != 0))
587 switch(eParam)
589 default:
590 alSetError(AL_INVALID_ENUM);
591 break;
594 else
596 alSetError(AL_INVALID_NAME);
599 ProcessContext(pContext);
603 ALAPI void ALAPIENTRY alBufferfv(ALuint buffer, ALenum eParam, const ALfloat* flValues)
605 ALCcontext *pContext;
607 (void)flValues;
609 pContext = GetContextSuspended();
610 if(!pContext) return;
612 if (alIsBuffer(buffer) && (buffer != 0))
614 switch(eParam)
616 default:
617 alSetError(AL_INVALID_ENUM);
618 break;
621 else
623 alSetError(AL_INVALID_NAME);
626 ProcessContext(pContext);
630 ALAPI void ALAPIENTRY alBufferi(ALuint buffer, ALenum eParam, ALint lValue)
632 ALCcontext *pContext;
634 (void)lValue;
636 pContext = GetContextSuspended();
637 if(!pContext) return;
639 if (alIsBuffer(buffer) && (buffer != 0))
641 switch(eParam)
643 default:
644 alSetError(AL_INVALID_ENUM);
645 break;
648 else
650 alSetError(AL_INVALID_NAME);
653 ProcessContext(pContext);
657 ALAPI void ALAPIENTRY alBuffer3i( ALuint buffer, ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
659 ALCcontext *pContext;
661 (void)lValue1;
662 (void)lValue2;
663 (void)lValue3;
665 pContext = GetContextSuspended();
666 if(!pContext) return;
668 if (alIsBuffer(buffer) && (buffer != 0))
670 switch(eParam)
672 default:
673 alSetError(AL_INVALID_ENUM);
674 break;
677 else
679 alSetError(AL_INVALID_NAME);
682 ProcessContext(pContext);
686 ALAPI void ALAPIENTRY alBufferiv(ALuint buffer, ALenum eParam, const ALint* plValues)
688 ALCcontext *pContext;
690 (void)plValues;
692 pContext = GetContextSuspended();
693 if(!pContext) return;
695 if (alIsBuffer(buffer) && (buffer != 0))
697 switch(eParam)
699 default:
700 alSetError(AL_INVALID_ENUM);
701 break;
704 else
706 alSetError(AL_INVALID_NAME);
709 ProcessContext(pContext);
713 ALAPI ALvoid ALAPIENTRY alGetBufferf(ALuint buffer, ALenum eParam, ALfloat *pflValue)
715 ALCcontext *pContext;
717 pContext = GetContextSuspended();
718 if(!pContext) return;
720 if (pflValue)
722 if (alIsBuffer(buffer) && (buffer != 0))
724 switch(eParam)
726 default:
727 alSetError(AL_INVALID_ENUM);
728 break;
731 else
733 alSetError(AL_INVALID_NAME);
736 else
738 alSetError(AL_INVALID_VALUE);
741 ProcessContext(pContext);
745 ALAPI void ALAPIENTRY alGetBuffer3f(ALuint buffer, ALenum eParam, ALfloat* pflValue1, ALfloat* pflValue2, ALfloat* pflValue3)
747 ALCcontext *pContext;
749 pContext = GetContextSuspended();
750 if(!pContext) return;
752 if ((pflValue1) && (pflValue2) && (pflValue3))
754 if (alIsBuffer(buffer) && (buffer != 0))
756 switch(eParam)
758 default:
759 alSetError(AL_INVALID_ENUM);
760 break;
763 else
765 alSetError(AL_INVALID_NAME);
768 else
770 alSetError(AL_INVALID_VALUE);
773 ProcessContext(pContext);
777 ALAPI void ALAPIENTRY alGetBufferfv(ALuint buffer, ALenum eParam, ALfloat* pflValues)
779 ALCcontext *pContext;
781 pContext = GetContextSuspended();
782 if(!pContext) return;
784 if (pflValues)
786 if (alIsBuffer(buffer) && (buffer != 0))
788 switch(eParam)
790 default:
791 alSetError(AL_INVALID_ENUM);
792 break;
795 else
797 alSetError(AL_INVALID_NAME);
800 else
802 alSetError(AL_INVALID_VALUE);
805 ProcessContext(pContext);
809 ALAPI ALvoid ALAPIENTRY alGetBufferi(ALuint buffer, ALenum eParam, ALint *plValue)
811 ALCcontext *pContext;
812 ALbuffer *pBuffer;
814 pContext = GetContextSuspended();
815 if(!pContext) return;
817 if (plValue)
819 if (alIsBuffer(buffer) && (buffer != 0))
821 pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
823 switch (eParam)
825 case AL_FREQUENCY:
826 *plValue = pBuffer->frequency;
827 break;
829 case AL_BITS:
830 *plValue = aluBytesFromFormat(pBuffer->format) * 8;
831 break;
833 case AL_CHANNELS:
834 *plValue = aluChannelsFromFormat(pBuffer->format);
835 break;
837 case AL_SIZE:
838 *plValue = pBuffer->size;
839 break;
841 default:
842 alSetError(AL_INVALID_ENUM);
843 break;
846 else
848 alSetError(AL_INVALID_NAME);
851 else
853 alSetError(AL_INVALID_VALUE);
856 ProcessContext(pContext);
860 ALAPI void ALAPIENTRY alGetBuffer3i(ALuint buffer, ALenum eParam, ALint* plValue1, ALint* plValue2, ALint* plValue3)
862 ALCcontext *pContext;
864 pContext = GetContextSuspended();
865 if(!pContext) return;
867 if ((plValue1) && (plValue2) && (plValue3))
869 if (alIsBuffer(buffer) && (buffer != 0))
871 switch(eParam)
873 default:
874 alSetError(AL_INVALID_ENUM);
875 break;
878 else
880 alSetError(AL_INVALID_NAME);
883 else
885 alSetError(AL_INVALID_VALUE);
888 ProcessContext(pContext);
892 ALAPI void ALAPIENTRY alGetBufferiv(ALuint buffer, ALenum eParam, ALint* plValues)
894 ALCcontext *pContext;
896 pContext = GetContextSuspended();
897 if(!pContext) return;
899 if (plValues)
901 if (alIsBuffer(buffer) && (buffer != 0))
903 switch (eParam)
905 case AL_FREQUENCY:
906 case AL_BITS:
907 case AL_CHANNELS:
908 case AL_SIZE:
909 alGetBufferi(buffer, eParam, plValues);
910 break;
912 default:
913 alSetError(AL_INVALID_ENUM);
914 break;
917 else
919 alSetError(AL_INVALID_NAME);
922 else
924 alSetError(AL_INVALID_VALUE);
927 ProcessContext(pContext);
931 * LoadData
933 * Loads the specified data into the buffer, using the specified formats.
934 * Currently, the new format must be 16-bit, and must have the same channel
935 * configuration as the original format. This does NOT handle compressed
936 * formats (eg. IMA4).
938 static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint freq, ALenum OrigFormat, ALenum NewFormat)
940 ALuint NewChannels = aluChannelsFromFormat(NewFormat);
941 ALuint OrigBytes = aluBytesFromFormat(OrigFormat);
942 ALuint OrigChannels = aluChannelsFromFormat(OrigFormat);
943 ALsizei padding = 2;
944 ALvoid *temp;
946 assert(aluBytesFromFormat(NewFormat) == 2);
947 assert(NewChannels == OrigChannels);
949 if ((size%(OrigBytes*OrigChannels)) != 0)
951 alSetError(AL_INVALID_VALUE);
952 return;
955 // Samples are converted to 16 bit here
956 size /= OrigBytes;
957 temp = realloc(ALBuf->data, (padding*NewChannels + size) * sizeof(ALshort));
958 if(temp)
960 ALBuf->data = temp;
961 ConvertData(ALBuf->data, data, OrigBytes, size);
963 memset(&(ALBuf->data[size]), 0, padding*NewChannels*sizeof(ALshort));
965 ALBuf->format = NewFormat;
966 ALBuf->eOriginalFormat = OrigFormat;
967 ALBuf->size = size*sizeof(ALshort);
968 ALBuf->frequency = freq;
969 ALBuf->padding = padding;
971 else
972 alSetError(AL_OUT_OF_MEMORY);
975 static void ConvertData(ALshort *dst, const ALvoid *src, ALint origBytes, ALsizei len)
977 ALsizei i;
978 switch(origBytes)
980 case 1:
981 for(i = 0;i < len;i++)
982 dst[i] = ((ALshort)((ALubyte*)src)[i] - 128) << 8;
983 break;
985 case 2:
986 memcpy(dst, src, len*sizeof(ALshort));
987 break;
989 case 4:
990 for(i = 0;i < len;i++)
992 ALint smp;
993 smp = (((ALfloat*)src)[i] * 32767.5f - 0.5f);
994 smp = min(smp, 32767);
995 smp = max(smp, -32768);
996 dst[i] = (ALshort)smp;
998 break;
1000 default:
1001 assert(0);
1005 static void ConvertDataRear(ALshort *dst, const ALvoid *src, ALint origBytes, ALsizei len)
1007 ALsizei i;
1008 switch(origBytes)
1010 case 1:
1011 for(i = 0;i < len;i+=4)
1013 dst[i+0] = 0;
1014 dst[i+1] = 0;
1015 dst[i+2] = ((ALshort)((ALubyte*)src)[i/2+0] - 128) << 8;
1016 dst[i+3] = ((ALshort)((ALubyte*)src)[i/2+1] - 128) << 8;
1018 break;
1020 case 2:
1021 for(i = 0;i < len;i+=4)
1023 dst[i+0] = 0;
1024 dst[i+1] = 0;
1025 dst[i+2] = ((ALshort*)src)[i/2+0];
1026 dst[i+3] = ((ALshort*)src)[i/2+1];
1028 break;
1030 case 4:
1031 for(i = 0;i < len;i+=4)
1033 ALint smp;
1034 dst[i+0] = 0;
1035 dst[i+1] = 0;
1036 smp = (((ALfloat*)src)[i/2+0] * 32767.5f - 0.5);
1037 smp = min(smp, 32767);
1038 smp = max(smp, -32768);
1039 dst[i+2] = (ALshort)smp;
1040 smp = (((ALfloat*)src)[i/2+1] * 32767.5f - 0.5);
1041 smp = min(smp, 32767);
1042 smp = max(smp, -32768);
1043 dst[i+3] = (ALshort)smp;
1045 break;
1047 default:
1048 assert(0);
1052 static void ConvertDataIMA4(ALshort *dst, const ALvoid *src, ALint origChans, ALsizei len)
1054 const ALuint *IMAData;
1055 ALint Sample[2],Index[2];
1056 ALuint IMACode[2];
1057 ALsizei i,j,k,c;
1059 assert(origChans <= 2);
1061 IMAData = src;
1062 for(i = 0;i < len/origChans;i++)
1064 for(c = 0;c < origChans;c++)
1066 Sample[c] = ((ALshort*)IMAData)[0];
1067 Index[c] = ((ALshort*)IMAData)[1];
1069 Index[c] = ((Index[c]<0) ? 0 : Index[c]);
1070 Index[c] = ((Index[c]>88) ? 88 : Index[c]);
1072 dst[i*65*origChans + c] = (ALshort)Sample[c];
1074 IMAData++;
1077 for(j = 1;j < 65;j += 8)
1079 for(c = 0;c < origChans;c++)
1080 IMACode[c] = *(IMAData++);
1082 for(k = 0;k < 8;k++)
1084 for(c = 0;c < origChans;c++)
1086 Sample[c] += ((g_IMAStep_size[Index[c]]*g_IMACodeword_4[IMACode[c]&15])/8);
1087 Index[c] += g_IMAIndex_adjust_4[IMACode[c]&15];
1089 if(Sample[c] < -32768) Sample[c] = -32768;
1090 else if(Sample[c] > 32767) Sample[c] = 32767;
1092 if(Index[c]<0) Index[c] = 0;
1093 else if(Index[c]>88) Index[c] = 88;
1095 dst[(i*65+j+k)*origChans + c] = (ALshort)Sample[c];
1096 IMACode[c] >>= 4;
1104 * ReleaseALBuffers()
1106 * INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
1108 ALvoid ReleaseALBuffers(ALCdevice *device)
1110 ALbuffer *ALBuffer;
1111 ALbuffer *ALBufferTemp;
1113 ALBuffer = device->Buffers;
1114 while(ALBuffer)
1116 // Release sample data
1117 free(ALBuffer->data);
1119 // Release Buffer structure
1120 ALBufferTemp = ALBuffer;
1121 ALBuffer = ALBuffer->next;
1122 memset(ALBufferTemp, 0, sizeof(ALbuffer));
1123 free(ALBufferTemp);
1125 device->Buffers = NULL;
1126 device->BufferCount = 0;