Use sample frames when handling the buffer length
This commit is contained in:
parent
35b4b31d57
commit
11caba9807
12
Alc/mixer.c
12
Alc/mixer.c
@ -622,7 +622,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
|
||||
|
||||
/* Copy what's left to play in the source buffer, and clear the
|
||||
* rest of the temp buffer */
|
||||
DataSize = ALBuffer->size/FrameSize - pos;
|
||||
DataSize = ALBuffer->SampleLen - pos;
|
||||
DataSize = minu(BufferSize, DataSize);
|
||||
|
||||
memcpy(&SrcData[SrcDataSize*FrameSize], &Data[pos*FrameSize], DataSize*FrameSize);
|
||||
@ -715,12 +715,12 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
|
||||
|
||||
if(BufferListIter->buffer)
|
||||
{
|
||||
if((ALuint)BufferListIter->buffer->size/FrameSize > pos)
|
||||
if((ALuint)BufferListIter->buffer->SampleLen > pos)
|
||||
{
|
||||
pos = BufferListIter->buffer->size/FrameSize - pos;
|
||||
pos = BufferListIter->buffer->SampleLen - pos;
|
||||
break;
|
||||
}
|
||||
pos -= BufferListIter->buffer->size/FrameSize;
|
||||
pos -= BufferListIter->buffer->SampleLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -731,7 +731,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
|
||||
if((ALBuffer=BufferListIter->buffer) != NULL)
|
||||
{
|
||||
const ALubyte *Data = ALBuffer->data;
|
||||
ALuint DataSize = ALBuffer->size/FrameSize;
|
||||
ALuint DataSize = ALBuffer->SampleLen;
|
||||
|
||||
/* Skip the data already played */
|
||||
if(DataSize <= pos)
|
||||
@ -785,7 +785,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
|
||||
|
||||
if((ALBuffer=BufferListItem->buffer) != NULL)
|
||||
{
|
||||
DataSize = ALBuffer->size / FrameSize;
|
||||
DataSize = ALBuffer->SampleLen;
|
||||
LoopStart = ALBuffer->LoopStart;
|
||||
LoopEnd = ALBuffer->LoopEnd;
|
||||
if(LoopEnd > DataPosInt)
|
||||
|
@ -69,10 +69,11 @@ static __inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType typ
|
||||
typedef struct ALbuffer
|
||||
{
|
||||
ALvoid *data;
|
||||
ALsizei size;
|
||||
|
||||
ALsizei Frequency;
|
||||
ALenum Format;
|
||||
ALsizei Frequency;
|
||||
ALenum Format;
|
||||
ALsizei SampleLen;
|
||||
|
||||
enum FmtChannels FmtChannels;
|
||||
enum FmtType FmtType;
|
||||
|
||||
|
@ -550,14 +550,12 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
|
||||
else
|
||||
{
|
||||
ALuint FrameSize;
|
||||
ALsizei FrameCount;
|
||||
|
||||
WriteLock(&ALBuf->lock);
|
||||
FrameSize = FrameSizeFromFmt(ALBuf->FmtChannels, ALBuf->FmtType);
|
||||
FrameCount = ALBuf->size / FrameSize;
|
||||
if(channels != (ALenum)ALBuf->FmtChannels)
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
else if(offset > FrameCount || samples > FrameCount-offset)
|
||||
else if(offset > ALBuf->SampleLen || samples > ALBuf->SampleLen-offset)
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
else if(type == UserFmtIMA4 && (samples%65) != 0)
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
@ -598,14 +596,12 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
|
||||
else
|
||||
{
|
||||
ALuint FrameSize;
|
||||
ALsizei FrameCount;
|
||||
|
||||
ReadLock(&ALBuf->lock);
|
||||
FrameSize = FrameSizeFromFmt(ALBuf->FmtChannels, ALBuf->FmtType);
|
||||
FrameCount = ALBuf->size / FrameSize;
|
||||
if(channels != (ALenum)ALBuf->FmtChannels)
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
else if(offset > FrameCount || samples > FrameCount-offset)
|
||||
else if(offset > ALBuf->SampleLen || samples > ALBuf->SampleLen-offset)
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
else if(type == UserFmtIMA4 && (samples%65) != 0)
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
@ -804,20 +800,13 @@ AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum eParam, const ALint* pl
|
||||
WriteLock(&ALBuf->lock);
|
||||
if(ALBuf->ref != 0)
|
||||
alSetError(pContext, AL_INVALID_OPERATION);
|
||||
else if(plValues[0] < 0 || plValues[1] < 0 ||
|
||||
plValues[0] >= plValues[1] || ALBuf->size == 0)
|
||||
else if(plValues[0] >= plValues[1] || plValues[0] < 0 ||
|
||||
plValues[1] > ALBuf->SampleLen)
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
else
|
||||
{
|
||||
ALint maxlen = ALBuf->size /
|
||||
FrameSizeFromFmt(ALBuf->FmtChannels, ALBuf->FmtType);
|
||||
if(plValues[0] > maxlen || plValues[1] > maxlen)
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
else
|
||||
{
|
||||
ALBuf->LoopStart = plValues[0];
|
||||
ALBuf->LoopEnd = plValues[1];
|
||||
}
|
||||
ALBuf->LoopStart = plValues[0];
|
||||
ALBuf->LoopEnd = plValues[1];
|
||||
}
|
||||
WriteUnlock(&ALBuf->lock);
|
||||
break;
|
||||
@ -852,10 +841,8 @@ AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum eParam, ALfloat *pf
|
||||
{
|
||||
case AL_SEC_LENGTH:
|
||||
ReadLock(&pBuffer->lock);
|
||||
if(pBuffer->size != 0)
|
||||
*pflValue = (pBuffer->size /
|
||||
FrameSizeFromFmt(pBuffer->FmtChannels, pBuffer->FmtType)) /
|
||||
(ALfloat)pBuffer->Frequency;
|
||||
if(pBuffer->SampleLen != 0)
|
||||
*pflValue = pBuffer->SampleLen / (ALfloat)pBuffer->Frequency;
|
||||
else
|
||||
*pflValue = 0.0f;
|
||||
ReadUnlock(&pBuffer->lock);
|
||||
@ -963,7 +950,10 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum eParam, ALint *plVa
|
||||
break;
|
||||
|
||||
case AL_SIZE:
|
||||
*plValue = pBuffer->size;
|
||||
ReadLock(&pBuffer->lock);
|
||||
*plValue = pBuffer->SampleLen *
|
||||
FrameSizeFromFmt(pBuffer->FmtChannels, pBuffer->FmtType);
|
||||
ReadUnlock(&pBuffer->lock);
|
||||
break;
|
||||
|
||||
case AL_INTERNAL_FORMAT:
|
||||
@ -975,13 +965,7 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum eParam, ALint *plVa
|
||||
break;
|
||||
|
||||
case AL_SAMPLE_LENGTH:
|
||||
ReadLock(&pBuffer->lock);
|
||||
if(pBuffer->size != 0)
|
||||
*plValue = pBuffer->size /
|
||||
FrameSizeFromFmt(pBuffer->FmtChannels, pBuffer->FmtType);
|
||||
else
|
||||
*plValue = 0;
|
||||
ReadUnlock(&pBuffer->lock);
|
||||
*plValue = pBuffer->SampleLen;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2028,7 +2012,7 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
ALBuf->data = temp;
|
||||
ALBuf->size = (ALsizei)newsize;
|
||||
ALBuf->SampleLen = frames*65;
|
||||
|
||||
if(data != NULL)
|
||||
ConvertData(ALBuf->data, DstType, data, SrcType, NewChannels, frames);
|
||||
@ -2061,7 +2045,7 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
ALBuf->data = temp;
|
||||
ALBuf->size = (ALsizei)newsize;
|
||||
ALBuf->SampleLen = frames;
|
||||
|
||||
if(data != NULL)
|
||||
ConvertData(ALBuf->data, DstType, data, SrcType, NewChannels, frames);
|
||||
@ -2086,7 +2070,7 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
|
||||
ALBuf->Format = NewFormat;
|
||||
|
||||
ALBuf->LoopStart = 0;
|
||||
ALBuf->LoopEnd = (ALsizei)(newsize / NewChannels / NewBytes);
|
||||
ALBuf->LoopEnd = ALBuf->SampleLen;
|
||||
|
||||
WriteUnlock(&ALBuf->lock);
|
||||
return AL_NO_ERROR;
|
||||
|
@ -48,7 +48,7 @@ const ALsizei ResamplerPrePadding[RESAMPLER_MAX] = {
|
||||
|
||||
static ALvoid InitSourceParams(ALsource *Source);
|
||||
static ALvoid GetSourceOffset(ALsource *Source, ALenum eName, ALdouble *Offsets, ALdouble updateLen);
|
||||
static ALint GetByteOffset(ALsource *Source);
|
||||
static ALint GetSampleOffset(ALsource *Source);
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n,ALuint *sources)
|
||||
@ -1866,7 +1866,7 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
|
||||
BufferList = Source->queue;
|
||||
while(BufferList)
|
||||
{
|
||||
if(BufferList->buffer != NULL && BufferList->buffer->size)
|
||||
if(BufferList->buffer != NULL && BufferList->buffer->SampleLen)
|
||||
break;
|
||||
BufferList = BufferList->next;
|
||||
}
|
||||
@ -1960,11 +1960,9 @@ static ALvoid GetSourceOffset(ALsource *Source, ALenum name, ALdouble *offset, A
|
||||
{
|
||||
const ALbufferlistitem *BufferList;
|
||||
const ALbuffer *Buffer = NULL;
|
||||
enum UserFmtType OriginalType;
|
||||
ALsizei BufferFreq;
|
||||
ALint Channels, Bytes;
|
||||
ALuint BufferFreq = 0;
|
||||
ALuint readPos, writePos;
|
||||
ALuint TotalBufferDataSize;
|
||||
ALuint totalBufferLen;
|
||||
ALuint i;
|
||||
|
||||
// Find the first non-NULL Buffer in the Queue
|
||||
@ -1974,6 +1972,7 @@ static ALvoid GetSourceOffset(ALsource *Source, ALenum name, ALdouble *offset, A
|
||||
if(BufferList->buffer)
|
||||
{
|
||||
Buffer = BufferList->buffer;
|
||||
BufferFreq = Buffer->Frequency;
|
||||
break;
|
||||
}
|
||||
BufferList = BufferList->next;
|
||||
@ -1986,64 +1985,58 @@ static ALvoid GetSourceOffset(ALsource *Source, ALenum name, ALdouble *offset, A
|
||||
return;
|
||||
}
|
||||
|
||||
// Get Current Buffer Size and frequency (in milliseconds)
|
||||
BufferFreq = Buffer->Frequency;
|
||||
OriginalType = Buffer->OriginalType;
|
||||
Channels = ChannelsFromFmt(Buffer->FmtChannels);
|
||||
Bytes = BytesFromFmt(Buffer->FmtType);
|
||||
|
||||
// Get Current BytesPlayed (NOTE : This is the byte offset into the *current* buffer)
|
||||
readPos = Source->position * Channels * Bytes;
|
||||
// Add byte length of any processed buffers in the queue
|
||||
TotalBufferDataSize = 0;
|
||||
// Get Current SamplesPlayed (NOTE : This is the offset into the *current* buffer)
|
||||
readPos = Source->position;
|
||||
// Add length of any processed buffers in the queue
|
||||
totalBufferLen = 0;
|
||||
BufferList = Source->queue;
|
||||
for(i = 0;BufferList;i++)
|
||||
{
|
||||
if(BufferList->buffer)
|
||||
{
|
||||
if(i < Source->BuffersPlayed)
|
||||
readPos += BufferList->buffer->size;
|
||||
TotalBufferDataSize += BufferList->buffer->size;
|
||||
readPos += BufferList->buffer->SampleLen;
|
||||
totalBufferLen += BufferList->buffer->SampleLen;
|
||||
}
|
||||
BufferList = BufferList->next;
|
||||
}
|
||||
if(Source->state == AL_PLAYING)
|
||||
writePos = readPos + ((ALuint)(updateLen*BufferFreq) * Channels * Bytes);
|
||||
writePos = readPos + (ALuint)(updateLen*BufferFreq);
|
||||
else
|
||||
writePos = readPos;
|
||||
|
||||
if(Source->bLooping)
|
||||
{
|
||||
readPos %= TotalBufferDataSize;
|
||||
writePos %= TotalBufferDataSize;
|
||||
readPos %= totalBufferLen;
|
||||
writePos %= totalBufferLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wrap positions back to 0
|
||||
if(readPos >= TotalBufferDataSize)
|
||||
if(readPos >= totalBufferLen)
|
||||
readPos = 0;
|
||||
if(writePos >= TotalBufferDataSize)
|
||||
if(writePos >= totalBufferLen)
|
||||
writePos = 0;
|
||||
}
|
||||
|
||||
switch(name)
|
||||
{
|
||||
case AL_SEC_OFFSET:
|
||||
offset[0] = (ALdouble)readPos / (Channels * Bytes * BufferFreq);
|
||||
offset[1] = (ALdouble)writePos / (Channels * Bytes * BufferFreq);
|
||||
offset[0] = (ALdouble)readPos / Buffer->Frequency;
|
||||
offset[1] = (ALdouble)writePos / Buffer->Frequency;
|
||||
break;
|
||||
case AL_SAMPLE_OFFSET:
|
||||
case AL_SAMPLE_RW_OFFSETS_SOFT:
|
||||
offset[0] = (ALdouble)(readPos / (Channels * Bytes));
|
||||
offset[1] = (ALdouble)(writePos / (Channels * Bytes));
|
||||
offset[0] = (ALdouble)readPos;
|
||||
offset[1] = (ALdouble)writePos;
|
||||
break;
|
||||
case AL_BYTE_OFFSET:
|
||||
case AL_BYTE_RW_OFFSETS_SOFT:
|
||||
// Take into account the original format of the Buffer
|
||||
if(OriginalType == UserFmtIMA4)
|
||||
if(Buffer->OriginalType == UserFmtIMA4)
|
||||
{
|
||||
ALuint FrameBlockSize = 65 * Bytes * Channels;
|
||||
ALuint BlockSize = 36 * Channels;
|
||||
ALuint BlockSize = 36 * ChannelsFromFmt(Buffer->FmtChannels);
|
||||
ALuint FrameBlockSize = 65;
|
||||
|
||||
// Round down to nearest ADPCM block
|
||||
offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
|
||||
@ -2058,9 +2051,9 @@ static ALvoid GetSourceOffset(ALsource *Source, ALenum name, ALdouble *offset, A
|
||||
}
|
||||
else
|
||||
{
|
||||
ALuint OrigBytes = BytesFromUserFmt(OriginalType);
|
||||
offset[0] = (ALdouble)(readPos / Bytes * OrigBytes);
|
||||
offset[1] = (ALdouble)(writePos / Bytes * OrigBytes);
|
||||
ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
|
||||
offset[0] = (ALdouble)(readPos * FrameSize);
|
||||
offset[1] = (ALdouble)(writePos * FrameSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2077,45 +2070,44 @@ ALboolean ApplyOffset(ALsource *Source)
|
||||
{
|
||||
const ALbufferlistitem *BufferList;
|
||||
const ALbuffer *Buffer;
|
||||
ALint lBufferSize, lTotalBufferSize;
|
||||
ALint BuffersPlayed;
|
||||
ALint lByteOffset;
|
||||
ALint bufferLen, totalBufferLen;
|
||||
ALint buffersPlayed;
|
||||
ALint offset;
|
||||
|
||||
// Get true byte offset
|
||||
lByteOffset = GetByteOffset(Source);
|
||||
offset = GetSampleOffset(Source);
|
||||
|
||||
// If the offset is invalid, don't apply it
|
||||
if(lByteOffset == -1)
|
||||
if(offset == -1)
|
||||
return AL_FALSE;
|
||||
|
||||
// Sort out the queue (pending and processed states)
|
||||
BufferList = Source->queue;
|
||||
lTotalBufferSize = 0;
|
||||
BuffersPlayed = 0;
|
||||
totalBufferLen = 0;
|
||||
buffersPlayed = 0;
|
||||
|
||||
while(BufferList)
|
||||
{
|
||||
Buffer = BufferList->buffer;
|
||||
lBufferSize = Buffer ? Buffer->size : 0;
|
||||
bufferLen = Buffer ? Buffer->SampleLen : 0;
|
||||
|
||||
if(lBufferSize <= lByteOffset-lTotalBufferSize)
|
||||
if(bufferLen <= offset-totalBufferLen)
|
||||
{
|
||||
// Offset is past this buffer so increment BuffersPlayed
|
||||
BuffersPlayed++;
|
||||
buffersPlayed++;
|
||||
}
|
||||
else if(lTotalBufferSize <= lByteOffset)
|
||||
else if(totalBufferLen <= offset)
|
||||
{
|
||||
// Offset is within this buffer
|
||||
Source->BuffersPlayed = BuffersPlayed;
|
||||
Source->BuffersPlayed = buffersPlayed;
|
||||
|
||||
// SW Mixer Positions are in Samples
|
||||
Source->position = (lByteOffset - lTotalBufferSize) /
|
||||
FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType);
|
||||
Source->position = offset - totalBufferLen;
|
||||
return AL_TRUE;
|
||||
}
|
||||
|
||||
// Increment the TotalBufferSize
|
||||
lTotalBufferSize += lBufferSize;
|
||||
totalBufferLen += bufferLen;
|
||||
|
||||
// Move on to next buffer in the Queue
|
||||
BufferList = BufferList->next;
|
||||
@ -2126,17 +2118,17 @@ ALboolean ApplyOffset(ALsource *Source)
|
||||
|
||||
|
||||
/*
|
||||
GetByteOffset
|
||||
GetSampleOffset
|
||||
|
||||
Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
|
||||
offset supplied by the application). This takes into account the fact that the buffer format
|
||||
may have been modifed by AL (e.g 8bit samples are converted to float)
|
||||
Returns the sample offset into the Source's queue (from the Sample, Byte or Millisecond offset
|
||||
supplied by the application). This takes into account the fact that the buffer format may have
|
||||
been modifed by AL
|
||||
*/
|
||||
static ALint GetByteOffset(ALsource *Source)
|
||||
static ALint GetSampleOffset(ALsource *Source)
|
||||
{
|
||||
const ALbuffer *Buffer = NULL;
|
||||
const ALbufferlistitem *BufferList;
|
||||
ALint ByteOffset = -1;
|
||||
ALint Offset = -1;
|
||||
|
||||
// Find the first non-NULL Buffer in the Queue
|
||||
BufferList = Source->queue;
|
||||
@ -2161,33 +2153,31 @@ static ALint GetByteOffset(ALsource *Source)
|
||||
{
|
||||
case AL_BYTE_OFFSET:
|
||||
// Take into consideration the original format
|
||||
ByteOffset = Source->lOffset;
|
||||
Offset = Source->lOffset;
|
||||
if(Buffer->OriginalType == UserFmtIMA4)
|
||||
{
|
||||
// Round down to nearest ADPCM block
|
||||
ByteOffset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
|
||||
Offset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
|
||||
// Multiply by compression rate (65 sample frames per block)
|
||||
ByteOffset *= 65;
|
||||
Offset *= 65;
|
||||
}
|
||||
else
|
||||
ByteOffset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
|
||||
ByteOffset *= FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType);
|
||||
Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
|
||||
break;
|
||||
|
||||
case AL_SAMPLE_OFFSET:
|
||||
ByteOffset = Source->lOffset * FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType);
|
||||
Offset = Source->lOffset;
|
||||
break;
|
||||
|
||||
case AL_SEC_OFFSET:
|
||||
// Note - lOffset is internally stored as Milliseconds
|
||||
ByteOffset = (ALint)(Source->lOffset / 1000.0 * Buffer->Frequency);
|
||||
ByteOffset *= FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType);
|
||||
Offset = (ALint)(Source->lOffset / 1000.0 * Buffer->Frequency);
|
||||
break;
|
||||
}
|
||||
// Clear Offset
|
||||
Source->lOffset = -1;
|
||||
|
||||
return ByteOffset;
|
||||
return Offset;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user