Store the number of periods in the device instead of the buffer size

Also keep all the fields in sync
This commit is contained in:
Chris Robinson 2009-09-16 22:58:54 -07:00
parent 94e3fca702
commit cbcaa54173
11 changed files with 72 additions and 71 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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");

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -210,7 +210,7 @@ struct ALCdevice_struct
ALuint Frequency;
ALuint UpdateSize;
ALuint BufferSize;
ALuint NumUpdates;
ALenum Format;
ALCchar *szDeviceName;

View File

@ -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
##