diff options
-rw-r--r-- | Alc/backends/oss.c | 64 | ||||
-rw-r--r-- | Alc/bformatdec.c | 110 | ||||
-rw-r--r-- | common/rwlock.c | 10 | ||||
-rw-r--r-- | include/atomic.h | 52 | ||||
-rw-r--r-- | include/rwlock.h | 9 |
5 files changed, 147 insertions, 98 deletions
diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 432c75f2..689a5c71 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -88,7 +88,7 @@ static struct oss_device oss_capture = { #ifdef ALC_OSS_COMPAT -static void ALCossListPopulate(struct oss_device *UNUSED(playback), struct oss_device *UNUSED(capture)) +static void ALCossListPopulate(struct oss_device *UNUSED(devlist), int UNUSED(type_flag)) { } @@ -153,7 +153,7 @@ static void ALCossListAppend(struct oss_device *list, const char *handle, size_t TRACE("Got device \"%s\", \"%s\"\n", next->handle, next->path); } -static void ALCossListPopulate(struct oss_device *playback, struct oss_device *capture) +static void ALCossListPopulate(struct oss_device *devlist, int type_flag) { struct oss_sysinfo si; struct oss_audioinfo ai; @@ -193,10 +193,9 @@ static void ALCossListPopulate(struct oss_device *playback, struct oss_device *c len = strnlen(ai.name, sizeof(ai.name)); handle = ai.name; } - if((ai.caps&DSP_CAP_INPUT) && capture != NULL) - ALCossListAppend(capture, handle, len, ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))); - if((ai.caps&DSP_CAP_OUTPUT) && playback != NULL) - ALCossListAppend(playback, handle, len, ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))); + if((ai.caps&type_flag)) + ALCossListAppend(devlist, handle, len, ai.devnode, + strnlen(ai.devnode, sizeof(ai.devnode))); } done: @@ -320,18 +319,26 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) struct oss_device *dev = &oss_playback; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - if(!name) + if(!name || strcmp(name, dev->handle) == 0) name = dev->handle; else { - while (dev != NULL) + if(!dev->next) + { + ALCossListPopulate(&oss_playback, DSP_CAP_OUTPUT); + dev = &oss_playback; + } + while(dev != NULL) { if (strcmp(dev->handle, name) == 0) break; dev = dev->next; } - if (dev == NULL) + if(dev == NULL) + { + WARN("Could not find \"%s\" in device list\n", name); return ALC_INVALID_VALUE; + } } self->killNow = 0; @@ -574,18 +581,26 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) int ossSpeed; char *err; - if(!name) + if(!name || strcmp(name, dev->handle) == 0) name = dev->handle; else { - while (dev != NULL) + if(!dev->next) + { + ALCossListPopulate(&oss_capture, DSP_CAP_INPUT); + dev = &oss_capture; + } + while(dev != NULL) { if (strcmp(dev->handle, name) == 0) break; dev = dev->next; } - if (dev == NULL) + if(dev == NULL) + { + WARN("Could not find \"%s\" in device list\n", name); return ALC_INVALID_VALUE; + } } self->fd = open(dev->path, O_RDONLY); @@ -770,33 +785,30 @@ ALCboolean ALCossBackendFactory_querySupport(ALCossBackendFactory* UNUSED(self), void ALCossBackendFactory_probe(ALCossBackendFactory* UNUSED(self), enum DevProbe type) { + struct oss_device *cur; switch(type) { case ALL_DEVICE_PROBE: - { - struct oss_device *cur = &oss_playback; - ALCossListFree(cur); - ALCossListPopulate(cur, NULL); - while (cur != NULL) + ALCossListFree(&oss_playback); + ALCossListPopulate(&oss_playback, DSP_CAP_OUTPUT); + cur = &oss_playback; + while(cur != NULL) { AppendAllDevicesList(cur->handle); cur = cur->next; } - } - break; + break; case CAPTURE_DEVICE_PROBE: - { - struct oss_device *cur = &oss_capture; - ALCossListFree(cur); - ALCossListPopulate(NULL, cur); - while (cur != NULL) + ALCossListFree(&oss_capture); + ALCossListPopulate(&oss_capture, DSP_CAP_INPUT); + cur = &oss_capture; + while(cur != NULL) { AppendCaptureDeviceList(cur->handle); cur = cur->next; } - } - break; + break; } } diff --git a/Alc/bformatdec.c b/Alc/bformatdec.c index 2aab4ed8..5556c2ef 100644 --- a/Alc/bformatdec.c +++ b/Alc/bformatdec.c @@ -135,7 +135,7 @@ static const ALfloat Ambi2DDecoder[4][FB_Max][MAX_AMBI_COEFFS] = { { { 0.353553f, 0.204094f, 0.0f, -0.204094f }, { 0.25f, 0.204094f, 0.0f, -0.204094f } }, { { 0.353553f, -0.204094f, 0.0f, -0.204094f }, { 0.25f, -0.204094f, 0.0f, -0.204094f } }, }; -static ALfloat Ambi2DEncoder[4][MAX_AMBI_COEFFS]; +static ALfloat Ambi2DEncoderT[4][MAX_AMBI_COEFFS]; /* These points are in AL coordinates! */ static const ALfloat Ambi3DPoints[8][3] = { @@ -158,7 +158,7 @@ static const ALfloat Ambi3DDecoder[8][FB_Max][MAX_AMBI_COEFFS] = { { { 0.25f, 0.1443375672f, -0.1443375672f, -0.1443375672f }, { 0.125f, 0.125f, -0.125f, -0.125f } }, { { 0.25f, -0.1443375672f, -0.1443375672f, -0.1443375672f }, { 0.125f, -0.125f, -0.125f, -0.125f } }, }; -static ALfloat Ambi3DEncoder[8][MAX_AMBI_COEFFS]; +static ALfloat Ambi3DEncoderT[8][MAX_AMBI_COEFFS]; static RowMixerFunc MixMatrixRow = MixRow_C; @@ -173,20 +173,53 @@ static void init_bformatdec(void) MixMatrixRow = SelectRowMixer(); for(i = 0;i < COUNTOF(Ambi3DPoints);i++) - CalcDirectionCoeffs(Ambi3DPoints[i], 0.0f, Ambi3DEncoder[i]); + CalcDirectionCoeffs(Ambi3DPoints[i], 0.0f, Ambi3DEncoderT[i]); for(i = 0;i < COUNTOF(Ambi2DPoints);i++) { - CalcDirectionCoeffs(Ambi2DPoints[i], 0.0f, Ambi2DEncoder[i]); + CalcDirectionCoeffs(Ambi2DPoints[i], 0.0f, Ambi2DEncoderT[i]); /* Remove the skipped height-related coefficients for 2D rendering. */ - Ambi2DEncoder[i][2] = Ambi2DEncoder[i][3]; - Ambi2DEncoder[i][3] = Ambi2DEncoder[i][4]; - Ambi2DEncoder[i][4] = Ambi2DEncoder[i][8]; - Ambi2DEncoder[i][5] = Ambi2DEncoder[i][9]; - Ambi2DEncoder[i][6] = Ambi2DEncoder[i][15]; + Ambi2DEncoderT[i][2] = Ambi2DEncoderT[i][3]; + Ambi2DEncoderT[i][3] = Ambi2DEncoderT[i][4]; + Ambi2DEncoderT[i][4] = Ambi2DEncoderT[i][8]; + Ambi2DEncoderT[i][5] = Ambi2DEncoderT[i][9]; + Ambi2DEncoderT[i][6] = Ambi2DEncoderT[i][15]; for(j = 7;j < MAX_AMBI_COEFFS;j++) - Ambi2DEncoder[i][j] = 0.0f; + Ambi2DEncoderT[i][j] = 0.0f; + } +} + + +/* This typedef is needed for SAFE_CONST to work. */ +typedef ALfloat ALfloatMAX_AMBI_COEFFS[MAX_AMBI_COEFFS]; + +static void GenUpsamplerGains(const ALfloat (*restrict EncoderT)[MAX_AMBI_COEFFS], + const ALfloat (*restrict Decoder)[FB_Max][MAX_AMBI_COEFFS], + ALsizei InChannels, + ALfloat (*restrict OutGains)[MAX_OUTPUT_CHANNELS][FB_Max], + ALsizei OutChannels) +{ + ALsizei i, j, k; + + /* Combine the matrices that do the in->virt and virt->out conversions so + * we get a single in->out conversion. NOTE: the Encoder matrix and output + * are transposed, so the input channels line up with the rows and the + * output channels line up with the columns. + */ + for(i = 0;i < 4;i++) + { + for(j = 0;j < OutChannels;j++) + { + ALfloat hfgain=0.0f, lfgain=0.0f; + for(k = 0;k < InChannels;k++) + { + hfgain += Decoder[k][FB_HighFreq][i]*EncoderT[k][j]; + lfgain += Decoder[k][FB_LowFreq][i]*EncoderT[k][j]; + } + OutGains[i][j][FB_HighFreq] = hfgain; + OutGains[i][j][FB_LowFreq] = lfgain; + } } } @@ -272,7 +305,7 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALuint chancount, const ALfloat *coeff_scale = UnitScale; ALfloat distgain[MAX_OUTPUT_CHANNELS]; ALfloat maxdist, ratio; - ALuint i, j, k; + ALuint i; al_free(dec->Samples); dec->Samples = NULL; @@ -300,39 +333,16 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALuint chancount, memset(dec->UpSampler.Gains, 0, sizeof(dec->UpSampler.Gains)); if((conf->ChanMask&AMBI_PERIPHONIC_MASK)) { - /* Combine the matrices that do the in->virt and virt->out conversions - * so we get a single in->out conversion. - */ - for(i = 0;i < 4;i++) - { - for(j = 0;j < dec->NumChannels;j++) - { - ALfloat *gains = dec->UpSampler.Gains[i][j]; - for(k = 0;k < COUNTOF(Ambi3DDecoder);k++) - { - gains[FB_HighFreq] += Ambi3DDecoder[k][FB_HighFreq][i]*Ambi3DEncoder[k][j]; - gains[FB_LowFreq] += Ambi3DDecoder[k][FB_LowFreq][i]*Ambi3DEncoder[k][j]; - } - } - } - + GenUpsamplerGains(SAFE_CONST(ALfloatMAX_AMBI_COEFFS*,Ambi3DEncoderT), + Ambi3DDecoder, COUNTOF(Ambi3DDecoder), + dec->UpSampler.Gains, dec->NumChannels); dec->Periphonic = AL_TRUE; } else { - for(i = 0;i < 4;i++) - { - for(j = 0;j < dec->NumChannels;j++) - { - ALfloat *gains = dec->UpSampler.Gains[i][j]; - for(k = 0;k < COUNTOF(Ambi2DDecoder);k++) - { - gains[FB_HighFreq] += Ambi2DDecoder[k][FB_HighFreq][i]*Ambi2DEncoder[k][j]; - gains[FB_LowFreq] += Ambi2DDecoder[k][FB_LowFreq][i]*Ambi2DEncoder[k][j]; - } - } - } - + GenUpsamplerGains(SAFE_CONST(ALfloatMAX_AMBI_COEFFS*,Ambi2DEncoderT), + Ambi2DDecoder, COUNTOF(Ambi2DDecoder), + dec->UpSampler.Gains, dec->NumChannels); dec->Periphonic = AL_FALSE; } @@ -627,27 +637,19 @@ void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device) { ALfloat gains[8][MAX_OUTPUT_CHANNELS]; ALfloat ratio; - ALuint i, j, k; + ALuint i; ratio = 400.0f / (ALfloat)device->Frequency; for(i = 0;i < 4;i++) bandsplit_init(&ambiup->XOver[i], ratio); - for(i = 0;i < COUNTOF(Ambi3DEncoder);i++) - ComputePanningGains(device->Dry, Ambi3DEncoder[i], 1.0f, gains[i]); + for(i = 0;i < COUNTOF(Ambi3DEncoderT);i++) + ComputePanningGains(device->Dry, Ambi3DEncoderT[i], 1.0f, gains[i]); memset(ambiup->Gains, 0, sizeof(ambiup->Gains)); - for(i = 0;i < 4;i++) - { - for(j = 0;j < device->Dry.NumChannels;j++) - { - for(k = 0;k < COUNTOF(Ambi3DDecoder);k++) - { - ambiup->Gains[i][j][FB_HighFreq] += Ambi3DDecoder[k][FB_HighFreq][i]*gains[k][j]; - ambiup->Gains[i][j][FB_LowFreq] += Ambi3DDecoder[k][FB_LowFreq][i]*gains[k][j]; - } - } - } + GenUpsamplerGains(SAFE_CONST(ALfloatMAX_AMBI_COEFFS*,gains), + Ambi3DDecoder, COUNTOF(Ambi3DDecoder), + ambiup->Gains, device->Dry.NumChannels); } void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo) diff --git a/common/rwlock.c b/common/rwlock.c index f1a86fa6..67cf3acf 100644 --- a/common/rwlock.c +++ b/common/rwlock.c @@ -11,19 +11,19 @@ /* A simple spinlock. Yield the thread while the given integer is set by * another. Could probably be improved... */ #define LOCK(l) do { \ - while(ATOMIC_EXCHANGE(int, &(l), true, almemory_order_acq_rel) == true) \ + while(ATOMIC_FLAG_TEST_AND_SET(&(l), almemory_order_acq_rel) == true) \ althrd_yield(); \ } while(0) -#define UNLOCK(l) ATOMIC_STORE(&(l), false, almemory_order_release) +#define UNLOCK(l) ATOMIC_FLAG_CLEAR(&(l), almemory_order_release) void RWLockInit(RWLock *lock) { InitRef(&lock->read_count, 0); InitRef(&lock->write_count, 0); - ATOMIC_INIT(&lock->read_lock, false); - ATOMIC_INIT(&lock->read_entry_lock, false); - ATOMIC_INIT(&lock->write_lock, false); + ATOMIC_FLAG_CLEAR(&lock->read_lock, almemory_order_relaxed); + ATOMIC_FLAG_CLEAR(&lock->read_entry_lock, almemory_order_relaxed); + ATOMIC_FLAG_CLEAR(&lock->write_lock, almemory_order_relaxed); } void ReadLock(RWLock *lock) diff --git a/include/atomic.h b/include/atomic.h index 3a662f8e..4dff05da 100644 --- a/include/atomic.h +++ b/include/atomic.h @@ -22,9 +22,11 @@ extern "C" { #define almemory_order_seq_cst memory_order_seq_cst #define ATOMIC(T) T _Atomic +#define ATOMIC_FLAG atomic_flag #define ATOMIC_INIT(_val, _newval) atomic_init((_val), (_newval)) #define ATOMIC_INIT_STATIC(_newval) ATOMIC_VAR_INIT(_newval) +/*#define ATOMIC_FLAG_INIT ATOMIC_FLAG_INIT*/ #define PARAM2(f, a, b, ...) (f((a), (b))) #define PARAM3(f, a, b, c, ...) (f((a), (b), (c))) @@ -42,6 +44,11 @@ extern "C" { #define ATOMIC_COMPARE_EXCHANGE_WEAK(T, ...) \ PARAM5(atomic_compare_exchange_weak_explicit, __VA_ARGS__, memory_order_seq_cst, memory_order_seq_cst) +#define ATOMIC_FLAG_TEST_AND_SET(...) \ + PARAM2(atomic_flag_test_and_set_explicit, __VA_ARGS__, memory_order_seq_cst) +#define ATOMIC_FLAG_CLEAR(...) \ + PARAM2(atomic_flag_clear_explicit, __VA_ARGS__, memory_order_seq_cst) + #define ATOMIC_THREAD_FENCE atomic_thread_fence /* Atomics using GCC intrinsics */ @@ -57,9 +64,11 @@ enum almemory_order { }; #define ATOMIC(T) struct { T volatile value; } +#define ATOMIC_FLAG ATOMIC(int) #define ATOMIC_INIT(_val, _newval) do { (_val)->value = (_newval); } while(0) #define ATOMIC_INIT_STATIC(_newval) {(_newval)} +#define ATOMIC_FLAG_INIT ATOMIC_INIT_STATIC(0) #define ATOMIC_LOAD(_val, ...) __extension__({ \ __typeof((_val)->value) _r = (_val)->value; \ @@ -76,6 +85,7 @@ enum almemory_order { #define ATOMIC_EXCHANGE(T, _val, _newval, ...) __extension__({ \ static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ + __asm__ __volatile__("" ::: "memory"); \ __sync_lock_test_and_set(&(_val)->value, (_newval)); \ }) #define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, ...) __extension__({ \ @@ -85,6 +95,16 @@ enum almemory_order { *(_oldval) == _o; \ }) +#define ATOMIC_FLAG_TEST_AND_SET(_val, ...) __extension__({ \ + __asm__ __volatile__("" ::: "memory"); \ + __sync_lock_test_and_set(&(_val)->value, 1); \ +}) +#define ATOMIC_FLAG_CLEAR(_val, ...) __extension__({ \ + __sync_lock_release(&(_val)->value); \ + __asm__ __volatile__("" ::: "memory"); \ +}) + + #define ATOMIC_THREAD_FENCE(order) do { \ enum { must_be_constant = (order) }; \ const int _o = must_be_constant; \ @@ -297,19 +317,23 @@ int _al_invalid_atomic_size(); /* not defined */ #define ATOMIC(T) T +#define ATOMIC_INIT(_val, _newval) ((void)0) #define ATOMIC_INIT_STATIC(_newval) (0) -#define ATOMIC_LOAD_UNSAFE(_val) (0) -#define ATOMIC_STORE_UNSAFE(_val, _newval) ((void)0) +#define ATOMIC_LOAD(...) (0) +#define ATOMIC_STORE(...) ((void)0) -#define ATOMIC_LOAD(_val, ...) (0) -#define ATOMIC_STORE(_val, _newval, ...) ((void)0) +#define ATOMIC_ADD(...) (0) +#define ATOMIC_SUB(...) (0) -#define ATOMIC_ADD(_val, _incr, ...) (0) -#define ATOMIC_SUB(_val, _decr, ...) (0) +#define ATOMIC_EXCHANGE(T, ...) (0) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, ...) (0) +#define ATOMIC_COMPARE_EXCHANGE_WEAK(T, ...) (0) -#define ATOMIC_EXCHANGE(T, _val, _newval, ...) (0) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, ...) (0) +#define ATOMIC_FLAG_TEST_AND_SET(...) (0) +#define ATOMIC_FLAG_CLEAR(...) ((void)0) + +#define ATOMIC_THREAD_FENCE ((void)0) #endif /* If no weak cmpxchg is provided (not all systems will have one), substitute a @@ -318,6 +342,18 @@ int _al_invalid_atomic_size(); /* not defined */ #define ATOMIC_COMPARE_EXCHANGE_WEAK ATOMIC_COMPARE_EXCHANGE_STRONG #endif +/* If no ATOMIC_FLAG is defined, simulate one with an atomic int using exchange + * and store ops. + */ +#ifndef ATOMIC_FLAG +#define ATOMIC_FLAG ATOMIC(int) +#define ATOMIC_FLAG_INIT ATOMIC_INIT_STATIC(0) +#define ATOMIC_FLAG_TEST_AND_SET_(_val, ...) ATOMIC_EXCHANGE(int, _val, 1, __VA_ARGS__) +#define ATOMIC_FLAG_TEST_AND_SET(...) ATOMIC_FLAG_TEST_AND_SET_(__VA_ARGS__, almemory_order_seq_cst) +#define ATOMIC_FLAG_CLEAR_(_val, ...) ATOMIC_STORE(_val, 0, __VA_ARGS__) +#define ATOMIC_FLAG_CLEAR(...) ATOMIC_FLAG_CLEAR_(__VA_ARGS__, almemory_order_seq_cst) +#endif + typedef unsigned int uint; typedef ATOMIC(uint) RefCount; diff --git a/include/rwlock.h b/include/rwlock.h index 158a0670..8e36fa1a 100644 --- a/include/rwlock.h +++ b/include/rwlock.h @@ -11,13 +11,12 @@ extern "C" { typedef struct { RefCount read_count; RefCount write_count; - ATOMIC(int) read_lock; - ATOMIC(int) read_entry_lock; - ATOMIC(int) write_lock; + ATOMIC_FLAG read_lock; + ATOMIC_FLAG read_entry_lock; + ATOMIC_FLAG write_lock; } RWLock; #define RWLOCK_STATIC_INITIALIZE { ATOMIC_INIT_STATIC(0), ATOMIC_INIT_STATIC(0), \ - ATOMIC_INIT_STATIC(false), ATOMIC_INIT_STATIC(false), \ - ATOMIC_INIT_STATIC(false) } + ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT } void RWLockInit(RWLock *lock); void ReadLock(RWLock *lock); |