/* DrawForm.c
   Copyright (c) 1990,1991,1992 by Thomas E. Janzen
   All Rights Reserved

   THIS SOFTWARE IS FURNISHED FREE OF CHARGE FOR STUDY AND USE AND MAY
   BE COPIED ONLY FOR PERSONAL USE OR COMPLETELY AS OFFERED WITH NO
   CHANGES FOR FREE DISTRIBUTION.  NO TITLE TO AND OWNERSHIP OF THE
   SOFTWARE IS HEREBY TRANSFERRED.  THOMAS E. JANZEN ASSUMES NO 
   RESPONSBILITY FOR THE USE OR RELIABILITY OF THIS SOFTWARE.
   
   Thomas E. Janzen
   58A School St. Apt. 2-L
   Hudson, MA 01749-2518
   (508)562-1295
*/
/*
**  FACILITY:
**
**	AlgoRhythms music improviser on Commodore (TM) Amiga (TM)
**	compiled with SAS/C V5.10b
**
**  ABSTRACT:
**
**	DrawForm.c contains functions for drawing the form settings as
**	a graphic representation with labels.
**
**  AUTHORS: Thomas E. Janzen
**
**  CREATION DATE:	26-MAR-1990
**
**  MODIFICATION HISTORY:
**    DATE	NAME	DESCRIPTION
**-- 12 May 91 TEJ Make a vertical line to mark time in Draw_Time()
**  4 Jan 92 TEJ  last changes for 2.0
*/

#include <stdlib.h>
#include <intuition/intuition.h>
#include <graphics/text.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <math.h>
#include <string.h>
#include <devices/timer.h>

#include "Window.h"
#include "AlgoRhythms.h"

/* Lables for graph */
const static char PitchLabelString[16]    = "Pitch",
                  RhythmLabelString[16]   = "Rhythm",
                  DynamicsLabelString[16] = "Dynamics",
                  TextureLabelString[16]  = "Texture";
static struct  IntuiText PitchLabelTxt = 
	{1, 1, JAM1, 5, 12, &font_choice, PitchLabelString, NULL},
               RhythmLabelTxt = 
	{1, 1, JAM1, 5, 56, NULL, RhythmLabelString, &PitchLabelTxt},
               DynamicsLabelTxt = 
	{1, 1, JAM1, 5, 100, NULL, DynamicsLabelString, &RhythmLabelTxt},
               TextureLabelTxt = 
	{1, 1, JAM1, 5, 144, NULL, TextureLabelString, &DynamicsLabelTxt};

const static char WorkingLabelString[16]  = "Working";
static struct IntuiText WorkingLabelTxt = 
	{2, 1, JAM2, 15, 10, &font_choice, WorkingLabelString, NULL};

static int last_inttime = 0;

void DrawForm( const struct timeval *Duration,
	            const PARAMETER *PitchForm, 
	            const PARAMETER *RhythmForm, 
	            const PARAMETER *DynamicsForm,
	            const PARAMETER *TextureForm)
