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
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
* 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
|
|
|
|
|
|
|
|
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);
|
2013-11-04 20:12:31 +00:00
|
|
|
extern inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
|
|
|
|
extern inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
|
|
|
|
|
2014-03-04 12:29:35 +00:00
|
|
|
static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels chans, enum UserFmtType type, const ALvoid *data, ALsizei align, ALboolean storesrc);
|
2014-05-23 17:00:58 +00:00
|
|
|
static ALboolean IsValidType(ALenum type) DECL_CONST;
|
|
|
|
static ALboolean IsValidChannels(ALenum channels) DECL_CONST;
|
|
|
|
static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type) DECL_CONST;
|
|
|
|
static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type) DECL_CONST;
|
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
|
|
|
static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align);
|
2007-12-29 04:25:18 +00:00
|
|
|
|
2010-11-27 23:33:33 +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
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALsizei cur = 0;
|
|
|
|
ALenum err;
|
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
|
|
|
device = context->Device;
|
|
|
|
for(cur = 0;cur < n;cur++)
|
|
|
|
{
|
|
|
|
ALbuffer *buffer = calloc(1, sizeof(ALbuffer));
|
|
|
|
if(!buffer)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
alDeleteBuffers(cur, buffers);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
|
|
|
|
}
|
|
|
|
RWLockInit(&buffer->lock);
|
2010-09-21 22:12:08 +00:00
|
|
|
|
2013-10-07 01:01:01 +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));
|
|
|
|
free(buffer);
|
2011-09-11 04:21:07 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
alDeleteBuffers(cur, buffers);
|
|
|
|
SET_ERROR_AND_GOTO(context, err, done);
|
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
|
|
|
|
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
|
|
|
device = context->Device;
|
|
|
|
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++)
|
|
|
|
{
|
|
|
|
if((ALBuf=RemoveBuffer(device, buffers[i])) == NULL)
|
|
|
|
continue;
|
|
|
|
FreeThunkEntry(ALBuf->id);
|
2010-09-21 23:54:33 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
free(ALBuf->data);
|
2010-09-21 23:54:33 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
memset(ALBuf, 0, sizeof(*ALBuf));
|
|
|
|
free(ALBuf);
|
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-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
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
ret = ((!buffer || LookupBuffer(context->Device, buffer)) ?
|
|
|
|
AL_TRUE : AL_FALSE);
|
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
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
enum UserFmtChannels srcchannels;
|
|
|
|
enum UserFmtType srctype;
|
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
2014-05-15 08:11:38 +00:00
|
|
|
ALenum newformat = AL_NONE;
|
|
|
|
ALuint 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;
|
|
|
|
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);
|
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
|
|
|
|
|
|
|
align = albuf->UnpackAlign;
|
|
|
|
if(SanitizeAlignment(srctype, &align) == AL_FALSE)
|
2014-03-04 12:29:35 +00:00
|
|
|
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 UserFmtByte:
|
|
|
|
case UserFmtUByte:
|
|
|
|
case UserFmtShort:
|
|
|
|
case UserFmtUShort:
|
|
|
|
case UserFmtFloat:
|
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);
|
|
|
|
|
2014-03-04 12:29:35 +00:00
|
|
|
err = LoadData(albuf, freq, format, size/framesize*align,
|
|
|
|
srcchannels, srctype, data, align, AL_TRUE);
|
2013-10-07 01:01:01 +00:00
|
|
|
if(err != AL_NO_ERROR)
|
|
|
|
SET_ERROR_AND_GOTO(context, err, done);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case UserFmtInt:
|
|
|
|
case UserFmtUInt:
|
|
|
|
case UserFmtByte3:
|
|
|
|
case UserFmtUByte3:
|
|
|
|
case UserFmtDouble:
|
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);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2014-03-04 12:29:35 +00:00
|
|
|
err = LoadData(albuf, freq, newformat, size/framesize*align,
|
|
|
|
srcchannels, srctype, data, align, AL_TRUE);
|
2013-10-07 01:01:01 +00:00
|
|
|
if(err != AL_NO_ERROR)
|
|
|
|
SET_ERROR_AND_GOTO(context, err, done);
|
|
|
|
break;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2014-03-04 12:29:35 +00:00
|
|
|
err = LoadData(albuf, freq, newformat, size/framesize*align,
|
|
|
|
srcchannels, srctype, data, align, AL_TRUE);
|
2013-10-07 01:01:01 +00:00
|
|
|
if(err != AL_NO_ERROR)
|
|
|
|
SET_ERROR_AND_GOTO(context, err, done);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case UserFmtIMA4:
|
2014-03-04 12:29:35 +00:00
|
|
|
framesize = (align-1)/2 + 4;
|
|
|
|
framesize *= ChannelsFromUserFmt(srcchannels);
|
|
|
|
if((size%framesize) != 0)
|
2013-10-07 01:01:01 +00:00
|
|
|
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;
|
|
|
|
}
|
2014-03-04 12:29:35 +00:00
|
|
|
err = LoadData(albuf, freq, newformat, size/framesize*align,
|
|
|
|
srcchannels, srctype, data, align, AL_TRUE);
|
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:
|
|
|
|
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;
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
enum UserFmtChannels srcchannels;
|
|
|
|
enum UserFmtType srctype;
|
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
2014-03-04 12:29:35 +00:00
|
|
|
ALuint byte_align;
|
2013-10-07 01:01:01 +00:00
|
|
|
ALuint channels;
|
|
|
|
ALuint bytes;
|
2014-03-04 12:29:35 +00:00
|
|
|
ALsizei align;
|
2013-10-07 01:01:01 +00:00
|
|
|
|
|
|
|
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);
|
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
|
|
|
align = albuf->UnpackAlign;
|
|
|
|
if(SanitizeAlignment(srctype, &align) == AL_FALSE)
|
2014-03-04 01:05:08 +00:00
|
|
|
{
|
2014-03-04 12:29:35 +00:00
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2014-03-04 01:05:08 +00:00
|
|
|
}
|
2014-03-04 12:29:35 +00:00
|
|
|
if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType)
|
2014-03-04 01:05:08 +00:00
|
|
|
{
|
2014-03-04 12:29:35 +00:00
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2014-03-04 01:05:08 +00:00
|
|
|
}
|
2014-03-04 12:29:35 +00:00
|
|
|
if(align != albuf->OriginalAlign)
|
2010-09-23 00:19:35 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
|
|
|
}
|
2014-03-04 12:29:35 +00:00
|
|
|
|
|
|
|
if(albuf->OriginalType == UserFmtIMA4)
|
|
|
|
{
|
|
|
|
byte_align = (albuf->OriginalAlign-1)/2 + 4;
|
|
|
|
byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
|
|
|
|
}
|
2014-03-05 06:44:30 +00:00
|
|
|
else if(albuf->OriginalType == UserFmtMSADPCM)
|
|
|
|
{
|
|
|
|
byte_align = (albuf->OriginalAlign-2)/2 + 7;
|
|
|
|
byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
|
|
|
|
}
|
2014-03-04 12:29:35 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
byte_align = albuf->OriginalAlign;
|
|
|
|
byte_align *= FrameSizeFromUserFmt(albuf->OriginalChannels,
|
|
|
|
albuf->OriginalType);
|
|
|
|
}
|
|
|
|
|
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)
|
2013-10-07 01:01:01 +00:00
|
|
|
{
|
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
}
|
2010-09-23 00:19:35 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
channels = ChannelsFromFmt(albuf->FmtChannels);
|
|
|
|
bytes = BytesFromFmt(albuf->FmtType);
|
|
|
|
/* offset -> byte offset, length -> sample count */
|
2014-03-04 12:29:35 +00:00
|
|
|
offset = offset/byte_align * channels*bytes;
|
|
|
|
length = length/byte_align * albuf->OriginalAlign;
|
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
|
2014-03-04 12:29:35 +00:00
|
|
|
data, srctype, channels, length, align);
|
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:
|
|
|
|
ALCcontext_DecRef(context);
|
2008-11-11 13:57:32 +00:00
|
|
|
}
|
|
|
|
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2011-03-16 18:29:22 +00:00
|
|
|
AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
|
2011-10-02 14:31:26 +00:00
|
|
|
ALuint samplerate, ALenum internalformat, ALsizei samples,
|
2011-03-16 18:29:22 +00:00
|
|
|
ALenum channels, ALenum type, const ALvoid *data)
|
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
2014-03-04 12:29:35 +00:00
|
|
|
ALsizei align;
|
2011-03-16 18:29:22 +00:00
|
|
|
ALenum err;
|
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2011-03-16 18:29:22 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
device = context->Device;
|
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
|
|
|
if(!(samples >= 0 && samplerate != 0))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
|
|
|
|
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
|
|
|
align = albuf->UnpackAlign;
|
|
|
|
if(SanitizeAlignment(type, &align) == AL_FALSE)
|
2014-03-04 12:29:35 +00:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
if((samples%align) != 0)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
err = LoadData(albuf, samplerate, internalformat, samples,
|
2014-03-04 12:29:35 +00:00
|
|
|
channels, type, data, align, AL_FALSE);
|
2013-10-07 01:01:01 +00:00
|
|
|
if(err != AL_NO_ERROR)
|
|
|
|
SET_ERROR_AND_GOTO(context, err, done);
|
2011-03-16 18:29:22 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2011-03-16 18:29:22 +00:00
|
|
|
}
|
|
|
|
|
2011-03-16 19:13:17 +00:00
|
|
|
AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
|
2011-10-02 14:31:26 +00:00
|
|
|
ALsizei offset, ALsizei samples,
|
2011-03-16 19:13:17 +00:00
|
|
|
ALenum channels, ALenum type, const ALvoid *data)
|
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
2014-03-04 12:29:35 +00:00
|
|
|
ALsizei align;
|
2013-10-07 01:01:01 +00:00
|
|
|
|
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
|
|
|
|
|
|
|
device = context->Device;
|
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
|
|
|
if(!(samples >= 0 && offset >= 0))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
if(IsValidType(type) == AL_FALSE)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
|
|
|
|
|
|
|
WriteLock(&albuf->lock);
|
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
|
|
|
align = albuf->UnpackAlign;
|
|
|
|
if(SanitizeAlignment(type, &align) == AL_FALSE)
|
2014-03-04 12:29:35 +00:00
|
|
|
{
|
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
}
|
2013-10-07 01:01:01 +00:00
|
|
|
if(channels != (ALenum)albuf->FmtChannels)
|
2011-03-16 19:13:17 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
|
|
|
}
|
2014-03-04 12:29:35 +00:00
|
|
|
if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
|
|
|
|
{
|
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
}
|
|
|
|
if((samples%align) != 0)
|
2013-10-07 01:01:01 +00:00
|
|
|
{
|
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2011-03-16 19:13:17 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
/* offset -> byte offset */
|
2014-03-04 12:29:35 +00:00
|
|
|
offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
|
2013-10-07 01:01:01 +00:00
|
|
|
ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
|
2014-03-04 12:29:35 +00:00
|
|
|
data, type, ChannelsFromFmt(albuf->FmtChannels), samples, align);
|
2013-10-07 01:01:01 +00:00
|
|
|
WriteUnlock(&albuf->lock);
|
|
|
|
|
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2011-03-16 19:13:17 +00:00
|
|
|
}
|
|
|
|
|
2011-03-16 19:56:39 +00:00
|
|
|
AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
|
2011-10-02 14:31:26 +00:00
|
|
|
ALsizei offset, ALsizei samples,
|
2011-03-16 19:56:39 +00:00
|
|
|
ALenum channels, ALenum type, ALvoid *data)
|
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCdevice *device;
|
|
|
|
ALCcontext *context;
|
|
|
|
ALbuffer *albuf;
|
2014-03-04 12:29:35 +00:00
|
|
|
ALsizei align;
|
2013-10-07 01:01:01 +00:00
|
|
|
|
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
|
|
|
|
|
|
|
device = context->Device;
|
|
|
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
|
|
|
if(!(samples >= 0 && offset >= 0))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
if(IsValidType(type) == AL_FALSE)
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
|
|
|
|
|
|
|
ReadLock(&albuf->lock);
|
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
|
|
|
align = albuf->PackAlign;
|
|
|
|
if(SanitizeAlignment(type, &align) == AL_FALSE)
|
2014-03-04 12:29:35 +00:00
|
|
|
{
|
|
|
|
ReadUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
}
|
2013-10-07 01:01:01 +00:00
|
|
|
if(channels != (ALenum)albuf->FmtChannels)
|
2011-03-16 19:56:39 +00:00
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
ReadUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2011-03-16 19:56:39 +00:00
|
|
|
}
|
2013-10-07 01:01:01 +00:00
|
|
|
if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
|
|
|
|
{
|
|
|
|
ReadUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
}
|
2014-03-04 12:29:35 +00:00
|
|
|
if((samples%align) != 0)
|
2013-10-07 01:01:01 +00:00
|
|
|
{
|
|
|
|
ReadUnlock(&albuf->lock);
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* offset -> byte offset */
|
2014-03-04 12:29:35 +00:00
|
|
|
offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
|
2013-10-07 01:01:01 +00:00
|
|
|
ConvertData(data, type, (char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
|
2014-03-04 12:29:35 +00:00
|
|
|
ChannelsFromFmt(albuf->FmtChannels), samples, align);
|
2013-10-07 01:01:01 +00:00
|
|
|
ReadUnlock(&albuf->lock);
|
2011-03-16 19:56:39 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2011-03-16 19:56:39 +00:00
|
|
|
}
|
|
|
|
|
2011-03-16 20:57:00 +00:00
|
|
|
AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format)
|
|
|
|
{
|
2013-10-07 01:01:01 +00:00
|
|
|
enum FmtChannels dstchannels;
|
|
|
|
enum FmtType dsttype;
|
|
|
|
ALCcontext *context;
|
2011-03-16 20:57:00 +00:00
|
|
|
ALboolean ret;
|
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return AL_FALSE;
|
2011-03-16 20:57:00 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
ret = DecomposeFormat(format, &dstchannels, &dsttype);
|
2011-03-16 20:57:00 +00:00
|
|
|
|
2013-10-07 01:01:01 +00:00
|
|
|
ALCcontext_DecRef(context);
|
2011-03-16 20:57:00 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
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 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;
|
|
|
|
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:
|
|
|
|
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;
|
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);
|
|
|
|
ExchangeInt(&albuf->UnpackAlign, value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_PACK_BLOCK_ALIGNMENT_SOFT:
|
|
|
|
if(!(value >= 0))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
ExchangeInt(&albuf->PackAlign, value);
|
|
|
|
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:
|
|
|
|
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;
|
|
|
|
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:
|
|
|
|
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;
|
|
|
|
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_SEC_LENGTH_SOFT:
|
|
|
|
ReadLock(&albuf->lock);
|
|
|
|
if(albuf->SampleLen != 0)
|
|
|
|
*value = albuf->SampleLen / (ALfloat)albuf->Frequency;
|
|
|
|
else
|
|
|
|
*value = 0.0f;
|
|
|
|
ReadUnlock(&albuf->lock);
|
|
|
|
break;
|
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
|
|
|
|
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:
|
|
|
|
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;
|
|
|
|
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:
|
|
|
|
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;
|
|
|
|
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:
|
|
|
|
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;
|
|
|
|
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
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
case AL_INTERNAL_FORMAT_SOFT:
|
|
|
|
*value = albuf->Format;
|
|
|
|
break;
|
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
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
case AL_BYTE_LENGTH_SOFT:
|
|
|
|
*value = albuf->OriginalSize;
|
|
|
|
break;
|
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
|
|
|
|
2013-10-07 14:06:01 +00:00
|
|
|
case AL_SAMPLE_LENGTH_SOFT:
|
|
|
|
*value = albuf->SampleLen;
|
|
|
|
break;
|
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
|
|
|
|
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:
|
|
|
|
*value = albuf->UnpackAlign;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_PACK_BLOCK_ALIGNMENT_SOFT:
|
|
|
|
*value = albuf->PackAlign;
|
|
|
|
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:
|
|
|
|
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;
|
|
|
|
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:
|
|
|
|
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;
|
|
|
|
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:
|
|
|
|
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
|
|
|
*/
|
2014-03-04 12:29:35 +00:00
|
|
|
static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc)
|
2010-11-28 04:33:37 +00:00
|
|
|
{
|
2010-11-30 08:28:02 +00:00
|
|
|
ALuint NewChannels, NewBytes;
|
2010-11-28 04:33:37 +00:00
|
|
|
enum FmtChannels DstChannels;
|
|
|
|
enum FmtType DstType;
|
|
|
|
ALuint64 newsize;
|
|
|
|
ALvoid *temp;
|
|
|
|
|
2011-03-17 02:39:31 +00:00
|
|
|
if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE ||
|
|
|
|
(long)SrcChannels != (long)DstChannels)
|
|
|
|
return AL_INVALID_ENUM;
|
|
|
|
|
2010-11-30 08:28:02 +00:00
|
|
|
NewChannels = ChannelsFromFmt(DstChannels);
|
|
|
|
NewBytes = BytesFromFmt(DstType);
|
2010-11-28 04:33:37 +00:00
|
|
|
|
2012-01-26 03:32:10 +00:00
|
|
|
newsize = frames;
|
|
|
|
newsize *= NewBytes;
|
|
|
|
newsize *= NewChannels;
|
|
|
|
if(newsize > INT_MAX)
|
|
|
|
return AL_OUT_OF_MEMORY;
|
2010-11-30 08:28:02 +00:00
|
|
|
|
2012-01-26 03:32:10 +00:00
|
|
|
WriteLock(&ALBuf->lock);
|
2014-05-14 09:47:07 +00:00
|
|
|
if(ReadRef(&ALBuf->ref) != 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
|
|
|
|
2012-01-26 03:32:10 +00:00
|
|
|
temp = realloc(ALBuf->data, (size_t)newsize);
|
|
|
|
if(!temp && newsize)
|
|
|
|
{
|
|
|
|
WriteUnlock(&ALBuf->lock);
|
|
|
|
return AL_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
ALBuf->data = temp;
|
2010-11-30 08:28:02 +00:00
|
|
|
|
2012-01-26 03:32:10 +00:00
|
|
|
if(data != NULL)
|
2014-03-04 12:29:35 +00:00
|
|
|
ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align);
|
2010-11-30 08:28:02 +00:00
|
|
|
|
2012-01-26 03:32:10 +00:00
|
|
|
if(storesrc)
|
|
|
|
{
|
|
|
|
ALBuf->OriginalChannels = SrcChannels;
|
|
|
|
ALBuf->OriginalType = SrcType;
|
2012-01-27 00:49:11 +00:00
|
|
|
if(SrcType == UserFmtIMA4)
|
2014-03-04 01:05:08 +00:00
|
|
|
{
|
2014-03-04 12:29:35 +00:00
|
|
|
ALsizei byte_align = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels);
|
|
|
|
ALBuf->OriginalSize = frames / align * byte_align;
|
|
|
|
ALBuf->OriginalAlign = align;
|
2014-03-04 01:05:08 +00:00
|
|
|
}
|
2014-03-05 06:44:30 +00:00
|
|
|
else if(SrcType == UserFmtMSADPCM)
|
|
|
|
{
|
|
|
|
ALsizei byte_align = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels);
|
|
|
|
ALBuf->OriginalSize = frames / align * byte_align;
|
|
|
|
ALBuf->OriginalAlign = align;
|
|
|
|
}
|
2012-01-27 00:49:11 +00:00
|
|
|
else
|
2014-03-04 01:05:08 +00:00
|
|
|
{
|
|
|
|
ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType);
|
|
|
|
ALBuf->OriginalAlign = 1;
|
|
|
|
}
|
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
|
|
|
{
|
2013-06-05 08:52:49 +00:00
|
|
|
ALBuf->OriginalChannels = (enum UserFmtChannels)DstChannels;
|
|
|
|
ALBuf->OriginalType = (enum UserFmtType)DstType;
|
2011-03-16 19:24:53 +00:00
|
|
|
ALBuf->OriginalSize = frames * NewBytes * NewChannels;
|
2014-03-04 01:05:08 +00:00
|
|
|
ALBuf->OriginalAlign = 1;
|
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;
|
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
|
|
|
ALBuf->Format = NewFormat;
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-04 06:33:41 +00:00
|
|
|
ALuint BytesFromUserFmt(enum UserFmtType type)
|
2010-11-29 23:01:27 +00:00
|
|
|
{
|
|
|
|
switch(type)
|
|
|
|
{
|
2010-12-04 06:33:41 +00:00
|
|
|
case UserFmtByte: return sizeof(ALbyte);
|
|
|
|
case UserFmtUByte: return sizeof(ALubyte);
|
|
|
|
case UserFmtShort: return sizeof(ALshort);
|
|
|
|
case UserFmtUShort: return sizeof(ALushort);
|
|
|
|
case UserFmtInt: return sizeof(ALint);
|
|
|
|
case UserFmtUInt: return sizeof(ALuint);
|
|
|
|
case UserFmtFloat: return sizeof(ALfloat);
|
|
|
|
case UserFmtDouble: return sizeof(ALdouble);
|
2014-03-06 00:17:47 +00:00
|
|
|
case UserFmtByte3: return sizeof(ALbyte[3]);
|
|
|
|
case UserFmtUByte3: return sizeof(ALubyte[3]);
|
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;
|
|
|
|
}
|
2010-12-04 06:33:41 +00:00
|
|
|
ALuint 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;
|
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 },
|
|
|
|
};
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2010-11-29 23:01:27 +00:00
|
|
|
ALuint BytesFromFmt(enum FmtType type)
|
|
|
|
{
|
|
|
|
switch(type)
|
|
|
|
{
|
2011-05-06 01:54:10 +00:00
|
|
|
case FmtByte: return sizeof(ALbyte);
|
2010-11-29 23:01:27 +00:00
|
|
|
case FmtShort: return sizeof(ALshort);
|
|
|
|
case FmtFloat: return sizeof(ALfloat);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ALuint ChannelsFromFmt(enum FmtChannels chans)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2011-09-19 02:06:19 +00:00
|
|
|
static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type)
|
2010-11-27 23:37:51 +00:00
|
|
|
{
|
2011-09-19 02:06:19 +00:00
|
|
|
static const struct {
|
|
|
|
ALenum format;
|
|
|
|
enum FmtChannels channels;
|
|
|
|
enum FmtType type;
|
|
|
|
} list[] = {
|
2012-01-10 08:41:05 +00:00
|
|
|
{ AL_MONO8_SOFT, FmtMono, FmtByte },
|
|
|
|
{ AL_MONO16_SOFT, FmtMono, FmtShort },
|
|
|
|
{ AL_MONO32F_SOFT, FmtMono, FmtFloat },
|
2011-09-19 02:06:19 +00:00
|
|
|
|
2012-01-10 08:41:05 +00:00
|
|
|
{ AL_STEREO8_SOFT, FmtStereo, FmtByte },
|
|
|
|
{ AL_STEREO16_SOFT, FmtStereo, FmtShort },
|
|
|
|
{ AL_STEREO32F_SOFT, FmtStereo, FmtFloat },
|
2011-09-19 02:06:19 +00:00
|
|
|
|
2012-01-10 08:41:05 +00:00
|
|
|
{ AL_REAR8_SOFT, FmtRear, FmtByte },
|
|
|
|
{ AL_REAR16_SOFT, FmtRear, FmtShort },
|
|
|
|
{ AL_REAR32F_SOFT, FmtRear, FmtFloat },
|
2011-09-19 02:06:19 +00:00
|
|
|
|
|
|
|
{ AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtByte },
|
|
|
|
{ AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort },
|
|
|
|
|
2012-01-10 08:41:05 +00:00
|
|
|
{ AL_QUAD8_SOFT, FmtQuad, FmtByte },
|
|
|
|
{ AL_QUAD16_SOFT, FmtQuad, FmtShort },
|
|
|
|
{ AL_QUAD32F_SOFT, FmtQuad, FmtFloat },
|
2011-09-19 02:06:19 +00:00
|
|
|
|
2012-01-10 08:41:05 +00:00
|
|
|
{ AL_5POINT1_8_SOFT, FmtX51, FmtByte },
|
|
|
|
{ AL_5POINT1_16_SOFT, FmtX51, FmtShort },
|
|
|
|
{ AL_5POINT1_32F_SOFT, FmtX51, FmtFloat },
|
2011-09-19 02:06:19 +00:00
|
|
|
|
2012-01-10 08:41:05 +00:00
|
|
|
{ AL_6POINT1_8_SOFT, FmtX61, FmtByte },
|
|
|
|
{ AL_6POINT1_16_SOFT, FmtX61, FmtShort },
|
|
|
|
{ AL_6POINT1_32F_SOFT, FmtX61, FmtFloat },
|
2011-09-19 02:06:19 +00:00
|
|
|
|
2012-01-10 08:41:05 +00:00
|
|
|
{ AL_7POINT1_8_SOFT, FmtX71, FmtByte },
|
|
|
|
{ AL_7POINT1_16_SOFT, FmtX71, FmtShort },
|
|
|
|
{ AL_7POINT1_32F_SOFT, FmtX71, FmtFloat },
|
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:37:51 +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:37:51 +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:37:51 +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
|
|
|
static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align)
|
2014-03-04 12:29:35 +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(*align < 0)
|
|
|
|
return AL_FALSE;
|
|
|
|
|
|
|
|
if(*align == 0)
|
|
|
|
{
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
*align = 65;
|
|
|
|
}
|
2014-03-05 06:44:30 +00:00
|
|
|
else if(type == UserFmtMSADPCM)
|
|
|
|
*align = 64;
|
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
|
|
|
else
|
|
|
|
*align = 1;
|
|
|
|
return AL_TRUE;
|
|
|
|
}
|
|
|
|
|
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. */
|
2014-03-05 06:44:30 +00:00
|
|
|
return ((*align)&7) == 1;
|
|
|
|
}
|
|
|
|
if(type == UserFmtMSADPCM)
|
|
|
|
{
|
2014-03-07 05:42:03 +00:00
|
|
|
/* MSADPCM block alignment must be a multiple of 2. */
|
2014-03-05 06:44:30 +00:00
|
|
|
/* FIXME: Too strict? Might only require align*channels to be a
|
|
|
|
* multiple of 2. */
|
2014-03-07 05:42:03 +00:00
|
|
|
return ((*align)&1) == 0;
|
2014-03-04 12:29:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return AL_TRUE;
|
|
|
|
}
|
|
|
|
|
2010-11-27 23:37:51 +00:00
|
|
|
|
2011-07-02 09:54:05 +00:00
|
|
|
static ALboolean IsValidType(ALenum type)
|
|
|
|
{
|
|
|
|
switch(type)
|
|
|
|
{
|
2012-01-10 08:41:05 +00:00
|
|
|
case AL_BYTE_SOFT:
|
|
|
|
case AL_UNSIGNED_BYTE_SOFT:
|
|
|
|
case AL_SHORT_SOFT:
|
|
|
|
case AL_UNSIGNED_SHORT_SOFT:
|
|
|
|
case AL_INT_SOFT:
|
|
|
|
case AL_UNSIGNED_INT_SOFT:
|
|
|
|
case AL_FLOAT_SOFT:
|
|
|
|
case AL_DOUBLE_SOFT:
|
|
|
|
case AL_BYTE3_SOFT:
|
|
|
|
case AL_UNSIGNED_BYTE3_SOFT:
|
2011-07-02 09:54:05 +00:00
|
|
|
return AL_TRUE;
|
|
|
|
}
|
|
|
|
return AL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ALboolean IsValidChannels(ALenum channels)
|
|
|
|
{
|
|
|
|
switch(channels)
|
|
|
|
{
|
2012-01-10 08:41:05 +00:00
|
|
|
case AL_MONO_SOFT:
|
|
|
|
case AL_STEREO_SOFT:
|
|
|
|
case AL_REAR_SOFT:
|
|
|
|
case AL_QUAD_SOFT:
|
|
|
|
case AL_5POINT1_SOFT:
|
|
|
|
case AL_6POINT1_SOFT:
|
|
|
|
case AL_7POINT1_SOFT:
|
2011-07-02 09:54:05 +00:00
|
|
|
return AL_TRUE;
|
|
|
|
}
|
|
|
|
return AL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2010-05-02 02:59:41 +00:00
|
|
|
ALbuffer *temp = device->BufferMap.array[i].value;
|
|
|
|
device->BufferMap.array[i].value = NULL;
|
2010-03-21 04:49:02 +00:00
|
|
|
|
|
|
|
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));
|
|
|
|
free(temp);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
}
|