[Sumover-dev] [svn commit] r4394 - rat/trunk
sumover-dev at cs.ucl.ac.uk
sumover-dev at cs.ucl.ac.uk
Thu Feb 19 11:23:48 GMT 2009
Author: piers
Date: Thu Feb 19 11:23:47 2009
New Revision: 4394
Modified:
rat/trunk/auddev_alsa.c
Log:
- Includes a fix for when ALSA seems to fail to read audio on startup (particularly with PulseAudio) - despite ALSA reporting it is in 'RUNNING' state. This situation is detected by checking the status of the snd_pcm_status_get_avail_max() - if it is zero there's a problem and we call snd_pcm_prepare() followed by snd_pcm_start()
- Added and updated debug code - commented it out for normal use
Modified: rat/trunk/auddev_alsa.c
==============================================================================
--- rat/trunk/auddev_alsa.c (original)
+++ rat/trunk/auddev_alsa.c Thu Feb 19 11:23:47 2009
@@ -260,8 +260,11 @@
// Open type (Capture or Playback)
err = snd_pcm_open(&stream->handle, info->pcm_device,
type, SND_PCM_NONBLOCK);
- debug_msg("ALSA:open_stream: %s\n",info->pcm_device);
- if (err<0) { debug_msg("Card open failed"); return FALSE; }
+ if (err<0) {
+ debug_msg("snd_pcm_open failed for: \n",info->pcm_device);
+ return FALSE;
+ }
+ debug_msg("snd_pcm_open ok for: %s\n",info->pcm_device);
snd_pcm_hw_params_alloca (&hw_params);
@@ -297,7 +300,7 @@
// is number of channel * sample - e.g one stereo frame is two samples).
// We can't convert with the helper functions (snd_pcm_bytes_to_frames())
// at this point as they require a working handle, and ours isn't setup
- // yet. We use a factor RAT_ALSA_BUFFER_DIVISOR which is buffer size in
+ // yet. We use a factor RAT_ALSA_BUFFER_DIVISOR(60) which is buffer size in
// millisec(10^-3) - it seems we need
// We don't actually do anything with these values anyway.
bsize = snd_pcm_format_size (mapformat(fmt->encoding),
@@ -348,8 +351,20 @@
err = snd_pcm_sw_params(stream->handle, sw_params);
CHECKOPENERR("Failed to set SW params");
+ snd_pcm_sw_params_get_boundary(sw_params, &avail_min);
+ debug_msg("snd_pcm_sw_params_get_boundary %d\n",avail_min);
+ snd_pcm_sw_params_set_stop_threshold(stream->handle,sw_params, avail_min);
+ snd_pcm_sw_params_get_stop_threshold(sw_params, &avail_min);
+ debug_msg("snd_pcm_sw_params_get_stop_threshold %d\n",avail_min);
+ snd_pcm_sw_params_get_silence_size(sw_params, &avail_min);
+ debug_msg("snd_pcm_sw_params_get_silence_size %d\n",avail_min);
snd_pcm_sw_params_get_avail_min(sw_params, &avail_min);
debug_msg("min available value %d\n",avail_min);
+
+ snd_output_t *output = NULL;
+ snd_output_stdio_attach(&output, stdout, 0);
+ snd_pcm_dump_setup(stream->handle, output);
+ snd_pcm_dump(stream->handle, output);
return TRUE;
}
@@ -582,20 +597,21 @@
current.info = ratCards + ad;
current.bytes_per_block = infmt->bytes_per_block;
- debug_msg( "Open device for playback\n");
if (!open_stream(current.info, ¤t.tx,
SND_PCM_STREAM_PLAYBACK, outfmt)) {
alsa_audio_close(ad);
debug_msg( "Failed to open device for playback\n");
return FALSE;
}
- debug_msg( "Open device for capture\n");
+ debug_msg( "Opened device for playback\n");
+
if (!open_stream(current.info, ¤t.rx,
SND_PCM_STREAM_CAPTURE, infmt)) {
alsa_audio_close(ad);
debug_msg( "Failed to open device for capture\n");
return FALSE;
}
+ debug_msg( "Opened device for capture\n");
if (setup_mixers() == FALSE) {
alsa_audio_close(ad);
@@ -825,9 +841,9 @@
int alsa_audio_read(audio_desc_t ad __attribute__((unused)),
u_char *buf, int bytes)
{
- snd_pcm_sframes_t fread;
+ snd_pcm_sframes_t fread, bread, avail;
int err;
- int read_interval;
+ long read_interval;
struct timeval curr_time;
static struct timeval last_read_time;
@@ -838,29 +854,37 @@
debug_msg("Handling mixer event\n");
}
- snd_pcm_sframes_t frames = snd_pcm_bytes_to_frames(current.rx.handle,bytes);
-
+ snd_pcm_sframes_t frames = snd_pcm_bytes_to_frames(current.rx.handle,current.bytes_per_block);
read_interval = (curr_time.tv_sec - last_read_time.tv_sec) * 1000000 + (curr_time.tv_usec - last_read_time.tv_usec);
- //debug_msg("Frames avail to be read=%d, time diff=%d\n",snd_pcm_avail_update(current.rx.handle), read_interval);
+ avail = snd_pcm_avail_update(current.rx.handle);
+ //debug_msg("Frames avail to be read=%d, time diff=%ld, want: %d frames, %d bytes (bytepb %d\n",avail, read_interval, frames, bytes, current.bytes_per_block);
last_read_time.tv_sec=curr_time.tv_sec;
last_read_time.tv_usec=curr_time.tv_usec;
+ if (avail < frames)
+ return 0;
+ frames = snd_pcm_bytes_to_frames(current.rx.handle,bytes);
fread = snd_pcm_readi(current.rx.handle, buf, frames);
if (fread >= 0) {
// Normal case
- fread = snd_pcm_frames_to_bytes(current.rx.handle, fread);
- //debug_msg("Read %d bytes\n", fread);
- return fread;
+ bread = snd_pcm_frames_to_bytes(current.rx.handle, fread);
+ gettimeofday(&curr_time, NULL);
+ read_interval = (curr_time.tv_sec - last_read_time.tv_sec) * 1000000 + (curr_time.tv_usec - last_read_time.tv_usec);
+ //debug_msg("Read %d bytes (%d frames) took %ld usecs\n", bread, fread, read_interval);
+ return bread;
}
- // Something happened
+ // Something happened
switch (fread)
{
case -EAGAIN:
- // Normal when non-blocking
- return 0;
+ // Normal when non-blocking
+ gettimeofday(&curr_time, NULL);
+ read_interval = (curr_time.tv_sec - last_read_time.tv_sec) * 1000000 + (curr_time.tv_usec - last_read_time.tv_usec);
+ debug_msg("failed %d Read %d bytes (%d frames) took %ld usecs\n", fread, bread, fread, read_interval);
+ return 0;
case -EPIPE:
debug_msg("Got capture overrun XRUN (EPIPE)\n");
@@ -881,7 +905,7 @@
return FALSE;
default:
- //debug_msg("Read failed status= %s\n", snd_strerror(fread));
+ debug_msg("Read failed status= %s\n", snd_strerror(fread));
return 0;
}
}
@@ -897,8 +921,19 @@
int fwritten, err, num_bytes=0 ,read_interval;
struct timeval curr_time;
static struct timeval last_read_time;
+ snd_pcm_sframes_t delay;
snd_pcm_sframes_t frames =
snd_pcm_bytes_to_frames(current.tx.handle,bytes);
+ snd_output_t *output = NULL;
+ snd_output_stdio_attach(&output, stdout, 0);
+
+ snd_pcm_status_t *status;
+ snd_pcm_status_alloca(&status);
+ err = snd_pcm_status(current.tx.handle, status);
+ if (err<0) {
+ debug_msg("Can't get status of tx");
+ return FALSE;
+ }
gettimeofday(&curr_time, NULL);
///debug_msg("Audio write %d\n", bytes);
@@ -912,10 +947,12 @@
break;
default:
break;
- }
+ }
read_interval = (curr_time.tv_sec - last_read_time.tv_sec) * 1000000 + (curr_time.tv_usec - last_read_time.tv_usec);
+ snd_pcm_delay(current.tx.handle, &delay);
- //debug_msg("Frames avail to be written=%d, time diff=%d\n",snd_pcm_avail_update(current.tx.handle), read_interval);
+ //debug_msg("Frames avail to be written=%d, time diff=%d, Trying to write %d frames, Curr delay %d \n",snd_pcm_avail_update(current.tx.handle), read_interval, frames, delay);
+ //snd_pcm_status_dump(status, output);
last_read_time.tv_sec=curr_time.tv_sec;
last_read_time.tv_usec=curr_time.tv_usec;
@@ -924,9 +961,11 @@
// Normal case
num_bytes = snd_pcm_frames_to_bytes(current.tx.handle, fwritten);
//debug_msg("Wrote %d bytes, frames: %d\n", num_bytes, fwritten);
+ err = snd_pcm_status(current.tx.handle, status);
+ //snd_pcm_status_dump(status, output);
return num_bytes;
}
- //debug_msg("Err: Tried to Write %d bytes, frames: %d, but got: %d\n", bytes,frames, fwritten);
+ debug_msg("Err: Tried to Write %d bytes, frames: %d, but got: %d\n", bytes,frames, fwritten);
// Something happened
switch (fwritten)
@@ -936,7 +975,7 @@
return 0;
case -EPIPE:
- debug_msg("Got transmit underun XRUN (EPIPE)\n");
+ debug_msg("Got transmit underun XRUN(EPIPE) when trying to write audio\n");
err = snd_pcm_prepare(current.tx.handle);
if (err<0) debug_msg("Failed snd_pcm_prepare from Transmit underrun\n");
debug_msg("Attempting Recovery from transmit underrun: Bytes:%d Frames:%d\n",num_bytes,fwritten);
@@ -947,6 +986,8 @@
} else {
num_bytes = snd_pcm_frames_to_bytes(current.tx.handle, fwritten);
debug_msg("Recovered from transmit underrun: Bytes:%d Frames:%d\n",num_bytes,fwritten);
+ err = snd_pcm_status(current.tx.handle, status);
+ snd_pcm_status_dump(status, output);
return num_bytes;
}
@@ -1124,19 +1165,34 @@
snd_pcm_uframes_t avail;
int err;
snd_pcm_sframes_t frames;
+ snd_output_t *output = NULL;
+ snd_output_stdio_attach(&output, stdout, 0);
snd_pcm_status_alloca(&status);
+
err = snd_pcm_status(current.rx.handle, status);
if (err<0) {
debug_msg("Can't get status of rx");
return FALSE;
}
- //frames= snd_pcm_avail_update(current.rx.handle);
- avail = snd_pcm_frames_to_bytes(current.rx.handle,
-// frames);
+
+ if (!snd_pcm_status_get_avail_max(status)) {
+ debug_msg("Resetting audio as statusmaxframes is zero\n");
+ err = snd_pcm_prepare(current.rx.handle);
+ if (err<0) debug_msg("Failed snd_pcm_prepare in audio_ready");
+ err = snd_pcm_start(current.rx.handle);
+ if (err<0) debug_msg("Failed to re-start in audio_ready");
+ //dump status
+ snd_pcm_status_dump(status, output);
+ frames= snd_pcm_avail_update(current.rx.handle);
+ debug_msg("audio_is_ready: snd_pcm_avail_update(current.rx.handle);: %d\n", snd_pcm_avail_update(current.rx.handle));
+ debug_msg("audio_is_ready: %d bytes (btye per blk %d), frames: %d\n", avail, current.bytes_per_block, frames);
+ }
+
+ avail = snd_pcm_frames_to_bytes(current.rx.handle, //frames
snd_pcm_status_get_avail(status));
- //debug_msg("Audio Is ready == %d, frames: %d\n", avail, frames);
+
return (avail >= current.bytes_per_block);
}
More information about the Sumover-dev
mailing list