[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, &current.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, &current.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