2007-11-14 02:02:18 +00:00
|
|
|
/**
|
|
|
|
* OpenAL cross platform audio library
|
|
|
|
* Copyright (C) 1999-2007 by authors.
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
2014-08-18 12:11:03 +00:00
|
|
|
* Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2007-11-14 02:02:18 +00:00
|
|
|
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
|
|
|
*/
|
|
|
|
|
2008-01-16 22:09:04 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2007-11-14 02:02:18 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
2008-01-06 09:15:44 +00:00
|
|
|
#include <assert.h>
|
2010-05-25 00:08:12 +00:00
|
|
|
#include <limits.h>
|
2014-03-04 04:02:15 +00:00
|
|
|
#ifdef HAVE_MALLOC_H
|
|
|
|
#include <malloc.h>
|
|
|
|
#endif
|
2010-05-25 00:08:12 +00:00
|
|
|
|
2007-11-14 02:02:18 +00:00
|
|
|
#include "alMain.h"
|
2012-09-14 09:14:29 +00:00
|
|
|
#include "alu.h"
|
2007-11-14 02:02:18 +00:00
|
|
|
#include "alError.h"
|
|
|
|
#include "alBuffer.h"
|
2007-12-31 09:09:57 +00:00
|
|
|
#include "alThunk.h"
|
2014-03-06 00:17:47 +00:00
|
|
|
#include "sample_cvt.h"
|
2007-11-14 02:02:18 +00:00
|
|
|
|
|
|
|
|
2016-05-11 06:42:44 +00:00
|
|
|
extern inline void LockBuffersRead(ALCdevice *device);
|
|
|
|
extern inline void UnlockBuffersRead(ALCdevice *device);
|
|
|
|
extern inline void LockBuffersWrite(ALCdevice *device);
|
|
|
|
extern inline void UnlockBuffersWrite(ALCdevice *device);
|
2013-11-04 21:44:46 +00:00
|
|
|
extern inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id);
|
|
|
|
extern inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id);
|
2017-01-18 15:13:23 +00:00
|
|
|
extern inline ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
|
|
|
|
extern inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
|
2013-11-04 20:12:31 +00:00
|
|
|
|
2018-01-22 07:35:28 +00:00
|
|
|
static ALenum LoadData(ALbuffer *buffer, ALuint freq, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALbitfieldSOFT access);
|
2016-09-06 16:09:25 +00:00
|
|
|
static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type);
|
2018-01-20 05:00:53 +00:00
|
|
|
static ALsizei SanitizeAlignment(enum UserFmtType type, ALsizei align);
|
2007-12-29 04:25:18 +00:00
|
|
|
|
2010-11-27 23:33:33 +00:00
|
|
|
|
2018-01-20 19:49:01 +00:00
|
|
|
#define FORMAT_MASK 0x00ffffff
|
2018-01-23 18:38:27 +00:00
|
|
|
#define CONSTRUCT_FLAGS (AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT | AL_PRESERVE_DATA_BIT_SOFT | AL_MAP_PERSISTENT_BIT_SOFT)
|
2018-01-22 19:34:16 +00:00
|
|
|
#define INVALID_FORMAT_MASK ~(FORMAT_MASK | CONSTRUCT_FLAGS)
|
2018-01-23 18:38:27 +00:00
|
|
|
#define MAP_ACCESS_FLAGS (AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT | AL_MAP_PERSISTENT_BIT_SOFT)
|
2018-01-20 19:49:01 +00:00
|
|
|
|
|
|
|
|
2010-05-02 02:59:41 +00:00
|
|
|
AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext *context;
|
|
|
|
ALsizei cur = 0;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
if(!(n >= 0))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2009-08-15 16:14:08 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
for(cur = 0;cur < n;cur++)
|
|
|
|
{
|
2014-06-29 09:04:05 +00:00
|
|
|
ALbuffer *buffer = NewBuffer(context);
|
2013-10-07 01:01:01 +00:00
|
|
|
if(!buffer)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
alDeleteBuffers(cur, buffers);
|
2014-06-29 09:04:05 +00:00
|
|
|
break;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
2013-10-07 01:01:01 +00:00
|
|
|
|
|
|
|
buffers[cur] = buffer->id;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2010-09-21 23:54:33 +00:00
|
|
|
AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
2007-11-14 02:02:18 +00:00
|
|
|
ALbuffer *ALBuf;
|
|
|
|
ALsizei i;
|
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2016-05-11 06:42:44 +00:00
|
|
|
device = context->Device;
|
|
|
|
|
|
|
|
LockBuffersWrite(device);
|
2013-10-07 01:01:01 +00:00
|
|
|
if(!(n >= 0))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
for(i = 0;i < n;i++)
|
|
|
|
{
|
|
|
|
if(!buffers[i])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Check for valid Buffer ID */
|
|
|
|
if((ALBuf=LookupBuffer(device, buffers[i])) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2014-05-14 09:47:07 +00:00
|
|
|
if(ReadRef(&ALBuf->ref) != 0)
|
2013-10-07 01:01:01 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
|
|
|
}
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
for(i = 0;i < n;i++)
|
2014-06-30 07:10:40 +00:00
|
|
|
{
|
|
|
|
if((ALBuf=LookupBuffer(device, buffers[i])) != NULL)
|
|
|
|
DeleteBuffer(device, ALBuf);
|
|
|
|
}
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersWrite(device);
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2010-05-19 18:06:13 +00:00
|
|
|
AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext *context;
|
|
|
|
ALboolean ret;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return AL_FALSE;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(context->Device);
|
2013-10-07 01:01:01 +00:00
|
|
|
ret = ((!buffer || LookupBuffer(context->Device, buffer)) ?
|
|
|
|
AL_TRUE : AL_FALSE);
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(context->Device);
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
return ret;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
|
|
|
|
AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2016-08-31 11:56:10 +00:00
|
|
|
enum UserFmtChannels srcchannels = UserFmtMono;
|
2018-01-22 02:15:25 +00:00
|
|
|
enum UserFmtType srctype = UserFmtUByte;
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
2017-01-18 15:13:23 +00:00
|
|
|
ALsizei framesize;
|
2014-03-04 12:29:35 +00:00
|
|
|
ALsizei align;
|
2010-03-17 00:35:51 +00:00
|
|
|
ALenum err;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
|
|
|
|
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 01:01:01 +00:00
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2018-01-22 19:34:16 +00:00
|
|
|
if(!(size >= 0 && freq > 0) || (format&INVALID_FORMAT_MASK) != 0)
|
2013-10-07 01:01:01 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2018-01-20 19:49:01 +00:00
|
|
|
if(DecomposeUserFormat(format&FORMAT_MASK, &srcchannels, &srctype) == AL_FALSE)
|
2013-10-07 01:01:01 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
|
2018-01-20 05:00:53 +00:00
|
|
|
align = SanitizeAlignment(srctype, ATOMIC_LOAD_SEQ(&albuf->UnpackAlign));
|
|
|
|
if(align < 1) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
switch(srctype)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
case UserFmtUByte:
|
|
|
|
case UserFmtShort:
|
|
|
|
case UserFmtFloat:
|
2018-01-22 02:34:03 +00:00
|
|
|
case UserFmtDouble:
|
2018-01-17 16:49:49 +00:00
|
|
|
case UserFmtMulaw:
|
|
|
|
case UserFmtAlaw:
|
2014-03-04 12:29:35 +00:00
|
|
|
framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
|
|
|
|
if((size%framesize) != 0)
|
2013-10-07 01:01:01 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
|
2018-01-22 07:35:28 +00:00
|
|
|
err = LoadData(albuf, freq, size/framesize*align, srcchannels, srctype,
|
2018-01-22 19:34:16 +00:00
|
|
|
data, align, format&CONSTRUCT_FLAGS);
|
2013-10-07 01:01:01 +00:00
|
|
|
if(err != AL_NO_ERROR)
|
|
|
|
SET_ERROR_AND_GOTO(context, err, done);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case UserFmtIMA4:
|
2018-01-22 07:35:28 +00:00
|
|
|
framesize = ((align-1)/2 + 4) * ChannelsFromUserFmt(srcchannels);
|
2014-03-04 12:29:35 +00:00
|
|
|
if((size%framesize) != 0)
|
2013-10-07 01:01:01 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
|
2018-01-22 07:35:28 +00:00
|
|
|
err = LoadData(albuf, freq, size/framesize*align, srcchannels, srctype,
|
2018-01-22 19:34:16 +00:00
|
|
|
data, align, format&CONSTRUCT_FLAGS);
|
2013-10-07 01:01:01 +00:00
|
|
|
if(err != AL_NO_ERROR)
|
|
|
|
SET_ERROR_AND_GOTO(context, err, done);
|
|
|
|
break;
|
2014-03-05 06:44:30 +00:00
|
|
|
|
|
|
|
case UserFmtMSADPCM:
|
2018-01-22 07:35:28 +00:00
|
|
|
framesize = ((align-2)/2 + 7) * ChannelsFromUserFmt(srcchannels);
|
2014-03-05 06:44:30 +00:00
|
|
|
if((size%framesize) != 0)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
|
2018-01-22 07:35:28 +00:00
|
|
|
err = LoadData(albuf, freq, size/framesize*align, srcchannels, srctype,
|
2018-01-22 19:34:16 +00:00
|
|
|
data, align, format&CONSTRUCT_FLAGS);
|
2014-03-05 06:44:30 +00:00
|
|
|
if(err != AL_NO_ERROR)
|
|
|
|
SET_ERROR_AND_GOTO(context, err, done);
|
|
|
|
break;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2018-01-20 19:49:01 +00:00
|
|
|
AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access)
|
|
|
|
{
|
|
|
|
void *retval = NULL;
|
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
|
|
|
|
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return retval;
|
|
|
|
|
|
|
|
device = context->Device;
|
|
|
|
LockBuffersRead(device);
|
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2018-01-22 19:34:16 +00:00
|
|
|
if(!access || (access&~MAP_ACCESS_FLAGS) != 0)
|
2018-01-20 19:49:01 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2018-01-21 18:32:48 +00:00
|
|
|
|
2018-01-20 19:49:01 +00:00
|
|
|
WriteLock(&albuf->lock);
|
|
|
|
if(((access&AL_MAP_READ_BIT_SOFT) && !(albuf->Access&AL_MAP_READ_BIT_SOFT)) ||
|
2018-01-23 18:38:27 +00:00
|
|
|
((access&AL_MAP_WRITE_BIT_SOFT) && !(albuf->Access&AL_MAP_WRITE_BIT_SOFT)) ||
|
|
|
|
((access&AL_MAP_PERSISTENT_BIT_SOFT) && !(albuf->Access&AL_MAP_PERSISTENT_BIT_SOFT)))
|
2018-01-21 18:32:48 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, unlock_done);
|
2018-01-20 19:49:01 +00:00
|
|
|
if(offset < 0 || offset >= albuf->OriginalSize ||
|
|
|
|
length <= 0 || length > albuf->OriginalSize - offset)
|
2018-01-21 18:32:48 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, unlock_done);
|
2018-01-23 18:38:27 +00:00
|
|
|
if(albuf->MappedAccess != 0 ||
|
|
|
|
(!(access&AL_MAP_PERSISTENT_BIT_SOFT) && ReadRef(&albuf->ref) != 0))
|
2018-01-21 18:32:48 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, unlock_done);
|
2018-01-20 19:49:01 +00:00
|
|
|
|
|
|
|
retval = (ALbyte*)albuf->data + offset;
|
|
|
|
albuf->MappedAccess = access;
|
2018-01-21 18:32:48 +00:00
|
|
|
|
|
|
|
unlock_done:
|
2018-01-20 19:49:01 +00:00
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
|
|
|
|
done:
|
|
|
|
UnlockBuffersRead(device);
|
|
|
|
ALCcontext_DecRef(context);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer)
|
|
|
|
{
|
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
|
|
|
|
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
|
|
|
|
|
|
|
device = context->Device;
|
|
|
|
LockBuffersRead(device);
|
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
|
|
|
|
|
|
|
WriteLock(&albuf->lock);
|
|
|
|
if(albuf->MappedAccess == 0)
|
|
|
|
alSetError(context, AL_INVALID_OPERATION);
|
|
|
|
else
|
|
|
|
albuf->MappedAccess = 0;
|
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
|
|
|
|
done:
|
|
|
|
UnlockBuffersRead(device);
|
|
|
|
ALCcontext_DecRef(context);
|
|
|
|
}
|
|
|
|
|
2018-01-23 18:38:27 +00:00
|
|
|
AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length)
|
|
|
|
{
|
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
|
|
|
|
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
|
|
|
|
|
|
|
device = context->Device;
|
|
|
|
LockBuffersRead(device);
|
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
|
|
|
|
|
|
|
WriteLock(&albuf->lock);
|
|
|
|
if(albuf->MappedAccess == 0 || !(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT))
|
|
|
|
alSetError(context, AL_INVALID_OPERATION);
|
|
|
|
/* TODO: Should check mapped range. */
|
|
|
|
else if(offset < 0 || offset >= albuf->OriginalSize ||
|
|
|
|
length <= 0 || length > albuf->OriginalSize - offset)
|
|
|
|
alSetError(context, AL_INVALID_VALUE);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* FIXME: Need to use some method of double-buffering for the mixer and
|
|
|
|
* app to hold separate memory, which can be safely transfered
|
|
|
|
* asynchronously. Currently we just say the app shouldn't write where
|
|
|
|
* OpenAL's reading, and hope for the best...
|
|
|
|
*/
|
|
|
|
ATOMIC_THREAD_FENCE(almemory_order_seq_cst);
|
|
|
|
}
|
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
|
|
|
|
done:
|
|
|
|
UnlockBuffersRead(device);
|
|
|
|
ALCcontext_DecRef(context);
|
|
|
|
}
|
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length)
|
2008-11-11 13:57:32 +00:00
|
|
|
{
|
2016-08-31 11:56:10 +00:00
|
|
|
enum UserFmtChannels srcchannels = UserFmtMono;
|
2018-01-22 02:15:25 +00:00
|
|
|
enum UserFmtType srctype = UserFmtUByte;
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
2017-01-18 15:13:23 +00:00
|
|
|
ALsizei byte_align;
|
2018-01-22 07:35:28 +00:00
|
|
|
ALsizei frame_size;
|
|
|
|
ALsizei num_chans;
|
2014-03-04 12:29:35 +00:00
|
|
|
ALsizei align;
|
2018-01-22 07:35:28 +00:00
|
|
|
void *dst;
|
2013-10-07 01:01:01 +00:00
|
|
|
|
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
|
|
|
|
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 01:01:01 +00:00
|
|
|
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);
|
2018-01-20 05:00:53 +00:00
|
|
|
align = SanitizeAlignment(srctype, ATOMIC_LOAD_SEQ(&albuf->UnpackAlign));
|
2018-01-23 00:17:45 +00:00
|
|
|
if(align < 1) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, unlock_done);
|
|
|
|
|
2018-01-22 07:35:28 +00:00
|
|
|
if((long)srcchannels != (long)albuf->FmtChannels || srctype != albuf->OriginalType)
|
2018-01-23 00:17:45 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, unlock_done);
|
2014-03-04 12:29:35 +00:00
|
|
|
if(align != albuf->OriginalAlign)
|
2018-01-23 00:17:45 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, unlock_done);
|
2018-01-20 19:49:01 +00:00
|
|
|
if(albuf->MappedAccess != 0)
|
2018-01-23 00:17:45 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, unlock_done);
|
2014-03-04 12:29:35 +00:00
|
|
|
|
2018-01-23 00:17:45 +00:00
|
|
|
num_chans = ChannelsFromFmt(albuf->FmtChannels);
|
|
|
|
frame_size = num_chans * BytesFromFmt(albuf->FmtType);
|
2014-03-04 12:29:35 +00:00
|
|
|
if(albuf->OriginalType == UserFmtIMA4)
|
2018-01-23 00:17:45 +00:00
|
|
|
byte_align = ((align-1)/2 + 4) * num_chans;
|
2014-03-05 06:44:30 +00:00
|
|
|
else if(albuf->OriginalType == UserFmtMSADPCM)
|
2018-01-23 00:17:45 +00:00
|
|
|
byte_align = ((align-2)/2 + 7) * num_chans;
|
2014-03-04 12:29:35 +00:00
|
|
|
else
|
2018-01-23 00:17:45 +00:00
|
|
|
byte_align = align * frame_size;
|
2014-03-04 12:29:35 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset ||
|
2014-03-04 12:29:35 +00:00
|
|
|
(offset%byte_align) != 0 || (length%byte_align) != 0)
|
2018-01-23 00:17:45 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, unlock_done);
|
2010-09-23 00:19:35 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
/* offset -> byte offset, length -> sample count */
|
2018-01-22 07:35:28 +00:00
|
|
|
offset = offset/byte_align * frame_size;
|
2014-03-04 12:29:35 +00:00
|
|
|
length = length/byte_align * albuf->OriginalAlign;
|
|
|
|
|
2018-01-22 07:35:28 +00:00
|
|
|
dst = (ALbyte*)albuf->data + offset;
|
|
|
|
if(srctype == UserFmtIMA4 && albuf->FmtType == FmtShort)
|
|
|
|
Convert_ALshort_ALima4(dst, data, num_chans, length, align);
|
|
|
|
else if(srctype == UserFmtMSADPCM && albuf->FmtType == FmtShort)
|
|
|
|
Convert_ALshort_ALmsadpcm(dst, data, num_chans, length, align);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert((long)srctype == (long)albuf->FmtType);
|
|
|
|
memcpy(dst, data, length*frame_size);
|
|
|
|
}
|
2018-01-23 00:17:45 +00:00
|
|
|
|
|
|
|
unlock_done:
|
2013-10-07 01:01:01 +00:00
|
|
|
WriteUnlock(&albuf->lock);
|
2008-11-11 13:57:32 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2008-11-11 13:57:32 +00:00
|
|
|
}
|
|
|
|
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2018-01-22 01:19:57 +00:00
|
|
|
AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint UNUSED(buffer),
|
|
|
|
ALuint UNUSED(samplerate), ALenum UNUSED(internalformat), ALsizei UNUSED(samples),
|
|
|
|
ALenum UNUSED(channels), ALenum UNUSED(type), const ALvoid *UNUSED(data))
|
2011-03-16 18:29:22 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext *context;
|
2011-03-16 18:29:22 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2011-03-16 18:29:22 +00:00
|
|
|
|
2018-01-22 01:19:57 +00:00
|
|
|
alSetError(context, AL_INVALID_OPERATION);
|
2013-10-07 01:01:01 +00:00
|
|
|
|
|
|
|
ALCcontext_DecRef(context);
|
2011-03-16 18:29:22 +00:00
|
|
|
}
|
|
|
|
|
2018-01-22 01:19:57 +00:00
|
|
|
AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint UNUSED(buffer),
|
|
|
|
ALsizei UNUSED(offset), ALsizei UNUSED(samples),
|
|
|
|
ALenum UNUSED(channels), ALenum UNUSED(type), const ALvoid *UNUSED(data))
|
2011-03-16 19:13:17 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext *context;
|
|
|
|
|
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
|
|
|
|
2018-01-22 01:19:57 +00:00
|
|
|
alSetError(context, AL_INVALID_OPERATION);
|
2013-10-07 01:01:01 +00:00
|
|
|
|
|
|
|
ALCcontext_DecRef(context);
|
2011-03-16 19:13:17 +00:00
|
|
|
}
|
|
|
|
|
2018-01-22 01:19:57 +00:00
|
|
|
AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint UNUSED(buffer),
|
|
|
|
ALsizei UNUSED(offset), ALsizei UNUSED(samples),
|
|
|
|
ALenum UNUSED(channels), ALenum UNUSED(type), ALvoid *UNUSED(data))
|
2011-03-16 19:56:39 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext *context;
|
|
|
|
|
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
|
|
|
|
2018-01-22 01:19:57 +00:00
|
|
|
alSetError(context, AL_INVALID_OPERATION);
|
2011-03-16 19:56:39 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2011-03-16 19:56:39 +00:00
|
|
|
}
|
|
|
|
|
2018-01-22 01:19:57 +00:00
|
|
|
AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum UNUSED(format))
|
2011-03-16 20:57:00 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext *context;
|
2011-03-16 20:57:00 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return AL_FALSE;
|
2011-03-16 20:57:00 +00:00
|
|
|
|
2018-01-22 01:19:57 +00:00
|
|
|
alSetError(context, AL_INVALID_OPERATION);
|
2011-03-16 20:57:00 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2018-01-22 01:19:57 +00:00
|
|
|
return AL_FALSE;
|
2011-03-16 20:57:00 +00:00
|
|
|
}
|
|
|
|
|
2011-03-16 18:29:22 +00:00
|
|
|
|
2013-10-07 14:44:09 +00:00
|
|
|
AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(value))
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
if(LookupBuffer(device, buffer) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-07 14:44:09 +00:00
|
|
|
AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(value1), ALfloat UNUSED(value2), ALfloat UNUSED(value3))
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
if(LookupBuffer(device, buffer) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
if(LookupBuffer(device, buffer) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
if(!(values))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
ALbuffer *albuf;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
2013-10-07 14:06:01 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
switch(param)
|
|
|
|
{
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
|
|
|
|
if(!(value >= 0))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2016-12-21 04:49:37 +00:00
|
|
|
ATOMIC_STORE_SEQ(&albuf->UnpackAlign, value);
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_PACK_BLOCK_ALIGNMENT_SOFT:
|
|
|
|
if(!(value >= 0))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2016-12-21 04:49:37 +00:00
|
|
|
ATOMIC_STORE_SEQ(&albuf->PackAlign, value);
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
break;
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-07 14:44:09 +00:00
|
|
|
AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint UNUSED(value1), ALint UNUSED(value2), ALint UNUSED(value3))
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
|
|
|
if(LookupBuffer(device, buffer) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
if(values)
|
|
|
|
{
|
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
|
|
|
|
case AL_PACK_BLOCK_ALIGNMENT_SOFT:
|
|
|
|
alBufferi(buffer, param, values[0]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
if(!(values))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
case AL_LOOP_POINTS_SOFT:
|
|
|
|
WriteLock(&albuf->lock);
|
2014-05-14 09:47:07 +00:00
|
|
|
if(ReadRef(&albuf->ref) != 0)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
|
|
|
}
|
|
|
|
if(values[0] >= values[1] || values[0] < 0 ||
|
|
|
|
values[1] > albuf->SampleLen)
|
|
|
|
{
|
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
}
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
albuf->LoopStart = values[0];
|
|
|
|
albuf->LoopEnd = values[1];
|
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
break;
|
2010-05-13 09:03:48 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
if(!(value))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
if(LookupBuffer(device, buffer) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
if(!(value1 && value2 && value3))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
switch(param)
|
Add buffer properties to get the internal format, and the length in bytes, samples, and seconds
The provided buffer lengths correspond to the source offsets, in that the byte
length specifies the end of the byte offset (ie, when the buffer is used for a
static source, the offset will range between 0 (inclusive) and the byte length
(exclusive)). Although an application could use the AL_SIZE, AL_CHANNELS,
AL_BITS, and AL_FREQUENCY properties to find the length in samples and seconds,
the byte length cannot be reliably calculated this way.
2011-10-01 13:19:55 +00:00
|
|
|
{
|
2012-01-10 08:41:05 +00:00
|
|
|
case AL_SEC_LENGTH_SOFT:
|
2012-04-24 07:17:05 +00:00
|
|
|
alGetBufferf(buffer, param, values);
|
Add buffer properties to get the internal format, and the length in bytes, samples, and seconds
The provided buffer lengths correspond to the source offsets, in that the byte
length specifies the end of the byte offset (ie, when the buffer is used for a
static source, the offset will range between 0 (inclusive) and the byte length
(exclusive)). Although an application could use the AL_SIZE, AL_CHANNELS,
AL_BITS, and AL_FREQUENCY properties to find the length in samples and seconds,
the byte length cannot be reliably calculated this way.
2011-10-01 13:19:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
if(LookupBuffer(device, buffer) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
if(!(values))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
if(!(value))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
case AL_FREQUENCY:
|
|
|
|
*value = albuf->Frequency;
|
|
|
|
break;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
case AL_BITS:
|
|
|
|
*value = BytesFromFmt(albuf->FmtType) * 8;
|
|
|
|
break;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
case AL_CHANNELS:
|
|
|
|
*value = ChannelsFromFmt(albuf->FmtChannels);
|
|
|
|
break;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
case AL_SIZE:
|
|
|
|
ReadLock(&albuf->lock);
|
|
|
|
*value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels,
|
|
|
|
albuf->FmtType);
|
|
|
|
ReadUnlock(&albuf->lock);
|
|
|
|
break;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
|
2016-12-21 04:49:37 +00:00
|
|
|
*value = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_PACK_BLOCK_ALIGNMENT_SOFT:
|
2016-12-21 04:49:37 +00:00
|
|
|
*value = ATOMIC_LOAD_SEQ(&albuf->PackAlign);
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
break;
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
if(LookupBuffer(device, buffer) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
if(!(value1 && value2 && value3))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2012-04-24 07:17:05 +00:00
|
|
|
switch(param)
|
2011-06-16 16:14:41 +00:00
|
|
|
{
|
|
|
|
case AL_FREQUENCY:
|
|
|
|
case AL_BITS:
|
|
|
|
case AL_CHANNELS:
|
|
|
|
case AL_SIZE:
|
2012-01-10 08:41:05 +00:00
|
|
|
case AL_INTERNAL_FORMAT_SOFT:
|
|
|
|
case AL_BYTE_LENGTH_SOFT:
|
|
|
|
case AL_SAMPLE_LENGTH_SOFT:
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
|
|
|
|
case AL_PACK_BLOCK_ALIGNMENT_SOFT:
|
2012-04-24 07:17:05 +00:00
|
|
|
alGetBufferi(buffer, param, values);
|
2011-06-16 16:14:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
device = context->Device;
|
2016-05-11 06:42:44 +00:00
|
|
|
LockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
2012-04-24 07:17:05 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
if(!(values))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
|
|
|
{
|
|
|
|
case AL_LOOP_POINTS_SOFT:
|
|
|
|
ReadLock(&albuf->lock);
|
|
|
|
values[0] = albuf->LoopStart;
|
|
|
|
values[1] = albuf->LoopEnd;
|
|
|
|
ReadUnlock(&albuf->lock);
|
|
|
|
break;
|
2010-05-13 09:03:48 +00:00
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
done:
|
2016-05-11 06:42:44 +00:00
|
|
|
UnlockBuffersRead(device);
|
2013-10-07 14:06:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2007-12-29 04:25:18 +00:00
|
|
|
|
2010-11-28 04:33:37 +00:00
|
|
|
/*
|
|
|
|
* LoadData
|
|
|
|
*
|
|
|
|
* Loads the specified data into the buffer, using the specified formats.
|
|
|
|
* Currently, the new format must have the same channel configuration as the
|
2010-11-30 08:28:02 +00:00
|
|
|
* original format.
|
2010-11-28 04:33:37 +00:00
|
|
|
*/
|
2018-01-22 07:35:28 +00:00
|
|
|
static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALbitfieldSOFT access)
|
2010-11-28 04:33:37 +00:00
|
|
|
{
|
2016-08-31 11:56:10 +00:00
|
|
|
enum FmtChannels DstChannels = FmtMono;
|
2018-01-20 04:10:31 +00:00
|
|
|
enum FmtType DstType = FmtUByte;
|
2018-01-22 07:35:28 +00:00
|
|
|
ALsizei NumChannels, FrameSize;
|
|
|
|
ALsizei newsize;
|
2010-11-28 04:33:37 +00:00
|
|
|
|
2018-01-22 07:35:28 +00:00
|
|
|
/* Currently no channels need to be converted. */
|
|
|
|
switch(SrcChannels)
|
|
|
|
{
|
|
|
|
case UserFmtMono: DstChannels = FmtMono; break;
|
|
|
|
case UserFmtStereo: DstChannels = FmtStereo; break;
|
|
|
|
case UserFmtRear: DstChannels = FmtRear; break;
|
|
|
|
case UserFmtQuad: DstChannels = FmtQuad; break;
|
|
|
|
case UserFmtX51: DstChannels = FmtX51; break;
|
|
|
|
case UserFmtX61: DstChannels = FmtX61; break;
|
|
|
|
case UserFmtX71: DstChannels = FmtX71; break;
|
|
|
|
case UserFmtBFormat2D: DstChannels = FmtBFormat2D; break;
|
|
|
|
case UserFmtBFormat3D: DstChannels = FmtBFormat3D; break;
|
|
|
|
}
|
2016-08-31 11:56:10 +00:00
|
|
|
if((long)SrcChannels != (long)DstChannels)
|
2011-03-17 02:39:31 +00:00
|
|
|
return AL_INVALID_ENUM;
|
|
|
|
|
2018-01-22 07:35:28 +00:00
|
|
|
/* IMA4 and MSADPCM convert to 16-bit short. */
|
|
|
|
switch(SrcType)
|
|
|
|
{
|
|
|
|
case UserFmtUByte: DstType = FmtUByte; break;
|
|
|
|
case UserFmtShort: DstType = FmtShort; break;
|
|
|
|
case UserFmtFloat: DstType = FmtFloat; break;
|
|
|
|
case UserFmtDouble: DstType = FmtDouble; break;
|
|
|
|
case UserFmtAlaw: DstType = FmtAlaw; break;
|
|
|
|
case UserFmtMulaw: DstType = FmtMulaw; break;
|
|
|
|
case UserFmtIMA4: DstType = FmtShort; break;
|
|
|
|
case UserFmtMSADPCM: DstType = FmtShort; break;
|
|
|
|
}
|
|
|
|
|
2018-01-20 19:49:01 +00:00
|
|
|
if(access != 0)
|
|
|
|
{
|
2018-01-22 07:35:28 +00:00
|
|
|
if((long)SrcType != (long)DstType)
|
2018-01-20 19:49:01 +00:00
|
|
|
return AL_INVALID_VALUE;
|
|
|
|
}
|
|
|
|
|
2018-01-22 07:35:28 +00:00
|
|
|
NumChannels = ChannelsFromFmt(DstChannels);
|
|
|
|
FrameSize = NumChannels * BytesFromFmt(DstType);
|
2010-11-28 04:33:37 +00:00
|
|
|
|
2018-01-22 07:35:28 +00:00
|
|
|
if(frames > INT_MAX/FrameSize)
|
2012-01-26 03:32:10 +00:00
|
|
|
return AL_OUT_OF_MEMORY;
|
2018-01-22 07:35:28 +00:00
|
|
|
newsize = frames*FrameSize;
|
2010-11-30 08:28:02 +00:00
|
|
|
|
2012-01-26 03:32:10 +00:00
|
|
|
WriteLock(&ALBuf->lock);
|
2018-01-20 19:49:01 +00:00
|
|
|
if(ReadRef(&ALBuf->ref) != 0 || ALBuf->MappedAccess != 0)
|
2010-11-30 08:28:02 +00:00
|
|
|
{
|
2012-01-26 03:32:10 +00:00
|
|
|
WriteUnlock(&ALBuf->lock);
|
|
|
|
return AL_INVALID_OPERATION;
|
|
|
|
}
|
2010-11-30 08:28:02 +00:00
|
|
|
|
2018-01-22 19:34:16 +00:00
|
|
|
if((access&AL_PRESERVE_DATA_BIT_SOFT))
|
|
|
|
{
|
2018-01-22 23:52:53 +00:00
|
|
|
/* Can only preserve data with the same format and alignment. */
|
|
|
|
if(ALBuf->FmtChannels != DstChannels || ALBuf->OriginalType != SrcType ||
|
|
|
|
ALBuf->OriginalAlign != align)
|
2018-01-22 19:34:16 +00:00
|
|
|
{
|
|
|
|
WriteUnlock(&ALBuf->lock);
|
|
|
|
return AL_INVALID_VALUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-21 10:27:51 +00:00
|
|
|
/* 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.
|
|
|
|
*/
|
2018-01-22 07:35:28 +00:00
|
|
|
if(newsize <= INT_MAX-15)
|
|
|
|
newsize = (newsize+15) & ~0xf;
|
2016-05-21 10:27:51 +00:00
|
|
|
if(newsize != ALBuf->BytesAlloc)
|
2012-01-26 03:32:10 +00:00
|
|
|
{
|
2018-01-22 23:46:46 +00:00
|
|
|
void *temp = al_malloc(16, (size_t)newsize);
|
2016-05-21 10:27:51 +00:00
|
|
|
if(!temp && newsize)
|
|
|
|
{
|
|
|
|
WriteUnlock(&ALBuf->lock);
|
|
|
|
return AL_OUT_OF_MEMORY;
|
|
|
|
}
|
2018-01-22 19:34:16 +00:00
|
|
|
if((access&AL_PRESERVE_DATA_BIT_SOFT))
|
|
|
|
{
|
|
|
|
ALsizei tocopy = mini(newsize, ALBuf->BytesAlloc);
|
|
|
|
if(tocopy > 0) memcpy(temp, ALBuf->data, tocopy);
|
|
|
|
}
|
2016-05-21 10:27:51 +00:00
|
|
|
al_free(ALBuf->data);
|
|
|
|
ALBuf->data = temp;
|
2018-01-22 07:35:28 +00:00
|
|
|
ALBuf->BytesAlloc = newsize;
|
2012-01-26 03:32:10 +00:00
|
|
|
}
|
2010-11-30 08:28:02 +00:00
|
|
|
|
2018-01-22 07:35:28 +00:00
|
|
|
ALBuf->OriginalType = SrcType;
|
|
|
|
if(SrcType == UserFmtIMA4)
|
2012-01-26 03:32:10 +00:00
|
|
|
{
|
2018-01-22 07:35:28 +00:00
|
|
|
ALsizei byte_align = ((align-1)/2 + 4) * NumChannels;
|
|
|
|
ALBuf->OriginalSize = frames / align * byte_align;
|
|
|
|
ALBuf->OriginalAlign = align;
|
|
|
|
assert(DstType == FmtShort);
|
2018-01-22 08:23:19 +00:00
|
|
|
if(data != NULL && ALBuf->data != NULL)
|
2018-01-22 07:35:28 +00:00
|
|
|
Convert_ALshort_ALima4(ALBuf->data, data, NumChannels, frames, align);
|
|
|
|
}
|
|
|
|
else if(SrcType == UserFmtMSADPCM)
|
|
|
|
{
|
|
|
|
ALsizei byte_align = ((align-2)/2 + 7) * NumChannels;
|
|
|
|
ALBuf->OriginalSize = frames / align * byte_align;
|
|
|
|
ALBuf->OriginalAlign = align;
|
|
|
|
assert(DstType == FmtShort);
|
2018-01-22 08:23:19 +00:00
|
|
|
if(data != NULL && ALBuf->data != NULL)
|
2018-01-22 07:35:28 +00:00
|
|
|
Convert_ALshort_ALmsadpcm(ALBuf->data, data, NumChannels, frames, align);
|
2010-11-28 04:33:37 +00:00
|
|
|
}
|
2012-01-26 03:32:10 +00:00
|
|
|
else
|
2011-03-16 19:24:53 +00:00
|
|
|
{
|
2018-01-22 07:35:28 +00:00
|
|
|
ALBuf->OriginalSize = frames * FrameSize;
|
|
|
|
ALBuf->OriginalAlign = 1;
|
2018-01-22 08:23:19 +00:00
|
|
|
assert((long)SrcType == (long)DstType);
|
|
|
|
if(data != NULL && ALBuf->data != NULL)
|
2018-01-22 07:35:28 +00:00
|
|
|
memcpy(ALBuf->data, data, frames*FrameSize);
|
2011-03-16 19:24:53 +00:00
|
|
|
}
|
2012-01-26 03:32:10 +00:00
|
|
|
|
2010-11-28 21:08:51 +00:00
|
|
|
ALBuf->Frequency = freq;
|
|
|
|
ALBuf->FmtChannels = DstChannels;
|
2010-11-30 08:28:02 +00:00
|
|
|
ALBuf->FmtType = DstType;
|
2018-01-20 19:49:01 +00:00
|
|
|
ALBuf->Access = access;
|
2010-11-28 04:33:37 +00:00
|
|
|
|
2012-01-27 00:49:11 +00:00
|
|
|
ALBuf->SampleLen = frames;
|
2010-11-28 04:33:37 +00:00
|
|
|
ALBuf->LoopStart = 0;
|
2011-10-03 17:07:50 +00:00
|
|
|
ALBuf->LoopEnd = ALBuf->SampleLen;
|
2010-11-28 04:33:37 +00:00
|
|
|
|
2011-09-11 10:57:40 +00:00
|
|
|
WriteUnlock(&ALBuf->lock);
|
2010-11-28 04:33:37 +00:00
|
|
|
return AL_NO_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-18 15:13:23 +00:00
|
|
|
ALsizei BytesFromUserFmt(enum UserFmtType type)
|
2010-11-29 23:01:27 +00:00
|
|
|
{
|
|
|
|
switch(type)
|
|
|
|
{
|
2010-12-04 06:33:41 +00:00
|
|
|
case UserFmtUByte: return sizeof(ALubyte);
|
|
|
|
case UserFmtShort: return sizeof(ALshort);
|
|
|
|
case UserFmtFloat: return sizeof(ALfloat);
|
|
|
|
case UserFmtDouble: return sizeof(ALdouble);
|
2011-04-28 04:05:46 +00:00
|
|
|
case UserFmtMulaw: return sizeof(ALubyte);
|
2011-10-01 11:55:03 +00:00
|
|
|
case UserFmtAlaw: return sizeof(ALubyte);
|
2011-04-28 04:05:46 +00:00
|
|
|
case UserFmtIMA4: break; /* not handled here */
|
2014-03-05 06:44:30 +00:00
|
|
|
case UserFmtMSADPCM: break; /* not handled here */
|
2010-11-29 23:01:27 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2017-01-18 15:13:23 +00:00
|
|
|
ALsizei ChannelsFromUserFmt(enum UserFmtChannels chans)
|
2010-11-29 23:01:27 +00:00
|
|
|
{
|
|
|
|
switch(chans)
|
|
|
|
{
|
2010-12-04 06:33:41 +00:00
|
|
|
case UserFmtMono: return 1;
|
|
|
|
case UserFmtStereo: return 2;
|
|
|
|
case UserFmtRear: return 2;
|
|
|
|
case UserFmtQuad: return 4;
|
|
|
|
case UserFmtX51: return 6;
|
|
|
|
case UserFmtX61: return 7;
|
|
|
|
case UserFmtX71: return 8;
|
2014-11-01 00:18:45 +00:00
|
|
|
case UserFmtBFormat2D: return 3;
|
|
|
|
case UserFmtBFormat3D: return 4;
|
2010-11-29 23:01:27 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2011-09-19 02:06:19 +00:00
|
|
|
static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
|
|
|
|
enum UserFmtType *type)
|
2010-11-27 23:33:33 +00:00
|
|
|
{
|
2011-09-19 02:06:19 +00:00
|
|
|
static const struct {
|
|
|
|
ALenum format;
|
|
|
|
enum UserFmtChannels channels;
|
|
|
|
enum UserFmtType type;
|
|
|
|
} list[] = {
|
2014-03-05 06:44:30 +00:00
|
|
|
{ AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte },
|
|
|
|
{ AL_FORMAT_MONO16, UserFmtMono, UserFmtShort },
|
|
|
|
{ AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat },
|
|
|
|
{ AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble },
|
|
|
|
{ AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 },
|
|
|
|
{ AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM },
|
|
|
|
{ AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw },
|
|
|
|
{ AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw },
|
|
|
|
|
|
|
|
{ AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte },
|
|
|
|
{ AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort },
|
|
|
|
{ AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat },
|
|
|
|
{ AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble },
|
|
|
|
{ AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 },
|
|
|
|
{ AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM },
|
|
|
|
{ AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw },
|
|
|
|
{ AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw },
|
2011-09-19 02:06:19 +00:00
|
|
|
|
|
|
|
{ AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte },
|
|
|
|
{ AL_FORMAT_REAR16, UserFmtRear, UserFmtShort },
|
|
|
|
{ AL_FORMAT_REAR32, UserFmtRear, UserFmtFloat },
|
|
|
|
{ AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw },
|
|
|
|
|
|
|
|
{ AL_FORMAT_QUAD8_LOKI, UserFmtQuad, UserFmtUByte },
|
|
|
|
{ AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort },
|
|
|
|
|
|
|
|
{ AL_FORMAT_QUAD8, UserFmtQuad, UserFmtUByte },
|
|
|
|
{ AL_FORMAT_QUAD16, UserFmtQuad, UserFmtShort },
|
|
|
|
{ AL_FORMAT_QUAD32, UserFmtQuad, UserFmtFloat },
|
|
|
|
{ AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw },
|
|
|
|
|
|
|
|
{ AL_FORMAT_51CHN8, UserFmtX51, UserFmtUByte },
|
|
|
|
{ AL_FORMAT_51CHN16, UserFmtX51, UserFmtShort },
|
|
|
|
{ AL_FORMAT_51CHN32, UserFmtX51, UserFmtFloat },
|
|
|
|
{ AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw },
|
|
|
|
|
|
|
|
{ AL_FORMAT_61CHN8, UserFmtX61, UserFmtUByte },
|
|
|
|
{ AL_FORMAT_61CHN16, UserFmtX61, UserFmtShort },
|
|
|
|
{ AL_FORMAT_61CHN32, UserFmtX61, UserFmtFloat },
|
|
|
|
{ AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw },
|
|
|
|
|
|
|
|
{ AL_FORMAT_71CHN8, UserFmtX71, UserFmtUByte },
|
|
|
|
{ AL_FORMAT_71CHN16, UserFmtX71, UserFmtShort },
|
|
|
|
{ AL_FORMAT_71CHN32, UserFmtX71, UserFmtFloat },
|
|
|
|
{ AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw },
|
2014-11-01 00:18:45 +00:00
|
|
|
|
|
|
|
{ AL_FORMAT_BFORMAT2D_8, UserFmtBFormat2D, UserFmtUByte },
|
|
|
|
{ AL_FORMAT_BFORMAT2D_16, UserFmtBFormat2D, UserFmtShort },
|
|
|
|
{ AL_FORMAT_BFORMAT2D_FLOAT32, UserFmtBFormat2D, UserFmtFloat },
|
2014-11-01 05:52:30 +00:00
|
|
|
{ AL_FORMAT_BFORMAT2D_MULAW, UserFmtBFormat2D, UserFmtMulaw },
|
2014-11-01 00:18:45 +00:00
|
|
|
|
|
|
|
{ AL_FORMAT_BFORMAT3D_8, UserFmtBFormat3D, UserFmtUByte },
|
|
|
|
{ AL_FORMAT_BFORMAT3D_16, UserFmtBFormat3D, UserFmtShort },
|
|
|
|
{ AL_FORMAT_BFORMAT3D_FLOAT32, UserFmtBFormat3D, UserFmtFloat },
|
2014-11-01 05:52:30 +00:00
|
|
|
{ AL_FORMAT_BFORMAT3D_MULAW, UserFmtBFormat3D, UserFmtMulaw },
|
2011-09-19 02:06:19 +00:00
|
|
|
};
|
|
|
|
ALuint i;
|
|
|
|
|
2012-02-19 20:07:40 +00:00
|
|
|
for(i = 0;i < COUNTOF(list);i++)
|
2010-11-27 23:33:33 +00:00
|
|
|
{
|
2011-09-19 02:06:19 +00:00
|
|
|
if(list[i].format == format)
|
|
|
|
{
|
|
|
|
*chans = list[i].channels;
|
|
|
|
*type = list[i].type;
|
2010-11-30 04:34:33 +00:00
|
|
|
return AL_TRUE;
|
2011-09-19 02:06:19 +00:00
|
|
|
}
|
2010-11-27 23:33:33 +00:00
|
|
|
}
|
2011-09-19 02:06:19 +00:00
|
|
|
|
2010-11-30 04:34:33 +00:00
|
|
|
return AL_FALSE;
|
2010-11-27 23:33:33 +00:00
|
|
|
}
|
|
|
|
|
2017-01-18 15:13:23 +00:00
|
|
|
ALsizei BytesFromFmt(enum FmtType type)
|
2010-11-29 23:01:27 +00:00
|
|
|
{
|
|
|
|
switch(type)
|
|
|
|
{
|
2018-01-20 04:10:31 +00:00
|
|
|
case FmtUByte: return sizeof(ALubyte);
|
2010-11-29 23:01:27 +00:00
|
|
|
case FmtShort: return sizeof(ALshort);
|
|
|
|
case FmtFloat: return sizeof(ALfloat);
|
2018-01-22 02:34:03 +00:00
|
|
|
case FmtDouble: return sizeof(ALdouble);
|
2018-01-17 16:49:49 +00:00
|
|
|
case FmtMulaw: return sizeof(ALubyte);
|
|
|
|
case FmtAlaw: return sizeof(ALubyte);
|
2010-11-29 23:01:27 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2017-01-18 15:13:23 +00:00
|
|
|
ALsizei ChannelsFromFmt(enum FmtChannels chans)
|
2010-11-29 23:01:27 +00:00
|
|
|
{
|
|
|
|
switch(chans)
|
|
|
|
{
|
|
|
|
case FmtMono: return 1;
|
|
|
|
case FmtStereo: return 2;
|
|
|
|
case FmtRear: return 2;
|
|
|
|
case FmtQuad: return 4;
|
|
|
|
case FmtX51: return 6;
|
|
|
|
case FmtX61: return 7;
|
|
|
|
case FmtX71: return 8;
|
2014-11-01 00:18:45 +00:00
|
|
|
case FmtBFormat2D: return 3;
|
|
|
|
case FmtBFormat3D: return 4;
|
2010-11-29 23:01:27 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2010-11-27 23:37:51 +00:00
|
|
|
|
2018-01-20 05:00:53 +00:00
|
|
|
static ALsizei SanitizeAlignment(enum UserFmtType type, ALsizei align)
|
2014-03-04 12:29:35 +00:00
|
|
|
{
|
2018-01-20 05:00:53 +00:00
|
|
|
if(align < 0)
|
|
|
|
return 0;
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
|
2018-01-20 05:00:53 +00:00
|
|
|
if(align == 0)
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
{
|
|
|
|
if(type == UserFmtIMA4)
|
|
|
|
{
|
|
|
|
/* Here is where things vary:
|
|
|
|
* nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
|
|
|
|
* Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
|
|
|
|
*/
|
2018-01-20 05:00:53 +00:00
|
|
|
return 65;
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
}
|
2018-01-20 05:00:53 +00:00
|
|
|
if(type == UserFmtMSADPCM)
|
|
|
|
return 64;
|
|
|
|
return 1;
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
}
|
|
|
|
|
2014-03-04 12:29:35 +00:00
|
|
|
if(type == UserFmtIMA4)
|
|
|
|
{
|
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g.
alGetBufferSamplesSOFT) operations. The alignments are specified in sample
frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment
must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error
will occur during (un)packing. Chenging the block alignment does not affect
already-loaded sample data, only future unpack/pack operations... so for
example, this is perfectly valid:
// Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample
// frames.
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041);
alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate);
alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
2014-03-04 13:16:45 +00:00
|
|
|
/* IMA4 block alignment must be a multiple of 8, plus 1. */
|
2018-01-20 05:00:53 +00:00
|
|
|
if((align&7) == 1) return align;
|
|
|
|
return 0;
|
2014-03-05 06:44:30 +00:00
|
|
|
}
|
|
|
|
if(type == UserFmtMSADPCM)
|
|
|
|
{
|
2014-03-07 05:42:03 +00:00
|
|
|
/* MSADPCM block alignment must be a multiple of 2. */
|
2018-01-20 05:00:53 +00:00
|
|
|
if((align&1) == 0) return align;
|
|
|
|
return 0;
|
2014-03-04 12:29:35 +00:00
|
|
|
}
|
|
|
|
|
2018-01-20 05:00:53 +00:00
|
|
|
return align;
|
2014-03-04 12:29:35 +00:00
|
|
|
}
|
|
|
|
|
2010-11-27 23:37:51 +00:00
|
|
|
|
2014-06-29 09:04:05 +00:00
|
|
|
ALbuffer *NewBuffer(ALCcontext *context)
|
|
|
|
{
|
|
|
|
ALCdevice *device = context->Device;
|
|
|
|
ALbuffer *buffer;
|
|
|
|
ALenum err;
|
|
|
|
|
2016-05-21 10:27:51 +00:00
|
|
|
buffer = al_calloc(16, sizeof(ALbuffer));
|
2014-06-29 09:04:05 +00:00
|
|
|
if(!buffer)
|
|
|
|
SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
|
|
|
|
RWLockInit(&buffer->lock);
|
2018-01-20 19:49:01 +00:00
|
|
|
buffer->Access = 0;
|
|
|
|
buffer->MappedAccess = 0;
|
2014-06-29 09:04:05 +00:00
|
|
|
|
|
|
|
err = NewThunkEntry(&buffer->id);
|
|
|
|
if(err == AL_NO_ERROR)
|
|
|
|
err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer);
|
|
|
|
if(err != AL_NO_ERROR)
|
|
|
|
{
|
|
|
|
FreeThunkEntry(buffer->id);
|
|
|
|
memset(buffer, 0, sizeof(ALbuffer));
|
2016-05-21 10:27:51 +00:00
|
|
|
al_free(buffer);
|
2014-06-29 09:04:05 +00:00
|
|
|
|
|
|
|
SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
2014-06-30 07:10:40 +00:00
|
|
|
void DeleteBuffer(ALCdevice *device, ALbuffer *buffer)
|
2014-06-29 09:04:05 +00:00
|
|
|
{
|
2014-06-30 07:10:40 +00:00
|
|
|
RemoveBuffer(device, buffer->id);
|
2014-06-29 09:04:05 +00:00
|
|
|
FreeThunkEntry(buffer->id);
|
|
|
|
|
2016-05-21 10:27:51 +00:00
|
|
|
al_free(buffer->data);
|
2014-06-29 09:04:05 +00:00
|
|
|
|
|
|
|
memset(buffer, 0, sizeof(*buffer));
|
2016-05-21 10:27:51 +00:00
|
|
|
al_free(buffer);
|
2014-06-29 09:04:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-14 02:02:18 +00:00
|
|
|
/*
|
2010-11-25 20:07:12 +00:00
|
|
|
* ReleaseALBuffers()
|
|
|
|
*
|
2010-12-02 04:34:29 +00:00
|
|
|
* INTERNAL: Called to destroy any buffers that still exist on the device
|
2010-11-25 20:07:12 +00:00
|
|
|
*/
|
2009-08-15 16:14:08 +00:00
|
|
|
ALvoid ReleaseALBuffers(ALCdevice *device)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2010-05-02 02:59:41 +00:00
|
|
|
ALsizei i;
|
|
|
|
for(i = 0;i < device->BufferMap.size;i++)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2016-07-05 03:35:32 +00:00
|
|
|
ALbuffer *temp = device->BufferMap.values[i];
|
|
|
|
device->BufferMap.values[i] = NULL;
|
2010-03-21 04:49:02 +00:00
|
|
|
|
2016-05-21 10:27:51 +00:00
|
|
|
al_free(temp->data);
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2012-04-20 05:14:02 +00:00
|
|
|
FreeThunkEntry(temp->id);
|
2010-03-21 04:49:02 +00:00
|
|
|
memset(temp, 0, sizeof(ALbuffer));
|
2016-05-21 10:27:51 +00:00
|
|
|
al_free(temp);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
}
|