aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c16
-rw-r--r--Alc/alsa.c42
-rw-r--r--Alc/dsound.c13
-rw-r--r--Alc/oss.c13
-rw-r--r--Alc/portaudio.c6
-rw-r--r--Alc/pulseaudio.c8
-rw-r--r--Alc/solaris.c4
-rw-r--r--Alc/wave.c2
-rw-r--r--Alc/winmm.c3
-rw-r--r--OpenAL32/Include/alMain.h2
-rw-r--r--alsoftrc.sample34
11 files changed, 72 insertions, 71 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 14fb3971..3a799dd9 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -614,7 +614,8 @@ ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, AL
pDevice->Frequency = frequency;
pDevice->Format = format;
- pDevice->BufferSize = SampleSize;
+ pDevice->UpdateSize = SampleSize;
+ pDevice->NumUpdates = 1;
SuspendContext(NULL);
for(i = 0;BackendList[i].Init;i++)
@@ -1481,9 +1482,16 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
device->Format = GetFormatFromString(fmt);
- device->BufferSize = GetConfigValueInt(NULL, "refresh", 4096);
- if((ALint)device->BufferSize <= 0)
- device->BufferSize = 4096;
+ device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);
+ if(device->NumUpdates < 2)
+ device->NumUpdates = 4;
+
+ i = GetConfigValueInt(NULL, "refresh", 4096);
+ if(i <= 0) i = 4096;
+
+ device->UpdateSize = GetConfigValueInt(NULL, "period_size", i/device->NumUpdates);
+ if(device->UpdateSize <= 0)
+ device->UpdateSize = i/device->NumUpdates;
device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
if((ALint)device->MaxNoOfSources <= 0)
diff --git a/Alc/alsa.c b/Alc/alsa.c
index e96e185f..2adf7b02 100644
--- a/Alc/alsa.c
+++ b/Alc/alsa.c
@@ -69,10 +69,12 @@ MAKE_FUNC(snd_pcm_hw_params_set_periods_near);
MAKE_FUNC(snd_pcm_hw_params_set_rate_near);
MAKE_FUNC(snd_pcm_hw_params_set_rate);
MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_near);
+MAKE_FUNC(snd_pcm_hw_params_set_period_size_near);
MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_min);
MAKE_FUNC(snd_pcm_hw_params_get_buffer_size);
MAKE_FUNC(snd_pcm_hw_params_get_period_size);
MAKE_FUNC(snd_pcm_hw_params_get_access);
+MAKE_FUNC(snd_pcm_hw_params_get_periods);
MAKE_FUNC(snd_pcm_hw_params);
MAKE_FUNC(snd_pcm_sw_params_malloc);
MAKE_FUNC(snd_pcm_sw_params_current);
@@ -411,7 +413,7 @@ static void alsa_close_playback(ALCdevice *device)
static ALCboolean alsa_reset_playback(ALCdevice *device)
{
alsa_data *data = (alsa_data*)device->ExtraData;
- snd_pcm_uframes_t bufferSizeInFrames;
+ snd_pcm_uframes_t periodSizeInFrames;
snd_pcm_sw_params_t *sp = NULL;
snd_pcm_hw_params_t *p = NULL;
snd_pcm_access_t access;
@@ -439,8 +441,8 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
}
allowmmap = GetConfigValueBool("alsa", "mmap", 1);
- periods = GetConfigValueInt("alsa", "periods", 0);
- bufferSizeInFrames = device->BufferSize;
+ periods = GetConfigValueInt("alsa", "periods", device->NumUpdates);
+ periodSizeInFrames = device->UpdateSize;
rate = device->Frequency;
err = NULL;
@@ -451,6 +453,7 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
/* set interleaved access */
if(err == NULL && (!allowmmap || (i=psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0))
{
+ if(periods > 2) periods--;
if((i=psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
err = "set access";
}
@@ -466,16 +469,18 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
/* set rate (implicitly constrains period/buffer parameters) */
if(err == NULL && (i=psnd_pcm_hw_params_set_rate_near(data->pcmHandle, p, &rate, NULL)) < 0)
err = "set rate near";
- /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
- if(err == NULL && (i=psnd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, p, &bufferSizeInFrames)) < 0)
- err = "set buffer size near";
+ /* set period size in frame units (implicitly sets buffer size/bytes/time and period time/bytes) */
+ if(err == NULL && (i=psnd_pcm_hw_params_set_period_size_near(data->pcmHandle, p, &periodSizeInFrames, NULL)) < 0)
+ err = "set period size near";
/* install and prepare hardware configuration */
if(err == NULL && (i=psnd_pcm_hw_params(data->pcmHandle, p)) < 0)
err = "set params";
if(err == NULL && (i=psnd_pcm_hw_params_get_access(p, &access)) < 0)
err = "get access";
- if(err == NULL && (i=psnd_pcm_hw_params_get_period_size(p, &bufferSizeInFrames, NULL)) < 0)
+ if(err == NULL && (i=psnd_pcm_hw_params_get_period_size(p, &periodSizeInFrames, NULL)) < 0)
err = "get period size";
+ if(err == NULL && (i=psnd_pcm_hw_params_get_periods(p, &periods, NULL)) < 0)
+ err = "get periods";
if(err != NULL)
{
AL_PRINT("%s failed: %s\n", err, psnd_strerror(i));
@@ -490,7 +495,7 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
if((i=psnd_pcm_sw_params_current(data->pcmHandle, sp)) != 0)
err = "sw current";
- if(err == NULL && (i=psnd_pcm_sw_params_set_avail_min(data->pcmHandle, sp, bufferSizeInFrames)) != 0)
+ if(err == NULL && (i=psnd_pcm_sw_params_set_avail_min(data->pcmHandle, sp, periodSizeInFrames)) != 0)
err = "sw set avail min";
if(err == NULL && (i=psnd_pcm_sw_params(data->pcmHandle, sp)) != 0)
err = "sw set params";
@@ -503,15 +508,19 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
psnd_pcm_sw_params_free(sp);
- data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, bufferSizeInFrames);
+ data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, periodSizeInFrames);
if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
{
+ /* Increase periods by one, since the temp buffer counts as an extra
+ * period */
+ periods++;
data->buffer = malloc(data->size);
if(!data->buffer)
{
AL_PRINT("buffer malloc failed\n");
return ALC_FALSE;
}
+ data->thread = StartThread(ALSANoMMapProc, device);
}
else
{
@@ -523,12 +532,8 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
data->buffer = NULL;
return ALC_FALSE;
}
- }
-
- if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
- data->thread = StartThread(ALSANoMMapProc, device);
- else
data->thread = StartThread(ALSAProc, device);
+ }
if(data->thread == NULL)
{
AL_PRINT("Could not create playback thread\n");
@@ -537,7 +542,8 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
return ALC_FALSE;
}
- device->UpdateSize = bufferSizeInFrames;
+ device->UpdateSize = periodSizeInFrames;
+ device->NumUpdates = periods;
device->Frequency = rate;
return ALC_TRUE;
@@ -631,7 +637,7 @@ open_alsa:
}
err = NULL;
- bufferSizeInFrames = pDevice->BufferSize;
+ bufferSizeInFrames = pDevice->UpdateSize * pDevice->NumUpdates;
psnd_pcm_hw_params_malloc(&p);
if((i=psnd_pcm_hw_params_any(data->pcmHandle, p)) < 0)
@@ -677,7 +683,7 @@ open_alsa:
frameSize = aluChannelsFromFormat(pDevice->Format);
frameSize *= aluBytesFromFormat(pDevice->Format);
- data->ring = CreateRingBuffer(frameSize, pDevice->BufferSize);
+ data->ring = CreateRingBuffer(frameSize, bufferSizeInFrames);
if(!data->ring)
{
AL_PRINT("ring buffer create failed\n");
@@ -815,9 +821,11 @@ LOAD_FUNC(snd_pcm_hw_params_set_rate_near);
LOAD_FUNC(snd_pcm_hw_params_set_rate);
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_near);
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_min);
+LOAD_FUNC(snd_pcm_hw_params_set_period_size_near);
LOAD_FUNC(snd_pcm_hw_params_get_buffer_size);
LOAD_FUNC(snd_pcm_hw_params_get_period_size);
LOAD_FUNC(snd_pcm_hw_params_get_access);
+LOAD_FUNC(snd_pcm_hw_params_get_periods);
LOAD_FUNC(snd_pcm_hw_params);
LOAD_FUNC(snd_pcm_sw_params_malloc);
LOAD_FUNC(snd_pcm_sw_params_current);
diff --git a/Alc/dsound.c b/Alc/dsound.c
index e4436258..959f55d2 100644
--- a/Alc/dsound.c
+++ b/Alc/dsound.c
@@ -51,8 +51,6 @@ static void *ds_handle;
static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter);
static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
-// Since DSound doesn't report the fragment size, emulate it
-static int num_frags;
typedef struct {
// DirectSound Playback Device
@@ -98,10 +96,10 @@ static ALuint DSoundProc(ALvoid *ptr)
aluHandleDisconnect(pDevice);
return 1;
}
- FragSize = DSBCaps.dwBufferBytes / num_frags;
FrameSize = aluChannelsFromFormat(pDevice->Format) *
aluBytesFromFormat(pDevice->Format);
+ FragSize = pDevice->UpdateSize * FrameSize;
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &LastCursor, NULL);
while(!pData->killNow)
@@ -344,10 +342,13 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
if(SUCCEEDED(hr))
{
+ DWORD num_frags = GetConfigValueInt("dsound", "periods", device->NumUpdates);
+ if(num_frags < 2) num_frags = 2;
+
memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
DSBDescription.dwSize=sizeof(DSBUFFERDESC);
DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2;
- DSBDescription.dwBufferBytes=(device->BufferSize/num_frags) * num_frags * frameSize;
+ DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * frameSize;
DSBDescription.lpwfxFormat=&OutputType.Format;
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
}
@@ -375,7 +376,6 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
}
device->Format = format;
- device->UpdateSize = device->BufferSize/num_frags;
return ALC_TRUE;
}
@@ -505,9 +505,6 @@ void alcDSoundInit(BackendFuncs *FuncList)
LOAD_FUNC(DirectSoundCreate);
LOAD_FUNC(DirectSoundEnumerateA);
#undef LOAD_FUNC
-
- num_frags = GetConfigValueInt("dsound", "periods", 4);
- if(num_frags < 2) num_frags = 2;
}
void alcDSoundDeinit(void)
diff --git a/Alc/oss.c b/Alc/oss.c
index 7af734ae..7c7fe73f 100644
--- a/Alc/oss.c
+++ b/Alc/oss.c
@@ -221,18 +221,19 @@ static ALCboolean oss_reset_playback(ALCdevice *device)
AL_PRINT("Unknown format?! %x\n", device->Format);
}
- periods = GetConfigValueInt("oss", "periods", 4);
- if((int)periods <= 0)
+ periods = GetConfigValueInt("oss", "periods", device->NumUpdates);
+ if((int)periods < 2)
periods = 4;
numChannels = aluChannelsFromFormat(device->Format);
frameSize = numChannels * aluBytesFromFormat(device->Format);
ossSpeed = device->Frequency;
- log2FragmentSize = log2i(device->BufferSize * frameSize / periods);
+ log2FragmentSize = log2i(device->UpdateSize * frameSize);
/* according to the OSS spec, 16 bytes are the minimum */
if (log2FragmentSize < 4)
log2FragmentSize = 4;
+ if(periods > 2) periods--;
numFragmentsLogSize = (periods << 16) | log2FragmentSize;
#define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1))
@@ -262,6 +263,7 @@ static ALCboolean oss_reset_playback(ALCdevice *device)
device->Frequency = ossSpeed;
device->UpdateSize = info.fragsize / frameSize;
+ device->NumUpdates = info.fragments + 1;
data->data_size = device->UpdateSize * frameSize;
data->mix_data = calloc(1, data->data_size);
@@ -343,7 +345,8 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
numChannels = aluChannelsFromFormat(device->Format);
frameSize = numChannels * aluBytesFromFormat(device->Format);
ossSpeed = device->Frequency;
- log2FragmentSize = log2i(device->BufferSize * frameSize / periods);
+ log2FragmentSize = log2i(device->UpdateSize * device->NumUpdates *
+ frameSize / periods);
/* according to the OSS spec, 16 bytes are the minimum */
if (log2FragmentSize < 4)
@@ -381,7 +384,7 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
return ALC_FALSE;
}
- data->ring = CreateRingBuffer(frameSize, device->BufferSize);
+ data->ring = CreateRingBuffer(frameSize, device->UpdateSize * device->NumUpdates);
if(!data->ring)
{
AL_PRINT("ring buffer create failed\n");
diff --git a/Alc/portaudio.c b/Alc/portaudio.c
index 50039286..e7330999 100644
--- a/Alc/portaudio.c
+++ b/Alc/portaudio.c
@@ -90,7 +90,7 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
outParams.device = GetConfigValueInt("port", "device", -1);
if(outParams.device < 0)
outParams.device = pPa_GetDefaultOutputDevice();
- outParams.suggestedLatency = (float)device->BufferSize /
+ outParams.suggestedLatency = (device->UpdateSize*device->NumUpdates) /
(float)device->Frequency;
outParams.hostApiSpecificStreamInfo = NULL;
@@ -116,8 +116,7 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
outParams.channelCount = aluChannelsFromFormat(device->Format);
err = pPa_OpenStream(&data->stream, NULL, &outParams, device->Frequency,
- device->BufferSize/periods, paNoFlag,
- pa_callback, device);
+ device->UpdateSize, paNoFlag, pa_callback, device);
if(err != paNoError)
{
AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err));
@@ -138,7 +137,6 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
}
device->szDeviceName = strdup(deviceName);
- device->UpdateSize = device->BufferSize/periods;
device->Frequency = streamInfo->sampleRate;
return ALC_TRUE;
}
diff --git a/Alc/pulseaudio.c b/Alc/pulseaudio.c
index c5453344..53e864b2 100644
--- a/Alc/pulseaudio.c
+++ b/Alc/pulseaudio.c
@@ -342,17 +342,13 @@ static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{
ppa_threaded_mainloop_lock(data->loop);
- data->samples = device->BufferSize;
data->frame_size = aluBytesFromFormat(device->Format) *
aluChannelsFromFormat(device->Format);
-
- device->UpdateSize = device->BufferSize / 4;
-
data->attr.minreq = -1;
data->attr.prebuf = -1;
data->attr.maxlength = -1;
data->attr.fragsize = data->frame_size * device->UpdateSize;
- data->attr.tlength = data->attr.fragsize * 4;
+ data->attr.tlength = data->attr.fragsize * device->NumUpdates;
data->stream_name = "Playback Stream";
data->spec.rate = device->Frequency;
@@ -464,7 +460,7 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
data = device->ExtraData;
ppa_threaded_mainloop_lock(data->loop);
- data->samples = device->BufferSize;
+ data->samples = device->UpdateSize * device->NumUpdates;
data->frame_size = aluBytesFromFormat(device->Format) *
aluChannelsFromFormat(device->Format);
diff --git a/Alc/solaris.c b/Alc/solaris.c
index 5cc9e201..58d6e081 100644
--- a/Alc/solaris.c
+++ b/Alc/solaris.c
@@ -167,7 +167,7 @@ static ALCboolean solaris_reset_playback(ALCdevice *device)
info.play.channels = numChannels;
frameSize = numChannels * aluBytesFromFormat(device->Format);
- info.play.buffer_size = device->BufferSize * frameSize;
+ info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize;
if(ioctl(data->fd, AUDIO_SETINFO, &info) < 0)
{
@@ -189,7 +189,7 @@ static ALCboolean solaris_reset_playback(ALCdevice *device)
}
device->Frequency = info.play.sample_rate;
- device->UpdateSize = info.play.buffer_size / 4;
+ device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1;
data->data_size = device->UpdateSize * frameSize;
data->mix_data = calloc(1, data->data_size);
diff --git a/Alc/wave.c b/Alc/wave.c
index 958144a4..60739738 100644
--- a/Alc/wave.c
+++ b/Alc/wave.c
@@ -219,8 +219,6 @@ static ALCboolean wave_reset_playback(ALCdevice *device)
data->DataStart = ftell(data->f);
- device->UpdateSize = device->BufferSize / 4;
-
data->size = device->UpdateSize * channels * bits / 8;
data->buffer = malloc(data->size);
if(!data->buffer)
diff --git a/Alc/winmm.c b/Alc/winmm.c
index e2a4a7b9..5ecf471f 100644
--- a/Alc/winmm.c
+++ b/Alc/winmm.c
@@ -229,7 +229,8 @@ static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName
goto failure;
// Allocate circular memory buffer for the captured audio
- pData->ulCapturedDataSize = pDevice->BufferSize * wfexCaptureFormat.nBlockAlign;
+ pData->ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates *
+ wfexCaptureFormat.nBlockAlign;
// Make sure circular buffer is at least 100ms in size (and an exact multiple of
// the block alignment
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index a7fdb6ee..a334fabd 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -210,7 +210,7 @@ struct ALCdevice_struct
ALuint Frequency;
ALuint UpdateSize;
- ALuint BufferSize;
+ ALuint NumUpdates;
ALenum Format;
ALCchar *szDeviceName;
diff --git a/alsoftrc.sample b/alsoftrc.sample
index 45d5ba07..83795f34 100644
--- a/alsoftrc.sample
+++ b/alsoftrc.sample
@@ -52,10 +52,17 @@
# Sets the output frequency.
#frequency = 44100
-## refresh:
-# Sets the buffer size, in frames. Note that the actual granularity may or may
-# not be less than this.
-#refresh = 4096
+## period_size:
+# Sets the update period size, in frames. This is the number of frames needed
+# for each mixing update. If the deprecated 'refresh' option is specified and
+# this isn't, the value will be calculated as size = refresh/periods.
+#period_size = 1024
+
+## periods:
+# Sets the number of update periods. Higher values create a larger mix ahead,
+# which helps protect against skips when the CPU is under load, but increases
+# the delay between a sound getting mixed and being heard.
+#periods = 4
## sources:
# Sets the maximum number of allocatable sources. Lower values may help for
@@ -136,11 +143,6 @@
# Sets the device name for the default playback device.
#device = default
-## periods:
-# Sets the number of update buffers for playback. A value of 0 means auto-
-# select.
-#periods = 0
-
## capture:
# Sets the device name for the default capture device.
#capture = default
@@ -161,10 +163,6 @@
# Sets the device name for OSS output.
#device = /dev/dsp
-## periods:
-# Sets the number of update buffers.
-#periods = 4
-
## capture:
# Sets the device name for OSS capture.
#capture = /dev/dsp
@@ -178,13 +176,11 @@
# Sets the device name for Solaris output.
#device = /dev/audio
+##
## DirectSound backend stuff
+##
[dsound]
-## periods:
-# Sets the number of updates for the output buffer.
-#periods = 4
-
##
## Windows Multimedia backend stuff
##
@@ -200,10 +196,6 @@
# given by PortAudio itself.
#device = -1
-## periods:
-# Sets the number of update buffers.
-#periods = 4
-
##
## PulseAudio backend stuff
##