aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/backends/wave.c
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/backends/wave.c')
-rw-r--r--Alc/backends/wave.c123
1 files changed, 67 insertions, 56 deletions
diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c
index 6b47c611..390b2a5f 100644
--- a/Alc/backends/wave.c
+++ b/Alc/backends/wave.c
@@ -27,6 +27,7 @@
#include "alMain.h"
#include "alu.h"
+#include "alconfig.h"
#include "threads.h"
#include "compat.h"
@@ -56,16 +57,14 @@ static const ALubyte SUBTYPE_BFORMAT_FLOAT[] = {
static void fwrite16le(ALushort val, FILE *f)
{
- fputc(val&0xff, f);
- fputc((val>>8)&0xff, f);
+ ALubyte data[2] = { val&0xff, (val>>8)&0xff };
+ fwrite(data, 1, 2, f);
}
static void fwrite32le(ALuint val, FILE *f)
{
- fputc(val&0xff, f);
- fputc((val>>8)&0xff, f);
- fputc((val>>16)&0xff, f);
- fputc((val>>24)&0xff, f);
+ ALubyte data[4] = { val&0xff, (val>>8)&0xff, (val>>16)&0xff, (val>>24)&0xff };
+ fwrite(data, 1, 4, f);
}
@@ -78,22 +77,21 @@ typedef struct ALCwaveBackend {
ALvoid *mBuffer;
ALuint mSize;
- volatile int killNow;
+ ATOMIC(ALenum) killNow;
althrd_t thread;
} ALCwaveBackend;
static int ALCwaveBackend_mixerProc(void *ptr);
static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device);
-static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, Destruct)
+static void ALCwaveBackend_Destruct(ALCwaveBackend *self);
static ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name);
-static void ALCwaveBackend_close(ALCwaveBackend *self);
static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self);
static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self);
static void ALCwaveBackend_stop(ALCwaveBackend *self);
static DECLARE_FORWARD2(ALCwaveBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ALCuint, availableSamples)
-static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ClockLatency, getClockLatency)
static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, lock)
static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, unlock)
DECLARE_DEFAULT_ALLOCATORS(ALCwaveBackend)
@@ -112,9 +110,17 @@ static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device)
self->mBuffer = NULL;
self->mSize = 0;
- self->killNow = 1;
+ ATOMIC_INIT(&self->killNow, AL_TRUE);
}
+static void ALCwaveBackend_Destruct(ALCwaveBackend *self)
+{
+ if(self->mFile)
+ fclose(self->mFile);
+ self->mFile = NULL;
+
+ ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
static int ALCwaveBackend_mixerProc(void *ptr)
{
@@ -129,7 +135,7 @@ static int ALCwaveBackend_mixerProc(void *ptr)
althrd_setname(althrd_current(), MIXER_THREAD_NAME);
- frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+ frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
done = 0;
if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC)
@@ -137,7 +143,8 @@ static int ALCwaveBackend_mixerProc(void *ptr)
ERR("Failed to get starting time\n");
return 1;
}
- while(!self->killNow && device->Connected)
+ while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+ ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
{
if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC)
{
@@ -159,42 +166,46 @@ static int ALCwaveBackend_mixerProc(void *ptr)
al_nssleep(restTime);
else while(avail-done >= device->UpdateSize)
{
+ ALCwaveBackend_lock(self);
aluMixData(device, self->mBuffer, device->UpdateSize);
+ ALCwaveBackend_unlock(self);
done += device->UpdateSize;
if(!IS_LITTLE_ENDIAN)
{
ALuint bytesize = BytesFromDevFmt(device->FmtType);
- ALubyte *bytes = self->mBuffer;
ALuint i;
- if(bytesize == 1)
- {
- for(i = 0;i < self->mSize;i++)
- fputc(bytes[i], self->mFile);
- }
- else if(bytesize == 2)
+ if(bytesize == 2)
{
- for(i = 0;i < self->mSize;i++)
- fputc(bytes[i^1], self->mFile);
+ ALushort *samples = self->mBuffer;
+ ALuint len = self->mSize / 2;
+ for(i = 0;i < len;i++)
+ {
+ ALushort samp = samples[i];
+ samples[i] = (samp>>8) | (samp<<8);
+ }
}
else if(bytesize == 4)
{
- for(i = 0;i < self->mSize;i++)
- fputc(bytes[i^3], self->mFile);
+ ALuint *samples = self->mBuffer;
+ ALuint len = self->mSize / 4;
+ for(i = 0;i < len;i++)
+ {
+ ALuint samp = samples[i];
+ samples[i] = (samp>>24) | ((samp>>8)&0x0000ff00) |
+ ((samp<<8)&0x00ff0000) | (samp<<24);
+ }
}
}
- else
- {
- fs = fwrite(self->mBuffer, frameSize, device->UpdateSize,
- self->mFile);
- (void)fs;
- }
+
+ fs = fwrite(self->mBuffer, frameSize, device->UpdateSize, self->mFile);
+ (void)fs;
if(ferror(self->mFile))
{
ERR("Error writing to file\n");
ALCdevice_Lock(device);
- aluHandleDisconnect(device);
+ aluHandleDisconnect(device, "Failed to write playback samples");
ALCdevice_Unlock(device);
break;
}
@@ -226,18 +237,11 @@ static ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name)
}
device = STATIC_CAST(ALCbackend, self)->mDevice;
- al_string_copy_cstr(&device->DeviceName, name);
+ alstr_copy_cstr(&device->DeviceName, name);
return ALC_NO_ERROR;
}
-static void ALCwaveBackend_close(ALCwaveBackend *self)
-{
- if(self->mFile)
- fclose(self->mFile);
- self->mFile = NULL;
-}
-
static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
{
ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -249,7 +253,10 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
clearerr(self->mFile);
if(GetConfigValueBool(NULL, "wave", "bformat", 0))
- device->FmtChans = DevFmtBFormat3D;
+ {
+ device->FmtChans = DevFmtAmbi3D;
+ device->AmbiOrder = 1;
+ }
switch(device->FmtType)
{
@@ -277,20 +284,23 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
case DevFmtX51Rear: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020; break;
case DevFmtX61: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x100 | 0x200 | 0x400; break;
case DevFmtX71: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400; break;
- case DevFmtBFormat3D:
+ case DevFmtAmbi3D:
+ /* .amb output requires FuMa */
+ device->AmbiLayout = AmbiLayout_FuMa;
+ device->AmbiScale = AmbiNorm_FuMa;
isbformat = 1;
chanmask = 0;
break;
}
bits = BytesFromDevFmt(device->FmtType) * 8;
- channels = ChannelsFromDevFmt(device->FmtChans);
+ channels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
- fprintf(self->mFile, "RIFF");
+ fputs("RIFF", self->mFile);
fwrite32le(0xFFFFFFFF, self->mFile); // 'RIFF' header len; filled in at close
- fprintf(self->mFile, "WAVE");
+ fputs("WAVE", self->mFile);
- fprintf(self->mFile, "fmt ");
+ fputs("fmt ", self->mFile);
fwrite32le(40, self->mFile); // 'fmt ' header len; 40 bytes for EXTENSIBLE
// 16-bit val, format type id (extensible: 0xFFFE)
@@ -312,11 +322,12 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
// 32-bit val, channel mask
fwrite32le(chanmask, self->mFile);
// 16 byte GUID, sub-type format
- val = fwrite(((bits==32) ? (isbformat ? SUBTYPE_BFORMAT_FLOAT : SUBTYPE_FLOAT) :
- (isbformat ? SUBTYPE_BFORMAT_PCM : SUBTYPE_PCM)), 1, 16, self->mFile);
+ val = fwrite((device->FmtType == DevFmtFloat) ?
+ (isbformat ? SUBTYPE_BFORMAT_FLOAT : SUBTYPE_FLOAT) :
+ (isbformat ? SUBTYPE_BFORMAT_PCM : SUBTYPE_PCM), 1, 16, self->mFile);
(void)val;
- fprintf(self->mFile, "data");
+ fputs("data", self->mFile);
fwrite32le(0xFFFFFFFF, self->mFile); // 'data' header len; filled in at close
if(ferror(self->mFile))
@@ -335,7 +346,9 @@ static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self)
{
ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- self->mSize = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+ self->mSize = device->UpdateSize * FrameSizeFromDevFmt(
+ device->FmtChans, device->FmtType, device->AmbiOrder
+ );
self->mBuffer = malloc(self->mSize);
if(!self->mBuffer)
{
@@ -343,7 +356,7 @@ static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self)
return ALC_FALSE;
}
- self->killNow = 0;
+ ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
if(althrd_create(&self->thread, ALCwaveBackend_mixerProc, self) != althrd_success)
{
free(self->mBuffer);
@@ -361,10 +374,8 @@ static void ALCwaveBackend_stop(ALCwaveBackend *self)
long size;
int res;
- if(self->killNow)
+ if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
return;
-
- self->killNow = 1;
althrd_join(self->thread, &res);
free(self->mBuffer);
@@ -392,7 +403,7 @@ ALCbackendFactory *ALCwaveBackendFactory_getFactory(void);
static ALCboolean ALCwaveBackendFactory_init(ALCwaveBackendFactory *self);
static DECLARE_FORWARD(ALCwaveBackendFactory, ALCbackendFactory, void, deinit)
static ALCboolean ALCwaveBackendFactory_querySupport(ALCwaveBackendFactory *self, ALCbackend_Type type);
-static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory *self, enum DevProbe type);
+static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory *self, enum DevProbe type, al_string *outnames);
static ALCbackend* ALCwaveBackendFactory_createBackend(ALCwaveBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
DEFINE_ALCBACKENDFACTORY_VTABLE(ALCwaveBackendFactory);
@@ -416,12 +427,12 @@ static ALCboolean ALCwaveBackendFactory_querySupport(ALCwaveBackendFactory* UNUS
return ALC_FALSE;
}
-static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory* UNUSED(self), enum DevProbe type)
+static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames)
{
switch(type)
{
case ALL_DEVICE_PROBE:
- AppendAllDevicesList(waveDevice);
+ alstr_append_range(outnames, waveDevice, waveDevice+sizeof(waveDevice));
break;
case CAPTURE_DEVICE_PROBE:
break;