/* * LoadData * * Loads the specified data into the buffer, using the specified formats. * Currently, the new format must have the same channel configuration as the * original format. */ ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc) { ALuint NewChannels, NewBytes; enum FmtChannels DstChannels; enum FmtType DstType; ALuint64 newsize; ALvoid *temp; if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE || (long)SrcChannels != (long)DstChannels) return AL_INVALID_ENUM; NewChannels = ChannelsFromFmt(DstChannels); NewBytes = BytesFromFmt(DstType); newsize = frames; newsize *= NewBytes; newsize *= NewChannels; if(newsize > INT_MAX) return AL_OUT_OF_MEMORY; WriteLock(&ALBuf->lock); if(ReadRef(&ALBuf->ref) != 0) { WriteUnlock(&ALBuf->lock); return AL_INVALID_OPERATION; } temp = realloc(ALBuf->data, (size_t)newsize); if(!temp && newsize) { WriteUnlock(&ALBuf->lock); return AL_OUT_OF_MEMORY; } ALBuf->data = temp; if(data != NULL) ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align); if(storesrc) { ALBuf->OriginalChannels = SrcChannels; ALBuf->OriginalType = SrcType; if(SrcType == UserFmtIMA4) { ALsizei byte_align = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels); ALBuf->OriginalSize = frames / align * byte_align; ALBuf->OriginalAlign = align; } else if(SrcType == UserFmtMSADPCM) { ALsizei byte_align = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels); ALBuf->OriginalSize = frames / align * byte_align; ALBuf->OriginalAlign = align; } else { ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType); ALBuf->OriginalAlign = 1; } } else { ALBuf->OriginalChannels = (enum UserFmtChannels)DstChannels; ALBuf->OriginalType = (enum UserFmtType)DstType; ALBuf->OriginalSize = frames * NewBytes * NewChannels; ALBuf->OriginalAlign = 1; } ALBuf->Frequency = freq; ALBuf->FmtChannels = DstChannels; ALBuf->FmtType = DstType; ALBuf->Format = NewFormat; ALBuf->SampleLen = frames; ALBuf->LoopStart = 0; ALBuf->LoopEnd = ALBuf->SampleLen; WriteUnlock(&ALBuf->lock); return AL_NO_ERROR; }
AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) { enum UserFmtChannels srcchannels; enum UserFmtType srctype; ALCdevice *device; ALCcontext *context; ALbuffer *albuf; ALenum newformat = AL_NONE; ALuint framesize; ALsizei align; ALenum err; context = GetContextRef(); if(!context) return; device = context->Device; if((albuf=LookupBuffer(device, buffer)) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); if(!(size >= 0 && freq > 0)) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE) SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); align = albuf->UnpackAlign; if(SanitizeAlignment(srctype, &align) == AL_FALSE) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); switch(srctype) { case UserFmtByte: case UserFmtUByte: case UserFmtShort: case UserFmtUShort: case UserFmtFloat: framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align; if((size%framesize) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); err = LoadData(albuf, freq, format, size/framesize*align, srcchannels, srctype, data, align, AL_TRUE); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); break; case UserFmtInt: case UserFmtUInt: case UserFmtByte3: case UserFmtUByte3: case UserFmtDouble: framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align; if((size%framesize) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); switch(srcchannels) { case UserFmtMono: newformat = AL_FORMAT_MONO_FLOAT32; break; case UserFmtStereo: newformat = AL_FORMAT_STEREO_FLOAT32; break; case UserFmtRear: newformat = AL_FORMAT_REAR32; break; case UserFmtQuad: newformat = AL_FORMAT_QUAD32; break; case UserFmtX51: newformat = AL_FORMAT_51CHN32; break; case UserFmtX61: newformat = AL_FORMAT_61CHN32; break; case UserFmtX71: newformat = AL_FORMAT_71CHN32; break; } err = LoadData(albuf, freq, newformat, size/framesize*align, srcchannels, srctype, data, align, AL_TRUE); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); break; case UserFmtMulaw: case UserFmtAlaw: framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align; if((size%framesize) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); switch(srcchannels) { case UserFmtMono: newformat = AL_FORMAT_MONO16; break; case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break; case UserFmtRear: newformat = AL_FORMAT_REAR16; break; case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break; case UserFmtX51: newformat = AL_FORMAT_51CHN16; break; case UserFmtX61: newformat = AL_FORMAT_61CHN16; break; case UserFmtX71: newformat = AL_FORMAT_71CHN16; break; } err = LoadData(albuf, freq, newformat, size/framesize*align, srcchannels, srctype, data, align, AL_TRUE); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); break; case UserFmtIMA4: framesize = (align-1)/2 + 4; framesize *= ChannelsFromUserFmt(srcchannels); if((size%framesize) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); switch(srcchannels) { case UserFmtMono: newformat = AL_FORMAT_MONO16; break; case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break; case UserFmtRear: newformat = AL_FORMAT_REAR16; break; case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break; case UserFmtX51: newformat = AL_FORMAT_51CHN16; break; case UserFmtX61: newformat = AL_FORMAT_61CHN16; break; case UserFmtX71: newformat = AL_FORMAT_71CHN16; break; } err = LoadData(albuf, freq, newformat, size/framesize*align, srcchannels, srctype, data, align, AL_TRUE); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); break; case UserFmtMSADPCM: framesize = (align-2)/2 + 7; framesize *= ChannelsFromUserFmt(srcchannels); if((size%framesize) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); switch(srcchannels) { case UserFmtMono: newformat = AL_FORMAT_MONO16; break; case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break; case UserFmtRear: newformat = AL_FORMAT_REAR16; break; case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break; case UserFmtX51: newformat = AL_FORMAT_51CHN16; break; case UserFmtX61: newformat = AL_FORMAT_61CHN16; break; case UserFmtX71: newformat = AL_FORMAT_71CHN16; break; } err = LoadData(albuf, freq, newformat, size/framesize*align, srcchannels, srctype, data, align, AL_TRUE); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); break; } done: ALCcontext_DecRef(context); }
AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) { enum UserFmtChannels srcchannels; enum UserFmtType srctype; ALCdevice *device; ALCcontext *context; ALbuffer *albuf; ALuint byte_align; ALuint channels; ALuint bytes; ALsizei align; context = GetContextRef(); if(!context) return; device = context->Device; if((albuf=LookupBuffer(device, buffer)) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); if(!(length >= 0 && offset >= 0)) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE) SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); WriteLock(&albuf->lock); align = albuf->UnpackAlign; if(SanitizeAlignment(srctype, &align) == AL_FALSE) { WriteUnlock(&albuf->lock); SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); } if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType) { WriteUnlock(&albuf->lock); SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } if(align != albuf->OriginalAlign) { WriteUnlock(&albuf->lock); SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } if(albuf->OriginalType == UserFmtIMA4) { byte_align = (albuf->OriginalAlign-1)/2 + 4; byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels); } else if(albuf->OriginalType == UserFmtMSADPCM) { byte_align = (albuf->OriginalAlign-2)/2 + 7; byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels); } else { byte_align = albuf->OriginalAlign; byte_align *= FrameSizeFromUserFmt(albuf->OriginalChannels, albuf->OriginalType); } if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset || (offset%byte_align) != 0 || (length%byte_align) != 0) { WriteUnlock(&albuf->lock); SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); } channels = ChannelsFromFmt(albuf->FmtChannels); bytes = BytesFromFmt(albuf->FmtType); /* offset -> byte offset, length -> sample count */ offset = offset/byte_align * channels*bytes; length = length/byte_align * albuf->OriginalAlign; ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType, data, srctype, channels, length, align); WriteUnlock(&albuf->lock); done: ALCcontext_DecRef(context); }
/* * LoadData * * Loads the specified data into the buffer, using the specified formats. * Currently, the new format must have the same channel configuration as the * original format. */ ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc) { enum FmtChannels DstChannels = FmtMono; enum FmtType DstType = FmtByte; ALuint NewChannels, NewBytes; ALuint64 newsize; if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE) return AL_INVALID_ENUM; if((long)SrcChannels != (long)DstChannels) return AL_INVALID_ENUM; NewChannels = ChannelsFromFmt(DstChannels); NewBytes = BytesFromFmt(DstType); newsize = frames; newsize *= NewBytes; newsize *= NewChannels; if(newsize > INT_MAX) return AL_OUT_OF_MEMORY; WriteLock(&ALBuf->lock); if(ReadRef(&ALBuf->ref) != 0) { WriteUnlock(&ALBuf->lock); return AL_INVALID_OPERATION; } /* Round up to the next 16-byte multiple. This could reallocate only when * increasing or the new size is less than half the current, but then the * buffer's AL_SIZE would not be very reliable for accounting buffer memory * usage, and reporting the real size could cause problems for apps that * use AL_SIZE to try to get the buffer's play length. */ newsize = (newsize+15) & ~0xf; if(newsize != ALBuf->BytesAlloc) { void *temp = al_calloc(16, (size_t)newsize); if(!temp && newsize) { WriteUnlock(&ALBuf->lock); return AL_OUT_OF_MEMORY; } al_free(ALBuf->data); ALBuf->data = temp; ALBuf->BytesAlloc = (ALuint)newsize; } if(data != NULL) ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align); if(storesrc) { ALBuf->OriginalChannels = SrcChannels; ALBuf->OriginalType = SrcType; if(SrcType == UserFmtIMA4) { ALsizei byte_align = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels); ALBuf->OriginalSize = frames / align * byte_align; ALBuf->OriginalAlign = align; } else if(SrcType == UserFmtMSADPCM) { ALsizei byte_align = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels); ALBuf->OriginalSize = frames / align * byte_align; ALBuf->OriginalAlign = align; } else { ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType); ALBuf->OriginalAlign = 1; } } else { ALBuf->OriginalChannels = (enum UserFmtChannels)DstChannels; ALBuf->OriginalType = (enum UserFmtType)DstType; ALBuf->OriginalSize = frames * NewBytes * NewChannels; ALBuf->OriginalAlign = 1; } ALBuf->Frequency = freq; ALBuf->FmtChannels = DstChannels; ALBuf->FmtType = DstType; ALBuf->Format = NewFormat; ALBuf->SampleLen = frames; ALBuf->LoopStart = 0; ALBuf->LoopEnd = ALBuf->SampleLen; WriteUnlock(&ALBuf->lock); return AL_NO_ERROR; }