diff options
Diffstat (limited to 'Alc/backends/wave.c')
-rw-r--r-- | Alc/backends/wave.c | 123 |
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; |