/* 
** DrawForm gives a graphic rendering of the Form of the piece of music.
** The inputs are the parameter form structures and the duration of
** the piece.
*/
{
	static int  Xlim, 
               Ylim;		            /* Window limits in pixels */
	int intLength = 631,             /* initialized horiz pixel length */
       inttime4,
       PitchStep,
       RhythmStep,
       DynStep,
       TextureStep;
   register int      inttime =  0,	/* horizontal pixel counter */
	                  Step = 22;     /* height of screen / 8 */ 
	register float curtime = 0.0;   /* current time found from  */
					                     /* inttime */
	float    HeightRatio = 12.0,
	         timeratio,		         /* ratio of pixel to seconds */
	         Spreadfixed, 
            Mean, 
            Top, 
	         phase,
            TwoPi;
	SHORT    *PitchArray,
            *RhythmArray,
            *DynArray,
            *TextureArray;
   
	Xlim = w->GZZWidth;
	Ylim = w->GZZHeight;

	PrintIText (rp, &WorkingLabelTxt, 1, 1);

	intLength = Xlim;		/* Length of screen */
	Step = Ylim / 8;		/* vertical increments on screen */
   PitchStep = Step;
   RhythmStep = Step * 3;
   DynStep = Step * 5;
   TextureStep = Step * 7;

	timeratio = ((double)intLength) / (double)Duration->tv_secs;
	HeightRatio = 12 * Ylim / 200;
	
   PitchArray   = (SHORT *) malloc (intLength * 4 * sizeof(SHORT));
   RhythmArray  = (SHORT *) malloc (intLength * 4 * sizeof(SHORT));
   DynArray     = (SHORT *) malloc (intLength * 4 * sizeof(SHORT));
   TextureArray = (SHORT *) malloc (intLength * 4 * sizeof(SHORT));
   
   TwoPi = 2.0 * PI;
   
	for (inttime = 0; inttime < intLength; inttime++) /* draw parameters*/
	{
		curtime = (double)inttime / timeratio;
		/* calculate real time*/
		/* from horz pixel */
      inttime4 = inttime * 4;

		phase = TwoPi * curtime;	/* find phase */
		/* Find range */
		Spreadfixed    = (1 + sin (phase / (float)PitchForm->SpreadCycle
                     + (float)PitchForm->SpreadPhase)) / 4.0;
		/* find mean */
		Mean  = sin (phase / (float)PitchForm->CenterCycle
            + (float)PitchForm->CenterPhase);
      PitchArray[inttime4 + 2] = PitchArray[inttime4] = inttime;
      PitchArray[inttime4 + 1] = PitchStep 
                               - (int)((Mean - Spreadfixed) * HeightRatio);
      PitchArray[inttime4 + 3] = PitchStep 
                               - (int)((Mean + Spreadfixed) * HeightRatio);

		Spreadfixed    = (1 + sin (phase / (float)RhythmForm->SpreadCycle
                     + (float)RhythmForm->SpreadPhase)) / 4.0;
		Mean  = sin (phase / (float)RhythmForm->CenterCycle
            + (float)RhythmForm->CenterPhase);
      RhythmArray[inttime4 + 2] = RhythmArray[inttime4] = inttime;
      RhythmArray[inttime4 + 1] = RhythmStep 
                               - (int)((Mean - Spreadfixed) * HeightRatio);
      RhythmArray[inttime4 + 3] = RhythmStep 
                               - (int)((Mean + Spreadfixed) * HeightRatio);

		Spreadfixed    = (1 + sin (phase / (float)DynamicsForm->SpreadCycle
                     + (float)DynamicsForm->SpreadPhase)) / 4.0;
		Mean  = sin (phase / (float)DynamicsForm->CenterCycle
            + (float)DynamicsForm->CenterPhase);
      DynArray[inttime4 + 2] = DynArray[inttime4] = inttime;
      DynArray[inttime4 + 1] = DynStep 
                               - (int)((Mean - Spreadfixed) * HeightRatio);
      DynArray[inttime4 + 3] = DynStep 
                               - (int)((Mean + Spreadfixed) * HeightRatio);
		
		Top   = (1 + sin (phase / (float)TextureForm->SpreadCycle
            + (float)TextureForm->SpreadPhase)) / 2.0;
      TextureArray[inttime4 + 2] = TextureArray[inttime4] = inttime;
      TextureArray[inttime4 + 1] = TextureStep - (int)(-Top * HeightRatio);
      TextureArray[inttime4 + 3] = TextureStep - (int)(Top * HeightRatio);
	}
   Move (rp, 0, 0);
	SetDrMd (rp, JAM1);		/* Draw with foreground pen */
	ClearScreen (rp);	/* erase screen */
	SetAPen (rp, 4);			/* Set foreground pen to white */

   Move (rp, PitchArray[0], PitchArray[1]);
   PolyDraw (rp, intLength * 2, PitchArray);

   Move (rp, RhythmArray[0], RhythmArray[1]);
   PolyDraw (rp, intLength * 2, RhythmArray);

   Move (rp, DynArray[0], DynArray[1]);
   PolyDraw (rp, intLength * 2, DynArray);

   Move (rp, TextureArray[0], TextureArray[1]);
   PolyDraw (rp, intLength * 2, TextureArray);

	SetAPen (rp, 7);
   SetDrMd (rp, COMPLEMENT);
	for (inttime = 0; inttime < 4; inttime++)
	{
		Move (rp, 0, Step * ((2 * inttime) + 1));
		Draw (rp, Xlim, Step * ((2 * inttime) + 1));
	}
	PitchLabelTxt.TopEdge = Step * (1 / 2);
	RhythmLabelTxt.TopEdge = Step * (5 / 2);
	DynamicsLabelTxt.TopEdge = Step * (9 / 2);
	TextureLabelTxt.TopEdge = Step * (13 / 2);
	PrintIText (rp, &TextureLabelTxt, 1, 1);
   SetAPen (rp, 7);
   if ((last_inttime != 0) && (last_inttime <= intLength))
   {
	   SetDrMd (rp, COMPLEMENT);		/* Draw with foreground pen */
      Move (rp, last_inttime, 0);
      Draw (rp, last_inttime, Xlim);
   }
   free (PitchArray);
   free (RhythmArray);
   free (DynArray);
   free (TextureArray);
}

void DrawTime (const struct timeval *CurTime, 
               const struct timeval *Duration)
{
	/* 
   ** This function draws a line clock on the Pitch 
	** parameter graph while
	** the piece plays 
   */
	int   Xlim,
         Ylim,
         intMean;
	register int inttime = 0;
	double   timeratio,
            HeightRatio = 12;
	SetAPen (rp, 2);			/* Set foreground pen to white */
	Xlim = w->GZZWidth - 1;
	Ylim = w->GZZHeight - 1;
	intMean = Ylim / 8;
	timeratio = ((double)Xlim) / (double)Duration->tv_secs;
	HeightRatio = (12.0 * Ylim) / 200.0;
	inttime = (int)(((double)CurTime->tv_secs) * timeratio);
   if (inttime == last_inttime)
   {
         return;
   }
   SetAPen (rp, 7);   
   SetDrMd (rp, COMPLEMENT);		/* Draw with foreground pen */
   Move (rp, last_inttime, 0);
   Draw (rp, last_inttime, Xlim);
   Move (rp, inttime, 0);
   Draw (rp, inttime, Xlim);

   last_inttime = inttime;
   return;
}


