aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32/alBuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'OpenAL32/alBuffer.c')
-rw-r--r--OpenAL32/alBuffer.c278
1 files changed, 212 insertions, 66 deletions
diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c
index 0abdb61f..2bcb6562 100644
--- a/OpenAL32/alBuffer.c
+++ b/OpenAL32/alBuffer.c
@@ -27,8 +27,11 @@
#include "AL/alc.h"
#include "alError.h"
#include "alBuffer.h"
+#include "alThunk.h"
+static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint freq, ALenum OrigFormat, ALenum NewFormat);
+
/*
* AL Buffer Functions
*
@@ -273,91 +276,143 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
switch(format)
{
case AL_FORMAT_MONO8:
- if ((size%1) == 0)
+ case AL_FORMAT_MONO16:
+ case AL_FORMAT_MONO_FLOAT32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO16);
+ break;
+
+ case AL_FORMAT_STEREO8:
+ case AL_FORMAT_STEREO16:
+ case AL_FORMAT_STEREO_FLOAT32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16);
+ break;
+
+ case AL_FORMAT_REAR8:
+ case AL_FORMAT_REAR16:
+ case AL_FORMAT_REAR32: {
+ ALuint NewFormat = AL_FORMAT_QUAD16;
+ ALuint NewChannels = aluChannelsFromFormat(NewFormat);
+ ALuint OrigBytes = ((format==AL_FORMAT_REAR8) ? 1 :
+ ((format==AL_FORMAT_REAR16) ? 2 :
+ 4));
+ ALsizei i;
+
+ assert(aluBytesFromFormat(NewFormat) == 2);
+
+ if ((size%(OrigBytes*2)) != 0)
{
- // 8bit Samples are converted to 16 bit here
- // Allocate 8 extra samples (16 bytes)
- ALBuf->data=realloc(ALBuf->data,16+(size/sizeof(ALubyte))*(1*sizeof(ALshort)));
- if (ALBuf->data)
- {
- ALBuf->format = AL_FORMAT_MONO16;
- ALBuf->eOriginalFormat = AL_FORMAT_MONO8;
- for (i=0;i<(ALsizei)(size/sizeof(ALubyte));i++)
- ALBuf->data[i]=(ALshort)((((ALubyte *)data)[i]-128)<<8);
- memset(&(ALBuf->data[size/sizeof(ALubyte)]), 0, 16);
- ALBuf->size=size/sizeof(ALubyte)*1*sizeof(ALshort);
- ALBuf->frequency=freq;
- }
- else
- alSetError(AL_OUT_OF_MEMORY);
- }
- else
alSetError(AL_INVALID_VALUE);
- break;
+ break;
+ }
- case AL_FORMAT_MONO16:
- if ((size%2) == 0)
+ switch(OrigBytes)
{
- // Allocate 8 extra samples (16 bytes)
- ALBuf->data=realloc(ALBuf->data,16+(size/sizeof(ALshort))*(1*sizeof(ALshort)));
+ case 1:
+ size /= sizeof(ALubyte);
+ size *= 2;
+
+ // 8bit Samples are converted to 16 bit here
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
if (ALBuf->data)
{
- ALBuf->format = AL_FORMAT_MONO16;
- ALBuf->eOriginalFormat = AL_FORMAT_MONO16;
- memcpy(ALBuf->data,data,size/sizeof(ALshort)*1*sizeof(ALshort));
- memset(&(ALBuf->data[size/sizeof(ALshort)]), 0, 16);
- ALBuf->size=size/sizeof(ALshort)*1*sizeof(ALshort);
- ALBuf->frequency=freq;
+ for (i = 0;i < size;i+=4)
+ {
+ ALBuf->data[i+0] = 0;
+ ALBuf->data[i+1] = 0;
+ ALBuf->data[i+2] = (ALshort)((((ALubyte*)data)[i/2+0]-128) << 8);
+ ALBuf->data[i+3] = (ALshort)((((ALubyte*)data)[i/2+1]-128) << 8);
+ }
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = format;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
}
else
alSetError(AL_OUT_OF_MEMORY);
- }
- else
- alSetError(AL_INVALID_VALUE);
- break;
+ break;
- case AL_FORMAT_STEREO8:
- if ((size%2) == 0)
- {
- // 8bit Samples are converted to 16 bit here
- // Allocate 8 extra samples (32 bytes)
- ALBuf->data=realloc(ALBuf->data,32+(size/sizeof(ALubyte))*(1*sizeof(ALshort)));
+ case 2:
+ size /= sizeof(ALshort);
+ size *= 2;
+
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
if (ALBuf->data)
{
- ALBuf->format = AL_FORMAT_STEREO16;
- ALBuf->eOriginalFormat = AL_FORMAT_STEREO8;
- for (i=0;i<(ALsizei)(size/sizeof(ALubyte));i++)
- ALBuf->data[i]=(ALshort)((((ALubyte *)data)[i]-128)<<8);
- memset(&(ALBuf->data[size/sizeof(ALubyte)]), 0, 32);
- ALBuf->size=size/sizeof(ALubyte)*1*sizeof(ALshort);
- ALBuf->frequency=freq;
+ for (i = 0;i < size;i+=4)
+ {
+ ALBuf->data[i+0] = 0;
+ ALBuf->data[i+1] = 0;
+ ALBuf->data[i+2] = ((ALshort*)data)[i/2+0];
+ ALBuf->data[i+3] = ((ALshort*)data)[i/2+1];
+ }
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = format;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
}
else
alSetError(AL_OUT_OF_MEMORY);
- }
- else
- alSetError(AL_INVALID_VALUE);
- break;
+ break;
- case AL_FORMAT_STEREO16:
- if ((size%4) == 0)
- {
- // Allocate 8 extra samples (32 bytes)
- ALBuf->data=realloc(ALBuf->data,32+(size/sizeof(ALshort))*(1*sizeof(ALshort)));
+ case 4:
+ size /= sizeof(ALfloat);
+ size *= 2;
+
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
if (ALBuf->data)
{
- ALBuf->format = AL_FORMAT_STEREO16;
- ALBuf->eOriginalFormat = AL_FORMAT_STEREO16;
- memcpy(ALBuf->data,data,size/sizeof(ALshort)*1*sizeof(ALshort));
- memset(&(ALBuf->data[size/sizeof(ALshort)]), 0, 32);
- ALBuf->size=size/sizeof(ALshort)*1*sizeof(ALshort);
- ALBuf->frequency=freq;
+ for (i = 0;i < size;i+=4)
+ {
+ ALBuf->data[i+0] = 0;
+ ALBuf->data[i+1] = 0;
+ ALBuf->data[i+2] = (ALshort)(((ALfloat*)data)[i/2+0] * 32767.5f - 0.5);
+ ALBuf->data[i+3] = (ALshort)(((ALfloat*)data)[i/2+1] * 32767.5f - 0.5);
+ }
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = format;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
}
else
alSetError(AL_OUT_OF_MEMORY);
+ break;
+
+ default:
+ assert(0);
}
- else
- alSetError(AL_INVALID_VALUE);
+ } break;
+
+ case AL_FORMAT_QUAD8:
+ case AL_FORMAT_QUAD16:
+ case AL_FORMAT_QUAD32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_QUAD16);
+ break;
+
+ case AL_FORMAT_51CHN8:
+ case AL_FORMAT_51CHN16:
+ case AL_FORMAT_51CHN32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_51CHN16);
+ break;
+
+ case AL_FORMAT_61CHN8:
+ case AL_FORMAT_61CHN16:
+ case AL_FORMAT_61CHN32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_61CHN16);
+ break;
+
+ case AL_FORMAT_71CHN8:
+ case AL_FORMAT_71CHN16:
+ case AL_FORMAT_71CHN32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_71CHN16);
break;
case AL_FORMAT_MONO_IMA4:
@@ -489,7 +544,7 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
else if (LeftIndex>88) LeftIndex=88;
ALBuf->data[i*2*65+j+k+2]=(short)LeftSample;
LeftIMACode>>=4;
-
+
RightSample+=((g_IMAStep_size[RightIndex]*g_IMACodeword_4[RightIMACode&15])/8);
RightIndex+=g_IMAIndex_adjust_4[RightIMACode&15];
if (RightSample<-32768) RightSample=-32768;
@@ -817,11 +872,11 @@ ALAPI ALvoid ALAPIENTRY alGetBufferi(ALuint buffer, ALenum eParam, ALint *plValu
break;
case AL_BITS:
- *plValue= (((pBuffer->format==AL_FORMAT_MONO8)||(pBuffer->format==AL_FORMAT_STEREO8))?8:16);
+ *plValue = aluBytesFromFormat(pBuffer->format) * 8;
break;
case AL_CHANNELS:
- *plValue = (((pBuffer->format==AL_FORMAT_MONO8)||(pBuffer->format==AL_FORMAT_MONO16))?1:2);
+ *plValue = aluChannelsFromFormat(pBuffer->format);
break;
case AL_SIZE:
@@ -917,6 +972,97 @@ ALAPI void ALAPIENTRY alGetBufferiv(ALuint buffer, ALenum eParam, ALint* plValue
ProcessContext(pContext);
}
+/*
+ * LoadData
+ *
+ * Loads the specified data into the buffer, using the specified formats.
+ * Currently, the new format must be 16-bit, and must have the same channel
+ * configuration as the original format. This does NOT handle compressed
+ * formats (eg. IMA4).
+ */
+static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint freq, ALenum OrigFormat, ALenum NewFormat)
+{
+ ALuint NewChannels = aluChannelsFromFormat(NewFormat);
+ ALuint OrigBytes = aluBytesFromFormat(OrigFormat);
+ ALuint OrigChannels = aluChannelsFromFormat(OrigFormat);
+ ALsizei i;
+
+ assert(aluBytesFromFormat(NewFormat) == 2);
+ assert(NewChannels == OrigChannels);
+
+ if ((size%(OrigBytes*OrigChannels)) != 0)
+ {
+ alSetError(AL_INVALID_VALUE);
+ return;
+ }
+
+ switch(OrigBytes)
+ {
+ case 1:
+ size /= sizeof(ALubyte);
+
+ // 8bit Samples are converted to 16 bit here
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ for (i = 0;i < size;i++)
+ ALBuf->data[i] = (ALshort)((data[i]-128) << 8);
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = OrigFormat;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ break;
+
+ case 2:
+ size /= sizeof(ALshort);
+
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ memcpy(ALBuf->data, data, size*1*sizeof(ALshort));
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = OrigFormat;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ break;
+
+ case 4:
+ size /= sizeof(ALfloat);
+
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ for (i = 0;i < size;i++)
+ ALBuf->data[i] = (ALshort)(((ALfloat*)data)[i] * 32767.5f - 0.5);
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = OrigFormat;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
/*
* ReleaseALBuffers()