diff model/review.c @ 0:5242703e91d3 tip

Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author tomwalters
date Fri, 20 May 2011 15:19:45 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/review.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,666 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee
+    is hereby granted for research purposes, provided that this copyright
+    notice appears in all copies and in all supporting documentation, and that
+    the software is not redistributed for any fee (except for a nominal shipping
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this
+    software for any purpose.  It is provided "as is" without express or implied
+    warranty.
+
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    review.c
+    ========
+
+    formerly known as revsai.c - reviews .ctn screen dump files from disk.
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Authors : Paul Manson and John Holdsworth.
+    Written : 11th March, 1989
+
+    Edited  :
+
+    03 April 1989 (Paul Manson) -- A new star on the horizon! The all-singing, all-dancing
+				   new revue emerges from the ashes of last week's version.
+
+    19 April 1989 (Paul Manson) -- Added the <input> option. Changed the name to revsai.
+
+    27 April 1989 (Paul Manson) -- The port to the DecStation (and by implication, the VAX)
+				   has revealed several problems and bugs. All such known
+				   bugs have been fixed. The <memory> option has been
+				   introduced (for non-PCs only) to permit rapid reviewing
+				   on X-windows servers. NOTE THAT THE SCREEN SIZE FOR NON
+				   PC MACHINES HAS BEEN HARD_CODED! THIS SHOULD CHANGE!
+
+    05 May   1989 (Paul Manson) -- The above problem has been temporarily rectified by
+				   using the default width and height options to indicate
+				   the actual screen size. Also, the options format change
+				   has been accounted for.
+
+    11 May   1989 (Paul Manson) -- Altered options to conform to the new(est) r'egime.
+
+    15 May   1989 (Paul Manson) -- Incorporated the PC-style wildcarding into the Unix version.
+				   Made display use "NULL" instead of (char *) 0.
+
+    05 June  1989 (Paul Manson) -- Altered a couple of the option comments to reflect their
+				   behaviour more accurately. I also encountered the rather
+				   suspicious "bug" whereby revsai gets a segmentation fault
+				   whenever it is run on an old "sai" file ... those generated
+				   by sai now appear to be OK... If this really is a problem,
+				   it should be tracked down!
+
+    06 July  1989 (Paul Manson) -- As well as altering revsai to accomodate all of the new
+				   options names, I note that the abovementioned bug appears
+				   to have disappeared without trace; hopefully it was just
+				   due to previous (buggy) files, etc.
+
+    3 August 1993 (M. Akeroyd) --  Added declarations of "colourstr"  and "planemaskstr".
+                                   They aren't used, but are in X.c (and thus libglib.a),
+				   and are therfore required to fool the linker.
+
+    25 March 1994 (M. Akeroyd) --  Added colour. mono etc, so that 'review' would actually work.
+                                   (the previuos cahnge just made it compile.)
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#if defined(THINK_C) || defined(NeXT) 
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+
+#include "windows.h"
+#include "options.h"
+
+
+char *monostr, *colourstr, *planemaskstr;   /* MAA 3-8-1993 */
+char *fgcolourstr, *bgcolourstr;  /* MAA 19-8-1993 */
+#ifndef  lint
+static char *sccs_id = "@(#)review.c	1.13 Paul Manson, John Holdsworth (MRC-APU) 5/31/91";
+#endif
+
+#define max(A,B) (((A) > (B)) ? (A) : (B))
+#define LENGTH_STR "remainder"
+#define MAX_LENGTH (9999)
+
+#define CENTER_STR "center"
+#define IMAGE_SUFFIX ".ctn"
+
+#ifdef PC
+#define READ_BINARY "rb"
+#else
+#define READ_BINARY "r"
+#endif
+
+/* configurables */
+
+static char *helpstr                               ;
+static char *speed1str, *speed2str                 ;
+static char *xstr, *ystr, *widthstr,  *heightstr   ;
+static char *start1str,   *stop1str,  *step1str    ;
+static char *start2str,   *stop2str,  *step2str    ;
+static char *minstr ,     *maxstr  ,  *framestr    ;
+static char *in1str,      *in2str,    *downstr     ;
+
+#if !defined( PC )
+extern void exit();
+static char *memorystr;
+#endif
+
+static Option res[] = {
+ { "help",       "none",       &helpstr,   "<wave1> [<wave2>]\n\n\
+	Redisplays stored images from memory or directly from disk.\n\
+	Review responds to various simple commands, viz.\n\n\
+	1\t Activate only wave1 (default when only one wave named).\n\
+	2\t Activate only wave2.\n\
+	b or B\t Activate Both waves (default when two waves named).\n\n\
+	a or A\t Animate cartoon wave(s). Hitting space bar is equivalent.\n\
+	s or S\t Single-step activated wave(s). Hit space bar to step.\n\
+	+\t Animate activated wave(s) faster.\n\
+	-\t Animate activated wave(s) slower.\n\n\
+	q or Q\t Quit Revue.\n", SilentOption },
+ { "input1",   NULL_OPTION,  &in1str,     "Default input file name 1",               InputOption},
+ { "start1" ,     "0" ,      &start1str , "Start point in wave 1 (in ms)",           InputOption},
+ { "length1", LENGTH_STR,    &stop1str  , "Length of wave 1 to display (in ms)",     InputOption},
+ { "step1"  ,     "1" ,      &step1str  , "Display every step-th image of wave 1",   InputOption},
+ { "speed1",     "1" ,       &speed1str,  "Image 1 display speed (1 is  fastest)", InputOption},
+
+ { "input2",   NULL_OPTION,  &in2str,     "Default input file name 2\n",             InputOption},
+ { "start2" ,     "0" ,      &start2str , "Start point in wave 2 (in ms)",           InputOption},
+ { "length2", LENGTH_STR,    &stop2str  , "Length of wave 2 to display (in ms)",     InputOption},
+ { "step2"  ,     "1" ,      &step2str  , "Display every step-th image of wave 2",   InputOption},
+ { "speed2",     "1" ,       &speed2str,  "Image 2 display speed (1 is  fastest)",   InputOption},
+
+ { "x0_win",  CENTER_STR,    &xstr,       "Left edge of window (in pixels)" ,        SilentOption},
+ { "y0_win",  CENTER_STR,    &ystr,       "Upper edge of window (in pixels)",        SilentOption},
+ { "width_screen", "960",    &widthstr,   "Physical screen width  in pixels",        SilentOption},
+ { "height_screen","750",    &heightstr,  "Physical screen height in pixels",        SilentOption},
+
+/* MAA: 25 March 1994
+ * These next added because they are used from within X.c (although defined in gen.c), and thus the graphics
+ * calls. They are of NO meaning, however; they define how the Model makes the bitmaps.
+ * Once made, you cannot edit bitmaps ... 
+ */
+ { "fg_col",         "black", &fgcolourstr, "Foreground Colour.\n",                   SilentOption},
+ { "bg_col",         "white", &bgcolourstr, "Background Colour.\n",                   SilentOption},
+ {    "mono_ctn",   ON_OPTION, &monostr, "Force monochrome (single plane) cartoons.", SilentOption},
+ {  "colour_ctn",  OFF_OPTION, &colourstr, "Force colour (multi-plane) cartoons.", SilentOption},
+ {"planemask_ctn", "1", &planemaskstr, "Planemask for creating cartoons.\n", SilentOption},
+/* MAA: End of that bit */
+
+#if !defined( PC )
+ { "memory",     ON_OPTION,  &memorystr,  "Read images into memory for reviewing\n", InputOption},
+#endif
+ ( char * ) 0 } ;
+
+static Option hiddenRes[] = {
+ { "downsample",     "20",   &downstr,    "Image file frame size (in ms)",           InputOption},
+ { "frstep_aid",     "20",   &framestr,   "Image file frame size (in ms)",           InputOption},
+ { "mincf_afb",     "220",   &minstr  ,   "Minimum Center Frequency in Hertz",       InputOption},
+ { "maxcf_afb",    "4400",   &maxstr  ,   "Maximum Center Frequency in Hertz",       InputOption},
+ { "width_win",     "900",   &widthstr,   "Window width  (pixels)",                  InputOption},
+ { "height_win",    "600",   &heightstr,  "Window height (pixels)",                  InputOption},
+ ( char * ) 0 } ;
+
+#define ONE (1)
+#define TWO (2)
+#define BOTH (0)
+
+#define FALSE (0)
+#define TRUE (1)
+#define OVERTHETOP (10000)
+#define AXES_WIDTH (15)
+
+static int msToImages(frame, ms)
+  double frame;
+  double ms   ;
+{
+  return (((int) (ms / frame)) + 1); /* Round Up */
+}
+
+/* File Name Suffix Conversion Parameters */
+
+#define BACKSLASH_CHAR  '\\'
+#define SLASH_CHARACTER '/'
+#define NULL_CHARACTER  '\000'
+#define DOT_CHARACTER '.'
+
+/******************************************************************************************/
+/*                                                                                        */
+/*    AlterSuffix(). Returns its argument fileName with a newSuffix appended in place of  */
+/*                   any previous suffix it may have had. It should be noted that this    */
+/*                   suffix must include any DOT it wishes to have appended to the name.  */
+/*                                                                                        */
+/******************************************************************************************/
+
+char *AlterSuffix(fileName, newSuffix)
+     char *fileName, *newSuffix;
+{
+  char *temp, *temp2, *lastPart;
+  int i;
+
+  temp = malloc((unsigned) (strlen(fileName) + strlen(newSuffix) + 1));
+
+  temp = strcpy(temp, fileName);
+
+#if defined( PC )
+  /* Change all backslashes to forward slashes */
+  for (i = 0; temp[i] != NULL_CHARACTER; i++)
+    if (temp[i] == BACKSLASH_CHAR)
+      temp[i] = SLASH_CHARACTER;
+#endif
+
+  if ((lastPart = strrchr(temp, SLASH_CHARACTER)) == NULL)
+    lastPart = temp;
+  else
+    lastPart++; /* Skip over the actual "/" */
+
+  /* lastPart points to the tail name of the path */
+
+  if ((temp2 = strchr(lastPart, DOT_CHARACTER)) == NULL)
+    temp = strcat(temp, newSuffix);
+  else
+    temp2 = strcpy(temp2, newSuffix);
+
+  return (temp);
+}
+
+/* -----------------------------------------------------------------------------------
+
+   A Routine to extend revsai for in-memory animation. This copies every image from
+   <start> to <stop> by <step> into the images buffer for the window <w>. It then
+   expects contiguous animation of these images. The integer returned is the number
+   of images that were saved; subsequent image Recall() calls should refer to images
+   in the range [1 .. this returned value].
+
+   ----------------------------------------------------------------------------------- */
+
+static int readIntoMemory(w, filePtr, start, stop, step)
+     WindowObject w;
+     FILE *filePtr ;
+     int      start;
+     int       stop;
+     int       step;
+{
+  int fileImage, memImage;
+
+  memImage = 0;
+
+  fileImage = start;
+
+  while (fileImage <= stop && Read(w, filePtr, fileImage)) {
+    Store(w);
+    fileImage += step;
+    memImage++;
+  }
+
+  return (memImage);
+}
+
+main( argc, argv )
+int argc ;
+char *argv[] ;
+{
+    WindowObject w1, w2;
+    int   screenWidth,  screenHeight ;
+    int   firstWidth ,  firstHeight  ;
+    int   secondWidth,  secondHeight ;
+    int   firstPixels,  secondPixels ;
+    FILE *firstWave  , *secondWave   ;
+
+    int OneWave, TwoWaves, spareWidth,
+	spareHeight                  ;
+
+    int waveMode , image1    , image2;
+    int            count1    , count2;
+    int stopFirst, stopSecond        ;
+    int start1   , stop1     , step1 ;
+    int start2   , stop2     , step2 ;
+    int speed1   , speed2            ;
+
+    char command, *firstWaveName,
+      *secondWaveName,
+      *programName;
+
+    double mincf1, mincf2, maxcf1, maxcf2, frame1, frame2;
+    int inMemory, x, y;
+
+    programName = argv[0];
+
+    (void) getopts( res, &argc, &argv );
+
+    /* Extract any information from the opts which is NECESSARY for the
+       operation of revue */
+
+    screenWidth = atoi( widthstr );
+    screenHeight= atoi( heightstr);
+
+#if defined( PC )
+    inMemory = FALSE;
+#else
+    inMemory = isON( memorystr );
+#endif
+
+    if (argc > 2 || (argc == 0 && isNULL(in1str))) {
+      (void) helpopts(res, programName);
+      exit(1);
+    }
+    else {
+      OneWave = ((argc == 0 && !isNULL(in1str)) ||
+		 (argc == 1 &&  isNULL(in2str)));
+      TwoWaves = !OneWave;
+    }
+
+    if (argc == 0)
+      firstWaveName = AlterSuffix(in1str, IMAGE_SUFFIX) ;
+    else
+      firstWaveName = AlterSuffix(argv[0], IMAGE_SUFFIX);
+
+    if ((firstWave = fopen(firstWaveName, READ_BINARY )) == NULL) {
+      (void) fprintf(stderr, "Could not open the image file %s.\n", firstWaveName);
+      exit(1);
+    }
+
+    (void) readopts(res, firstWave);
+
+    if (fseek(firstWave, 0l, 0)) {
+	(void) fprintf(stderr, "revsai: Could not re-seek the %s file.\n",
+		       firstWaveName);
+	exit(1);
+    }
+
+    (void) readopts(hiddenRes, firstWave);
+
+    if( framestr == (char *) 0 )
+		if( downstr == (char *) 0 )
+		 	frame1 = 1 ;
+		else
+			frame1 = atof(downstr);
+    else if ((frame1 = atof(framestr)) < 0.0)
+	frame1 = 0.0;
+
+    firstWidth  = atoi( widthstr );
+    firstHeight = atoi( heightstr);
+
+    start1 = msToImages(frame1, atof( start1str ));
+
+    if (strcmp(stop1str, LENGTH_STR) == 0)
+      stop1 = MAX_LENGTH;
+    else
+      stop1  = msToImages(frame1, atof( stop1str  )) + start1;
+
+    step1  = atoi( step1str  );
+    if (step1 < 1)
+      step1 = 1;
+
+    firstPixels = 1; /* atoi( pixelstr ); */
+
+    mincf1 = atof( minstr );
+    maxcf1 = atof( maxstr );
+
+    if (TwoWaves) {
+
+      if (argc == 1)
+	secondWaveName = AlterSuffix(in2str, IMAGE_SUFFIX);
+      else
+	secondWaveName = AlterSuffix(argv[1],IMAGE_SUFFIX);
+
+      if ((secondWave = fopen(secondWaveName, READ_BINARY )) == NULL) {
+	(void) fprintf(stderr, "Could not open the image file %s.\n",
+		       secondWaveName);
+	exit(1);
+      }
+
+      (void) readopts(res, secondWave);
+      if (fseek(secondWave, 0l, 0)) {
+	  (void) fprintf(stderr, "revsai: Could not re-seek the %s file.\n",
+			 secondWaveName);
+	  exit(1);
+      }
+      (void) readopts(hiddenRes, secondWave);
+
+      if( framestr == (char *) 0 )
+		if( downstr == (char *) 0 )
+		 	frame2 = 1. ;
+		else
+		  frame2 = atof(downstr);
+      else if ((frame2 = atof(framestr)) < 0.0)
+	  frame2 = atof(downstr);
+
+      secondWidth  = atoi( widthstr );
+      secondHeight = atoi( heightstr);
+
+      start2 = msToImages(frame2, atof( start2str ));
+
+      if (strcmp(stop2str, LENGTH_STR) == 0)
+	stop2 = MAX_LENGTH;
+      else
+	stop2  = msToImages(frame2, atof( stop2str  )) + start2;
+
+      step2  = atoi( step2str  );
+      if (step2 < 1)
+	step2 = 1;
+
+      secondPixels = 1; /* atoi( pixelstr ); */
+
+      mincf2 = atof( minstr );
+      maxcf2 = atof( maxstr );
+
+    }
+
+
+    /* Open display window(s) */
+
+    if (TwoWaves) {
+      /* Center them both for height, but try to fit them both on the screen
+	 at once, width-wise. Firstly, get the REAL screen size */
+#if defined( PC )
+      w1 = newDisplayWindow(firstWaveName, -1, -1, OVERTHETOP, OVERTHETOP, 1);
+      screenWidth  = Width(w1);
+      screenHeight = Height(w1);
+      Close(w1);
+#endif
+
+      if (screenHeight < firstHeight || screenHeight < secondHeight) {
+	(void) fprintf(stderr, "revsai: One (or both) of the waves specified was too\n        high for this screen.\n");
+	exit(1);
+      }
+      if (screenWidth < firstWidth + secondWidth) {
+	(void) fprintf(stderr, "revsai: These two waves are too wide to be viewed side-by-side.\n        Please revue them one at a time, or perhaps generate them smaller.\n");
+	exit(1);
+      }
+
+      spareWidth  = screenWidth  - (firstWidth  + secondWidth  + (2 * AXES_WIDTH));
+      spareHeight = screenHeight - (firstHeight + (2 * AXES_WIDTH));
+
+      w1 = newDisplayWindow(firstWaveName, spareWidth/6 + AXES_WIDTH, spareHeight/2,
+			    firstWidth, firstHeight, firstPixels);
+      Axes(w1, firstWaveName, 0.0, frame1, "Image Frame Size (in ms)",
+	       mincf1, maxcf1, "Center Frequency (in Hz)");
+
+      spareHeight = screenHeight - (secondHeight + (2 * AXES_WIDTH));
+
+      w2 = newDisplayWindow(secondWaveName, (5 * spareWidth / 6) +
+				     firstWidth + (2 * AXES_WIDTH),
+				     spareHeight/2, secondWidth, secondHeight,
+				     secondPixels);
+      Axes(w2, secondWaveName, 0.0, frame2, "Image Frame Size (in ms)",
+	       mincf2, maxcf2, "Center Frequency (in Hz)");
+    }
+    else {
+      /* Easy .. MetaPC Centers it for us */
+      if (OptionStringsEqual(xstr, CENTER_STR))
+	x = -1;
+      else
+	x = atoi(xstr);
+
+      if (OptionStringsEqual(ystr, CENTER_STR))
+	y = -1;
+      else
+	y = atoi(ystr);
+
+      w1 = newDisplayWindow(firstWaveName, x, y, firstWidth, firstHeight,
+			    firstPixels );
+      Axes(w1, firstWaveName, 0.0, frame1, "Image Frame Size (in ms)",
+	       mincf1, maxcf1, "Center Frequency (in Hz)");
+
+#if defined( SUN )
+      /* Kludge to overcome the window-sizing inconsistency when
+	 you open a SunView window with a frame */
+
+      if (Height(w1) >  firstHeight || Width(w1) >  firstWidth) {
+#else
+      if (Height(w1) != firstHeight || Width(w1) != firstWidth) {
+#endif
+	(void) fprintf(stderr, "revsai: The wave you wish to view is too large (ie. either too wide\nor too tall) for the current screen.\n");
+	exit(1);
+      }
+    }
+
+    /* Do the actual reviewing */
+
+    if (TwoWaves)
+      waveMode = BOTH;
+    else
+      waveMode = ONE ;
+
+    speed1 = atoi( speed1str );
+    if (speed1 < 1)
+      speed1 = 1;
+    speed2 = atoi( speed2str );
+    if (speed2 < 1)
+      speed2 = 1;
+
+    /* Initially, just open the files and display the first frame of each, */
+    /* UNLESS the inMemory switch is set, in which case you should read in */
+    /* all of the images and adjust start, stop to suit.                   */
+
+    if (inMemory) {
+	stop1 = readIntoMemory(w1, firstWave, start1, stop1, step1);
+	start1 = 1; /* Now runs from 0 to the adjusted stop */
+	step1  = 1; /* Now the images are contiguous        */
+	if (TwoWaves) {
+	  stop2 = readIntoMemory(w2, secondWave, start2, stop2, step2);
+	  start2 = 1; /* Now runs from 0 to the adjusted stop */
+	  step2  = 1; /* Now the images are contiguous        */
+	}
+    }
+    else {
+      if (!Read(w1, firstWave, start1)) {
+	(void) fprintf(stderr, "revsai: Could not read the first image from the first wave.\n");
+	exit(1);
+      }
+
+      if (TwoWaves && !Read(w2, secondWave, start2)) {
+	(void) fprintf(stderr, "revsai: Couldn't read the first image from the second wave.\n");
+	exit(1);
+      }
+    }
+
+    /* Sit and take commands */
+
+    while ((command = Pause(w1)) != 'q' && command != 'Q') {
+      switch (command) {
+      case '1':
+	    /* Toggle to Wave number One */
+	    waveMode = ONE;
+	break;
+      case '2':
+	    /* Try to toggle to Wave number Two */
+	    if (TwoWaves)
+	      waveMode = TWO;
+	    break;
+      case 'b': case 'B':
+	    /* Try to toggle to Both Waves */
+	    if (TwoWaves)
+	      waveMode = BOTH;
+	    break;
+      case '+':
+	    /* Speed up current Wave(s) */
+	if (waveMode == ONE || waveMode == BOTH)
+	  speed1 = ((speed1 > 1) ? (speed1 /= 2) : (1));
+	    if (waveMode == TWO || waveMode == BOTH)
+	  speed2 = ((speed2 > 1) ? (speed2 /= 2) : (1));
+	    break;
+      case '-':
+	    /* Slow down current Wave(s) */
+	if (waveMode == ONE || waveMode == BOTH)
+	  speed1 *= 2;
+	    if (waveMode == TWO || waveMode == BOTH)
+	  speed2 *= 2;
+	    break;
+      case 's': case 'S':
+	stopFirst  = (waveMode == TWO);
+	stopSecond = (waveMode == ONE);
+	image1 = start1;
+	image2 = start2;
+	while (!(stopFirst && stopSecond) && (Pause(w1) == ' ')) {
+	    if (!stopFirst) {
+		if (inMemory)
+			  Recall(w1, image1);
+		else
+			  stopFirst  = !Read(w1, firstWave , image1);
+		if (!stopFirst) {
+			  image1 += step1;
+			  stopFirst = (image1 > stop1);
+		}
+	    }
+	    if (!stopSecond) {
+		if (inMemory)
+			  Recall(w2, image2);
+			else
+			  stopSecond = !Read(w2, secondWave, image2);
+		if (!stopSecond) {
+			  image2 += step2;
+			  stopSecond = (image2 > stop2);
+		}
+	    }
+	}
+	break;
+      case 'a': case 'A': case ' ':
+	stopFirst  = (waveMode == TWO);
+	stopSecond = (waveMode == ONE);
+	image1 = start1;
+	image2 = start2;
+	count1 = count2 = 0    ;
+	while (!(stopFirst && stopSecond)) {
+		if (stopFirst || image1 > stop1) {
+		if (waveMode == BOTH && !stopSecond && image2 <= stop2 &&
+		    image1 > start1  && count1 == 0) {
+			/* Redisplay the previous image for constant speed */
+			if (inMemory)
+			  Recall(w1, image1-1);
+			else
+			  stopFirst = !Read(w1, firstWave, image1-1);
+		    }
+		    stopFirst = TRUE;
+		}
+		else {
+		    if (inMemory)
+		      Recall(w1, image1);
+		    else
+		      stopFirst = !Read(w1, firstWave, image1);
+		    if (!stopFirst)
+			    if (++count1 >= speed1) {
+			      image1 += step1;
+			      count1  = 0    ;
+			}
+	    }
+		if (stopSecond || image2 > stop2) {
+		if (waveMode == BOTH && !stopFirst && image1 <= stop1 &&
+		    image2 > start2  && count2 == 0) {
+			/* Redisplay the previous image for constant speed */
+			if (inMemory)
+			  Recall(w2, image2-1);
+			else
+			  stopSecond = !Read(w2, secondWave, image2-1);
+			}
+		    stopSecond = TRUE;
+		}
+		else {
+		    if (inMemory)
+		      Recall(w2, image2);
+		    else
+		      stopSecond = !Read(w2, secondWave, image2);
+		    if (!stopSecond)
+			    if (++count2 >= speed2) {
+			      image2 += step2;
+			      count2  = 0    ;
+			}
+	    }
+	}
+	break;
+      default:
+	    break;
+      }
+    }
+    if (fclose(firstWave)) {
+	(void) fprintf(stderr, "revsai: Could not close file % correctly.\n",
+		       firstWaveName);
+	exit(1);
+    }
+    if (TwoWaves && fclose(secondWave)) {
+	(void) fprintf(stderr, "revsai: Could not close file % correctly.\n",
+		       secondWaveName);
+	exit(1);
+    }
+  }