[xiph-commits] r17666 - trunk/squishyball

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Sat Nov 27 11:51:58 PST 2010


Author: xiphmont
Date: 2010-11-27 11:51:58 -0800 (Sat, 27 Nov 2010)
New Revision: 17666

Modified:
   trunk/squishyball/main.c
   trunk/squishyball/main.h
   trunk/squishyball/mincurses.c
   trunk/squishyball/squishyball.1
   trunk/squishyball/tty.c
Log:
All basic functionality implemented; now for testing/debugging.



Modified: trunk/squishyball/main.c
===================================================================
--- trunk/squishyball/main.c	2010-11-27 16:27:01 UTC (rev 17665)
+++ trunk/squishyball/main.c	2010-11-27 19:51:58 UTC (rev 17666)
@@ -1416,24 +1416,24 @@
           "  -x --xxy               : Perform randomized X/X/Y test.\n"
           "\n"
           "INTERACTION:\n"
-          "   a b x   : Switch playback between A, B [and X] samples.\n"
-          "    A B    : Choose A or B sample for A/B[/X] trial result.\n"
-          "  1 2 3... : Switch between first, second, etc samples.\n"
-          "   ! @ #   : Choose sample 1, 2, or 3 for X/X/Y trial result.\n"
-          "<ins> <del>: Undo/redo last trial result selection.\n"
-          "  <enter>  : Choose current sample for this trial\n"
-          "   <- ->   : Seek back/forward two seconds, +shift for 10 seconds\n"
-          " <up/down> : Select sample from list (casual mode)\n"
-          "  <space>  : Pause/resume playback\n"
-          " <backspc> : Reset playback to start point\n"
-          "     e     : set end playback point to current playback time.\n"
-          "     E     : reset end playback time to end of sample\n"
-          "     f     : Toggle through beep-flip/mark-flip/seamless-flip modes.\n"
-          "     r     : Toggle through restart-after/restart-every/no-restart.\n"
-          "     s     : set start playback point to current playback time.\n"
-          "     S     : reset start playback time to 0:00:00.00\n"
-          "     ?     : Print this keymap\n"
-          "    ^-c    : Quit\n"
+          "    a b x    : Switch playback between A, B [and X] samples.\n"
+          "     A B     : Choose A or B sample for A/B[/X] trial result.\n"
+          "   1 2 3...  : Switch between first, second, etc samples.\n"
+          "    ! @ #    : Choose sample 1, 2, or 3 for X/X/Y trial result.\n"
+          " <del> <ins> : Undo/redo last trial result selection.\n"
+          "   <enter>   : Choose current sample for this trial\n"
+          "    <- ->    : Seek back/forward two seconds, +shift for 10 seconds\n"
+          "  <up/down>  : Select sample from list (casual mode)\n"
+          "   <space>   : Pause/resume playback\n"
+          "  <backspc>  : Reset playback to start point\n"
+          "      e      : set end playback point to current playback time.\n"
+          "      E      : reset end playback time to end of sample\n"
+          "      f      : Toggle through beep-flip/mark-flip/seamless-flip modes.\n"
+          "      r      : Toggle through restart-after/restart-every/no-restart.\n"
+          "      s      : set start playback point to current playback time.\n"
+          "      S      : reset start playback time to 0:00:00.00\n"
+          "      ?      : Print this keymap\n"
+          "     ^-c     : Quit\n"
           "\n"
           "SUPPORTED FILE TYPES:\n"
           "  WAV and WAVEX    : 8-, 16-, 24-bit linear integer PCM (format 1)\n"
@@ -1853,14 +1853,18 @@
   }
 }
 
