[Sumover-dev] [svn commit] r3968 - rat/trunk
sumover-dev at cs.ucl.ac.uk
sumover-dev at cs.ucl.ac.uk
Fri Mar 2 18:31:28 GMT 2007
Author: piers
Date: Fri Mar 2 18:30:59 2007
New Revision: 3968
Modified:
rat/trunk/auddev_alsa.c
rat/trunk/auddev_alsa.h
rat/trunk/audio_fmt.c
rat/trunk/audio_types.h
rat/trunk/transmit.c
Log:
Updates for ALSA:
- Added more info on ALSA setup - buffer sizes are in frames and period size - which should be of the order of the current bytes_per_block (the size of data
reqired for a packet using the current codec)
- Debug code to try to work why underrun XRUN is occurring (still NOT fixed - it seems to be related to cushion size but it's not clear where the prob is)
- Minor change for Audigy style cards which don't have a 'capture swictches'
- Moved mixer update calls to mixer upate functions - instead of using the global variable from earlier - seems to work, and makes more sense.
- Added some more informative comments around the place.
Modified: rat/trunk/auddev_alsa.c
==============================================================================
--- rat/trunk/auddev_alsa.c (original)
+++ rat/trunk/auddev_alsa.c Fri Mar 2 18:30:59 2007
@@ -250,9 +250,11 @@
snd_pcm_sw_params_t *sw_params;
/* Set avail min inside a software configuration container */
/* Can we tweak this up/down?*/
- snd_pcm_uframes_t avail_min=100; //4
+ //snd_pcm_uframes_t avail_min=100; //4
+ snd_pcm_uframes_t avail_min=4;
snd_pcm_uframes_t xfer_align=1;
+ // 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);
@@ -288,32 +290,38 @@
return FALSE;
}
- // Setup the buffer size. This stuff's all in frames, BTW. We can't
- // convert with the helper functions at this point as they require
- // a working handle, and ours isn't setup yet. We don't actually do
- // anything with these values anyway.
+ // Setup the buffer size. This stuff's all in frames (one frame
+ // 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
+ // 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),
fmt->sample_rate / RAT_ALSA_BUFFER_DIVISOR);
+ debug_msg("Bsize1 == %d\n", bsize);
bsize = (fmt->sample_rate * (fmt->bits_per_sample/8) * fmt->channels* RAT_ALSA_BUFFER_DIVISOR)/ (1000);
- //* fmt->bytes_per_block
+ debug_msg("Bsize2 == %d\n", bsize);
+ bsize = (fmt->sample_rate*RAT_ALSA_BUFFER_DIVISOR)/1000;
frames = bsize;
+ debug_msg("sample_rate, bytes_per_block == %d, %d\n", fmt->sample_rate, fmt->bytes_per_block);
debug_msg("Bsize == %d\n", bsize);
err = snd_pcm_hw_params_set_buffer_size_near(stream->handle, hw_params,
&frames);
CHECKOPENERR("Failed to set buffer size");
stream->buffer_size = frames;
- debug_msg("Buffer == %d\n", stream->buffer_size);
+ debug_msg("Return Bsize == %d\n", stream->buffer_size);
- frames = stream->buffer_size / 2;
+ frames= fmt->bytes_per_block / ((fmt->bits_per_sample/8)* fmt->channels);
+ frames= bsize /(RAT_ALSA_BUFFER_DIVISOR/10);
err = snd_pcm_hw_params_set_period_size_near(stream->handle, hw_params,
&frames, &dir);
- stream->buffer_size = frames;
CHECKOPENERR("Failed to set period size");
stream->period_size = frames;
- debug_msg("Period == %d\n", stream->period_size);
+ debug_msg("Returned Period == %d\n", stream->period_size);
err = snd_pcm_hw_params (stream->handle, hw_params);
CHECKOPENERR("Failed to install HW parameters");
@@ -325,10 +333,10 @@
CHECKOPENERR("Failed to initialise SW params");
err = snd_pcm_sw_params_set_start_threshold(stream->handle, sw_params,
- stream->buffer_size);
+ stream->period_size);
CHECKOPENERR("Failed to set threshold value");
- err = snd_pcm_sw_params_set_avail_min(stream->handle, sw_params, avail_min);
+ err = snd_pcm_sw_params_set_avail_min(stream->handle, sw_params, stream->period_size);
CHECKOPENERR("Failed to set min available value");
err = snd_pcm_sw_params_set_xfer_align(stream->handle,sw_params,xfer_align);
@@ -337,6 +345,8 @@
err = snd_pcm_sw_params(stream->handle, sw_params);
CHECKOPENERR("Failed to set SW params");
+ snd_pcm_sw_params_get_avail_min(sw_params, &avail_min);
+ debug_msg("min available value %d\n",avail_min);
return TRUE;
}
@@ -377,10 +387,12 @@
debug_msg("Got volume control %s of type CAPTURE\n", name);
snd_mixer_selem_set_capture_volume_range (*ctl, 0, 100);
- err = snd_mixer_selem_set_capture_switch_all(*ctl, 1);
- if (err<0) {
- debug_msg("Failed to switch on capture volume");
- return FALSE;
+ if (snd_mixer_selem_has_capture_switch(*ctl)) {
+ err = snd_mixer_selem_set_capture_switch_all(*ctl, 1);
+ if (err<0) {
+ debug_msg("Failed to switch on capture volume");
+ return FALSE;
+ }
}
} else {
@@ -562,13 +574,14 @@
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( "to open device for capture\n");
+ debug_msg( "Open device for capture\n");
if (!open_stream(current.info, ¤t.rx,
SND_PCM_STREAM_CAPTURE, infmt)) {
alsa_audio_close(ad);
@@ -645,7 +658,57 @@
err = snd_pcm_drain(current.rx.handle);
if (err<0) debug_msg("Problem draining input\n");
}
-
+
+static void handle_mixer_events(snd_mixer_t *mixer_handle)
+{
+ int count, err;
+ struct pollfd *fds;
+ int num_revents = 0;
+ unsigned short revents;
+
+ /* Get count of poll descriptors for mixer handle */
+ if ((count = snd_mixer_poll_descriptors_count(mixer_handle)) < 0) {
+ debug_msg("Error in snd_mixer_poll_descriptors_count(%d)\n", count);
+ return;
+ }
+
+ fds =(struct pollfd*)calloc(count, sizeof(struct pollfd));
+ if (fds == NULL) {
+ debug_msg("snd_mixer fds calloc err\n");
+ return;
+ }
+
+ if ((err = snd_mixer_poll_descriptors(mixer_handle, fds, count)) < 0){
+ debug_msg ("snd_mixer_poll_descriptors err=%d\n", err);
+ free(fds);
+ return;
+ }
+
+ if (err != count){
+ debug_msg ("snd_mixer_poll_descriptors (err(%d) != count(%d))\n",err,count);
+ free(fds);
+ return;
+ }
+
+ num_revents = poll(fds, count, 1);
+
+ /* Graceful handling of signals recvd in poll() */
+ if (num_revents < 0 && errno == EINTR)
+ num_revents = 0;
+
+ if (num_revents > 0) {
+ if (snd_mixer_poll_descriptors_revents(mixer_handle, fds, count, &revents) >= 0) {
+ if (revents & POLLNVAL)
+ debug_msg ("snd_mixer_poll_descriptors (POLLNVAL)\n");
+ if (revents & POLLERR)
+ debug_msg ("snd_mixer_poll_descriptors (POLLERR)\n");
+ if (revents & POLLIN)
+ snd_mixer_handle_events(mixer_handle);
+ }
+ }
+ free(fds);
+}
+
/*
@@ -672,7 +735,8 @@
err = snd_mixer_selem_set_capture_volume_all(iports[current.iport].smixer_elem, gain);
if(err<0) debug_msg("Failed to set capture volume\n");
}
- mixer_state_change = 1;
+handle_mixer_events(current.mixer);
+// mixer_state_change = 1;
}
@@ -724,7 +788,8 @@
err = snd_mixer_selem_set_playback_volume_all(current.txgain, vol);
if(err<0) debug_msg("Couldn't set mixer playback volume");
- mixer_state_change = 1;
+handle_mixer_events(current.mixer);
+// mixer_state_change = 1;
}
/*
@@ -744,56 +809,6 @@
return (int)ogain;
}
-static void handle_mixer_events(snd_mixer_t *mixer_handle)
-{
- int count, err;
- struct pollfd *fds;
- int num_revents = 0;
- unsigned short revents;
-
- /* Get count of poll descriptors for mixer handle */
- if ((count = snd_mixer_poll_descriptors_count(mixer_handle)) < 0) {
- debug_msg("Error in snd_mixer_poll_descriptors_count(%d)\n", count);
- return;
- }
-
- fds =(struct pollfd*)calloc(count, sizeof(struct pollfd));
- if (fds == NULL) {
- debug_msg("snd_mixer fds calloc err\n");
- return;
- }
-
- if ((err = snd_mixer_poll_descriptors(mixer_handle, fds, count)) < 0){
- debug_msg ("snd_mixer_poll_descriptors err=%d\n", err);
- free(fds);
- return;
- }
-
- if (err != count){
- debug_msg ("snd_mixer_poll_descriptors (err(%d) != count(%d))\n",err,count);
- free(fds);
- return;
- }
- errno = 0;
-
- num_revents = poll(fds, count, 1);
-
- /* Graceful handling of signals recvd in poll() */
- if (num_revents < 0 && errno == EINTR)
- num_revents = 0;
-
- if (num_revents > 0) {
- if (snd_mixer_poll_descriptors_revents(mixer_handle, fds, count, &revents) >= 0) {
- if (revents & POLLNVAL)
- debug_msg ("snd_mixer_poll_descriptors (POLLNVAL)\n");
- if (revents & POLLERR)
- debug_msg ("snd_mixer_poll_descriptors (POLLERR)\n");
- if (revents & POLLIN)
- snd_mixer_handle_events(mixer_handle);
- }
- }
- free(fds);
-}
/*
* Record audio data.
@@ -804,14 +819,25 @@
{
snd_pcm_sframes_t fread;
int err;
+ int read_interval;
+ struct timeval curr_time;
+ static struct timeval last_read_time;
+ gettimeofday(&curr_time, NULL);
if (mixer_state_change) {
mixer_state_change=0;
handle_mixer_events (current.mixer);
+ debug_msg("Handling mixer event\n");
}
snd_pcm_sframes_t frames = snd_pcm_bytes_to_frames(current.rx.handle,bytes);
+ 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);
+ last_read_time.tv_sec=curr_time.tv_sec;
+ last_read_time.tv_usec=curr_time.tv_usec;
+
+
fread = snd_pcm_readi(current.rx.handle, buf, frames);
if (fread >= 0) {
@@ -829,7 +855,7 @@
return 0;
case -EPIPE:
- debug_msg("Got capture XRUN (EPIPE)\n");
+ debug_msg("Got capture overrun XRUN (EPIPE)\n");
err = snd_pcm_prepare(current.rx.handle);
if (err<0) debug_msg("Failed snd_pcm_prepare from capture overrun");
err = snd_pcm_start(current.rx.handle);
@@ -860,19 +886,39 @@
int alsa_audio_write(audio_desc_t ad __attribute__((unused)),
u_char *buf, int bytes)
{
- int fwritten, err, num_bytes=0;
+ int fwritten, err, num_bytes=0 ,read_interval;
+ struct timeval curr_time;
+ static struct timeval last_read_time;
snd_pcm_sframes_t frames =
snd_pcm_bytes_to_frames(current.tx.handle,bytes);
+ gettimeofday(&curr_time, NULL);
///debug_msg("Audio write %d\n", bytes);
+ switch (snd_pcm_state(current.tx.handle)) {
+ case SND_PCM_STATE_RUNNING:
+ //debug_msg("In SND_PCM_STATE_RUNNING \n");
+ break;
+ case SND_PCM_STATE_XRUN:
+ debug_msg("In SND_PCM_STATE_XRUN - preparing audio \n");
+ err = snd_pcm_prepare(current.tx.handle);
+ break;
+ default:
+ break;
+ }
+ 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 written=%d, time diff=%d\n",snd_pcm_avail_update(current.tx.handle), read_interval);
+ last_read_time.tv_sec=curr_time.tv_sec;
+ last_read_time.tv_usec=curr_time.tv_usec;
fwritten = snd_pcm_writei(current.tx.handle, buf, frames);
if (fwritten >= 0) {
// Normal case
num_bytes = snd_pcm_frames_to_bytes(current.tx.handle, fwritten);
- debug_msg("Wrote %d bytes, frames: %d\n", num_bytes, fwritten);
+ //debug_msg("Wrote %d bytes, frames: %d\n", num_bytes, fwritten);
return num_bytes;
}
+ //debug_msg("Err: Tried to Write %d bytes, frames: %d, but got: %d\n", bytes,frames, fwritten);
// Something happened
switch (fwritten)
@@ -882,17 +928,17 @@
return 0;
case -EPIPE:
- debug_msg("Got transmit XRUN (EPIPE)\n");
+ debug_msg("Got transmit underun XRUN (EPIPE)\n");
err = snd_pcm_prepare(current.tx.handle);
- if (err<0) debug_msg("Failed snd_pcm_prepare from Transmit overrun\n");
- debug_msg("Attempting Recovery from transmit overrun: Bytes:%d Frames:%d\n",num_bytes,fwritten);
+ 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);
fwritten = snd_pcm_writei(current.tx.handle, buf, frames);
if (fwritten<0) {
- debug_msg("Can't recover from transmit overrun\n");
+ debug_msg("Can't recover from transmit underrun\n");
return 0;
} else {
num_bytes = snd_pcm_frames_to_bytes(current.tx.handle, fwritten);
- debug_msg("Recovered from transmit overrun: Bytes:%d Frames:%d\n",num_bytes,fwritten);
+ debug_msg("Recovered from transmit underrun: Bytes:%d Frames:%d\n",num_bytes,fwritten);
return num_bytes;
}
@@ -1025,7 +1071,8 @@
}
}
}
- mixer_state_change = 1;
+handle_mixer_events(current.mixer);
+// mixer_state_change = 1;
}
@@ -1065,6 +1112,7 @@
snd_pcm_status_t *status;
snd_pcm_uframes_t avail;
int err;
+ snd_pcm_sframes_t frames;
snd_pcm_status_alloca(&status);
err = snd_pcm_status(current.rx.handle, status);
@@ -1073,9 +1121,11 @@
return FALSE;
}
+ //frames= snd_pcm_avail_update(current.rx.handle);
avail = snd_pcm_frames_to_bytes(current.rx.handle,
+// frames);
snd_pcm_status_get_avail(status));
- //debug_msg("Audio ready == %d\n", avail);
+ //debug_msg("Audio Is ready == %d, frames: %d\n", avail, frames);
return (avail >= current.bytes_per_block);
}
Modified: rat/trunk/auddev_alsa.h
==============================================================================
--- rat/trunk/auddev_alsa.h (original)
+++ rat/trunk/auddev_alsa.h Fri Mar 2 18:30:59 2007
@@ -23,7 +23,7 @@
/* Buffer length, in milliseconds. This value is used to
* divide the sample-rate to define the buffer-size. */
-#define RAT_ALSA_BUFFER_DIVISOR 40
+#define RAT_ALSA_BUFFER_DIVISOR 60
// External prototypes
int alsa_audio_open (audio_desc_t ad, audio_format* ifmt, audio_format *ofmt);
Modified: rat/trunk/audio_fmt.c
==============================================================================
--- rat/trunk/audio_fmt.c (original)
+++ rat/trunk/audio_fmt.c Fri Mar 2 18:30:59 2007
@@ -468,7 +468,9 @@
break;
}
+ debug_msg("audio_format_change_encoding,bitsPerSam = %d, bytesPerBlk = %d ,", bits_per_sample, cur->bytes_per_block);
cur->bytes_per_block = cur->bytes_per_block * bits_per_sample / cur->bits_per_sample;
+ debug_msg("new bpb = %d\n ",cur->bytes_per_block);
cur->bits_per_sample = bits_per_sample;
cur->encoding = new_enc;
/* If this is zero something has gone wrong! */
Modified: rat/trunk/audio_types.h
==============================================================================
--- rat/trunk/audio_types.h (original)
+++ rat/trunk/audio_types.h Fri Mar 2 18:30:59 2007
@@ -29,12 +29,12 @@
typedef struct s_audio_format {
deve_e encoding;
uint32_t sample_rate; /* Should be one of 8000, 16000, 24000, 32000, 48000 */
- int bits_per_sample; /* Should be 8 or 16 */
- int channels; /* Should be 1 or 2 */
- int bytes_per_block; /* size of unit we will read/write in */
+ int bits_per_sample; /* Should be 8 or 16 */
+ int channels; /* Should be 1 or 2 */
+ int bytes_per_block; /* size of unit we will read/write in - which is defined by the codec - see the codec_format_t structures in each codec - typically multiples of 20ms (160 samples at 8KHz) and bytes_per_sample */
} audio_format;
-typedef int16_t sample; /* Sample representation 16 bit signed */
+typedef int16_t sample; /* Sample representation 16 bit signed */
/* Macro's reserved for future work, ie internal 16bit and 32bit samples */
typedef int16_t sample16_t;
Modified: rat/trunk/transmit.c
==============================================================================
--- rat/trunk/transmit.c (original)
+++ rat/trunk/transmit.c Fri Mar 2 18:30:59 2007
@@ -296,6 +296,7 @@
tx_unit *u;
timestamp_t u_ts;
uint32_t read_dur = 0, this_read, ulen;
+ //int times=0;
tx_buffer_validate(tb);
@@ -318,8 +319,10 @@
filled_unit = FALSE;
u->dur_used += this_read;
+ //debug_msg("Reading %d to get unit dur: %d (used:%d), this read: %d\n", ++times,tb->unit_dur, u->dur_used, this_read);
if (u->dur_used == tb->unit_dur) {
read_dur += tb->unit_dur;
+ //debug_msg("Got %d to get unit, unit dur: %d (used:%d)\n", times,tb->unit_dur, u->dur_used);
if (sp->in_file) {
/* Reading from a file overwrites any audio we've captured... */
tx_read_sndfile(sp, tb->sample_rate, tb->channels, u);
@@ -330,7 +333,8 @@
/* We've filled one unit, so create the next one... */
tx_unit_create(tb, &u, tb->unit_dur * tb->channels);
pb_add(tb->audio_buffer, (u_char*)u, ulen, u_ts);
- pb_iterator_advance(tb->reading);
+ if (pb_iterator_advance(tb->reading)==FALSE)
+ debug_msg("***********************pb_iterator_advance FALSE\n");
}
} while (filled_unit == TRUE);
assert(pb_iterator_count(tb->audio_buffer) == 3);
More information about the Sumover-dev
mailing list