diff options
Diffstat (limited to 'OpenAL32/alSource.c')
-rw-r--r-- | OpenAL32/alSource.c | 1314 |
1 files changed, 739 insertions, 575 deletions
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index a580c45c..0d454882 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -13,14 +13,15 @@ * * 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. + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * Or go to http://www.gnu.org/copyleft/lgpl.html */ #include "config.h" #include <stdlib.h> +#include <limits.h> #include <math.h> #include <float.h> @@ -33,328 +34,331 @@ #include "alThunk.h" #include "alAuxEffectSlot.h" -#include "threads.h" - +#include "backends/base.h" -enum Resampler DefaultResampler = LinearResampler; -const ALsizei ResamplerPadding[ResamplerMax] = { - 0, /* Point */ - 1, /* Linear */ - 2, /* Cubic */ -}; -const ALsizei ResamplerPrePadding[ResamplerMax] = { - 0, /* Point */ - 0, /* Linear */ - 1, /* Cubic */ -}; +#include "threads.h" extern inline struct ALsource *LookupSource(ALCcontext *context, ALuint id); extern inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id); static ALvoid InitSourceParams(ALsource *Source); -static ALint64 GetSourceOffset(const ALsource *Source); -static ALdouble GetSourceSecOffset(const ALsource *Source); -static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offsets, ALdouble updateLen); -static ALint GetSampleOffset(ALsource *Source); - -typedef enum SrcFloatProp { - sfPitch = AL_PITCH, - sfGain = AL_GAIN, - sfMinGain = AL_MIN_GAIN, - sfMaxGain = AL_MAX_GAIN, - sfMaxDistance = AL_MAX_DISTANCE, - sfRolloffFactor = AL_ROLLOFF_FACTOR, - sfDopplerFactor = AL_DOPPLER_FACTOR, - sfConeOuterGain = AL_CONE_OUTER_GAIN, - sfSecOffset = AL_SEC_OFFSET, - sfSampleOffset = AL_SAMPLE_OFFSET, - sfByteOffset = AL_BYTE_OFFSET, - sfConeInnerAngle = AL_CONE_INNER_ANGLE, - sfConeOuterAngle = AL_CONE_OUTER_ANGLE, - sfRefDistance = AL_REFERENCE_DISTANCE, - - sfPosition = AL_POSITION, - sfVelocity = AL_VELOCITY, - sfDirection = AL_DIRECTION, - - sfSourceRelative = AL_SOURCE_RELATIVE, - sfLooping = AL_LOOPING, - sfBuffer = AL_BUFFER, - sfSourceState = AL_SOURCE_STATE, - sfBuffersQueued = AL_BUFFERS_QUEUED, - sfBuffersProcessed = AL_BUFFERS_PROCESSED, - sfSourceType = AL_SOURCE_TYPE, +static ALint64 GetSourceSampleOffset(ALsource *Source); +static ALdouble GetSourceSecOffset(ALsource *Source); +static ALvoid GetSourceOffsets(ALsource *Source, ALenum name, ALdouble *offsets, ALdouble updateLen); +static ALboolean GetSampleOffset(ALsource *Source, ALuint *offset, ALuint *frac); + +typedef enum SourceProp { + srcPitch = AL_PITCH, + srcGain = AL_GAIN, + srcMinGain = AL_MIN_GAIN, + srcMaxGain = AL_MAX_GAIN, + srcMaxDistance = AL_MAX_DISTANCE, + srcRolloffFactor = AL_ROLLOFF_FACTOR, + srcDopplerFactor = AL_DOPPLER_FACTOR, + srcConeOuterGain = AL_CONE_OUTER_GAIN, + srcSecOffset = AL_SEC_OFFSET, + srcSampleOffset = AL_SAMPLE_OFFSET, + srcByteOffset = AL_BYTE_OFFSET, + srcConeInnerAngle = AL_CONE_INNER_ANGLE, + srcConeOuterAngle = AL_CONE_OUTER_ANGLE, + srcRefDistance = AL_REFERENCE_DISTANCE, + + srcPosition = AL_POSITION, + srcVelocity = AL_VELOCITY, + srcDirection = AL_DIRECTION, + + srcSourceRelative = AL_SOURCE_RELATIVE, + srcLooping = AL_LOOPING, + srcBuffer = AL_BUFFER, + srcSourceState = AL_SOURCE_STATE, + srcBuffersQueued = AL_BUFFERS_QUEUED, + srcBuffersProcessed = AL_BUFFERS_PROCESSED, + srcSourceType = AL_SOURCE_TYPE, /* ALC_EXT_EFX */ - sfConeOuterGainHF = AL_CONE_OUTER_GAINHF, - sfAirAbsorptionFactor = AL_AIR_ABSORPTION_FACTOR, - sfRoomRolloffFactor = AL_ROOM_ROLLOFF_FACTOR, - sfDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO, - sfAuxSendFilterGainAuto = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO, - sfAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO, + srcConeOuterGainHF = AL_CONE_OUTER_GAINHF, + srcAirAbsorptionFactor = AL_AIR_ABSORPTION_FACTOR, + srcRoomRolloffFactor = AL_ROOM_ROLLOFF_FACTOR, + srcDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO, + srcAuxSendFilterGainAuto = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO, + srcAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO, + srcDirectFilter = AL_DIRECT_FILTER, + srcAuxSendFilter = AL_AUXILIARY_SEND_FILTER, /* AL_SOFT_direct_channels */ - sfDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT, + srcDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT, /* AL_EXT_source_distance_model */ - sfDistanceModel = AL_DISTANCE_MODEL, + srcDistanceModel = AL_DISTANCE_MODEL, - sfSecLength = AL_SEC_LENGTH_SOFT, + srcByteLengthSOFT = AL_BYTE_LENGTH_SOFT, + srcSampleLengthSOFT = AL_SAMPLE_LENGTH_SOFT, + srcSecLengthSOFT = AL_SEC_LENGTH_SOFT, /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */ - sfSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT, - sfByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT, + srcSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT, + srcByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT, /* AL_SOFT_source_latency */ - sfSecOffsetLatencySOFT = AL_SEC_OFFSET_LATENCY_SOFT, -} SrcFloatProp; - -typedef enum SrcIntProp { - siMaxDistance = AL_MAX_DISTANCE, - siRolloffFactor = AL_ROLLOFF_FACTOR, - siRefDistance = AL_REFERENCE_DISTANCE, - siSourceRelative = AL_SOURCE_RELATIVE, - siConeInnerAngle = AL_CONE_INNER_ANGLE, - siConeOuterAngle = AL_CONE_OUTER_ANGLE, - siLooping = AL_LOOPING, - siBuffer = AL_BUFFER, - siSourceState = AL_SOURCE_STATE, - siBuffersQueued = AL_BUFFERS_QUEUED, - siBuffersProcessed = AL_BUFFERS_PROCESSED, - siSourceType = AL_SOURCE_TYPE, - siSecOffset = AL_SEC_OFFSET, - siSampleOffset = AL_SAMPLE_OFFSET, - siByteOffset = AL_BYTE_OFFSET, - siDopplerFactor = AL_DOPPLER_FACTOR, - siPosition = AL_POSITION, - siVelocity = AL_VELOCITY, - siDirection = AL_DIRECTION, - - /* ALC_EXT_EFX */ - siDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO, - siAuxSendFilterGainAutio = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO, - siAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO, - siDirectFilter = AL_DIRECT_FILTER, - siAuxSendFilter = AL_AUXILIARY_SEND_FILTER, - - /* AL_SOFT_direct_channels */ - siDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT, + srcSampleOffsetLatencySOFT = AL_SAMPLE_OFFSET_LATENCY_SOFT, + srcSecOffsetLatencySOFT = AL_SEC_OFFSET_LATENCY_SOFT, - /* AL_EXT_source_distance_model */ - siDistanceModel = AL_DISTANCE_MODEL, - - siByteLength = AL_BYTE_LENGTH_SOFT, - siSampleLength = AL_SAMPLE_LENGTH_SOFT, + /* AL_EXT_BFORMAT */ + srcOrientation = AL_ORIENTATION, +} SourceProp; - /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */ - siSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT, - siByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT, +static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALfloat *values); +static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALint *values); +static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALint64SOFT *values); - /* AL_SOFT_source_latency */ - siSampleOffsetLatencySOFT = AL_SAMPLE_OFFSET_LATENCY_SOFT, -} SrcIntProp; - -static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values); -static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint *values); -static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values); - -static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values); -static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values); -static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values); +static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp prop, ALdouble *values); +static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint *values); +static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint64 *values); static ALint FloatValsByProp(ALenum prop) { - if(prop != (ALenum)((SrcFloatProp)prop)) + if(prop != (ALenum)((SourceProp)prop)) return 0; - switch((SrcFloatProp)prop) + switch((SourceProp)prop) { - case sfPitch: - case sfGain: - case sfMinGain: - case sfMaxGain: - case sfMaxDistance: - case sfRolloffFactor: - case sfDopplerFactor: - case sfConeOuterGain: - case sfSecOffset: - case sfSampleOffset: - case sfByteOffset: - case sfConeInnerAngle: - case sfConeOuterAngle: - case sfRefDistance: - case sfConeOuterGainHF: - case sfAirAbsorptionFactor: - case sfRoomRolloffFactor: - case sfDirectFilterGainHFAuto: - case sfAuxSendFilterGainAuto: - case sfAuxSendFilterGainHFAuto: - case sfDirectChannelsSOFT: - case sfDistanceModel: - case sfSourceRelative: - case sfLooping: - case sfBuffer: - case sfSourceState: - case sfBuffersQueued: - case sfBuffersProcessed: - case sfSourceType: - case sfSecLength: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_MAX_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_REFERENCE_DISTANCE: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_DIRECT_FILTER_GAINHF_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + case AL_DIRECT_CHANNELS_SOFT: + case AL_DISTANCE_MODEL: + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_TYPE: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: return 1; - case sfSampleRWOffsetsSOFT: - case sfByteRWOffsetsSOFT: + case AL_SAMPLE_RW_OFFSETS_SOFT: + case AL_BYTE_RW_OFFSETS_SOFT: return 2; - case sfPosition: - case sfVelocity: - case sfDirection: + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: return 3; - case sfSecOffsetLatencySOFT: + case AL_ORIENTATION: + return 6; + + case AL_SEC_OFFSET_LATENCY_SOFT: break; /* Double only */ + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + break; /* i/i64 only */ + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + break; /* i64 only */ } return 0; } static ALint DoubleValsByProp(ALenum prop) { - if(prop != (ALenum)((SrcFloatProp)prop)) + if(prop != (ALenum)((SourceProp)prop)) return 0; - switch((SrcFloatProp)prop) + switch((SourceProp)prop) { - case sfPitch: - case sfGain: - case sfMinGain: - case sfMaxGain: - case sfMaxDistance: - case sfRolloffFactor: - case sfDopplerFactor: - case sfConeOuterGain: - case sfSecOffset: - case sfSampleOffset: - case sfByteOffset: - case sfConeInnerAngle: - case sfConeOuterAngle: - case sfRefDistance: - case sfConeOuterGainHF: - case sfAirAbsorptionFactor: - case sfRoomRolloffFactor: - case sfDirectFilterGainHFAuto: - case sfAuxSendFilterGainAuto: - case sfAuxSendFilterGainHFAuto: - case sfDirectChannelsSOFT: - case sfDistanceModel: - case sfSourceRelative: - case sfLooping: - case sfBuffer: - case sfSourceState: - case sfBuffersQueued: - case sfBuffersProcessed: - case sfSourceType: - case sfSecLength: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_MAX_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_REFERENCE_DISTANCE: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_DIRECT_FILTER_GAINHF_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + case AL_DIRECT_CHANNELS_SOFT: + case AL_DISTANCE_MODEL: + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_TYPE: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: return 1; - case sfSampleRWOffsetsSOFT: - case sfByteRWOffsetsSOFT: - case sfSecOffsetLatencySOFT: + case AL_SAMPLE_RW_OFFSETS_SOFT: + case AL_BYTE_RW_OFFSETS_SOFT: + case AL_SEC_OFFSET_LATENCY_SOFT: return 2; - case sfPosition: - case sfVelocity: - case sfDirection: + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: return 3; + + case AL_ORIENTATION: + return 6; + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + break; /* i/i64 only */ + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + break; /* i64 only */ } return 0; } static ALint IntValsByProp(ALenum prop) { - if(prop != (ALenum)((SrcIntProp)prop)) + if(prop != (ALenum)((SourceProp)prop)) return 0; - switch((SrcIntProp)prop) + switch((SourceProp)prop) { - case siMaxDistance: - case siRolloffFactor: - case siRefDistance: - case siSourceRelative: - case siConeInnerAngle: - case siConeOuterAngle: - case siLooping: - case siBuffer: - case siSourceState: - case siBuffersQueued: - case siBuffersProcessed: - case siSourceType: - case siSecOffset: - case siSampleOffset: - case siByteOffset: - case siDopplerFactor: - case siDirectFilterGainHFAuto: - case siAuxSendFilterGainAutio: - case siAuxSendFilterGainHFAuto: - case siDirectFilter: - case siDirectChannelsSOFT: - case siDistanceModel: - case siByteLength: - case siSampleLength: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_MAX_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_REFERENCE_DISTANCE: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_DIRECT_FILTER_GAINHF_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + case AL_DIRECT_CHANNELS_SOFT: + case AL_DISTANCE_MODEL: + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_BUFFER: + case AL_SOURCE_STATE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_TYPE: + case AL_DIRECT_FILTER: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: return 1; - case siSampleRWOffsetsSOFT: - case siByteRWOffsetsSOFT: + case AL_SAMPLE_RW_OFFSETS_SOFT: + case AL_BYTE_RW_OFFSETS_SOFT: return 2; - case siPosition: - case siVelocity: - case siDirection: - case siAuxSendFilter: + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + case AL_AUXILIARY_SEND_FILTER: return 3; - case siSampleOffsetLatencySOFT: + case AL_ORIENTATION: + return 6; + + case AL_SAMPLE_OFFSET_LATENCY_SOFT: break; /* i64 only */ + case AL_SEC_OFFSET_LATENCY_SOFT: + break; /* Double only */ } return 0; } static ALint Int64ValsByProp(ALenum prop) { - if(prop != (ALenum)((SrcIntProp)prop)) + if(prop != (ALenum)((SourceProp)prop)) return 0; - switch((SrcIntProp)prop) + switch((SourceProp)prop) { - case siMaxDistance: - case siRolloffFactor: - case siRefDistance: - case siSourceRelative: - case siConeInnerAngle: - case siConeOuterAngle: - case siLooping: - case siBuffer: - case siSourceState: - case siBuffersQueued: - case siBuffersProcessed: - case siSourceType: - case siSecOffset: - case siSampleOffset: - case siByteOffset: - case siDopplerFactor: - case siDirectFilterGainHFAuto: - case siAuxSendFilterGainAutio: - case siAuxSendFilterGainHFAuto: - case siDirectFilter: - case siDirectChannelsSOFT: - case siDistanceModel: - case siByteLength: - case siSampleLength: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_MAX_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_REFERENCE_DISTANCE: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_DIRECT_FILTER_GAINHF_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + case AL_DIRECT_CHANNELS_SOFT: + case AL_DISTANCE_MODEL: + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_BUFFER: + case AL_SOURCE_STATE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_TYPE: + case AL_DIRECT_FILTER: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: return 1; - case siSampleRWOffsetsSOFT: - case siByteRWOffsetsSOFT: - case siSampleOffsetLatencySOFT: + case AL_SAMPLE_RW_OFFSETS_SOFT: + case AL_BYTE_RW_OFFSETS_SOFT: + case AL_SAMPLE_OFFSET_LATENCY_SOFT: return 2; - case siPosition: - case siVelocity: - case siDirection: - case siAuxSendFilter: + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + case AL_AUXILIARY_SEND_FILTER: return 3; + + case AL_ORIENTATION: + return 6; + + case AL_SEC_OFFSET_LATENCY_SOFT: + break; /* Double only */ } return 0; } @@ -365,108 +369,117 @@ static ALint Int64ValsByProp(ALenum prop) SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); \ } while(0) -static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values) +static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALfloat *values) { ALint ival; switch(prop) { + case AL_BYTE_RW_OFFSETS_SOFT: + case AL_SAMPLE_RW_OFFSETS_SOFT: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: + case AL_SEC_OFFSET_LATENCY_SOFT: + /* Query only */ + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); + case AL_PITCH: CHECKVAL(*values >= 0.0f); Source->Pitch = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_INNER_ANGLE: CHECKVAL(*values >= 0.0f && *values <= 360.0f); Source->InnerAngle = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_OUTER_ANGLE: CHECKVAL(*values >= 0.0f && *values <= 360.0f); Source->OuterAngle = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_GAIN: CHECKVAL(*values >= 0.0f); Source->Gain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_MAX_DISTANCE: CHECKVAL(*values >= 0.0f); Source->MaxDistance = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_ROLLOFF_FACTOR: CHECKVAL(*values >= 0.0f); Source->RollOffFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_REFERENCE_DISTANCE: CHECKVAL(*values >= 0.0f); Source->RefDistance = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_MIN_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->MinGain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_MAX_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->MaxGain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_OUTER_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->OuterGain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_OUTER_GAINHF: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->OuterGainHF = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_AIR_ABSORPTION_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 10.0f); Source->AirAbsorptionFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_ROOM_ROLLOFF_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 10.0f); Source->RoomRolloffFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DOPPLER_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->DopplerFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_SEC_OFFSET: @@ -481,100 +494,119 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && !Context->DeferUpdates) { + WriteLock(&Source->queue_lock); if(ApplyOffset(Source) == AL_FALSE) { + WriteUnlock(&Source->queue_lock); UnlockContext(Context); SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); } + WriteUnlock(&Source->queue_lock); } UnlockContext(Context); return AL_TRUE; - case sfSecLength: - case AL_SEC_OFFSET_LATENCY_SOFT: - /* Query only */ - SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); - - case AL_POSITION: CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2])); LockContext(Context); - Source->Position[0] = values[0]; - Source->Position[1] = values[1]; - Source->Position[2] = values[2]; + aluVectorSet(&Source->Position, values[0], values[1], values[2], 1.0f); UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_VELOCITY: CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2])); LockContext(Context); - Source->Velocity[0] = values[0]; - Source->Velocity[1] = values[1]; - Source->Velocity[2] = values[2]; + aluVectorSet(&Source->Velocity, values[0], values[1], values[2], 0.0f); UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DIRECTION: CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2])); LockContext(Context); - Source->Orientation[0] = values[0]; - Source->Orientation[1] = values[1]; - Source->Orientation[2] = values[2]; + aluVectorSet(&Source->Direction, values[0], values[1], values[2], 0.0f); UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; + case AL_ORIENTATION: + CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]) && + isfinite(values[3]) && isfinite(values[4]) && isfinite(values[5])); - case sfSampleRWOffsetsSOFT: - case sfByteRWOffsetsSOFT: - SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); + LockContext(Context); + Source->Orientation[0][0] = values[0]; + Source->Orientation[0][1] = values[1]; + Source->Orientation[0][2] = values[2]; + Source->Orientation[1][0] = values[3]; + Source->Orientation[1][1] = values[4]; + Source->Orientation[1][2] = values[5]; + UnlockContext(Context); + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + return AL_TRUE; - case sfSourceRelative: - case sfLooping: - case sfSourceState: - case sfSourceType: - case sfDistanceModel: - case sfDirectFilterGainHFAuto: - case sfAuxSendFilterGainAuto: - case sfAuxSendFilterGainHFAuto: - case sfDirectChannelsSOFT: + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_SOURCE_TYPE: + case AL_DISTANCE_MODEL: + case AL_DIRECT_FILTER_GAINHF_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + case AL_DIRECT_CHANNELS_SOFT: ival = (ALint)values[0]; - return SetSourceiv(Source, Context, (SrcIntProp)prop, &ival); + return SetSourceiv(Source, Context, prop, &ival); - case sfBuffer: - case sfBuffersQueued: - case sfBuffersProcessed: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: ival = (ALint)((ALuint)values[0]); - return SetSourceiv(Source, Context, (SrcIntProp)prop, &ival); + return SetSourceiv(Source, Context, prop, &ival); + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + break; } ERR("Unexpected property: 0x%04x\n", prop); SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE); } -static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint *values) +static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALint *values) { ALCdevice *device = Context->Device; ALbuffer *buffer = NULL; ALfilter *filter = NULL; ALeffectslot *slot = NULL; ALbufferlistitem *oldlist; - ALfloat fvals[3]; + ALbufferlistitem *newlist; + ALfloat fvals[6]; switch(prop) { + case AL_SOURCE_STATE: + case AL_SOURCE_TYPE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SAMPLE_RW_OFFSETS_SOFT: + case AL_BYTE_RW_OFFSETS_SOFT: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: + /* Query only */ + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); + case AL_SOURCE_RELATIVE: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->HeadRelative = (ALboolean)*values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_LOOPING: @@ -595,18 +627,15 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p if(buffer != NULL) { - ALbufferlistitem *BufferListItem; - /* Add the selected buffer to a one-item queue */ - BufferListItem = malloc(sizeof(ALbufferlistitem)); - BufferListItem->buffer = buffer; - BufferListItem->next = NULL; - BufferListItem->prev = NULL; + newlist = malloc(sizeof(ALbufferlistitem)); + newlist->buffer = buffer; + newlist->next = NULL; + newlist->prev = NULL; IncrementRef(&buffer->ref); /* Source is now Static */ Source->SourceType = AL_STATIC; - oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem); ReadLock(&buffer->lock); Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels); @@ -617,9 +646,10 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p { /* Source is now Undetermined */ Source->SourceType = AL_UNDETERMINED; - oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL); + newlist = NULL; } - Source->current_buffer = Source->queue; + oldlist = ATOMIC_EXCHANGE(ALbufferlistitem*, &Source->queue, newlist); + ATOMIC_STORE(&Source->current_buffer, newlist); WriteUnlock(&Source->queue_lock); /* Delete all elements in the previous queue */ @@ -634,13 +664,6 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p } return AL_TRUE; - case siSourceState: - case siSourceType: - case siBuffersQueued: - case siBuffersProcessed: - /* Query only */ - SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); - case AL_SEC_OFFSET: case AL_SAMPLE_OFFSET: case AL_BYTE_OFFSET: @@ -653,24 +676,18 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && !Context->DeferUpdates) { + WriteLock(&Source->queue_lock); if(ApplyOffset(Source) == AL_FALSE) { + WriteUnlock(&Source->queue_lock); UnlockContext(Context); SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); } + WriteUnlock(&Source->queue_lock); } UnlockContext(Context); return AL_TRUE; - - case siByteLength: - case siSampleLength: - case siSampleRWOffsetsSOFT: - case siByteRWOffsetsSOFT: - /* Query only */ - SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); - - case AL_DIRECT_FILTER: CHECKVAL(*values == 0 || (filter=LookupFilter(device, *values)) != NULL); @@ -692,35 +709,35 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p Source->Direct.LFReference = filter->LFReference; } UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DIRECT_FILTER_GAINHF_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->DryGainHFAuto = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->WetGainAuto = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->WetGainHFAuto = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DIRECT_CHANNELS_SOFT: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->DirectChannels = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DISTANCE_MODEL: @@ -734,7 +751,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p Source->DistanceModel = *values; if(Context->SourceDistanceModel) - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; @@ -770,20 +787,30 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p Source->Send[values[1]].GainLF = filter->GainLF; Source->Send[values[1]].LFReference = filter->LFReference; } - Source->NeedsUpdate = AL_TRUE; UnlockContext(Context); + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; - case AL_MAX_DISTANCE: - case AL_ROLLOFF_FACTOR: + /* 1x float */ case AL_CONE_INNER_ANGLE: case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: case AL_REFERENCE_DISTANCE: - case siDopplerFactor: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: fvals[0] = (ALfloat)*values; return SetSourcefv(Source, Context, (int)prop, fvals); + /* 3x float */ case AL_POSITION: case AL_VELOCITY: case AL_DIRECTION: @@ -792,8 +819,18 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p fvals[2] = (ALfloat)values[2]; return SetSourcefv(Source, Context, (int)prop, fvals); - case siSampleOffsetLatencySOFT: - /* i64 only */ + /* 6x float */ + case AL_ORIENTATION: + fvals[0] = (ALfloat)values[0]; + fvals[1] = (ALfloat)values[1]; + fvals[2] = (ALfloat)values[2]; + fvals[3] = (ALfloat)values[3]; + fvals[4] = (ALfloat)values[4]; + fvals[5] = (ALfloat)values[5]; + return SetSourcefv(Source, Context, (int)prop, fvals); + + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + case AL_SEC_OFFSET_LATENCY_SOFT: break; } @@ -801,16 +838,23 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE); } -static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values) +static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALint64SOFT *values) { - ALfloat fvals[3]; + ALfloat fvals[6]; ALint ivals[3]; switch(prop) { - case siSampleRWOffsetsSOFT: - case siByteRWOffsetsSOFT: - case siSampleOffsetLatencySOFT: + case AL_SOURCE_TYPE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_STATE: + case AL_SAMPLE_RW_OFFSETS_SOFT: + case AL_BYTE_RW_OFFSETS_SOFT: + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: /* Query only */ SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); @@ -818,14 +862,9 @@ static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp /* 1x int */ case AL_SOURCE_RELATIVE: case AL_LOOPING: - case AL_SOURCE_STATE: - case AL_BYTE_OFFSET: + case AL_SEC_OFFSET: case AL_SAMPLE_OFFSET: - case siByteLength: - case siSampleLength: - case siSourceType: - case siBuffersQueued: - case siBuffersProcessed: + case AL_BYTE_OFFSET: case AL_DIRECT_FILTER_GAINHF_AUTO: case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: @@ -856,13 +895,20 @@ static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp return SetSourceiv(Source, Context, (int)prop, ivals); /* 1x float */ - case AL_MAX_DISTANCE: - case AL_ROLLOFF_FACTOR: case AL_CONE_INNER_ANGLE: case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: case AL_REFERENCE_DISTANCE: - case AL_SEC_OFFSET: - case siDopplerFactor: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: fvals[0] = (ALfloat)*values; return SetSourcefv(Source, Context, (int)prop, fvals); @@ -874,6 +920,19 @@ static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp fvals[1] = (ALfloat)values[1]; fvals[2] = (ALfloat)values[2]; return SetSourcefv(Source, Context, (int)prop, fvals); + + /* 6x float */ + case AL_ORIENTATION: + fvals[0] = (ALfloat)values[0]; + fvals[1] = (ALfloat)values[1]; + fvals[2] = (ALfloat)values[2]; + fvals[3] = (ALfloat)values[3]; + fvals[4] = (ALfloat)values[4]; + fvals[5] = (ALfloat)values[5]; + return SetSourcefv(Source, Context, (int)prop, fvals); + + case AL_SEC_OFFSET_LATENCY_SOFT: + break; } ERR("Unexpected property: 0x%04x\n", prop); @@ -883,8 +942,9 @@ static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp #undef CHECKVAL -static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values) +static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp prop, ALdouble *values) { + ALCdevice *device = Context->Device; ALbufferlistitem *BufferList; ALdouble offsets[2]; ALdouble updateLen; @@ -936,11 +996,9 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp case AL_SEC_OFFSET: case AL_SAMPLE_OFFSET: case AL_BYTE_OFFSET: - ReadLock(&Source->queue_lock); LockContext(Context); GetSourceOffsets(Source, prop, offsets, 0.0); UnlockContext(Context); - ReadUnlock(&Source->queue_lock); *values = offsets[0]; return AL_TRUE; @@ -960,9 +1018,9 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp *values = Source->DopplerFactor; return AL_TRUE; - case sfSecLength: + case AL_SEC_LENGTH_SOFT: ReadLock(&Source->queue_lock); - if(!(BufferList=Source->queue)) + if(!(BufferList=ATOMIC_LOAD(&Source->queue))) *values = 0; else { @@ -983,52 +1041,58 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp case AL_SAMPLE_RW_OFFSETS_SOFT: case AL_BYTE_RW_OFFSETS_SOFT: - ReadLock(&Source->queue_lock); LockContext(Context); - updateLen = (ALdouble)Context->Device->UpdateSize / - Context->Device->Frequency; + updateLen = (ALdouble)device->UpdateSize / device->Frequency; GetSourceOffsets(Source, prop, values, updateLen); UnlockContext(Context); - ReadUnlock(&Source->queue_lock); return AL_TRUE; case AL_SEC_OFFSET_LATENCY_SOFT: - ReadLock(&Source->queue_lock); LockContext(Context); values[0] = GetSourceSecOffset(Source); - values[1] = (ALdouble)ALCdevice_GetLatency(Context->Device) / + values[1] = (ALdouble)(V0(device->Backend,getLatency)()) / 1000000000.0; UnlockContext(Context); - ReadUnlock(&Source->queue_lock); return AL_TRUE; case AL_POSITION: LockContext(Context); - values[0] = Source->Position[0]; - values[1] = Source->Position[1]; - values[2] = Source->Position[2]; + values[0] = Source->Position.v[0]; + values[1] = Source->Position.v[1]; + values[2] = Source->Position.v[2]; UnlockContext(Context); return AL_TRUE; case AL_VELOCITY: LockContext(Context); - values[0] = Source->Velocity[0]; - values[1] = Source->Velocity[1]; - values[2] = Source->Velocity[2]; + values[0] = Source->Velocity.v[0]; + values[1] = Source->Velocity.v[1]; + values[2] = Source->Velocity.v[2]; UnlockContext(Context); return AL_TRUE; case AL_DIRECTION: LockContext(Context); - values[0] = Source->Orientation[0]; - values[1] = Source->Orientation[1]; - values[2] = Source->Orientation[2]; + values[0] = Source->Direction.v[0]; + values[1] = Source->Direction.v[1]; + values[2] = Source->Direction.v[2]; UnlockContext(Context); return AL_TRUE; + case AL_ORIENTATION: + LockContext(Context); + values[0] = Source->Orientation[0][0]; + values[1] = Source->Orientation[0][1]; + values[2] = Source->Orientation[0][2]; + values[3] = Source->Orientation[1][0]; + values[4] = Source->Orientation[1][1]; + values[5] = Source->Orientation[1][2]; + UnlockContext(Context); + return AL_TRUE; + + /* 1x int */ case AL_SOURCE_RELATIVE: case AL_LOOPING: - case AL_BUFFER: case AL_SOURCE_STATE: case AL_BUFFERS_QUEUED: case AL_BUFFERS_PROCESSED: @@ -1037,20 +1101,28 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: case AL_DIRECT_CHANNELS_SOFT: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: case AL_DISTANCE_MODEL: if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE) *values = (ALdouble)ivals[0]; return err; + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + break; } ERR("Unexpected property: 0x%04x\n", prop); SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE); } -static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values) +static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint *values) { ALbufferlistitem *BufferList; - ALdouble dvals[3]; + ALdouble dvals[6]; ALboolean err; switch(prop) @@ -1065,8 +1137,8 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p case AL_BUFFER: ReadLock(&Source->queue_lock); - BufferList = (Source->SourceType == AL_STATIC) ? Source->queue : - Source->current_buffer; + BufferList = (Source->SourceType == AL_STATIC) ? ATOMIC_LOAD(&Source->queue) : + ATOMIC_LOAD(&Source->current_buffer); *values = (BufferList && BufferList->buffer) ? BufferList->buffer->id : 0; ReadUnlock(&Source->queue_lock); return AL_TRUE; @@ -1075,9 +1147,9 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p *values = Source->state; return AL_TRUE; - case siByteLength: + case AL_BYTE_LENGTH_SOFT: ReadLock(&Source->queue_lock); - if(!(BufferList=Source->queue)) + if(!(BufferList=ATOMIC_LOAD(&Source->queue))) *values = 0; else { @@ -1114,9 +1186,9 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p ReadUnlock(&Source->queue_lock); return AL_TRUE; - case siSampleLength: + case AL_SAMPLE_LENGTH_SOFT: ReadLock(&Source->queue_lock); - if(!(BufferList=Source->queue)) + if(!(BufferList=ATOMIC_LOAD(&Source->queue))) *values = 0; else { @@ -1132,7 +1204,7 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p case AL_BUFFERS_QUEUED: ReadLock(&Source->queue_lock); - if(!(BufferList=Source->queue)) + if(!(BufferList=ATOMIC_LOAD(&Source->queue))) *values = 0; else { @@ -1155,9 +1227,10 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p } else { - const ALbufferlistitem *BufferList = Source->queue; + const ALbufferlistitem *BufferList = ATOMIC_LOAD(&Source->queue); + const ALbufferlistitem *Current = ATOMIC_LOAD(&Source->current_buffer); ALsizei played = 0; - while(BufferList && BufferList != Source->current_buffer) + while(BufferList && BufferList != Current) { played++; BufferList = BufferList->next; @@ -1191,32 +1264,44 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p *values = Source->DistanceModel; return AL_TRUE; - case AL_MAX_DISTANCE: - case AL_ROLLOFF_FACTOR: - case AL_REFERENCE_DISTANCE: + /* 1x float/double */ case AL_CONE_INNER_ANGLE: case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: case AL_SEC_OFFSET: case AL_SAMPLE_OFFSET: case AL_BYTE_OFFSET: case AL_DOPPLER_FACTOR: - if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE) + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_SEC_LENGTH_SOFT: + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) *values = (ALint)dvals[0]; return err; + /* 2x float/double */ case AL_SAMPLE_RW_OFFSETS_SOFT: case AL_BYTE_RW_OFFSETS_SOFT: - if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE) + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) { values[0] = (ALint)dvals[0]; values[1] = (ALint)dvals[1]; } return err; + /* 3x float/double */ case AL_POSITION: case AL_VELOCITY: case AL_DIRECTION: - if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE) + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) { values[0] = (ALint)dvals[0]; values[1] = (ALint)dvals[1]; @@ -1224,101 +1309,144 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p } return err; - case siSampleOffsetLatencySOFT: - /* i64 only */ - break; + /* 6x float/double */ + case AL_ORIENTATION: + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) + { + values[0] = (ALint)dvals[0]; + values[1] = (ALint)dvals[1]; + values[2] = (ALint)dvals[2]; + values[3] = (ALint)dvals[3]; + values[4] = (ALint)dvals[4]; + values[5] = (ALint)dvals[5]; + } + return err; - case siDirectFilter: - case siAuxSendFilter: - /* ??? */ - break; + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + break; /* i64 only */ + case AL_SEC_OFFSET_LATENCY_SOFT: + break; /* Double only */ + + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + break; /* ??? */ } ERR("Unexpected property: 0x%04x\n", prop); SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE); } -static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values) +static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint64 *values) { - ALdouble dvals[3]; + ALCdevice *device = Context->Device; + ALdouble dvals[6]; ALint ivals[3]; ALboolean err; switch(prop) { case AL_SAMPLE_OFFSET_LATENCY_SOFT: - ReadLock(&Source->queue_lock); LockContext(Context); - values[0] = GetSourceOffset(Source); - values[1] = ALCdevice_GetLatency(Context->Device); + values[0] = GetSourceSampleOffset(Source); + values[1] = V0(device->Backend,getLatency)(); UnlockContext(Context); - ReadUnlock(&Source->queue_lock); return AL_TRUE; - case AL_MAX_DISTANCE: - case AL_ROLLOFF_FACTOR: - case AL_REFERENCE_DISTANCE: + /* 1x float/double */ case AL_CONE_INNER_ANGLE: case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: case AL_SEC_OFFSET: case AL_SAMPLE_OFFSET: case AL_BYTE_OFFSET: case AL_DOPPLER_FACTOR: - if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE) + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_SEC_LENGTH_SOFT: + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) *values = (ALint64)dvals[0]; return err; + /* 2x float/double */ case AL_SAMPLE_RW_OFFSETS_SOFT: case AL_BYTE_RW_OFFSETS_SOFT: - if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE) + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) { values[0] = (ALint64)dvals[0]; values[1] = (ALint64)dvals[1]; } return err; + /* 3x float/double */ case AL_POSITION: case AL_VELOCITY: case AL_DIRECTION: - if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE) + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) + { + values[0] = (ALint64)dvals[0]; + values[1] = (ALint64)dvals[1]; + values[2] = (ALint64)dvals[2]; + } + return err; + + /* 6x float/double */ + case AL_ORIENTATION: + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) { values[0] = (ALint64)dvals[0]; values[1] = (ALint64)dvals[1]; values[2] = (ALint64)dvals[2]; + values[3] = (ALint64)dvals[3]; + values[4] = (ALint64)dvals[4]; + values[5] = (ALint64)dvals[5]; } return err; + /* 1x int */ case AL_SOURCE_RELATIVE: case AL_LOOPING: case AL_SOURCE_STATE: case AL_BUFFERS_QUEUED: case AL_BUFFERS_PROCESSED: - case siByteLength: - case siSampleLength: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: case AL_SOURCE_TYPE: case AL_DIRECT_FILTER_GAINHF_AUTO: case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: case AL_DIRECT_CHANNELS_SOFT: case AL_DISTANCE_MODEL: - if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE) + if((err=GetSourceiv(Source, Context, prop, ivals)) != AL_FALSE) *values = ivals[0]; return err; - case siBuffer: - case siDirectFilter: - if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE) - *values = ((ALuint*)ivals)[0]; + /* 1x uint */ + case AL_BUFFER: + case AL_DIRECT_FILTER: + if((err=GetSourceiv(Source, Context, prop, ivals)) != AL_FALSE) + *values = (ALuint)ivals[0]; return err; - case siAuxSendFilter: - if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE) + /* 3x uint */ + case AL_AUXILIARY_SEND_FILTER: + if((err=GetSourceiv(Source, Context, prop, ivals)) != AL_FALSE) { - values[0] = ((ALuint*)ivals)[0]; - values[1] = ((ALuint*)ivals)[1]; - values[2] = ((ALuint*)ivals)[2]; + values[0] = (ALuint)ivals[0]; + values[1] = (ALuint)ivals[1]; + values[2] = (ALuint)ivals[2]; } return err; + + case AL_SEC_OFFSET_LATENCY_SOFT: + break; /* Double only */ } ERR("Unexpected property: 0x%04x\n", prop); @@ -1389,37 +1517,32 @@ AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) } for(i = 0;i < n;i++) { - ALactivesource **srclist, **srclistend; + ALvoice *voice, *voice_end; if((Source=RemoveSource(context, sources[i])) == NULL) continue; FreeThunkEntry(Source->id); LockContext(context); - srclist = context->ActiveSources; - srclistend = srclist + context->ActiveSourceCount; - while(srclist != srclistend) + voice = context->Voices; + voice_end = voice + context->VoiceCount; + while(voice != voice_end) { - if((*srclist)->Source == Source) - { - ALactivesource *temp = *(--srclistend); - *srclistend = *srclist; - *srclist = temp; - --(context->ActiveSourceCount); + ALsource *old = Source; + if(COMPARE_EXCHANGE(&voice->Source, &old, NULL)) break; - } - srclist++; + voice++; } UnlockContext(context); - while(Source->queue != NULL) + BufferList = ATOMIC_EXCHANGE(ALbufferlistitem*, &Source->queue, NULL); + while(BufferList != NULL) { - BufferList = Source->queue; - Source->queue = BufferList->next; - + ALbufferlistitem *next = BufferList->next; if(BufferList->buffer != NULL) DecrementRef(&BufferList->buffer->ref); free(BufferList); + BufferList = next; } for(j = 0;j < MAX_SENDS;++j) @@ -1569,11 +1692,11 @@ AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdo alSetError(Context, AL_INVALID_NAME); else if(!values) alSetError(Context, AL_INVALID_VALUE); - else if(!((count=DoubleValsByProp(param)) > 0 && count <= 3)) + else if(!((count=DoubleValsByProp(param)) > 0 && count <= 6)) alSetError(Context, AL_INVALID_ENUM); else { - ALfloat fvals[3]; + ALfloat fvals[6]; ALint i; for(i = 0;i < count;i++) @@ -1772,11 +1895,11 @@ AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *va alSetError(Context, AL_INVALID_NAME); else if(!values) alSetError(Context, AL_INVALID_VALUE); - else if(!((count=FloatValsByProp(param)) > 0 && count <= 3)) + else if(!((count=FloatValsByProp(param)) > 0 && count <= 6)) alSetError(Context, AL_INVALID_ENUM); else { - ALdouble dvals[3]; + ALdouble dvals[6]; if(GetSourcedv(Source, Context, param, dvals)) { ALint i; @@ -2020,25 +2143,23 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) } LockContext(context); - while(n > context->MaxActiveSources-context->ActiveSourceCount) + while(n > context->MaxVoices-context->VoiceCount) { - ALactivesource **temp = NULL; + ALvoice *temp = NULL; ALsizei newcount; - newcount = context->MaxActiveSources << 1; + newcount = context->MaxVoices << 1; if(newcount > 0) - temp = realloc(context->ActiveSources, - newcount * sizeof(context->ActiveSources[0])); + temp = realloc(context->Voices, newcount * sizeof(context->Voices[0])); if(!temp) { UnlockContext(context); SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done); } - for(i = context->MaxActiveSources;i < newcount;i++) - temp[i] = NULL; + memset(&temp[context->MaxVoices], 0, (newcount-context->MaxVoices) * sizeof(temp[0])); - context->ActiveSources = temp; - context->MaxActiveSources = newcount; + context->Voices = temp; + context->MaxVoices = newcount; } for(i = 0;i < n;i++) @@ -2188,7 +2309,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu } /* Check for a valid Buffer, for its frequency and format */ - BufferList = source->queue; + BufferList = ATOMIC_LOAD(&source->queue); while(BufferList) { if(BufferList->buffer) @@ -2276,7 +2397,8 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu /* Source is now streaming */ source->SourceType = AL_STREAMING; - if((BufferList=CompExchangePtr((XchgPtr*)&source->queue, NULL, BufferListStart)) != NULL) + BufferList = NULL; + if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem*, &source->queue, &BufferList, BufferListStart)) { /* Queue head is not NULL, append to the end of the queue */ while(BufferList->next != NULL) @@ -2285,7 +2407,8 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu BufferListStart->prev = BufferList; BufferList->next = BufferListStart; } - CompExchangePtr((XchgPtr*)&source->current_buffer, NULL, BufferListStart); + BufferList = NULL; + ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem*, &source->current_buffer, &BufferList, BufferListStart); WriteUnlock(&source->queue_lock); done: @@ -2296,8 +2419,9 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint { ALCcontext *context; ALsource *source; - ALbufferlistitem *BufferList; + ALbufferlistitem *NewHead; ALbufferlistitem *OldHead; + ALbufferlistitem *Current; ALsizei i; if(nb == 0) @@ -2314,12 +2438,13 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint WriteLock(&source->queue_lock); /* Find the new buffer queue head */ - BufferList = source->queue; - for(i = 0;i < nb && BufferList;i++) + NewHead = ATOMIC_LOAD(&source->queue); + Current = ATOMIC_LOAD(&source->current_buffer); + for(i = 0;i < nb && NewHead;i++) { - if(BufferList == source->current_buffer) + if(NewHead == Current) break; - BufferList = BufferList->next; + NewHead = NewHead->next; } if(source->Looping || source->SourceType != AL_STREAMING || i != nb) { @@ -2329,23 +2454,24 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint } /* Swap it, and cut the new head from the old. */ - OldHead = ExchangePtr((XchgPtr*)&source->queue, BufferList); - if(BufferList) + OldHead = ATOMIC_EXCHANGE(ALbufferlistitem*, &source->queue, NewHead); + if(NewHead) { ALCdevice *device = context->Device; + ALbufferlistitem *OldTail = NewHead->prev; uint count; /* Cut the new head's link back to the old body. The mixer is robust * enough to handle the link back going away. Once the active mix (if * any) is complete, it's safe to finish cutting the old tail from the * new head. */ - BufferList = ExchangePtr((XchgPtr*)&BufferList->prev, NULL); + NewHead->prev = NULL; if(((count=ReadRef(&device->MixCount))&1) != 0) { while(count == ReadRef(&device->MixCount)) althrd_yield(); } - BufferList->next = NULL; + OldTail->next = NULL; } WriteUnlock(&source->queue_lock); @@ -2380,15 +2506,15 @@ static ALvoid InitSourceParams(ALsource *Source) Source->InnerAngle = 360.0f; Source->OuterAngle = 360.0f; Source->Pitch = 1.0f; - Source->Position[0] = 0.0f; - Source->Position[1] = 0.0f; - Source->Position[2] = 0.0f; - Source->Orientation[0] = 0.0f; - Source->Orientation[1] = 0.0f; - Source->Orientation[2] = 0.0f; - Source->Velocity[0] = 0.0f; - Source->Velocity[1] = 0.0f; - Source->Velocity[2] = 0.0f; + aluVectorSet(&Source->Position, 0.0f, 0.0f, 0.0f, 1.0f); + aluVectorSet(&Source->Velocity, 0.0f, 0.0f, 0.0f, 0.0f); + aluVectorSet(&Source->Direction, 0.0f, 0.0f, 0.0f, 0.0f); + Source->Orientation[0][0] = 0.0f; + Source->Orientation[0][1] = 0.0f; + Source->Orientation[0][2] = -1.0f; + Source->Orientation[1][0] = 0.0f; + Source->Orientation[1][1] = 1.0f; + Source->Orientation[1][2] = 0.0f; Source->RefDistance = 1.0f; Source->MaxDistance = FLT_MAX; Source->RollOffFactor = 1.0f; @@ -2407,17 +2533,17 @@ static ALvoid InitSourceParams(ALsource *Source) Source->DopplerFactor = 1.0f; Source->DirectChannels = AL_FALSE; - Source->DistanceModel = DefaultDistanceModel; + Source->Radius = 0.0f; - Source->Resampler = DefaultResampler; + Source->DistanceModel = DefaultDistanceModel; Source->state = AL_INITIAL; Source->new_state = AL_NONE; Source->SourceType = AL_UNDETERMINED; Source->Offset = -1.0; - Source->queue = NULL; - Source->current_buffer = NULL; + ATOMIC_INIT(&Source->queue, NULL); + ATOMIC_INIT(&Source->current_buffer, NULL); Source->Direct.Gain = 1.0f; Source->Direct.GainHF = 1.0f; @@ -2433,7 +2559,7 @@ static ALvoid InitSourceParams(ALsource *Source) Source->Send[i].LFReference = HIGHPASSFREQREF; } - Source->NeedsUpdate = AL_TRUE; + ATOMIC_INIT(&Source->NeedsUpdate, AL_TRUE); } @@ -2443,17 +2569,18 @@ static ALvoid InitSourceParams(ALsource *Source) */ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) { - ReadLock(&Source->queue_lock); + WriteLock(&Source->queue_lock); if(state == AL_PLAYING) { ALCdevice *device = Context->Device; ALbufferlistitem *BufferList; - ALactivesource *src = NULL; - ALsizei j, k; + ALboolean discontinuity; + ALvoice *voice = NULL; + ALsizei i; /* Check that there is a queue containing at least one valid, non zero * length Buffer. */ - BufferList = Source->queue; + BufferList = ATOMIC_LOAD(&Source->queue); while(BufferList) { ALbuffer *buffer; @@ -2467,68 +2594,80 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) Source->state = AL_PLAYING; Source->position = 0; Source->position_fraction = 0; - Source->current_buffer = BufferList; + ATOMIC_STORE(&Source->current_buffer, BufferList); + discontinuity = AL_TRUE; } else + { Source->state = AL_PLAYING; + discontinuity = AL_FALSE; + } // Check if an Offset has been set if(Source->Offset >= 0.0) + { ApplyOffset(Source); + /* discontinuity = AL_TRUE;??? */ + } /* If there's nothing to play, or device is disconnected, go right to * stopped */ if(!BufferList || !device->Connected) goto do_stop; - for(j = 0;j < Context->ActiveSourceCount;j++) + /* Make sure this source isn't already active, while looking for an + * unused active source slot to put it in. */ + for(i = 0;i < Context->VoiceCount;i++) { - if(Context->ActiveSources[j]->Source == Source) + ALsource *old = Source; + if(COMPARE_EXCHANGE(&Context->Voices[i].Source, &old, NULL)) { - src = Context->ActiveSources[j]; + if(voice == NULL) + { + voice = &Context->Voices[i]; + voice->Source = Source; + } break; } + old = NULL; + if(voice == NULL && COMPARE_EXCHANGE(&Context->Voices[i].Source, &old, Source)) + voice = &Context->Voices[i]; } - if(src == NULL) + if(voice == NULL) { - src = Context->ActiveSources[Context->ActiveSourceCount]; - if(src == NULL) - { - src = al_malloc(16, sizeof(src[0])); - Context->ActiveSources[Context->ActiveSourceCount] = src; - } - memset(src, 0, sizeof(*src)); - - src->Source = Source; - if(BufferList->buffer->FmtChannels == FmtMono) - src->Update = CalcSourceParams; - else - src->Update = CalcNonAttnSourceParams; - Context->ActiveSourceCount++; + voice = &Context->Voices[Context->VoiceCount++]; + voice->Source = Source; } - else - { - ALuint i; - src->Direct.Moving = AL_FALSE; - src->Direct.Counter = 0; - for(j = 0;j < MAX_INPUT_CHANNELS;j++) - { - for(k = 0;k < SRC_HISTORY_LENGTH;k++) - src->Direct.Mix.Hrtf.State[j].History[k] = 0.0f; - for(k = 0;k < HRIR_LENGTH;k++) - { - src->Direct.Mix.Hrtf.State[j].Values[k][0] = 0.0f; - src->Direct.Mix.Hrtf.State[j].Values[k][1] = 0.0f; - } - } - for(i = 0;i < device->NumAuxSends;i++) + /* Clear previous samples if playback is discontinuous. */ + if(discontinuity) + memset(voice->PrevSamples, 0, sizeof(voice->PrevSamples)); + + voice->Direct.Moving = AL_FALSE; + voice->Direct.Counter = 0; + for(i = 0;i < MAX_INPUT_CHANNELS;i++) + { + ALsizei j; + for(j = 0;j < HRTF_HISTORY_LENGTH;j++) + voice->Direct.Hrtf[i].State.History[j] = 0.0f; + for(j = 0;j < HRIR_LENGTH;j++) { - src->Send[i].Counter = 0; - src->Send[i].Moving = AL_FALSE; + voice->Direct.Hrtf[i].State.Values[j][0] = 0.0f; + voice->Direct.Hrtf[i].State.Values[j][1] = 0.0f; } } - Source->NeedsUpdate = AL_TRUE; + for(i = 0;i < (ALsizei)device->NumAuxSends;i++) + { + voice->Send[i].Moving = AL_FALSE; + voice->Send[i].Counter = 0; + } + + if(BufferList->buffer->FmtChannels == FmtMono) + voice->Update = CalcSourceParams; + else + voice->Update = CalcNonAttnSourceParams; + + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); } else if(state == AL_PAUSED) { @@ -2541,7 +2680,7 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) if(Source->state != AL_INITIAL) { Source->state = AL_STOPPED; - Source->current_buffer = NULL; + ATOMIC_STORE(&Source->current_buffer, NULL); } Source->Offset = -1.0; } @@ -2552,39 +2691,46 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) Source->state = AL_INITIAL; Source->position = 0; Source->position_fraction = 0; - Source->current_buffer = Source->queue; + ATOMIC_STORE(&Source->current_buffer, ATOMIC_LOAD(&Source->queue)); } Source->Offset = -1.0; } - ReadUnlock(&Source->queue_lock); + WriteUnlock(&Source->queue_lock); } -/* GetSourceOffset +/* GetSourceSampleOffset * * Gets the current read offset for the given Source, in 32.32 fixed-point * samples. The offset is relative to the start of the queue (not the start of * the current buffer). */ -static ALint64 GetSourceOffset(const ALsource *Source) +ALint64 GetSourceSampleOffset(ALsource *Source) { const ALbufferlistitem *BufferList; + const ALbufferlistitem *Current; ALuint64 readPos; + ReadLock(&Source->queue_lock); if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) + { + ReadUnlock(&Source->queue_lock); return 0; + } /* NOTE: This is the offset into the *current* buffer, so add the length of * any played buffers */ readPos = (ALuint64)Source->position << 32; readPos |= (ALuint64)Source->position_fraction << (32-FRACTIONBITS); - BufferList = Source->queue; - while(BufferList && BufferList != Source->current_buffer) + BufferList = ATOMIC_LOAD(&Source->queue); + Current = ATOMIC_LOAD(&Source->current_buffer); + while(BufferList && BufferList != Current) { if(BufferList->buffer) readPos += (ALuint64)BufferList->buffer->SampleLen << 32; BufferList = BufferList->next; } + ReadUnlock(&Source->queue_lock); return (ALint64)minu64(readPos, U64(0x7fffffffffffffff)); } @@ -2593,21 +2739,27 @@ static ALint64 GetSourceOffset(const ALsource *Source) * Gets the current read offset for the given Source, in seconds. The offset is * relative to the start of the queue (not the start of the current buffer). */ -static ALdouble GetSourceSecOffset(const ALsource *Source) +static ALdouble GetSourceSecOffset(ALsource *Source) { const ALbufferlistitem *BufferList; + const ALbufferlistitem *Current; const ALbuffer *Buffer = NULL; ALuint64 readPos; + ReadLock(&Source->queue_lock); if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) + { + ReadUnlock(&Source->queue_lock); return 0.0; + } /* NOTE: This is the offset into the *current* buffer, so add the length of * any played buffers */ readPos = (ALuint64)Source->position << FRACTIONBITS; readPos |= (ALuint64)Source->position_fraction; - BufferList = Source->queue; - while(BufferList && BufferList != Source->current_buffer) + BufferList = ATOMIC_LOAD(&Source->queue); + Current = ATOMIC_LOAD(&Source->current_buffer); + while(BufferList && BufferList != Current) { const ALbuffer *buffer = BufferList->buffer; if(buffer != NULL) @@ -2625,6 +2777,7 @@ static ALdouble GetSourceSecOffset(const ALsource *Source) } assert(Buffer != NULL); + ReadUnlock(&Source->queue_lock); return (ALdouble)readPos / (ALdouble)FRACTIONONE / (ALdouble)Buffer->Frequency; } @@ -2634,18 +2787,21 @@ static ALdouble GetSourceSecOffset(const ALsource *Source) * appropriate format (Bytes, Samples or Seconds). The offsets are relative to * the start of the queue (not the start of the current buffer). */ -static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen) +static ALvoid GetSourceOffsets(ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen) { const ALbufferlistitem *BufferList; + const ALbufferlistitem *Current; const ALbuffer *Buffer = NULL; ALboolean readFin = AL_FALSE; - ALuint readPos, writePos; + ALuint readPos, readPosFrac, writePos; ALuint totalBufferLen; + ReadLock(&Source->queue_lock); if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) { offset[0] = 0.0; offset[1] = 0.0; + ReadUnlock(&Source->queue_lock); return; } @@ -2656,11 +2812,13 @@ static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *of * any played buffers */ totalBufferLen = 0; readPos = Source->position; - BufferList = Source->queue; + readPosFrac = Source->position_fraction; + BufferList = ATOMIC_LOAD(&Source->queue); + Current = ATOMIC_LOAD(&Source->current_buffer); while(BufferList != NULL) { const ALbuffer *buffer; - readFin = readFin || (BufferList == Source->current_buffer); + readFin = readFin || (BufferList == Current); if((buffer=BufferList->buffer) != NULL) { if(!Buffer) Buffer = buffer; @@ -2672,7 +2830,7 @@ static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *of assert(Buffer != NULL); if(Source->state == AL_PLAYING) - writePos = readPos + (ALuint)(updateLen*Buffer->Frequency); + writePos = readPos + (ALuint)(updateLen*Buffer->Frequency + 0.5f); else writePos = readPos; @@ -2685,7 +2843,7 @@ static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *of { /* Wrap positions back to 0 */ if(readPos >= totalBufferLen) - readPos = 0; + readPos = readPosFrac = 0; if(writePos >= totalBufferLen) writePos = 0; } @@ -2693,13 +2851,13 @@ static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *of switch(name) { case AL_SEC_OFFSET: - offset[0] = (ALdouble)readPos / Buffer->Frequency; - offset[1] = (ALdouble)writePos / Buffer->Frequency; + offset[0] = (readPos + (ALdouble)readPosFrac/FRACTIONONE)/Buffer->Frequency; + offset[1] = (ALdouble)writePos/Buffer->Frequency; break; case AL_SAMPLE_OFFSET: case AL_SAMPLE_RW_OFFSETS_SOFT: - offset[0] = (ALdouble)readPos; + offset[0] = readPos + (ALdouble)readPosFrac/FRACTIONONE; offset[1] = (ALdouble)writePos; break; @@ -2747,6 +2905,8 @@ static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *of } break; } + + ReadUnlock(&Source->queue_lock); } @@ -2759,16 +2919,15 @@ ALboolean ApplyOffset(ALsource *Source) { ALbufferlistitem *BufferList; const ALbuffer *Buffer; - ALint bufferLen, totalBufferLen; - ALint offset; + ALuint bufferLen, totalBufferLen; + ALuint offset=0, frac=0; /* Get sample frame offset */ - offset = GetSampleOffset(Source); - if(offset == -1) + if(!GetSampleOffset(Source, &offset, &frac)) return AL_FALSE; totalBufferLen = 0; - BufferList = Source->queue; + BufferList = ATOMIC_LOAD(&Source->queue); while(BufferList && totalBufferLen <= offset) { Buffer = BufferList->buffer; @@ -2777,10 +2936,10 @@ ALboolean ApplyOffset(ALsource *Source) if(bufferLen > offset-totalBufferLen) { /* Offset is in this buffer */ - Source->current_buffer = BufferList; + ATOMIC_STORE(&Source->current_buffer, BufferList); Source->position = offset - totalBufferLen; - Source->position_fraction = 0; + Source->position_fraction = frac; return AL_TRUE; } @@ -2796,18 +2955,18 @@ ALboolean ApplyOffset(ALsource *Source) /* GetSampleOffset * - * Returns the sample offset into the Source's queue (from the Sample, Byte or - * Second offset supplied by the application). This takes into account the fact - * that the buffer format may have been modifed since. + * Retrieves the sample offset into the Source's queue (from the Sample, Byte + * or Second offset supplied by the application). This takes into account the + * fact that the buffer format may have been modifed since. */ -static ALint GetSampleOffset(ALsource *Source) +static ALboolean GetSampleOffset(ALsource *Source, ALuint *offset, ALuint *frac) { const ALbuffer *Buffer = NULL; const ALbufferlistitem *BufferList; - ALint Offset = -1; + ALdouble dbloff, dblfrac; /* Find the first valid Buffer in the Queue */ - BufferList = Source->queue; + BufferList = ATOMIC_LOAD(&Source->queue); while(BufferList) { if(BufferList->buffer) @@ -2817,45 +2976,49 @@ static ALint GetSampleOffset(ALsource *Source) } BufferList = BufferList->next; } - if(!Buffer) { Source->Offset = -1.0; - return -1; + return AL_FALSE; } switch(Source->OffsetType) { case AL_BYTE_OFFSET: /* Determine the ByteOffset (and ensure it is block aligned) */ - Offset = (ALint)Source->Offset; + *offset = (ALuint)Source->Offset; if(Buffer->OriginalType == UserFmtIMA4) { ALsizei align = (Buffer->OriginalAlign-1)/2 + 4; - Offset /= align * ChannelsFromUserFmt(Buffer->OriginalChannels); - Offset *= Buffer->OriginalAlign; + *offset /= align * ChannelsFromUserFmt(Buffer->OriginalChannels); + *offset *= Buffer->OriginalAlign; } else if(Buffer->OriginalType == UserFmtMSADPCM) { ALsizei align = (Buffer->OriginalAlign-2)/2 + 7; - Offset /= align * ChannelsFromUserFmt(Buffer->OriginalChannels); - Offset *= Buffer->OriginalAlign; + *offset /= align * ChannelsFromUserFmt(Buffer->OriginalChannels); + *offset *= Buffer->OriginalAlign; } else - Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType); + *offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType); + *frac = 0; break; case AL_SAMPLE_OFFSET: - Offset = (ALint)Source->Offset; + dblfrac = modf(Source->Offset, &dbloff); + *offset = (ALuint)mind(dbloff, UINT_MAX); + *frac = (ALuint)mind(dblfrac*FRACTIONONE, FRACTIONONE-1.0); break; case AL_SEC_OFFSET: - Offset = (ALint)(Source->Offset * Buffer->Frequency); + dblfrac = modf(Source->Offset*Buffer->Frequency, &dbloff); + *offset = (ALuint)mind(dbloff, UINT_MAX); + *frac = (ALuint)mind(dblfrac*FRACTIONONE, FRACTIONONE-1.0); break; } Source->Offset = -1.0; - return Offset; + return AL_TRUE; } @@ -2865,6 +3028,7 @@ static ALint GetSampleOffset(ALsource *Source) */ ALvoid ReleaseALSources(ALCcontext *Context) { + ALbufferlistitem *item; ALsizei pos; ALuint j; for(pos = 0;pos < Context->SourceMap.size;pos++) @@ -2872,14 +3036,14 @@ ALvoid ReleaseALSources(ALCcontext *Context) ALsource *temp = Context->SourceMap.array[pos].value; Context->SourceMap.array[pos].value = NULL; - while(temp->queue != NULL) + item = ATOMIC_EXCHANGE(ALbufferlistitem*, &temp->queue, NULL); + while(item != NULL) { - ALbufferlistitem *BufferList = temp->queue; - temp->queue = BufferList->next; - - if(BufferList->buffer != NULL) - DecrementRef(&BufferList->buffer->ref); - free(BufferList); + ALbufferlistitem *next = item->next; + if(item->buffer != NULL) + DecrementRef(&item->buffer->ref); + free(item); + item = next; } for(j = 0;j < MAX_SENDS;++j) |