-void randomize_samples(int *r,int test_mode){
+void randomize_samples(int *r,int *cchoice, int test_mode){
   switch(test_mode){
   case 1:
+    r[0] = random()&1;
+    r[1] = 1-r[0];
     r[2] = random()&1;
-    /* fall through */
+    *cchoice = (r[1]==r[2] ? 1 : 0);
+    break;
   case 0:
     r[0] = random()&1;
     r[1] = 1-r[0];
+    *cchoice = (r[1]==1);
     break;
   case 2:
     r[0] = random()&1;
@@ -1870,9 +1874,19 @@
     else
       r[2] = random()&1;
     break;
+    *cchoice = (r[0]==r[1] ? 2 : (r[1]==r[2] ? 0 : 1));
   }
 }
 
+double factorial(int x){
+  double f = 1.;
+  while(x>1){
+    f*=x;
+    x--;
+  }
+  return f;
+}
+
 int main(int argc, char **argv){
   int fragsamples;
   int fragsize;
@@ -1897,6 +1911,13 @@
   ao_device *adev=NULL;
   int randomize[MAXFILES];
   int i;
+
+  int  cchoice=-1;
+  char choice_list[MAXTRIALS];
+  char sample_list[MAXTRIALS];
+  int  tests_cursor=0;
+  int  tests_total=0;
+
   /* parse options */
 
   while((c=getopt_long(argc,argv,short_options,long_options,&long_option_index))!=EOF){
@@ -1942,6 +1963,10 @@
         fprintf(stderr,"Error parsing argument to -n\n");
         exit(1);
       }
+      if(tests>MAXTRIALS){
+        fprintf(stderr,"Error parsing argument to -n (max %d trials)\n",MAXTRIALS);
+        exit(1);
+      }
       break;
     case 'e':
       parse_time(optarg,&end);
@@ -2106,7 +2131,7 @@
     randomize[i]=i;
   /* randomize samples for first trial */
   srandom(time(NULL)+getpid());
-  randomize_samples(randomize,test_mode);
+  randomize_samples(randomize,&cchoice,test_mode);
 
   /* playback loop */
   pthread_mutex_lock(&state.mutex);
@@ -2263,6 +2288,14 @@
         case '?':
           panel_toggle_keymap();
           break;
+        case 331:
+          if(tests_cursor<tests_total)
+            tests_cursor++;
+          break;
+        case 330:
+          if(tests_cursor>0)
+            tests_cursor--;
+            break;
         }
 
         if(do_flip && flip_to==current_choice) do_flip=0;
@@ -2300,7 +2333,6 @@
         pthread_cond_signal(&state.key_cond);
       }
 
-
       /* update terminal */
       {
         double base = 1.f/(rate*bpf);
@@ -2317,7 +2349,7 @@
         panel_update_playing(current_choice);
         panel_update_repeat_mode(restart_mode);
         panel_update_flip_mode(beep_mode);
-        //panel_update_trials(trial_list);
+        panel_update_trials(choice_list,tests_cursor);
         min_flush();
         pthread_mutex_lock(&state.mutex);
       }
