------------------------------------------------------------------------

r4191 | acceptthis | 2013-02-10 17:19:47 +0000 (Sun, 10 Feb 2013) | 1 line

Try to fix alsa latencies. Again.
------------------------------------------------------------------------


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4189 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2013-03-12 22:48:31 +00:00
parent c23206fefd
commit 051a32d742

View file

@ -53,9 +53,11 @@ int (*psnd_pcm_sw_params_set_stop_threshold) (snd_pcm_t *pcm, snd_pcm_sw_params_
int (*psnd_pcm_sw_params) (snd_pcm_t *pcm, snd_pcm_sw_params_t *params); int (*psnd_pcm_sw_params) (snd_pcm_t *pcm, snd_pcm_sw_params_t *params);
int (*psnd_pcm_hw_params_get_buffer_size) (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); int (*psnd_pcm_hw_params_get_buffer_size) (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val);
int (*psnd_pcm_hw_params_set_buffer_size_near) (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); int (*psnd_pcm_hw_params_set_buffer_size_near) (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val);
int (*psnd_pcm_set_params) (snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency);
snd_pcm_sframes_t (*psnd_pcm_avail_update) (snd_pcm_t *pcm); snd_pcm_sframes_t (*psnd_pcm_avail_update) (snd_pcm_t *pcm);
snd_pcm_state_t (*psnd_pcm_state) (snd_pcm_t *pcm); snd_pcm_state_t (*psnd_pcm_state) (snd_pcm_t *pcm);
int (*psnd_pcm_start) (snd_pcm_t *pcm); int (*psnd_pcm_start) (snd_pcm_t *pcm);
int (*psnd_pcm_recover) (snd_pcm_t *pcm, int err, int silent);
size_t (*psnd_pcm_hw_params_sizeof) (void); size_t (*psnd_pcm_hw_params_sizeof) (void);
size_t (*psnd_pcm_sw_params_sizeof) (void); size_t (*psnd_pcm_sw_params_sizeof) (void);
@ -113,6 +115,12 @@ static unsigned int ALSA_RW_GetDMAPos (soundcardinfo_t *sc)
{ {
int frames; int frames;
frames = psnd_pcm_avail_update(sc->handle); frames = psnd_pcm_avail_update(sc->handle);
if (frames < 0)
{
psnd_pcm_start (sc->handle);
psnd_pcm_recover(sc->handle, frames, true);
frames = psnd_pcm_avail_update(sc->handle);
}
if (frames >= 0) if (frames >= 0)
{ {
sc->sn.samplepos = (sc->snd_sent + frames) * sc->sn.numchannels; sc->sn.samplepos = (sc->snd_sent + frames) * sc->sn.numchannels;
@ -121,45 +129,47 @@ static unsigned int ALSA_RW_GetDMAPos (soundcardinfo_t *sc)
} }
static void ALSA_RW_Submit (soundcardinfo_t *sc, int start, int end) static void ALSA_RW_Submit (soundcardinfo_t *sc, int start, int end)
{ {
int state; // int state;
unsigned int frames, offset, ringsize; unsigned int frames, offset, ringsize;
unsigned chunk; unsigned chunk;
int result; int result;
int stride = sc->sn.numchannels * (sc->sn.samplebits/8); int stride = sc->sn.numchannels * (sc->sn.samplebits/8);
/*we can't change the data that was already written*/ while(1)
frames = end - sc->snd_sent;
if (!frames)
return;
state = psnd_pcm_state (sc->handle);
ringsize = sc->sn.samples / sc->sn.numchannels;
chunk = frames;
offset = sc->snd_sent % ringsize;
if (offset + chunk >= ringsize)
chunk = ringsize - offset;
result = psnd_pcm_writei(sc->handle, sc->sn.buffer + offset*stride, chunk);
if (result < chunk)
{ {
if (result >= 0) /*we can't change the data that was already written*/
sc->snd_sent += result; frames = end - sc->snd_sent;
return; if (frames <= 0)
} return;
sc->snd_sent += chunk;
chunk = frames - chunk; // state = psnd_pcm_state (sc->handle);
if (chunk)
{
result = psnd_pcm_writei(sc->handle, sc->sn.buffer, chunk);
if (result > 0)
sc->snd_sent += result;
}
if (state == SND_PCM_STATE_PREPARED) ringsize = sc->sn.samples / sc->sn.numchannels;
psnd_pcm_start (sc->handle);
chunk = frames;
offset = sc->snd_sent % ringsize;
if (offset + chunk >= ringsize)
chunk = ringsize - offset;
result = psnd_pcm_writei(sc->handle, sc->sn.buffer + offset*stride, chunk);
if (result < chunk)
{
if (result < 0)
return;
}
sc->snd_sent += chunk;
chunk = frames - chunk;
if (chunk)
{
result = psnd_pcm_writei(sc->handle, sc->sn.buffer, chunk);
if (result > 0)
sc->snd_sent += result;
}
// if (state == SND_PCM_STATE_PREPARED)
// psnd_pcm_start (sc->handle);
};
} }
static void ALSA_Shutdown (soundcardinfo_t *sc) static void ALSA_Shutdown (soundcardinfo_t *sc)
@ -221,6 +231,8 @@ static qboolean Alsa_InitAlsa(void)
psnd_pcm_avail_update = dlsym(alsasharedobject, "snd_pcm_avail_update"); psnd_pcm_avail_update = dlsym(alsasharedobject, "snd_pcm_avail_update");
psnd_pcm_state = dlsym(alsasharedobject, "snd_pcm_state"); psnd_pcm_state = dlsym(alsasharedobject, "snd_pcm_state");
psnd_pcm_start = dlsym(alsasharedobject, "snd_pcm_start"); psnd_pcm_start = dlsym(alsasharedobject, "snd_pcm_start");
psnd_pcm_recover = dlsym(alsasharedobject, "snd_pcm_recover");
psnd_pcm_set_params = dlsym(alsasharedobject, "snd_pcm_set_params");
psnd_pcm_hw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_hw_params_sizeof"); psnd_pcm_hw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_hw_params_sizeof");
psnd_pcm_sw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_sw_params_sizeof"); psnd_pcm_sw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_sw_params_sizeof");
psnd_pcm_hw_params_set_buffer_size_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_buffer_size_near"); psnd_pcm_hw_params_set_buffer_size_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_buffer_size_near");
@ -314,8 +326,24 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
} }
Con_Printf ("ALSA: Using PCM %s.\n", pcmname); Con_Printf ("ALSA: Using PCM %s.\n", pcmname);
#if 1
err = psnd_pcm_set_params(pcm, ((sc->sn.samplebits==8)?SND_PCM_FORMAT_U8:SND_PCM_FORMAT_S16), (mmap?SND_PCM_ACCESS_MMAP_INTERLEAVED:SND_PCM_ACCESS_RW_INTERLEAVED), sc->sn.numchannels, sc->sn.speed, true, 0.04*1000000);
if (0 > err)
{
Con_Printf (CON_ERROR "ALSA: error setting params. %s\n",
psnd_strerror (err));
goto error;
}
// sc->sn.numchannels = stereo;
// sc->sn.samplepos = 0;
// sc->sn.samplebits = bps;
sc->samplequeue = buffer_size = 2048;
#else
err = psnd_pcm_hw_params_any (pcm, hw); err = psnd_pcm_hw_params_any (pcm, hw);
if (0 > err) { if (0 > err)
{
Con_Printf (CON_ERROR "ALSA: error setting hw_params_any. %s\n", Con_Printf (CON_ERROR "ALSA: error setting hw_params_any. %s\n",
psnd_strerror (err)); psnd_strerror (err));
goto error; goto error;
@ -401,7 +429,8 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
frag_size = 8 * bps; frag_size = 8 * bps;
err = psnd_pcm_hw_params_set_period_size_near (pcm, hw, &frag_size, 0); err = psnd_pcm_hw_params_set_period_size_near (pcm, hw, &frag_size, 0);
if (0 > err) { if (0 > err)
{
Con_Printf (CON_ERROR "ALSA: unable to set period size near %i. %s\n", Con_Printf (CON_ERROR "ALSA: unable to set period size near %i. %s\n",
(int) frag_size, psnd_strerror (err)); (int) frag_size, psnd_strerror (err));
goto error; goto error;
@ -458,9 +487,10 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
psnd_strerror (err)); psnd_strerror (err));
goto error; goto error;
} }
sc->sn.speed = rate;
#endif
sc->sn.samples = buffer_size * sc->sn.numchannels; // mono samples in buffer sc->sn.samples = buffer_size * sc->sn.numchannels; // mono samples in buffer
sc->sn.speed = rate;
sc->handle = pcm; sc->handle = pcm;
sc->Lock = ALSA_LockBuffer; sc->Lock = ALSA_LockBuffer;