/* * alBufferSubDataEXT(ALuint buffer,ALenum format,ALvoid *data,ALsizei offset,ALsizei length) * * Fill buffer with audio data */ ALvoid ALAPIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length) { ALCcontext *Context; ALbuffer *ALBuf; Context = alcGetCurrentContext(); SuspendContext(Context); if(alIsBuffer(buffer) && buffer != 0) { ALBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(buffer); if(ALBuf->data == NULL) { // buffer does not have any data alSetError(AL_INVALID_NAME); } else if(length < 0 || offset < 0 || (length > 0 && data == NULL)) { // data is NULL or offset/length is negative alSetError(AL_INVALID_VALUE); } else { switch(format) { case AL_FORMAT_REAR8: case AL_FORMAT_REAR16: case AL_FORMAT_REAR32: { ALuint OrigBytes = ((format==AL_FORMAT_REAR8) ? 1 : ((format==AL_FORMAT_REAR16) ? 2 : 4)); if(ALBuf->eOriginalFormat != AL_FORMAT_REAR8 && ALBuf->eOriginalFormat != AL_FORMAT_REAR16 && ALBuf->eOriginalFormat != AL_FORMAT_REAR32) { alSetError(AL_INVALID_ENUM); break; } if(ALBuf->size/4/sizeof(ALshort) < (ALuint)offset+length) { alSetError(AL_INVALID_VALUE); break; } ConvertDataRear(&ALBuf->data[offset*4], data, OrigBytes, length*2); } break; case AL_FORMAT_MONO_IMA4: case AL_FORMAT_STEREO_IMA4: { int Channels = aluChannelsFromFormat(ALBuf->format); if(ALBuf->eOriginalFormat != format) { alSetError(AL_INVALID_ENUM); break; } if((offset%65) != 0 || (length%65) != 0 || ALBuf->size/Channels/sizeof(ALshort) < (ALuint)offset+length) { alSetError(AL_INVALID_VALUE); break; } ConvertDataIMA4(&ALBuf->data[offset*Channels], data, Channels, length/65*Channels); } break; default: { ALuint Channels = aluChannelsFromFormat(format); ALuint Bytes = aluBytesFromFormat(format); if(Channels != aluChannelsFromFormat(ALBuf->format)) { alSetError(AL_INVALID_ENUM); break; } if(ALBuf->size/Channels/sizeof(ALshort) < (ALuint)offset+length) { alSetError(AL_INVALID_VALUE); break; } ConvertData(&ALBuf->data[offset*Channels], data, Bytes, length*Channels); } break; } } } else { // Invalid Buffer Name alSetError(AL_INVALID_NAME); } ProcessContext(Context); }
/* * alBufferSubDataEXT(ALuint buffer,ALenum format,ALvoid *data,ALsizei offset,ALsizei length) * * Fill buffer with audio data */ AL_API ALvoid AL_APIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length) { ALCcontext *Context; ALCdevice *device; ALbuffer *ALBuf; Context = GetContextSuspended(); if(!Context) return; device = Context->Device; if((ALBuf=LookupBuffer(device->BufferMap, buffer)) == NULL) alSetError(Context, AL_INVALID_NAME); else { if(Context->SampleSource) { ALintptrEXT offset; if(Context->SampleSource->state == MAPPED) { alSetError(Context, AL_INVALID_OPERATION); ProcessContext(Context); return; } offset = (const ALubyte*)data - (ALubyte*)NULL; data = Context->SampleSource->data + offset; } if(length < 0 || offset < 0 || (length > 0 && data == NULL)) alSetError(Context, AL_INVALID_VALUE); else if(ALBuf->eOriginalFormat != format) alSetError(Context, AL_INVALID_ENUM); else if(offset+length < offset || offset+length > ALBuf->OriginalSize || (offset%ALBuf->OriginalAlign) != 0 || (length%ALBuf->OriginalAlign) != 0) alSetError(Context, AL_INVALID_VALUE); else { switch(format) { case AL_FORMAT_MONO8: case AL_FORMAT_MONO16: case AL_FORMAT_MONO_FLOAT32: case AL_FORMAT_MONO_DOUBLE_EXT: case AL_FORMAT_STEREO8: case AL_FORMAT_STEREO16: case AL_FORMAT_STEREO_FLOAT32: case AL_FORMAT_STEREO_DOUBLE_EXT: case AL_FORMAT_QUAD8_LOKI: case AL_FORMAT_QUAD16_LOKI: case AL_FORMAT_QUAD8: case AL_FORMAT_QUAD16: case AL_FORMAT_QUAD32: case AL_FORMAT_51CHN8: case AL_FORMAT_51CHN16: case AL_FORMAT_51CHN32: case AL_FORMAT_61CHN8: case AL_FORMAT_61CHN16: case AL_FORMAT_61CHN32: case AL_FORMAT_71CHN8: case AL_FORMAT_71CHN16: case AL_FORMAT_71CHN32: { ALuint Bytes = aluBytesFromFormat(format); offset /= Bytes; length /= Bytes; ConvertData(&ALBuf->data[offset], data, Bytes, length); } break; case AL_FORMAT_REAR8: case AL_FORMAT_REAR16: case AL_FORMAT_REAR32: { ALuint Bytes = ((format==AL_FORMAT_REAR8) ? 1 : ((format==AL_FORMAT_REAR16) ? 2 : 4)); offset /= Bytes; offset *= 2; length /= Bytes; length *= 2; ConvertDataRear(&ALBuf->data[offset], data, Bytes, length); } break; case AL_FORMAT_MONO_IMA4: case AL_FORMAT_STEREO_IMA4: { int Channels = aluChannelsFromFormat(ALBuf->format); // offset -> sample*channel offset, length -> block count offset /= 36; offset *= 65; length /= ALBuf->OriginalAlign; ConvertDataIMA4(&ALBuf->data[offset], data, Channels, length); } break; case AL_FORMAT_MONO_MULAW: case AL_FORMAT_STEREO_MULAW: case AL_FORMAT_QUAD_MULAW: case AL_FORMAT_51CHN_MULAW: case AL_FORMAT_61CHN_MULAW: case AL_FORMAT_71CHN_MULAW: ConvertDataMULaw(&ALBuf->data[offset], data, length); break; case AL_FORMAT_REAR_MULAW: offset *= 2; length *= 2; ConvertDataMULawRear(&ALBuf->data[offset], data, length); break; default: alSetError(Context, AL_INVALID_ENUM); break; } } } ProcessContext(Context); }
/* * alBufferData(ALuint buffer,ALenum format,ALvoid *data,ALsizei size,ALsizei freq) * * Fill buffer with audio data */ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *data,ALsizei size,ALsizei freq) { ALCcontext *Context; ALsizei padding = 2; ALbuffer *ALBuf; ALvoid *temp; Context = alcGetCurrentContext(); SuspendContext(Context); if (alIsBuffer(buffer) && (buffer != 0)) { ALBuf=((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer)); if ((ALBuf->refcount==0)&&(data)) { switch(format) { case AL_FORMAT_MONO8: 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)); assert(aluBytesFromFormat(NewFormat) == 2); if((size%(OrigBytes*2)) != 0) { alSetError(AL_INVALID_VALUE); break; } size /= OrigBytes; size *= 2; // Samples are converted to 16 bit here temp = realloc(ALBuf->data, (padding*NewChannels + size) * sizeof(ALshort)); if(temp) { ALBuf->data = temp; ConvertDataRear(ALBuf->data, data, OrigBytes, size); memset(&(ALBuf->data[size]), 0, padding*NewChannels*sizeof(ALshort)); ALBuf->format = NewFormat; ALBuf->eOriginalFormat = format; ALBuf->size = size*sizeof(ALshort); ALBuf->frequency = freq; ALBuf->padding = padding; } else alSetError(AL_OUT_OF_MEMORY); } break; case AL_FORMAT_QUAD8_LOKI: case AL_FORMAT_QUAD16_LOKI: 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: case AL_FORMAT_STEREO_IMA4: { int OrigChans = ((format==AL_FORMAT_MONO_IMA4) ? 1 : 2); // Here is where things vary: // nVidia and Apple use 64+1 samples per channel per block => block_size=36*chans bytes // Most PC sound software uses 2040+1 samples per channel per block -> block_size=1024*chans bytes if((size%(36*OrigChans)) != 0) { alSetError(AL_INVALID_VALUE); break; } size /= 36; size *= 65; // Allocate extra padding samples temp = realloc(ALBuf->data, (padding*OrigChans + size)*sizeof(ALshort)); if(temp) { ALBuf->data = temp; ConvertDataIMA4(ALBuf->data, data, OrigChans, size/65); memset(&(ALBuf->data[size]), 0, padding*sizeof(ALshort)*OrigChans); ALBuf->format = ((OrigChans==1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16); ALBuf->eOriginalFormat = format; ALBuf->size = size*sizeof(ALshort); ALBuf->frequency = freq; ALBuf->padding = padding; } else alSetError(AL_OUT_OF_MEMORY); } break; default: alSetError(AL_INVALID_ENUM); break; } } else { // Buffer is in use, or data is a NULL pointer alSetError(AL_INVALID_VALUE); } } else { // Invalid Buffer Name alSetError(AL_INVALID_NAME); } ProcessContext(Context); }
/* * alBufferData(ALuint buffer,ALenum format,ALvoid *data,ALsizei size,ALsizei freq) * * Fill buffer with audio data */ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *data,ALsizei size,ALsizei freq) { ALCcontext *Context; ALCdevice *device; ALbuffer *ALBuf; ALvoid *temp; ALenum err; Context = GetContextSuspended(); if(!Context) return; device = Context->Device; if((ALBuf=LookupBuffer(device->BufferMap, buffer)) == NULL) alSetError(Context, AL_INVALID_NAME); /* Invalid Buffer Name */ else { if(Context->SampleSource) { ALintptrEXT offset; if(Context->SampleSource->state == MAPPED) { alSetError(Context, AL_INVALID_OPERATION); ProcessContext(Context); return; } offset = (const ALubyte*)data - (ALubyte*)NULL; data = Context->SampleSource->data + offset; } if(size < 0) alSetError(Context, AL_INVALID_VALUE); else if(ALBuf->refcount != 0) alSetError(Context, AL_INVALID_VALUE); else { switch(format) { case AL_FORMAT_MONO8: case AL_FORMAT_MONO16: case AL_FORMAT_MONO_FLOAT32: case AL_FORMAT_MONO_DOUBLE_EXT: err = LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO_FLOAT32); if(err != AL_NO_ERROR) alSetError(Context, err); break; case AL_FORMAT_STEREO8: case AL_FORMAT_STEREO16: case AL_FORMAT_STEREO_FLOAT32: case AL_FORMAT_STEREO_DOUBLE_EXT: err = LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO_FLOAT32); if(err != AL_NO_ERROR) alSetError(Context, err); break; case AL_FORMAT_REAR8: case AL_FORMAT_REAR16: case AL_FORMAT_REAR32: { ALenum NewFormat = AL_FORMAT_QUAD32; ALuint NewChannels = aluChannelsFromFormat(NewFormat); ALuint NewBytes = aluBytesFromFormat(NewFormat); ALuint OrigBytes = ((format==AL_FORMAT_REAR8) ? 1 : ((format==AL_FORMAT_REAR16) ? 2 : 4)); ALuint64 newsize, allocsize; if((size%(OrigBytes*2)) != 0) { alSetError(Context, AL_INVALID_VALUE); break; } newsize = size / OrigBytes; newsize *= 2; allocsize = (BUFFER_PADDING*NewChannels + newsize)*NewBytes; if(allocsize > INT_MAX) { alSetError(Context, AL_OUT_OF_MEMORY); break; } temp = realloc(ALBuf->data, allocsize); if(temp) { ALBuf->data = temp; ConvertDataRear(ALBuf->data, data, OrigBytes, newsize); ALBuf->format = NewFormat; ALBuf->eOriginalFormat = format; ALBuf->size = newsize*NewBytes; ALBuf->frequency = freq; ALBuf->LoopStart = 0; ALBuf->LoopEnd = newsize / NewChannels; ALBuf->OriginalSize = size; ALBuf->OriginalAlign = OrigBytes * 2; } else alSetError(Context, AL_OUT_OF_MEMORY); } break; case AL_FORMAT_QUAD8_LOKI: case AL_FORMAT_QUAD16_LOKI: case AL_FORMAT_QUAD8: case AL_FORMAT_QUAD16: case AL_FORMAT_QUAD32: err = LoadData(ALBuf, data, size, freq, format, AL_FORMAT_QUAD32); if(err != AL_NO_ERROR) alSetError(Context, err); break; case AL_FORMAT_51CHN8: case AL_FORMAT_51CHN16: case AL_FORMAT_51CHN32: err = LoadData(ALBuf, data, size, freq, format, AL_FORMAT_51CHN32); if(err != AL_NO_ERROR) alSetError(Context, err); break; case AL_FORMAT_61CHN8: case AL_FORMAT_61CHN16: case AL_FORMAT_61CHN32: err = LoadData(ALBuf, data, size, freq, format, AL_FORMAT_61CHN32); if(err != AL_NO_ERROR) alSetError(Context, err); break; case AL_FORMAT_71CHN8: case AL_FORMAT_71CHN16: case AL_FORMAT_71CHN32: err = LoadData(ALBuf, data, size, freq, format, AL_FORMAT_71CHN32); if(err != AL_NO_ERROR) alSetError(Context, err); break; case AL_FORMAT_MONO_IMA4: case AL_FORMAT_STEREO_IMA4: { int Channels = ((format==AL_FORMAT_MONO_IMA4) ? 1 : 2); ALenum NewFormat = ((Channels==1) ? AL_FORMAT_MONO_FLOAT32 : AL_FORMAT_STEREO_FLOAT32); ALuint NewBytes = aluBytesFromFormat(NewFormat); ALuint64 newsize, allocsize; // Here is where things vary: // nVidia and Apple use 64+1 samples per channel per block => block_size=36*chans bytes // Most PC sound software uses 2040+1 samples per channel per block -> block_size=1024*chans bytes if((size%(36*Channels)) != 0) { alSetError(Context, AL_INVALID_VALUE); break; } newsize = size / 36; newsize *= 65; allocsize = (BUFFER_PADDING*Channels + newsize)*NewBytes; if(allocsize > INT_MAX) { alSetError(Context, AL_OUT_OF_MEMORY); break; } temp = realloc(ALBuf->data, allocsize); if(temp) { ALBuf->data = temp; ConvertDataIMA4(ALBuf->data, data, Channels, newsize/(65*Channels)); ALBuf->format = NewFormat; ALBuf->eOriginalFormat = format; ALBuf->size = newsize*NewBytes; ALBuf->frequency = freq; ALBuf->LoopStart = 0; ALBuf->LoopEnd = newsize / Channels; ALBuf->OriginalSize = size; ALBuf->OriginalAlign = 36 * Channels; } else alSetError(Context, AL_OUT_OF_MEMORY); } break; case AL_FORMAT_MONO_MULAW: case AL_FORMAT_STEREO_MULAW: case AL_FORMAT_QUAD_MULAW: case AL_FORMAT_51CHN_MULAW: case AL_FORMAT_61CHN_MULAW: case AL_FORMAT_71CHN_MULAW: { int Channels = ((format==AL_FORMAT_MONO_MULAW) ? 1 : ((format==AL_FORMAT_STEREO_MULAW) ? 2 : ((format==AL_FORMAT_QUAD_MULAW) ? 4 : ((format==AL_FORMAT_51CHN_MULAW) ? 6 : ((format==AL_FORMAT_61CHN_MULAW) ? 7 : 8))))); ALenum NewFormat = ((Channels==1) ? AL_FORMAT_MONO_FLOAT32 : ((Channels==2) ? AL_FORMAT_STEREO_FLOAT32 : ((Channels==4) ? AL_FORMAT_QUAD32 : ((Channels==6) ? AL_FORMAT_51CHN32 : ((Channels==7) ? AL_FORMAT_61CHN32 : AL_FORMAT_71CHN32))))); ALuint NewBytes = aluBytesFromFormat(NewFormat); ALuint64 allocsize; if((size%(1*Channels)) != 0) { alSetError(Context, AL_INVALID_VALUE); break; } allocsize = (BUFFER_PADDING*Channels + size)*NewBytes; if(allocsize > INT_MAX) { alSetError(Context, AL_OUT_OF_MEMORY); break; } temp = realloc(ALBuf->data, allocsize); if(temp) { ALBuf->data = temp; ConvertDataMULaw(ALBuf->data, data, size); ALBuf->format = NewFormat; ALBuf->eOriginalFormat = format; ALBuf->size = size*NewBytes; ALBuf->frequency = freq; ALBuf->LoopStart = 0; ALBuf->LoopEnd = size / Channels; ALBuf->OriginalSize = size; ALBuf->OriginalAlign = 1 * Channels; } else alSetError(Context, AL_OUT_OF_MEMORY); } break; case AL_FORMAT_REAR_MULAW: { ALenum NewFormat = AL_FORMAT_QUAD32; ALuint NewChannels = aluChannelsFromFormat(NewFormat); ALuint NewBytes = aluBytesFromFormat(NewFormat); ALuint64 newsize, allocsize; if((size%(1*2)) != 0) { alSetError(Context, AL_INVALID_VALUE); break; } newsize = size * 2; allocsize = (BUFFER_PADDING*NewChannels + newsize)*NewBytes; if(allocsize > INT_MAX) { alSetError(Context, AL_OUT_OF_MEMORY); break; } temp = realloc(ALBuf->data, allocsize); if(temp) { ALBuf->data = temp; ConvertDataMULawRear(ALBuf->data, data, newsize); ALBuf->format = NewFormat; ALBuf->eOriginalFormat = format; ALBuf->size = newsize*NewBytes; ALBuf->frequency = freq; ALBuf->LoopStart = 0; ALBuf->LoopEnd = newsize / NewChannels; ALBuf->OriginalSize = size; ALBuf->OriginalAlign = 1 * 2; } else alSetError(Context, AL_OUT_OF_MEMORY); } break; default: alSetError(Context, AL_INVALID_ENUM); break; } } } ProcessContext(Context); }