@@ -2337,12 +2369,27 @@
         }
 
         if(do_select){
+
+          /* record choice; during selection, flip_to contains the test choice  */
+          choice_list[tests_cursor] = flip_to;
+          sample_list[tests_cursor] = (randomize[flip_to] == cchoice);
+          tests_cursor++;
+          tests_total=tests_cursor;
+
           /* randomize now so we can fill in fragmentB */
-          randomize_samples(randomize,test_mode);
+          randomize_samples(randomize,&cchoice,test_mode);
           if(restart_mode){
             seek_to += start_pos-current_pos;
             do_seek=1;
           }
+          current_choice=0;
+
+          if(tests_cursor==tests){
+            pthread_mutex_lock(&state.mutex);
+            state.exiting=1;
+            pthread_mutex_unlock(&state.mutex);
+            break;
+          }
         }
 
         if(paused){
@@ -2448,9 +2495,43 @@
   pthread_cond_signal(&state.play_cond);
   pthread_cancel(fd_handle);
   pthread_mutex_unlock(&state.mutex);
+
+  if(test_mode!=3 && tests_cursor>0){
+    int total1=0;
+    tests=tests_cursor;
+    for(i=0;i<tests;i++)
+      total1+=sample_list[i];
+
+    switch(test_mode){
+    case 0:
+      fprintf(stdout, "\nA/B test results:\n");
+      fprintf(stdout, "\tSample 1 (%s) chosen %d/%d trials.\n",pcm[0]->path,tests-total1,tests);
+      fprintf(stdout, "\tSample 2 (%s) chosen %d/%d trials.\n",pcm[1]->path,total1,tests);
+      break;
+    case 1:
+      fprintf(stdout, "\nA/B/X test results:\n");
+      fprintf(stdout, "\tCorrect sample identified %d/%d trials.\n",total1,tests);
+      break;
+    case 2:
+      fprintf(stdout, "\nX/X/Y test results:\n");
+      fprintf(stdout, "\tCorrect sample identified %d/%d trials.\n",total1,tests);
+      break;
+    }
+
+    if(test_mode==1 || test_mode==2){
+      // 0.5^20*(20!/(17!*3!))
+      double p=0;
+      for(i=total1;i<=tests;i++)
+        p += pow(.5,tests) * (factorial(tests) / (factorial(tests-i)*factorial(i)));
+      fprintf(stdout, "\tProbability of %d or better correct via random chance: %.2f%%\n",total1,p*100);
+      if(p<.05)
+        fprintf(stdout,"\tStatistically significant result (>=95%% confidence)\n");
+    }
+    fprintf(stdout,"\n");
+  }
+
   pthread_join(playback_handle,NULL);
   pthread_join(fd_handle,NULL);
-
   for(i=0;i<test_files;i++)
     free_pcm(pcm[i]);
   return 0;

Modified: trunk/squishyball/main.h
===================================================================
--- trunk/squishyball/main.h	2010-11-27 16:27:01 UTC (rev 17665)
+++ trunk/squishyball/main.h	2010-11-27 19:51:58 UTC (rev 17666)
@@ -24,6 +24,7 @@
 #ifndef _SB__H_
 #define _SB__H_
 
+#define MAXTRIALS 50
 typedef struct pcm_struct pcm_t;
 
 struct pcm_struct {
@@ -47,7 +48,7 @@
 extern void panel_update_end(double time);
 extern void panel_update_repeat_mode(int mode);
 extern void panel_update_flip_mode(int mode);
-extern void panel_update_trials(char *trial_list);
+extern void panel_update_trials(char *trial_list, int n);
 extern void panel_update_pause(int flag);
 extern void panel_toggle_keymap(void);
 #endif

Modified: trunk/squishyball/mincurses.c
===================================================================
--- trunk/squishyball/mincurses.c	2010-11-27 16:27:01 UTC (rev 17665)
+++ trunk/squishyball/mincurses.c	2010-11-27 19:51:58 UTC (rev 17666)
@@ -369,9 +369,9 @@
     //if(ena_acs)min_putp(ena_acs);
     _nc_init_acs();
 
-    if(!cursor_up || !cursor_down || !column_address){
+    if(!cursor_up || !cursor_down || !column_address || pl>lines){
       SET_TTY(outfd,&orig);
-      ret=ERR;
+      return ERR;
     }
 
     /* set up keytables */
@@ -390,6 +390,9 @@
 
 int min_panel_expand(int l,int bottomp){
   int i,ret=0;
+
+  if(panel_lines+l>lines)return 1;
+
   if(bottomp){
     min_mvcur(0,panel_lines);
     for(i=0;i<l-1;i++)
@@ -397,6 +400,7 @@
     panel_lines+=l;
     cursor_line_offset=panel_lines-1;
   }else{
+    min_mvcur(0,panel_lines+l-1);
     min_mvcur(0,0);
     if(parm_insert_line){
       ret|=min_putp(tparm(parm_insert_line,l));

Modified: trunk/squishyball/squishyball.1
===================================================================
--- trunk/squishyball/squishyball.1	2010-11-27 16:27:01 UTC (rev 17665)
+++ trunk/squishyball/squishyball.1	2010-11-27 19:51:58 UTC (rev 17666)
@@ -101,14 +101,18 @@
 
 .SH KEYBOARD INTERACTION
 .IP "\fBa\fR, \fBb\fR, \fBx"  
-Switch between A and B samples (A/B mode), or A, B and X samples (A/B/X mode)
+Switch between A and B samples (A/B mode), or A, B and X samples (A/B/X mode).
 .IP "\fBA\fR, \fBB"
 Select A or B as preferred sample (A/B mode), or sample A or sample B as
-match to sample X (A/B/X testing mode)
+match to sample X (A/B/X testing mode).
 .IP "\fB1\fR, \fB2\fR, \fB3\fR..."
-Switch between first, second, third [etc] samples (X/X/Y testing mode, casual comparison mode)
+Switch between first, second, third [etc] samples (X/X/Y testing mode, casual comparison mode).
 .IP "\fB!\fR, \fB@\fR, \fB#"
-Indicate the 'odd sample out' as sample 1, 2, or 3 (X/X/Y testing mode)
+Indicate the 'odd sample out' as sample 1, 2, or 3 (X/X/Y testing mode).
+.IP "\fB<del>\fR, <ins>"
+Undo/redo previous trial result selection.
+.IP "\fB<enter>"
+Choose current sample for this trial.
 .IP "\fB<-\fR, \fB->"
 Seek back/forward two seconds, \fB+shift \fRfor ten seconds.
 .IP "\fB<up/down>"

Modified: trunk/squishyball/tty.c
===================================================================
--- trunk/squishyball/tty.c	2010-11-27 16:27:01 UTC (rev 17665)
+++ trunk/squishyball/tty.c	2010-11-27 19:51:58 UTC (rev 17666)
@@ -35,9 +35,9 @@
 #include "mincurses.h"
 
 static int force=0;
-static int p_tm,p_ch,p_b,p_r,p_fm,p_rm,pcm_n,p_tr,p_tn,p_pau,p_pl;
+static int p_tm,p_ch,p_b,p_r,p_fm,p_rm,pcm_n,p_tr,p_tmax,p_pau,p_pl,p_tn;
 static double p_st,p_cur,p_end,p_len;
-static char *p_tl;
+static char p_tl[MAXTRIALS];
 static pcm_t **pcm_p;
 
 static char timebuffer[80];
@@ -289,7 +289,7 @@
   panel_update_repeat_mode(p_rm);
   panel_update_flip_mode(p_fm);
   if(p_tm!=3)
-    panel_update_trials(p_tl);
+    panel_update_trials(p_tl,p_tn);
   force=0;
   min_flush();
 }
@@ -297,7 +297,7 @@
 void panel_init(pcm_t **pcm, int test_files, int test_mode, double start, double end, double size,
                 int flip_mode,int repeat_mode,int trials,char *trial_list){
   if(min_panel_init(test_mode==3 ? test_files+6:7)){
-    fprintf(stderr,"Unable to initialize terminal\n");
+    fprintf(stderr,"Unable to initialize terminal (possibly insufficient lines)\n");
     exit(101);
   }
 
@@ -318,10 +318,10 @@
   p_fm=flip_mode;
   p_rm=repeat_mode;
   p_tr=0;
-  p_tn=trials;
-  p_tl=strdup(trial_list);
+  p_tmax=trials;
+  p_tn=0;
   pcm_n=test_files;
-   pcm_p=pcm;
+  pcm_p=pcm;
   p_pau=0;
 
   min_hidecur();
@@ -454,33 +454,26 @@
   }
 }
 
-static int old_p_tl_len=-1;
-void panel_update_trials(char *trial_list){
-  if(force || strcmp(p_tl,trial_list)){
+void panel_update_trials(char *choices, int n){
+  if(force || n!=p_tn || memcmp(p_tl,choices,n)){
     char buf[columns+1];
-    int k,l = strlen(trial_list);
-    if(p_tl)free(p_tl);
-    p_tl=strdup(trial_list);
-    min_mvcur(1,boxrow+1);
+    int i;
+    p_tn=n;
 
-    sprintf(buf," %d/%d trials: ",l,p_tn);
+    min_mvcur(1,boxrow+1);
+    sprintf(buf," %d/%d trials: ",p_tn,p_tmax);
     min_putstr(buf);
 
-    l+=strlen(buf);
-    if(l>columns-4){
-      min_putstr("...");
-      min_putstr(p_tl+l-columns-7);
-      l+=strlen(p_tl+l-columns-7);
-    }else{
-      min_putstr(p_tl);
-      l+=strlen(p_tl);
-    }
-    {
-      k=l;
-      while(k++<old_p_tl_len)
-        min_putchar(' ');
-      old_p_tl_len=l;
-    }
+    memcpy(p_tl,choices,n);
+    for(i=0;i<n;i++)
+      if(p_tm<2){
+        min_putchar(p_tl[i]+'A');
+      }else{
+        min_putchar(p_tl[i]+'1');
+      }
+    i+=strlen(buf);
+    for(;i<columns-2;i++)
+      min_putchar(' ');
   }
 }
 
@@ -563,8 +556,9 @@
 void panel_toggle_keymap(){
   int l=18;
   int o=1;
-  p_keymap = !p_keymap;
-  if(p_keymap){
+  if(!p_keymap){
+    if(min_panel_expand(l,0))return;
+    p_keymap = !p_keymap;
     timerow+=l;
     playrow+=l;
     toprow+=l;
@@ -622,6 +616,7 @@
     min_putstr(": Quit");
     min_unset();
   }else{
+    p_keymap = !p_keymap;
     min_panel_contract(l,0);
     timerow-=l;
     playrow-=l;



More information about the commits mailing list