Ver Fonte

initial commit

richarddobson há 3 anos atrás
pai
commit
ed82457490
8 ficheiros alterados com 6764 adições e 0 exclusões
  1. 20 0
      dev/hfperm/CMakeLists.txt
  2. 944 0
      dev/hfperm/ap_hfperm.c
  3. 2117 0
      dev/hfperm/hfperm.c
  4. 239 0
      dev/hfperm/main.c
  5. 20 0
      dev/hilite/CMakeLists.txt
  6. 1586 0
      dev/hilite/ap_hilite.c
  7. 1593 0
      dev/hilite/hilite.c
  8. 245 0
      dev/hilite/main.c

+ 20 - 0
dev/hfperm/CMakeLists.txt

@@ -0,0 +1,20 @@
+if(APPLE)
+  set(CMAKE_C_FLAGS "-O2 -Wall -mmacosx-version-min=10.5 -Dunix")
+else()
+  if(MINGW)
+    set(CMAKE_C_FLAGS "-O2 -Wall -DWIN32")
+  else()
+    set(CMAKE_C_FLAGS "-O2 -Wall -Dlinux -Dunix")
+  endif()
+endif()
+
+link_directories(../cdp2k ../sfsys)
+
+include_directories(../../include)
+
+add_executable(hfperm main.c ap_hfperm.c hfperm.c)
+
+target_link_libraries(hfperm cdp2k sfsys ${EXTRA_LIBRARIES})
+
+my_install(hfperm)
+

+ 944 - 0
dev/hfperm/ap_hfperm.c

@@ -0,0 +1,944 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <cdpmain.h>
+#include <tkglobals.h>
+#include <pnames.h>
+#include <synth.h>
+#include <processno.h>
+#include <modeno.h>
+#include <globcon.h>
+#include <logic.h>
+#include <filetype.h>
+#include <mixxcon.h>
+#include <speccon.h>
+#include <flags.h>
+#include <arrays.h>
+#include <special.h>
+#include <formants.h>
+#include <sfsys.h>
+#include <osbind.h>
+#include <string.h>
+#include <hfperm.h>
+#include <math.h>
+#include <srates.h>
+
+#if defined unix || defined __GNUC__
+#define round(x) lround((x))
+#endif
+
+static int eliminate_octave_duplications(dataptr dz);
+static int check_for_invalid_data(int k,dataptr dz);
+static void transpose_to_lowest_oct(dataptr dz);
+static void bublsort_hf(dataptr dz);
+static void elim_dupls(dataptr dz);
+static int create_hfpermbufs(dataptr dz);
+static void establish_waveform(dataptr dz);
+static int read_delperm_data(char *filename,dataptr dz);
+static int read_delperm2_data(char *filename,dataptr dz);
+
+char warnstr[2400];
+
+/***************************** ESTABLISH_BUFPTRS_AND_EXTRA_BUFFERS **************************/
+
+int establish_bufptrs_and_extra_buffers(dataptr dz)
+{
+//	int is_spec = FALSE;
+	dz->extra_bufcnt = -1;	/* ENSURE EVERY CASE HAS A PAIR OF ENTRIES !! */
+	dz->bptrcnt = 0;
+	dz->bufcnt  = 0;
+	switch(dz->process) {
+	case(HF_PERM1):			case(HF_PERM2):
+		dz->extra_bufcnt = 0;	
+		dz->bufcnt = 3;
+		break;
+	case(DEL_PERM):		
+	case(DEL_PERM2):		
+		dz->extra_bufcnt = 0;	
+		dz->bufcnt = 4;
+		break;
+	default:
+		sprintf(errstr,"Unknown program type [%d] in establish_bufptrs_and_extra_buffers()\n",dz->process);
+		return(PROGRAM_ERROR);
+	}
+
+	if(dz->extra_bufcnt < 0) {
+		sprintf(errstr,"bufcnts have not been set: establish_bufptrs_and_extra_buffers()\n");
+		return(PROGRAM_ERROR);
+	}
+	return establish_groucho_bufptrs_and_extra_buffers(dz);
+}
+
+/***************************** SETUP_INTERNAL_ARRAYS_AND_ARRAY_POINTERS **************************/
+
+int setup_internal_arrays_and_array_pointers(dataptr dz)
+{
+	int n;		 
+	dz->ptr_cnt    = -1;		/* base constructor...process */
+	dz->array_cnt  = -1;
+	dz->iarray_cnt = -1;
+	dz->larray_cnt = -1;
+	switch(dz->process) {
+	case(HF_PERM1):	
+	case(HF_PERM2):
+		dz->array_cnt=1; dz->iarray_cnt=0; dz->larray_cnt=0; dz->ptr_cnt= 0; dz->fptr_cnt = 0; break;
+	case(DEL_PERM):	  
+	case(DEL_PERM2):	  
+		dz->array_cnt=3; dz->iarray_cnt=0; dz->larray_cnt=0; dz->ptr_cnt= 0; dz->fptr_cnt = 0; break;
+	}
+
+/*** WARNING ***
+ANY APPLICATION DEALING WITH A NUMLIST INPUT: MUST establish AT LEAST 1 double array: i.e. dz->array_cnt = at least 1
+**** WARNING ***/
+
+	if(dz->array_cnt < 0 || dz->iarray_cnt < 0 || dz->larray_cnt < 0 || dz->ptr_cnt < 0 || dz->fptr_cnt < 0) {
+		sprintf(errstr,"array_cnt not set in setup_internal_arrays_and_array_pointers()\n");	   
+		return(PROGRAM_ERROR);
+	}
+
+	if(dz->array_cnt > 0) {  
+		if((dz->parray  = (double **)malloc(dz->array_cnt * sizeof(double *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal double arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->array_cnt;n++)
+			dz->parray[n] = NULL;
+	}
+	if(dz->iarray_cnt > 0) {
+		if((dz->iparray = (int     **)malloc(dz->iarray_cnt * sizeof(int *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal int arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->iarray_cnt;n++)
+			dz->iparray[n] = NULL;
+	}
+	if(dz->larray_cnt > 0) {	  
+		if((dz->lparray = (int    **)malloc(dz->larray_cnt * sizeof(int *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal long arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->larray_cnt;n++)
+			dz->lparray[n] = NULL;
+	}
+	if(dz->ptr_cnt > 0)   {  	  
+		if((dz->ptr    	= (double  **)malloc(dz->ptr_cnt  * sizeof(double *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal pointer arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->ptr_cnt;n++)
+			dz->ptr[n] = NULL;
+	}
+	if(dz->fptr_cnt > 0)   {  	  
+		if((dz->fptr = (float  **)malloc(dz->fptr_cnt * sizeof(float *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal float-pointer arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->fptr_cnt;n++)
+			dz->fptr[n] = NULL;
+	}
+	return(FINISHED);
+}
+
+/****************************** ASSIGN_PROCESS_LOGIC *********************************/
+
+int assign_process_logic(dataptr dz)
+{						 
+	switch(dz->process) {
+	case(HF_PERM1):
+	case(HF_PERM2):
+		switch(dz->mode) {
+		case(HFP_SNDOUT):	setup_process_logic(WORDLIST_ONLY,UNEQUAL_SNDFILE,SNDFILE_OUT,dz);	 break;
+		case(HFP_SNDSOUT):	setup_process_logic(WORDLIST_ONLY,OTHER_PROCESS,  NO_OUTPUTFILE,dz); break;
+		case(HFP_TEXTOUT):	setup_process_logic(WORDLIST_ONLY,TO_TEXTFILE,	  TEXTFILE_OUT,dz);	 break;
+		case(HFP_MIDIOUT):	setup_process_logic(WORDLIST_ONLY,TO_TEXTFILE,	  TEXTFILE_OUT,dz);	 break;
+		default:
+			sprintf(errstr,"Unknown mode: assign_process_logic()\n");
+			return(PROGRAM_ERROR);
+		}
+		break;
+	case(DEL_PERM):			setup_process_logic(WORDLIST_ONLY,UNEQUAL_SNDFILE,SNDFILE_OUT,dz);	 break;
+	case(DEL_PERM2):		setup_process_logic(SNDFILES_ONLY,UNEQUAL_SNDFILE,SNDFILE_OUT,dz);	 break;
+	default:
+		sprintf(errstr,"Unknown process: assign_process_logic()\n");
+		return(PROGRAM_ERROR);
+		break;
+	}
+	return(FINISHED);
+}
+
+/***************************** SET_LEGAL_INFILE_STRUCTURE **************************
+ *
+ * Allows 2nd infile to have different props to first infile.
+ */
+
+void set_legal_infile_structure(dataptr dz)
+{
+	switch(dz->process) {
+	default:
+		dz->has_otherfile = FALSE;
+		break;
+	}
+}
+
+/****************************** FORMERLY IN internal.c *********************************/
+/***************************************************************************************/
+
+/****************************** SET_LEGAL_INTERNALPARAM_STRUCTURE *********************************/
+
+int set_legal_internalparam_structure(int process,int mode,aplptr ap)
+{
+	int exit_status = FINISHED;
+	mode = 0;
+	switch(process) {
+	case(HF_PERM1):
+	case(HF_PERM2):		
+		exit_status = set_internalparam_data("i",ap); 		
+		break;
+	case(DEL_PERM):
+	case(DEL_PERM2):		
+		exit_status = set_internalparam_data("ii",ap); 		
+		break;
+	default:
+		sprintf(errstr,"Unknown process in set_legal_internalparam_structure()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(exit_status);		
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN specialin.c *********************************/
+/********************************************************************************************/
+
+/********************** READ_SPECIAL_DATA ************************/
+
+int read_special_data(char *str,dataptr dz)	   
+{
+//	int exit_status = FINISHED;
+	aplptr ap = dz->application;
+
+	switch(ap->special_data) {
+	case(DELPERM):	return read_delperm_data(str,dz);
+	case(DELPERM2):	return read_delperm2_data(str,dz);
+	default:
+		sprintf(errstr,"Unknown special_data type: read_special_data()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+/****************************** PARAM_PREPROCESS *********************************/
+
+int param_preprocess(dataptr dz)	
+{
+	int exit_status = FINISHED;
+	int octaves_eliminated;
+	double *hf = dz->parray[0];
+	switch(dz->process) {
+	case(HF_PERM1):		
+		dz->iparam[HP1_HFCNT] =  dz->numsize;
+		if((exit_status = check_for_invalid_data(HP1_HFCNT,dz))<0)
+			return(exit_status);
+		octaves_eliminated = eliminate_octave_duplications(dz);
+		if(dz->iparam[HP1_HFCNT] < dz->iparam[HP1_MINSET]) {
+			sprintf(errstr,"Minimum size of note set (%d)",dz->iparam[HP1_HFCNT]);
+			if(octaves_eliminated) {
+				sprintf(warnstr," (after octave duplication elimination)");
+				strcat(errstr,warnstr);
+			}
+			sprintf(warnstr,"\nis less than minimum size specified for chords (%d): cannot proceed.\n",dz->iparam[HP1_MINSET]);
+			strcat(errstr,warnstr);
+			return(DATA_ERROR);
+		}
+		transpose_to_lowest_oct(dz);
+		bublsort_hf(dz);
+		if(hf[dz->iparam[HP1_HFCNT]-1] > (double)dz->iparam[HP1_TOPNOTE]) {
+			sprintf(errstr,"Entered range does not span the given harmonic field\n");
+			return(DATA_ERROR);
+		}
+		break;
+	case(HF_PERM2):		
+		dz->iparam[HP1_HFCNT] =  dz->numsize;
+		if((exit_status = check_for_invalid_data(HP1_HFCNT,dz))<0)
+			return(exit_status);
+		elim_dupls(dz);
+		if(dz->iparam[HP1_HFCNT] < dz->iparam[HP1_MINSET]) {
+			sprintf(errstr,"Minimum size of note set (%d)",dz->iparam[HP1_HFCNT]);
+			sprintf(warnstr,"\nis less than minimum size specified for chords (%d): cannot proceed.\n",dz->iparam[HP1_MINSET]);
+			strcat(errstr,warnstr);
+			return(DATA_ERROR);
+		}
+		bublsort_hf(dz);
+		break;
+	case(DEL_PERM2):		
+		if((dz->ssampsread = fgetfbufEx(dz->sampbuf[1],dz->insams[0],dz->ifd[0],0)) < 0) {
+			sprintf(errstr,"Can't read samps from input soundfile.\n");
+			return(SYSTEM_ERROR);
+		}
+		if((exit_status = check_for_invalid_data(DP_NOTECNT,dz))<0)
+			return(exit_status);
+		break;
+	case(DEL_PERM):		
+		dz->iparam[DP_NOTECNT] =  dz->numsize;
+		if((exit_status = check_for_invalid_data(DP_NOTECNT,dz))<0)
+			return(exit_status);
+		break;
+	default:
+		sprintf(errstr,"Unknown process in param_preprocess()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN procgrou.c **********************************/
+/********************************************************************************************/
+
+/**************************** GROUCHO_PROCESS_FILE ****************************/
+
+int groucho_process_file(dataptr dz)   /* FUNCTIONS FOUND IN PROCESS.C */
+{	
+//	int exit_status = FINISHED;
+
+	switch(dz->process) {
+	case(HF_PERM1):		
+	case(HF_PERM2):		
+		return do_hfperm(dz);
+	case(DEL_PERM):		
+	case(DEL_PERM2):		
+		return gen_dp_output(dz);
+	default:
+		sprintf(errstr,"Unknown case in process_file()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN pconsistency.c ******************************/
+/********************************************************************************************/
+
+/****************************** CHECK_PARAM_VALIDITY_AND_CONSISTENCY *********************************/
+
+int check_param_validity_and_consistency(dataptr dz)
+{
+	int exit_status = FINISHED;
+	int temp;
+	switch(dz->process) {
+	case(HF_PERM1):
+		dz->iparam[HP1_BOTNOTE] += MIDDLE_C_MIDI + (dz->iparam[HP1_BOTOCT] * 12);
+		dz->iparam[HP1_TOPNOTE] += MIDDLE_C_MIDI + (dz->iparam[HP1_TOPOCT] * 12);
+		if(dz->iparam[HP1_TOPNOTE] < dz->iparam[HP1_BOTNOTE]) {
+			temp = dz->iparam[HP1_TOPNOTE];
+			dz->iparam[HP1_TOPNOTE] = dz->iparam[HP1_BOTNOTE];
+			dz->iparam[HP1_BOTNOTE] = temp;
+		}
+		/* fall thro */
+	case(HF_PERM2):
+		if(dz->mode == HFP_SNDOUT || dz->mode == HFP_SNDSOUT) {
+			if(BAD_SR(dz->iparam[HP1_SRATE])) {
+				sprintf(errstr,"Invalid sample rate.\n");
+				return(DATA_ERROR);
+			}
+			dz->infile->channels = 1;
+			dz->infile->srate    = dz->iparam[HP1_SRATE];
+			dz->infile->stype    = SAMP_SHORT;
+
+			dz->iparam[HP1_ELEMENT_SIZE] = (int)round(dz->param[HP1_ELEMENT_SIZE] * dz->infile->srate);
+			dz->iparam[HP1_GAP_SIZE] 	 = (int)round(dz->param[HP1_GAP_SIZE] 	  * dz->infile->srate);
+			dz->iparam[HP1_GGAP_SIZE] 	 = (int)round(dz->param[HP1_GGAP_SIZE] 	  * dz->infile->srate);
+		}
+		if(dz->mode == HFP_SNDOUT) {
+			if((exit_status = create_sized_outfile(dz->outfilename,dz))<0)
+				return(exit_status);
+		}
+		break;
+	case(DEL_PERM):
+		if(BAD_SR(dz->iparam[DP_SRATE])) {
+			sprintf(errstr,"Invalid sample rate.\n");
+			return(DATA_ERROR);
+		}
+		dz->infile->channels = 1;
+		dz->infile->srate    = dz->iparam[DP_SRATE];
+		dz->infile->stype    = SAMP_SHORT;
+		dz->iparam[DP_DUR] = (int)round(dz->param[DP_DUR] * dz->infile->srate);
+		if((exit_status = create_sized_outfile(dz->outfilename,dz))<0)
+			return(exit_status);
+		break;
+	case(DEL_PERM2):
+		dz->iparam[DP_DUR] = (int)(dz->insams[0]);
+		break;
+	}
+	return(FINISHED);
+}
+
+/****************************** HFPERM_CONSISTENCY *********************************/
+
+int hfperm_consistency(dataptr dz)
+{
+	return(FINISHED);
+}
+
+
+/********************************************************************************************/
+/********************************** FORMERLY IN buffers.c ***********************************/
+/********************************************************************************************/
+
+/**************************** ALLOCATE_LARGE_BUFFERS ******************************/
+
+int allocate_large_buffers(dataptr dz)
+{
+	switch(dz->process) {
+	case(HF_PERM1):
+	case(HF_PERM2):
+		if(dz->mode == HFP_SNDOUT || dz->mode == HFP_SNDSOUT)
+			return create_hfpermbufs(dz);
+		break;
+	case(DEL_PERM):
+	case(DEL_PERM2):
+		return create_hfpermbufs(dz);
+	default:
+		sprintf(errstr,"Unknown program no. in allocate_large_buffers()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN cmdline.c ***********************************/
+/********************************************************************************************/
+
+int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
+{
+	if     (!strcmp(prog_identifier_from_cmdline,"hfchords"))	dz->process = HF_PERM1;
+	else if(!strcmp(prog_identifier_from_cmdline,"hfchords2"))	dz->process = HF_PERM2;
+	else if(!strcmp(prog_identifier_from_cmdline,"delperm"))	dz->process = DEL_PERM;
+	else if(!strcmp(prog_identifier_from_cmdline,"delperm2"))	dz->process = DEL_PERM2;
+	else {
+		sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
+		return(USAGE_ONLY);
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN usage.c *************************************/
+/********************************************************************************************/
+
+/******************************** USAGE1 ********************************/
+
+int usage1(void)
+{
+	sprintf(errstr,
+	"USAGE: hfperm NAME (mode) outfile parameters\n"
+	"\n"
+	"where NAME can be any one of\n"
+	"\n"
+	"hfchords hfchords2 delperm\n"
+	"\n"
+	"OR: hfperm NAME (mode) infile outfile parameters\n"
+	"\n"
+	"where NAME can be any one of\n"
+	"\n"
+	"delperm2\n"
+	"\n"
+	"Type 'hfperm hfchords'  for more info on hfperm hfchords option... ETC.\n");
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE2 ********************************/
+
+int usage2(char *str)
+{
+	if(!strcmp(str,"hfchords")) {
+		fprintf(stdout,
+    	"GENERATE ALL CHORDS POSSIBLE FROM NOTES IN GIVEN SET, WITHIN GIVEN PITCH RANGE\n"
+    	"USING EACH  NOTE (OR ITS OCTAVE TRANSPOSITION) ONCE ONLY IN ANY ONE CHORD.\n\n"
+		"USAGE: hfperm hfchords 1   ifil ofil sr nd gd pd min bn bo tn to srt [-m -s -a -o]\n"
+		"OR:    hfperm hfchords 2   ifil ofil sr nd gd    min bn bo tn to srt [-m -s -a -o]\n"
+		"OR:    hfperm hfchords 3-4 ifil ofil sr      min bn bo tn to srt [-m -s -a -o]\n"
+		"IFIL   text input file of midi note values\n"
+		"MODES: 1 SOUND OUT...Outputs 1 soundfile of all chords.\n"
+		"       2 SOUNDS OUT..Outputs several sndfiles, chords grouped by sort specified\n"
+		"       3 TEXT OUT ...Outputs textfile listing chords described by note names.\n"
+		"       4 MIDI OUT ...Outputs list of chords described by MIDI values.\n"
+		"PARAMETERS: OFIL output filename              SR  sample rate sound output\n"
+		"            ND   duration each chord (secs)   GD  gap btwn chords (secs)\n"
+		"            PD   gap btwn chord-groups        MIN min no. notes to combine\n"
+		"BN  bottom note pitchrange, for derived chords (0-11 for C-C#....Bb-B)\n"
+		"BO  octave of bottom note (0 = octave upwards from middle C)\n"
+		"            TN  top note of pitchrange        TO  octave of top note\n"
+		"SRT 0 root: 1 topnote: 2 pitchclass: 3 chordtype: 4 chordtype(keep 1 of each)\n"
+		"   -m  generate only chords of min number of notes specified\n"
+		"   -s  in each group, put smallest span chord first (otherwise it goes last).\n"
+		"-a  do final sort by a method other than by chord density\n"
+		"    For ROOT or TOP NOTE sort, sort by way intervals stacked inside chord.\n"
+		"    For PITCHCLASS SET, sort by size of containing interval, then by density.\n"
+		"-o  eliminate chords duplicating-as-a-whole any chord 1 or more 8vas distant.\n");
+	} else if(!strcmp(str,"hfchords2")) {
+		fprintf(stdout,
+     	"GENERATE ALL CHORDS POSSIBLE FROM NOTES IN GIVEN SET.\n\n"
+		"USAGE: hfperm hfchords2 1   ifil ofil sr nd gd pd min srt [-m -s -a -o]\n"
+		"OR:    hfperm hfchords2 2   ifil ofil sr nd gd    min srt [-m -s -a -o]\n"
+		"OR:    hfperm hfchords2 3-4 ifil ofil sr          min srt [-m -s -a -o]\n"
+		"IFIL   text input file of midi note values\n"
+		"MODES: 1 SOUND OUT...Outputs 1 soundfile of the chords.\n"
+		"       2 SOUNDS OUT..Outputs several sndfiles, chords grouped by sort specified\n"
+		"       3 TEXT OUT ...Outputs textfile listing chords described by note names.\n"
+		"       4 MIDI OUT ...Outputs list of chords described by MIDI values.\n"
+		"PARAMETERS ARE\n"
+		"SRATE       sample rate of the sound output\n"
+		"NOTE-DUR    duration of each chord generated (secs)\n"
+		"GAP-DUR     duration of pauses between chords (secs)\n"
+		"PAUSE-DUR   duration of pauses between groups of chords (secs)\n"
+		"MINSET      minimum number of input notes to combine\n"
+		"SORT BY     0 root:         1 topnote:         2 pitchclass set:\n"
+		"            3 chord type:   4 chord type (keep 1 of each).\n"
+		"-m  generate only chords of min number of notes specified\n"
+		"-s  in each group, put smallest span chord first (otherwise it goes last).\n"
+		"-a  do final sort by a method other than by chord density\n"
+		"    For ROOT or TOP NOTE sort, sort by way intervals stacked inside chord.\n"
+		"    For PITCHCLASS SET, sort by size of containing interval, then by density\n"
+		"   -o  eliminate chords duplicating-as-a-whole any chord 1 or more 8vas distant\n");
+	} else if(!strcmp(str,"delperm")) {
+		fprintf(stdout,
+    	"DELAY AND TRANSFORM EACH INPUT NOTE, CUMULATIVELY.\n\n"
+		"USAGE: hfperm delperm 0 \n"
+		"   infile outfile permfile srate initial-notelen cycles-of-perm\n"
+		"PARAMETERS ARE\n"
+		"   INFILE          text input file of midi note values\n"
+		"   PERMFILE		pairs of vals: 1st a semitone transpos, 2nd a time multiplier\n"
+		"                   Sum of all time-multipliers must be 1.0\n"
+		"   SRATE           sample rate of the sound output\n"
+		"   INITIAL-NOTELEN length of each input note, before it is transformed\n"
+		"   CYCLES-OF-PERM  Number of times the permutation is recursively applied.\n");
+	} else if(!strcmp(str,"delperm2")) {
+		fprintf(stdout,
+    	"DELAY AND TRANSFORM EACH INPUT NOTE, CUMULATIVELY.\n\n"
+		"USAGE: hfperm delperm2 0 \n"
+		"   infile outfile permfile cycles-of-perm\n"
+		"PARAMETERS ARE\n"
+		"   PERMFILE		pairs of vals: 1st a semitone transpos, 2nd a time multiplier\n"
+		"                   Sum of all time-multipliers must be 1.0\n"
+		"   CYCLES-OF-PERM  Number of times the permutation is recursively applied.\n");
+	} else
+		fprintf(stdout,"Unknown option '%s'\n",str);
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE3 ********************************/
+
+int usage3(char *str1,char *str2)
+{
+	sprintf(errstr,"Insufficient parameters on command line.\n");
+	return(USAGE_ONLY);
+}
+
+/************************** ELIMINATE_OCTAVE_DUPLICATIONS **************************/
+
+int eliminate_octave_duplications(dataptr dz)
+{
+	double *hf = dz->parray[0];
+	int n, m, k, octaves_eliminated = 0;
+	for(n=0;n< dz->iparam[HP1_HFCNT]-1;n++) {	
+		for(m=n+1;m< dz->iparam[HP1_HFCNT];m++) {
+			if(flteq(fmod(hf[n],12.0),fmod(hf[m],12.0))) {
+				octaves_eliminated = 1;
+				k = m;
+				dz->iparam[HP1_HFCNT]--;
+				while(k < dz->iparam[HP1_HFCNT]) {
+					hf[k] = hf[k+1];
+					k++;
+				}
+				m--;
+			}
+		}
+	}
+	return octaves_eliminated;
+}
+
+/************************** CHECK_FOR_INVALID_DATA **************************/
+ 
+int check_for_invalid_data(int k,dataptr dz)
+{
+	double *hf = dz->parray[0];
+	int *bad, badcnt = 0;
+	int n;
+	if((bad = (int *)malloc(dz->iparam[k] * sizeof(int)))==NULL)
+		return(MEMORY_ERROR);
+	for(n=0;n< dz->iparam[k];n++) {	
+		if(hf[n] < MIDIMIN || hf[n] > MIDIMAX)
+			bad[badcnt++] = n;						
+	}
+	if(badcnt) {
+		print_outmessage_flush("Invalid midi data in input.....\n");
+		for(n=0;n < badcnt;n++) {
+			sprintf(errstr,"item %d : value %ld\n",bad[n], round(hf[bad[n]]));
+			print_outmessage_flush(errstr);
+		}
+		sprintf(errstr,"Cannot proceed\n");	
+		return(DATA_ERROR);
+	}
+	return FINISHED;
+}
+
+/**************************** TRANSPOSE_TO_LOWEST_OCT *******************************/
+
+void transpose_to_lowest_oct(dataptr dz)
+{
+	int n;
+	double *hf = dz->parray[0];
+	for(n=0;n<dz->iparam[HP1_HFCNT];n++) {
+		while(hf[n] < (double)dz->iparam[HP1_BOTNOTE])
+			hf[n] += 12.0;
+		while(hf[n] >= (double)dz->iparam[HP1_BOTNOTE])
+			hf[n] -= 12.0;
+		hf[n] += 12.0;
+	}
+}
+
+/**************************** BUBLSORT_HF *******************************/
+
+void bublsort_hf(dataptr dz)
+{
+	int n, m;
+	double temp;
+	double *hf = dz->parray[0];
+	for(n=0;n<dz->iparam[HP1_HFCNT]-1;n++) {
+		for(m = n; m<dz->iparam[HP1_HFCNT]; m++) {
+			if(hf[m] < hf[n]) {
+				temp = hf[n];
+				hf[n] = hf[m];
+				hf[m] = temp;
+			}
+		}
+	}
+}
+
+/**************************** ELIM_DUPLS *******************************/
+
+void elim_dupls(dataptr dz)
+{
+	int n, m, k;
+	double *hf = dz->parray[0];
+	for(n=0;n<dz->iparam[HP1_HFCNT]-1;n++) {
+		for(m = n+1; m<dz->iparam[HP1_HFCNT]; m++) {
+			if(hf[m] == hf[n]) {
+				for(k = m+1; k < dz->iparam[HP1_HFCNT];k++)
+					hf[k-1] = hf[k];
+				dz->iparam[HP1_HFCNT]--;
+				m--;					
+			}
+		}
+	}
+}
+
+/******************************** INNER_LOOP (redundant)  ********************************/
+
+int inner_loop
+(int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
+{
+	return(FINISHED);
+}
+
+
+
+
+/*************************** CREATE_HFPERMBUFS **************************/
+
+int create_hfpermbufs(dataptr dz)
+{
+	unsigned int presize = 0;
+//TW ADDED
+	size_t bigbufsize;
+    int fbytesector = F_SECSIZE * sizeof(float);
+	int max_jitter = (int)round((double)HFP_MAXJITTER * (double)MS_TO_SECS * (double)dz->infile->srate);
+	int k = 0;
+
+	switch(dz->process) {
+	case(HF_PERM1):
+	case(HF_PERM2):	
+		k = HP1_ELEMENT_SIZE;	
+		break;
+	case(DEL_PERM):	
+	case(DEL_PERM2):	
+		k = DP_DUR;				
+		break;
+	}
+
+	if(dz->sbufptr == 0 || dz->sampbuf==0) {
+		sprintf(errstr,"buffer pointers not allocated: create_hfpermbufs()\n");
+		return(PROGRAM_ERROR);
+	}
+	switch(dz->process) {
+	case(HF_PERM1):
+	case(HF_PERM2):
+		presize = (dz->iparam[k] + max_jitter + HFP_TABSIZE + 1) * sizeof(double);
+		break;
+	case(DEL_PERM):
+		presize = ((dz->iparam[k] * 2) + max_jitter + HFP_TABSIZE + 1) * sizeof(double);
+		break;
+	case(DEL_PERM2):
+		presize = ((dz->iparam[k] * 2) + max_jitter) * sizeof(double)
+					+ dz->iparam[k] * sizeof(float);
+		break;
+	}	
+//TW CHANGED FOR FLOATS
+	bigbufsize = (size_t) Malloc(-1);
+	if((bigbufsize  = (bigbufsize/fbytesector) * fbytesector)<=0)
+		bigbufsize  = fbytesector;
+	while((dz->bigbuf = (float *)malloc((size_t)(bigbufsize + presize))) == NULL) {
+		if((bigbufsize -= fbytesector) <= 0) {
+			sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
+			return(PROGRAM_ERROR);
+		}
+	}
+	dz->buflen = (int)(bigbufsize/sizeof(float));
+	memset(dz->bigbuf,0,bigbufsize + presize);
+	switch(dz->process) {
+	case(HF_PERM1):
+	case(HF_PERM2):
+	case(DEL_PERM):
+		dz->sbufptr[0] = dz->sampbuf[0] = dz->bigbuf;
+		dz->sbufptr[1] = dz->sampbuf[1] = dz->bigbuf + dz->buflen;
+		dz->sampbuf[2] = (float *)((double *)dz->sampbuf[1] + HFP_TABSIZE + 1);
+		dz->sampbuf[3] = (float *)((double *)dz->sampbuf[2] + dz->iparam[k] + max_jitter);
+		if(dz->process == DEL_PERM)
+			dz->sampbuf[4] = (float *)((double *)dz->sampbuf[3] + dz->iparam[k]);
+		establish_waveform(dz);
+		break;
+	case(DEL_PERM2):
+		dz->sbufptr[0] = dz->sampbuf[0] = dz->bigbuf;
+		dz->sbufptr[1] = dz->sampbuf[1] = dz->bigbuf + dz->buflen;
+		dz->sampbuf[2] = dz->sampbuf[1] + dz->insams[0];
+		dz->sampbuf[3] = (float *)((double *)dz->sampbuf[2] + dz->iparam[k] + max_jitter);
+		dz->sampbuf[4] = (float *)((double *)dz->sampbuf[3] + dz->iparam[k]);
+		break;
+	}
+	return(FINISHED);
+}
+
+/*************************** ESTABLISH_WAVEFORM **************************
+ *
+ * Odd harmonics, declining in amplitude 1, 1/2. 1.3, 1/4 etc...
+ */
+
+void establish_waveform(dataptr dz)
+{
+	int n, partialno, ampdivide;
+	double j, maxval = 0.0, normaliser;
+	double *sintab = (double *)dz->sampbuf[1];
+
+	memset((char *)sintab,0,HFP_TABSIZE * sizeof(double));
+	for(partialno=1,ampdivide=1;partialno<12;partialno+=2,ampdivide++) {
+		for(n=0;n < HFP_TABSIZE; n++) {
+			j = sin(TWOPI * partialno * (double)n/(double)HFP_TABSIZE)/(double)ampdivide;
+			*sintab += j;
+			maxval = max(maxval,fabs(*sintab));
+			sintab++;
+		}
+		j = sin(TWOPI * partialno * (double)n/(double)HFP_TABSIZE)/(double)ampdivide;
+		*sintab += j;
+		maxval = max(maxval,fabs(*sintab));
+		sintab = (double *)dz->sampbuf[1];
+	}
+	normaliser = 1.0/maxval;
+	for(n=0;n < HFP_TABSIZE; n++)
+		*sintab++ *= normaliser;
+}
+
+
+/************************** READ_DELPERM_DATA ********************************/
+
+int read_delperm_data(char *filename,dataptr dz)
+{
+	int n = 0, k, valcnt = 0;
+	char temp[200], *p;
+	double *val;
+//	int is_transpos = TRUE;
+	double dursum = 0.0;
+	int arraysize = BIGARRAY;
+
+	if((dz->fp = fopen(filename,"r"))==NULL) {
+		sprintf(errstr,"Cannot open datafile %s\n",filename);
+		return(DATA_ERROR);
+	}
+	if((val = (double *)malloc(arraysize * sizeof(double)))==NULL) {
+		sprintf(errstr,"No memory for permutation data.\n");
+		return(MEMORY_ERROR);
+	}
+	
+	while(fgets(temp,200,dz->fp)!=NULL) {
+		p = temp;
+		while(strgetfloat(&p,&(val[valcnt]))) {
+			if(++valcnt > arraysize) {
+				arraysize += BIGARRAY;
+				if((val = (double *)realloc((char *)val,arraysize * sizeof(double)))==NULL) {
+					sprintf(errstr,"Out of memory loading permutation data.\n");
+					return(MEMORY_ERROR);
+				}
+			}			
+		}
+	}
+	if(valcnt < arraysize) {
+		if((val = (double *)realloc((char *)val,valcnt * sizeof(double)))==NULL) {
+			sprintf(errstr,"Squeezing permutation data.\n");
+			return(MEMORY_ERROR);
+		}
+	}
+	if(ODD(valcnt)) {
+		sprintf(errstr,"Permutation data incorrectly paired.\n");
+		return(DATA_ERROR);
+	}
+	valcnt /= 2;
+	if((dz->parray[1] = (double *)malloc(valcnt * sizeof(double)))==NULL) {
+		sprintf(errstr,"No memory for transposition data.\n");
+		return(MEMORY_ERROR);
+	}
+	if((dz->parray[2] = (double *)malloc(valcnt * sizeof(double)))==NULL) {
+		sprintf(errstr,"No memory for transposition data.\n");
+		return(MEMORY_ERROR);
+	}
+	for(n=0,k=0;n<valcnt;n++) {
+		if((dz->parray[1][n] = val[k++]) < dz->application->min_special
+		||	dz->parray[1][n] > dz->application->max_special) {
+			sprintf(errstr,"Transposition value %lf out of range, in permutation data.\n",dz->parray[1][n]);
+			return(DATA_ERROR);
+		}		
+		if((dz->parray[2][n] = val[k++]) < dz->application->min_special2
+		||	dz->parray[2][n] > dz->application->max_special2) {
+			sprintf(errstr,"Duration multiplier value %lf out of range, in permutation data.\n",dz->parray[2][n]);
+			return(DATA_ERROR);
+		}		
+		dursum += dz->parray[2][n];
+	}
+	if(!flteq(dursum,1.0)) {
+		sprintf(errstr,"Duration multipliers in permutation data do not sum to 1.0.\n");
+		return(DATA_ERROR);
+	}				
+	free(val);
+	if(fclose(dz->fp)<0) {
+		fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
+		fflush(stdout);
+	}
+	dz->iparam[DP_PERMCNT] = valcnt;
+	return(FINISHED);
+}
+
+/************************** READ_DELPERM2_DATA ********************************/
+
+int read_delperm2_data(char *filename,dataptr dz)
+{
+	int n = 0, k, valcnt = 0/*, linecnt = 0*/;
+	char temp[200], *p;
+	double *val;
+//	int is_transpos = TRUE;
+	double dursum = 0.0;
+	int arraysize = BIGARRAY;
+
+	if((dz->fp = fopen(filename,"r"))==NULL) {
+		sprintf(errstr,"Cannot open datafile %s\n",filename);
+		return(DATA_ERROR);
+	}
+	if((val = (double *)malloc(arraysize * sizeof(double)))==NULL) {
+		sprintf(errstr,"No memory for permutation data.\n");
+		return(MEMORY_ERROR);
+	}
+	while(fgets(temp,200,dz->fp)!=NULL) {
+		p = temp;
+		while(strgetfloat(&p,&(val[valcnt]))) {
+			if(++valcnt > arraysize) {
+				arraysize += BIGARRAY;
+				if((val = (double *)realloc((char *)val,arraysize * sizeof(double)))==NULL) {
+					sprintf(errstr,"Out of memory loading permutation data.\n");
+					return(MEMORY_ERROR);
+				}
+			}			
+		}
+/*		if(!linecnt) {
+			if((dz->parray[0] = (double *)malloc(valcnt * sizeof(double)))==NULL) {
+				sprintf(errstr,"No memory for midi transposition data data.\n");
+				return(MEMORY_ERROR);
+			}
+			dz->iparam[DP_NOTECNT] = valcnt;
+			memcpy((char *)dz->parray[0],(char *)val,valcnt * sizeof(double));
+			linecnt++;
+			valcnt = 0;
+			continue;
+		}
+*/
+	}
+	if(valcnt < arraysize) {
+		if((val = (double *)realloc((char *)val,valcnt * sizeof(double)))==NULL) {
+			sprintf(errstr,"Squeezing permutation data.\n");
+			return(MEMORY_ERROR);
+		}
+	}
+	if(ODD(valcnt)) {
+		sprintf(errstr,"Permutation data incorrectly paired.\n");
+		return(DATA_ERROR);
+	}
+	valcnt /= 2;
+	if((dz->parray[1] = (double *)malloc(valcnt * sizeof(double)))==NULL) {
+		sprintf(errstr,"No memory for transposition data.\n");
+		return(MEMORY_ERROR);
+	}
+	if((dz->parray[2] = (double *)malloc(valcnt * sizeof(double)))==NULL) {
+		sprintf(errstr,"No memory for duration multiplier data.\n");
+		return(MEMORY_ERROR);
+	}
+	for(n=0,k=0;n<valcnt;n++) {
+		if((dz->parray[1][n] = val[k++]) < dz->application->min_special
+		||	dz->parray[1][n] > dz->application->max_special) {
+			sprintf(errstr,"Transposition value %lf out of range, in permutation data.\n",dz->parray[1][n]);
+			return(DATA_ERROR);
+		}		
+		if((dz->parray[2][n] = val[k++]) < dz->application->min_special2
+		||	dz->parray[2][n] > dz->application->max_special2) {
+			sprintf(errstr,"Duration multiplier value %lf out of range, in permutation data.\n",dz->parray[2][n]);
+			return(DATA_ERROR);
+		}		
+		dursum += dz->parray[2][n];
+	}
+	if(!flteq(dursum,1.0)) {
+		sprintf(errstr,"Duration multipliers in permutation data do not sum to 1.0. (%lf)\n",dursum);
+		return(DATA_ERROR);
+	}				
+	free(val);
+	if(fclose(dz->fp)<0) {
+		fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
+		fflush(stdout);
+	}
+	dz->iparam[DP_PERMCNT] = valcnt;
+	return(FINISHED);
+}
+

+ 2117 - 0
dev/hfperm/hfperm.c

@@ -0,0 +1,2117 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sfsys.h>
+#include <osbind.h>
+#include <ctype.h>
+#include <structures.h>
+#include <pnames.h>
+#include <processno.h>
+#include <flags.h>
+#include <modeno.h>
+#include <cdpmain.h>
+#include <globcon.h>
+#include <tkglobals.h>
+#include <logic.h>
+#include <math.h>
+#include <hfperm.h>
+
+#if defined unix || defined __GNUC__
+#define round(x) lround((x))
+#endif
+
+#define BY_STACKING (0)
+#define BY_DENSITY  (1)
+
+#define SMALLEST_FIRST (0)
+#define LARGEST_FIRST (1)
+
+#define ROOT (0)
+#define TOPNOTE (1)
+
+#define KEEP_OCT_EQUIVS (0)
+#define ELIMINATE_OCT_EQUIVS (1)
+
+#define ROLLOFF (0.66)
+
+static int 	generate_perms(double ***combo,int **combolen,int *combocnt,dataptr dz);
+static int	set_element(int element_no,int total_elements,int field_cnt,int *element,
+				double ***combo,int **combolen,int *combocnt);
+static int 	store_combo(double ***combo,int *combocnt,int **combolen,int *element,int total_elements);
+static void substitute_midivals_in_perms(double **combo,int *combolen,int combocnt,dataptr dz);
+static int 	generate_hfsets(int combocnt,double **combo,int *combolen,
+				double ***hfset,int **hfsetlen,int *hfsetcnt,dataptr dz);
+static int 	transpose_element(int element_no,double *thiscombo,int thiscombolen,double *origval,
+				double ***hfset,int **hfsetlen,int *hfsetcnt,dataptr dz);
+static int 	store_transposition(double ***hfset,int **hfsetlen,int *hfsetcnt,double *thiscombo,int thiscombolen);
+static int sort_hfsets(double **hfset,int *hfsetlen,int *hfsetcnt,int *grping,dataptr dz);
+static int gen_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz);
+static int gen_outputs(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz);
+static int gen_text_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz);
+static int gen_midi_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz);
+static void print_grouping_structure(int n,int *grping,int *grping_cnt,int *in_grp,int hfsetcnt);
+static void printout_grouping_structure(int n,int *grping,int *grping_cnt,int *in_grp,int hfsetcnt,dataptr dz);
+static void set_pitch_to_print(int midi);
+static void set_midi_to_print(int midi);
+static void print_pitchset(void);
+static void printout_pitchset(dataptr dz);
+static int sort_by_chord(double **hfset,int *hfsetlen,double *intv,int *hfsetcnt,int *grping,dataptr dz);
+static int sort_by_pitchclass_equivalence
+	(double **hfset,int *hfsetlen,double *pich,int hfsetcnt,int *grping,int *intcnt,
+	double *intv,int *intvcnt,double *intv2,int *intvcnt2,dataptr dz);
+static int sort_by_reference_note_equivalence
+	(double **hfset,int *hfsetlen,int hfsetcnt,int *grping,dataptr dz);
+static void sort_by_maxint(double **hfset,int n,int m,int setlen,dataptr dz);
+static void sort_by_density(double **hfset,int n,int m,int setlen,int lowest);
+static void sort_by_density_regardless_of_size
+	(double **hfset,double *intv,int *intcnt,double *intv2,int *intcnt2,int n,int m,int setlen,int densest_first);
+static void sort_by_maxintsize_and_density(double **hfset,int n,int m,int setlen,int lowest);
+static void sort_by_octave_equivalence(double **hfset,int n,int m,int setlen);
+static void sort_by_interval_stacking(double **hfset,int n,int m,int setlen,int highest_first);
+static void eliminate_oct_duplicated_sets(double **hfset,int *hfsetcnt,int *hfsetlen,int *grping,int *grping_cnt,int type);
+static int  setup_naming(char **thisfilename,dataptr dz);
+static int  create_outfile_name(int ccnt,char *thisfilename,dataptr dz);
+static void gen_note(int maxjitter,double *tabstart,double *tabend,double **tabmin, double **tabmax,double **hfset,
+	double tabscale,double sintabsize,int splicelen, double *sintab,int n, int j);
+int next_file(int *samps_written,char *thisfilename,int *ccnt,unsigned int *space_needed,
+	int *samp_space_available, dataptr dz);
+static void gen_note2(double *tabstart,double *tabend,double midival,
+	double tabscale,double sintabsize,int splicelen, double *sintab);
+//static void gen_note3(double *tabstart,double *tabend,double midival,int tabsize,int splicelen, short *intab);
+static void gen_note3(double *tabstart,double *tabend,double midival,int tabsize,int splicelen, float *intab);
+int gen_dp_output(dataptr dz);
+
+#define LEAVESPACE	(10*1024)
+
+int sorting_type = 0;
+
+int do_hfperm(dataptr dz)
+{
+	int exit_status;
+	char temp[48];
+	double **hfset = 0, **combo, secs;
+	int *combolen, combocnt = 0;
+	int hfsetcnt = 0, hrs = 0, mins = 0;
+	int *hfsetlen = 0;
+	int *grping = NULL;
+	int grping_cnt;
+	if((exit_status = generate_perms(&combo,&combolen,&combocnt,dz))<0)
+		return(exit_status);
+	substitute_midivals_in_perms(combo,combolen,combocnt,dz);	
+	switch(dz->process) {
+	case(HF_PERM1) :
+		if((exit_status = generate_hfsets(combocnt,combo,combolen,&hfset,&hfsetlen,&hfsetcnt,dz))<0)
+			return(exit_status);
+		break;
+	case(HF_PERM2):
+		hfset = combo;
+		hfsetcnt = combocnt;
+		hfsetlen = combolen;
+	}
+	if((grping = (int *)malloc(hfsetcnt * sizeof(int)))==NULL)
+		 print_outwarning_flush("Insufficient memory to store grouping information.\n");
+	grping_cnt = sort_hfsets(hfset,hfsetlen,&hfsetcnt,grping,dz);
+	grping_cnt /= 2;
+	dz->tempsize  = hfsetcnt * (dz->iparam[HP1_ELEMENT_SIZE] + dz->iparam[HP1_GAP_SIZE]);
+	dz->tempsize += grping_cnt * dz->iparam[HP1_GGAP_SIZE];
+	if(dz->true_outfile_stype == SAMP_FLOAT)
+		dz->tempsize *= sizeof(float);
+	else
+		dz->tempsize *= sizeof(short);
+	if(dz->mode == HFP_SNDOUT || dz->mode == HFP_SNDSOUT) {
+		if(dz->mode == HFP_SNDOUT && ((unsigned int)dz->tempsize > (getdrivefreespace(dz->outfilename) - LEAVESPACE))) {
+			sprintf(errstr,"dz->tempsize = %d dz->outfilesize = %d Insufficient space on the hard disk to store the output file.\n",
+				 dz->tempsize,dz->outfilesize);
+			 return(MEMORY_ERROR);
+		} else {
+			sprintf(errstr,"Generating %d chords\n",hfsetcnt);
+			print_outmessage(errstr);
+			if((secs = dz->tempsize/(double)dz->infile->srate) > 60.0) {
+				mins = (int)floor(secs/60.0);
+				secs -= (mins * 60.0);
+				if(mins  > 60) {
+					hrs = mins/60;
+					mins -= (hrs * 60);
+				}
+			}
+			sprintf(errstr,"Duration of output file: ");
+			if(hrs) {
+				sprintf(temp,"%d hrs ",hrs);
+				strcat(errstr,temp);
+			}
+			if(mins) {
+				sprintf(temp,"%d mins ",mins);
+				strcat(errstr,temp);
+			}
+			sprintf(temp,"%.2lf secs\n",secs);
+			strcat(errstr,temp);
+			print_outmessage_flush(errstr);
+		}		
+	}
+	switch(dz->mode) {
+	case(HFP_SNDOUT):
+		if((exit_status = gen_output(hfsetcnt,hfset,hfsetlen,grping,dz))<0)
+			return(exit_status);
+		break;
+	case(HFP_SNDSOUT):
+		if((exit_status = gen_outputs(hfsetcnt,hfset,hfsetlen,grping,dz))<0)
+			return(exit_status);
+		break;
+	case(HFP_TEXTOUT):
+		if((exit_status = gen_text_output(hfsetcnt,hfset,hfsetlen,grping,dz))<0)
+			return(exit_status);
+		break;
+	case(HFP_MIDIOUT):
+		if((exit_status = gen_midi_output(hfsetcnt,hfset,hfsetlen,grping,dz))<0)
+			return(exit_status);
+		break;
+	}
+	return(FINISHED);
+}
+
+/************************** GENERATE_PERMS **************************/
+
+int generate_perms(double ***combo,int **combolen,int *combocnt,dataptr dz)
+{
+	int exit_status;
+	int n, j, maxsize;	
+	int *element;
+	if(dz->iparam[HP1_HFCNT] == dz->iparam[HP1_MINSET]) {
+		if((*combo = (double **)malloc(sizeof(double *)))==NULL) {
+			sprintf(errstr,"Out of memory for harmonic combinations.\n");
+			return(MEMORY_ERROR);
+		}				
+		if((*combolen = (int *)malloc(sizeof(int)))==NULL) {
+			sprintf(errstr,"Out of memory for harmonic combination counts.\n");
+			return(MEMORY_ERROR);
+		}				
+		if(((*combo)[0] = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
+			sprintf(errstr,"Out of memory for harmonic combinations.\n");
+			return(MEMORY_ERROR);
+		}				
+		for(n=0;n<dz->iparam[HP1_HFCNT];n++)
+			(*combo)[0][n] = n;
+		(*combolen)[0] = dz->iparam[HP1_HFCNT];
+		*combocnt = 1;
+		return(FINISHED);
+	} else {
+		if((element = (int *)malloc(dz->iparam[HP1_HFCNT] * sizeof(int)))==NULL) {
+			sprintf(errstr,"Out of memory for permutation elements.\n");
+			return(MEMORY_ERROR);
+		}				
+		if(dz->vflag[HP1_MINONLY]) 
+			maxsize = dz->iparam[HP1_MINSET];
+		else
+			maxsize = dz->iparam[HP1_HFCNT];
+
+		for(n=dz->iparam[HP1_MINSET];n<=maxsize;n++) {
+			for(j=0;j<n;j++)	 	/* initialise perm elements */
+				element[j] = j-1;
+			if((exit_status = set_element(0,n,dz->iparam[HP1_HFCNT],element,combo,combolen,combocnt))<0) {
+				free(element);
+				return(exit_status);
+			}
+		}
+	}
+	free(element);
+	return(FINISHED);
+}
+
+/************************** SET_ELEMENT **************************
+ *
+ * Recursive function to set successive elements of a permutation.
+ */
+
+int set_element(int element_no,int total_elements,int field_cnt,int *element,double ***combo,int **combolen,int *combocnt)
+{
+	int exit_status, k;
+	int limit = field_cnt - total_elements + element_no;
+	for(;;) {
+		element[element_no]++;					/* incr the element number */
+		if(element[element_no] > limit) {		/* if it's now beyond max for this element */
+			if(element_no > 0) {				/* reset this, & all elements above it */
+				k = element_no;					/* to be in ascending sequence from element below */
+				while(k < total_elements) {		/* ready for incrementation of next lowest element */
+					element[k] = element[k-1] + 1;
+					k++;
+				}
+			}
+			return(CONTINUE);					/* then return to next lowest element */
+		}
+		if(element_no >= total_elements-1) {	/* if all elements have been set, store the combination */
+			if((exit_status = store_combo(combo,combocnt,combolen,element,total_elements))<0)
+				return(exit_status);
+		} else  { 								/* but if not, go on to set the next element */
+			if((exit_status = set_element(element_no+1,total_elements,field_cnt,element,combo,combolen,combocnt))<0)
+				return(exit_status);
+		}
+	}
+	return(CONTINUE);	/* NOTREACHED */
+}
+
+/************************** STORE_COMBO **************************/
+
+int store_combo(double ***combo,int *combocnt,int **combolen,int *element,int total_elements)
+{
+	int n, j;
+	j = *combocnt;
+	(*combocnt)++;								/* incr count of combinations */
+	if(*combocnt == 1) {						/* create a new combo_store location */
+		if((*combo = (double **)malloc(sizeof(double *)))==NULL) {
+			sprintf(errstr,"Out of memory for harmonic combinations.\n");
+			return(MEMORY_ERROR);
+		}										/* create a new combo_store_cnt location */
+		if((*combolen = (int *)malloc(sizeof(int)))==NULL) {
+			sprintf(errstr,"Out of memory for harmonic combinations.\n");
+			return(MEMORY_ERROR);
+		}				
+	} else {									
+		if((*combo = (double **)realloc((char *)(*combo),(*combocnt) * sizeof(double *)))==NULL) {
+			sprintf(errstr,"Out of memory for harmonic combinations.\n");
+			return(MEMORY_ERROR);
+		}				
+		if((*combolen = (int *)realloc((char *)(*combolen),(*combocnt) * sizeof(int)))==NULL) {
+			sprintf(errstr,"Out of memory for harmonic combinations.\n");
+			return(MEMORY_ERROR);
+		}				
+	}											/* create the new combo_store */
+	if(((*combo)[j] = (double *)malloc(total_elements * sizeof(double)))==NULL) {
+		sprintf(errstr,"Out of memory for harmonic combinations.\n");
+		return(MEMORY_ERROR);
+	}				
+	for(n=0; n < total_elements; n++)			/* store the new combo */
+		(*combo)[j][n] = (double)element[n];
+	(*combolen)[j] = total_elements;			/* store the count of the new combo */
+	return(FINISHED);
+}
+
+/************************** ELIMINATE_OCTAVE_DUPLICATIONS **************************/
+
+int eliminate_octave_duplications(dataptr dz)
+{
+	double *hf = dz->parray[0];
+	int n, m, k, octaves_eliminated = 0;
+	for(n=0;n< dz->iparam[HP1_HFCNT]-1;n++) {	
+		for(m=n+1;m< dz->iparam[HP1_HFCNT];m++) {
+			if(flteq(fmod(hf[n],12.0),fmod(hf[m],12.0))) {
+				octaves_eliminated = 1;
+				k = m;
+				dz->iparam[HP1_HFCNT]--;
+				while(k < dz->iparam[HP1_HFCNT]) {
+					hf[k] = hf[k+1];
+					k++;
+				}
+				m--;
+			}
+		}
+	}
+	return octaves_eliminated;
+}
+
+/**************************** SUBSTITUTE_MIDIVALS_IN_PERMS *******************************/
+
+void substitute_midivals_in_perms(double **combo,int *combolen,int combocnt,dataptr dz)
+{
+	double *hf = dz->parray[0];
+	int n, m, k;
+	for(n=0;n<combocnt;n++) {
+		for(m=0;m < combolen[n];m++) {
+			k = (int)combo[n][m];
+			combo[n][m] = hf[k];
+		}
+	}
+}
+
+/**************************** BUBLSORT_HF *******************************/
+
+void bublsort_hf(double *hf,dataptr dz)
+{
+	int n, m;
+	double temp;
+	for(n=0;n<dz->iparam[HP1_HFCNT]-1;n++) {
+		for(m = n+1; m<dz->iparam[HP1_HFCNT]; m++) {
+			if(hf[m] < hf[n]) {
+				temp = hf[n];
+				hf[n] = hf[m];
+				hf[m] = temp;
+			}
+		}
+	}
+}
+
+/**************************** GENERATE_OCTS *******************************/
+
+int transpose_element(int element_no,double *thiscombo,int thiscombolen,double *origval,
+	double ***hfset,int **hfsetlen,int *hfsetcnt,dataptr dz)
+{
+	int exit_status;
+	for(;;) {
+		thiscombo[element_no] += 12.0;
+		if(thiscombo[element_no] > (double)dz->iparam[HP1_TOPNOTE]) {
+			thiscombo[element_no] = origval[element_no];
+			return CONTINUE;					
+		}
+		if(element_no >= thiscombolen-1) {	/* if all elements have been set, store the hfset */
+			if((exit_status = store_transposition(hfset,hfsetlen,hfsetcnt,thiscombo,thiscombolen))<0)
+				return(exit_status);
+		} else  { 								/* but if not, go on to set the next element */
+			if((exit_status = 
+			transpose_element(element_no+1,thiscombo,thiscombolen,origval,hfset,hfsetlen,hfsetcnt,dz))<0)
+				return(exit_status);
+		}
+	}
+	return(CONTINUE);	/* NOTREACHED */
+}
+
+/**************************** STORE_TRANSPOSITION *******************************/
+
+int store_transposition(double ***hfset,int **hfsetlen,int *hfsetcnt,double *thiscombo,int thiscombolen)
+{
+	int n, j;
+	j = *hfsetcnt;
+	(*hfsetcnt)++;								/* incr count of hfset */
+	if(*hfsetcnt == 1) {						/* create a new hfset_store location */
+		if((*hfset = (double **)malloc(sizeof(double *)))==NULL) {
+			sprintf(errstr,"Out of memory for final sets.\n");
+			return(MEMORY_ERROR);
+		}										/* create a new hfset_store_cnt location */
+		if((*hfsetlen = (int *)malloc(sizeof(int)))==NULL) {
+			sprintf(errstr,"Out of memory for final sets.\n");
+			return(MEMORY_ERROR);
+		}				
+	} else {									
+		if((*hfset = (double **)realloc((char *)(*hfset),(*hfsetcnt) * sizeof(double *)))==NULL) {
+			sprintf(errstr,"Out of memory for final sets.\n");
+			return(MEMORY_ERROR);
+		}				
+		if((*hfsetlen = (int *)realloc((char *)(*hfsetlen),(*hfsetcnt) * sizeof(int)))==NULL) {
+			sprintf(errstr,"Out of memory for final sets.\n");
+			return(MEMORY_ERROR);
+		}				
+	}											/* create the new hfset store */
+	if(((*hfset)[j] = (double *)malloc(thiscombolen * sizeof(double)))==NULL) {
+		sprintf(errstr,"Out of memory for final sets.\n");
+		return(MEMORY_ERROR);
+	}				
+	for(n=0; n < thiscombolen; n++)			/* store the new hfset */
+		(*hfset)[j][n] = thiscombo[n];
+	(*hfsetlen)[j] = thiscombolen;			/* store the count of the new hfset */
+	return(FINISHED);
+}
+
+/************************** GENERATE_HFSETS **************************/
+
+int generate_hfsets(int combocnt,double **combo,int *combolen,double ***hfset,int **hfsetlen,int *hfsetcnt,dataptr dz)
+{
+	int exit_status;
+	int n, j;
+	double *origval;
+	if((origval = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
+		sprintf(errstr,"Out of memory for storing original comobo vals.\n");
+		return(MEMORY_ERROR);
+	}
+	for(n=0;n<combocnt;n++) {
+		for(j=0;j<combolen[n];j++) {
+			combo[n][j] -= 12.0;
+			origval[j] = combo[n][j];
+		}
+		if((exit_status = transpose_element(0,combo[n],combolen[n],origval,hfset,hfsetlen,hfsetcnt,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/************************** SORT_HFSETS **************************/
+
+int sort_hfsets(double **hfset,int *hfsetlen,int *hfsetcnt,int *grping,dataptr dz)
+{
+	int n, m, j;
+	double temp;
+	int itemp;
+	double *intv, *intv2, *pich;
+	int *intvcnt, *intvcnt2;
+//	int grping_cnt = 0, in_grp = 0;
+	int grping_cnt = 0;
+	int *minint = NULL, *intcnt = NULL;
+	int hfsetcount = *hfsetcnt;
+
+	grping[0] = -1;					/* flags output not to do grouping */
+
+	for(j = 0;j<hfsetcount;j++) {		 /*	Sort the individual sets themselves, so pitches are in ascending order */
+		for(n=0;n<hfsetlen[j]-1;n++) {
+			for(m = n+1; m<hfsetlen[j]; m++) {
+				if(hfset[j][m] < hfset[j][n]) {
+					temp = hfset[j][n];
+					hfset[j][n] = hfset[j][m];
+					hfset[j][m] = temp;
+				}
+			}
+		}
+	}
+	print_outmessage_flush("Sorting chords by note-count.\n");
+	for(n=0;n<hfsetcount-1;n++) {		 /*	Sort the sets by size */
+		for(m = n+1; m<hfsetcount; m++) {
+			if(hfsetlen[m] < hfsetlen[n]) {
+				itemp = hfsetlen[n];
+				hfsetlen[n] = hfsetlen[m];
+				hfsetlen[m] = itemp;
+			}
+		}
+	}
+	switch(dz->iparam[HP1_SORT1]) {
+	case(ROOT):
+	case(TOP):
+	case(PCLASS):
+		if ((intv = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
+			print_outwarning_flush("Insufficient memory to sort chords in terms of pitch equivalence.\n");
+			return 0;
+		}														
+		if ((intv2 = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
+			print_outwarning_flush("Insufficient memory to sort chords in terms of pitch equivalence.\n");
+			return 0;
+		}														
+		if ((intvcnt = (int *)malloc(dz->iparam[HP1_HFCNT] * sizeof(int)))==NULL) {
+			print_outwarning_flush("Insufficient memory to sort chords in terms of pitch equivalence.\n");
+			return 0;
+		}														
+		if ((intvcnt2 = (int *)malloc(dz->iparam[HP1_HFCNT] * sizeof(int)))==NULL) {
+			print_outwarning_flush("Insufficient memory to sort chords in terms of pitch equivalence.\n");
+			return 0;
+		}														
+		if ((pich = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
+			print_outwarning_flush("Insufficient memory to sort chords in terms of pitch equivalence.\n");
+			return 0;
+		}														
+		if(dz->vflag[HP1_DENS] == OTHER_SORT) {
+			if ((minint = (int *)malloc(hfsetcount * sizeof(int)))==NULL)
+				print_outwarning_flush("Insufficient memory to sort chord-groups.\n");
+			else if ((intcnt = (int *)malloc(hfsetcount * sizeof(int)))==NULL)
+				print_outwarning_flush("Insufficient memory to sort chord-groups.\n");
+		}										
+		switch(dz->iparam[HP1_SORT1]) {
+		case(PCLASS):
+			print_outmessage_flush("Sorting chords by pitchclass-equivalence.\n");
+			grping_cnt = sort_by_pitchclass_equivalence
+				(hfset,hfsetlen,pich,hfsetcount,grping,intcnt,intv,intvcnt,intv2,intvcnt2,dz);
+			break;
+		default:
+			print_outmessage_flush("Sorting chords by reference-note-equivalence.\n");
+			grping_cnt = sort_by_reference_note_equivalence(hfset,hfsetlen,hfsetcount,grping,dz);
+			break;
+		}
+		break;
+	case(CHORDTYPE):
+	case(CHORD_1):
+		if ((intv = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
+			print_outwarning_flush("Insufficient memory to sort chords in terms of interval equivalence.\n");
+			return 0;
+		}														
+		print_outmessage_flush("Sorting chords by interval-equivalence.\n");
+		grping_cnt = sort_by_chord(hfset,hfsetlen,intv,hfsetcnt,grping,dz);
+		break;
+	default:
+		sprintf(errstr,"Unknown chord sort type.\n");
+		return(PROGRAM_ERROR);
+	}
+	if(dz->vflag[HP1_ELIMOCTS] && (dz->iparam[HP1_SORT1] != CHORD_1))
+		eliminate_oct_duplicated_sets(hfset,hfsetcnt,hfsetlen,grping,&grping_cnt,sorting_type);	
+	return grping_cnt;
+}
+
+/************************** GEN_OUTPUT **************************/
+
+int gen_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz)
+{
+	int exit_status;
+//	short *obuf = dz->sampbuf[0];
+	float *obuf = dz->sampbuf[0];
+	double *tab = (double *)dz->sampbuf[2];
+	double *tabend = tab + dz->iparam[HP1_ELEMENT_SIZE];
+	double tabscale = (double)HFP_TABSIZE/dz->infile->srate;
+	double *sintab = (double *)dz->sampbuf[1];
+	double sintabsize = (double)HFP_TABSIZE;
+	double element_level;
+	int samps_written = 0, samp_space_available, samps_to_write, gap_size;
+	int n, i, j, grping_cnt = 0;
+	int maxjitter = (int)round(drand48() * HFP_MAXJITTER * MS_TO_SECS * (double)dz->infile->srate);
+	unsigned int element_byte_len = dz->iparam[HP1_ELEMENT_SIZE] * sizeof(double);
+	unsigned int element_full_len = element_byte_len + (maxjitter * sizeof(double));
+	double *tabmax = 0, *tabmin = tab + dz->iparam[HP1_ELEMENT_SIZE] + maxjitter;
+	int splicelen = (int)round(HP1_SPLICELEN * MS_TO_SECS * (double)dz->infile->srate);
+	int in_group = 0, in_grp = 0;
+
+	print_outmessage_flush("Synthesis beginning.\n");
+	memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
+	for(n=0;n<hfsetcnt;n++) {
+		memset((char *)dz->sampbuf[2],0,element_full_len);
+
+		if(grping!=NULL && grping[0] != -1)
+			print_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt);
+		errstr[0] = ENDOFSTR;
+
+		for(j=0;j<hfsetlen[n];j++) {
+			set_pitch_to_print((int)hfset[n][j]);
+			gen_note(maxjitter,tab,tabend,&tabmin,&tabmax,hfset,tabscale,sintabsize,splicelen,sintab,n,j);
+		}
+		print_pitchset();
+		element_level = HFP_OUTLEVEL/hfsetlen[n];
+		tab = tabmin;
+		while(tab < tabmax)
+			*tab++ *= element_level;
+		/* DO OUTPUT */
+		samp_space_available = dz->buflen - samps_written;
+		gap_size = dz->iparam[HP1_GAP_SIZE];
+		if(grping!=NULL && grping[0] != -1) {
+			if(grping[grping_cnt]==n) {
+				in_group = 1;
+				gap_size += dz->iparam[HP1_GGAP_SIZE];	 /* make gap at start */
+				grping_cnt++;
+			} else if(grping[grping_cnt]==-n) {
+				in_group = 0;
+				gap_size += dz->iparam[HP1_GGAP_SIZE];		/* make gap at end */
+				grping_cnt++;				/* if grp end coincides with gp start */
+				if(grping[grping_cnt]==n) { /* skip a grping value */
+					in_group = 1;
+					grping_cnt++;
+				}
+			} else if (!in_group)
+				gap_size += dz->iparam[HP1_GGAP_SIZE]; 		/* make gap between non-grouped entries */
+		}
+		if(n!=0) {							/* no gap at start */
+			while(gap_size >= samp_space_available) {
+				if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
+					return(exit_status);
+				memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
+				gap_size -= samp_space_available;
+				samp_space_available = dz->buflen;
+				samps_written = 0;
+			}
+			samps_written += gap_size;
+			samp_space_available = dz->buflen - samps_written;
+		}
+		i = 0;
+		tab = tabmin;
+		samp_space_available = dz->buflen - samps_written;
+		samps_to_write = tabmax - tabmin;
+		while(i < samps_to_write) {
+			if(samp_space_available > samps_to_write) {
+				while(i < samps_to_write)
+//					obuf[samps_written++] = (short)round(tab[i++] * MAXSAMP);
+					obuf[samps_written++] = (float)tab[i++];
+			} else {
+				while(samps_written < dz->buflen)
+//					obuf[samps_written++] = (short)round(tab[i++] * MAXSAMP);
+					obuf[samps_written++] = (float)tab[i++];
+				if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
+					return(exit_status);
+				memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
+				samps_written = 0;
+				samp_space_available = dz->buflen;
+			}
+		}
+	}
+	if(grping!=NULL && grping[0] != -1)
+		print_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt);
+	samps_written += dz->iparam[HP1_GAP_SIZE];
+	while(samps_written >= dz->buflen) {
+		if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
+			return(exit_status);
+		samps_written -= dz->buflen;
+	}	
+	if(samps_written > 0) {
+		if((exit_status = write_samps(dz->sampbuf[0],samps_written,dz))<0)
+			return(exit_status);
+	}	
+	return(FINISHED);
+}
+
+/************************** GEN_OUTPUTS **************************/
+
+int gen_outputs(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz)
+{
+	int exit_status;
+	float *obuf = dz->sampbuf[0];
+	double *tab = (double *)dz->sampbuf[2];
+	double *tabend = tab + dz->iparam[HP1_ELEMENT_SIZE];
+	double tabscale = (double)HFP_TABSIZE/dz->infile->srate;
+	double *sintab = (double *)dz->sampbuf[1];
+	double sintabsize = (double)HFP_TABSIZE;
+	double element_level;
+	int samps_written = 0, samp_space_available, samps_to_write, gap_size;
+	int n, i, j, grping_cnt = 0;
+	int maxjitter = (int)round(drand48() * HFP_MAXJITTER * MS_TO_SECS * (double)dz->infile->srate);
+	unsigned int element_byte_len = dz->iparam[HP1_ELEMENT_SIZE] * sizeof(double);
+	unsigned int element_full_len = element_byte_len + (maxjitter * sizeof(double));
+	double *tabmax = 0, *tabmin = tab + dz->iparam[HP1_ELEMENT_SIZE] + maxjitter;
+	int splicelen = (int)round(HP1_SPLICELEN * MS_TO_SECS * (double)dz->infile->srate);
+	int in_group = 0, in_grp = 0;
+	char *thisfilename;
+	int ccnt = 0;
+	unsigned int space_needed = dz->tempsize;
+
+	superzargo = 0;
+	if((exit_status = setup_naming(&thisfilename,dz))<0)
+		return(exit_status);
+	if((exit_status = create_outfile_name(0,thisfilename,dz))<0)
+		return(exit_status);
+	dz->process_type = UNEQUAL_SNDFILE;	/* allow sndfile to be created */
+	if((exit_status = create_sized_outfile(thisfilename,dz))<0) {
+		fprintf(stdout, "WARNING: Soundfile %s already exists.\n", thisfilename);
+		fflush(stdout);
+		dz->process_type = OTHER_PROCESS;
+		dz->ofd = -1;
+		return(PROGRAM_ERROR);
+	}							
+	if((unsigned int)dz->outfilesize < space_needed) {
+		 sprintf(errstr,"Insufficient space on the hard disk to store the output files.\n");
+		 return(MEMORY_ERROR);
+	}
+	dz->total_samps_written = 0;
+	print_outmessage_flush("Synthesis beginning.\n");
+	memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
+	for(n=0;n<hfsetcnt;n++) {
+		memset((char *)dz->sampbuf[2],0,element_full_len);
+
+		if(grping!=NULL && grping[0] != -1)
+			print_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt);
+		errstr[0] = ENDOFSTR;
+
+		for(j=0;j<hfsetlen[n];j++) {
+			set_pitch_to_print((int)hfset[n][j]);
+			gen_note(maxjitter,tab,tabend,&tabmin,&tabmax,hfset,tabscale,sintabsize,splicelen,sintab,n,j);
+		}
+		print_pitchset();
+		element_level = HFP_OUTLEVEL/hfsetlen[n];
+		tab = tabmin;
+		while(tab < tabmax)
+			*tab++ *= element_level;
+		/* DO OUTPUT */
+		samp_space_available = dz->buflen - samps_written;
+		gap_size = dz->iparam[HP1_GAP_SIZE];
+		if(grping!=NULL && grping[0] != -1) {
+			if(grping[grping_cnt]==n) {
+				if(in_group == 0 && n!=0) {
+					if((exit_status = next_file(&samps_written,thisfilename,&ccnt,&space_needed,&samp_space_available,dz))<0)
+						return(exit_status);
+				}
+				in_group = 1;
+				grping_cnt++;
+			} else if(grping[grping_cnt]==-n) {	/* if at end of group */
+				in_group = 0;
+				if((exit_status = next_file(&samps_written,thisfilename,&ccnt,&space_needed,&samp_space_available,dz))<0)
+					return(exit_status);
+				grping_cnt++;				/* if grp end coincides with gp start */
+				if(grping[grping_cnt]==n) { /* skip a grping value */
+					in_group = 1;
+					grping_cnt++;
+				}
+			} else if(in_group == 0 && n!=0) {	/* if not a grouped chord */
+				if((exit_status = next_file(&samps_written,thisfilename,&ccnt,&space_needed,&samp_space_available,dz))<0)
+					return(exit_status);
+			}
+		}
+		if(n!=0) {							/* no gap at start */
+			while(gap_size >= samp_space_available) {
+				if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
+					return(exit_status);
+				memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
+				gap_size -= samp_space_available;
+				samp_space_available = dz->buflen;
+				samps_written = 0;
+			}
+			samps_written += gap_size;
+			samp_space_available = dz->buflen - samps_written;
+		}
+		i = 0;
+		tab = tabmin;
+		samp_space_available = dz->buflen - samps_written;
+		samps_to_write = tabmax - tabmin;
+		while(i < samps_to_write) {
+			if(samp_space_available > samps_to_write) {
+				while(i < samps_to_write)
+					obuf[samps_written++] = (float)tab[i++];
+			} else {
+				while(samps_written < dz->buflen)
+					obuf[samps_written++] = (float)tab[i++];
+				if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
+					return(exit_status);
+				memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
+				samps_written = 0;
+				samp_space_available = dz->buflen;
+			}
+		}
+	}
+	if(grping!=NULL && grping[0] != -1)
+		print_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt);
+	samps_written += dz->iparam[HP1_GAP_SIZE];
+	while(samps_written >= dz->buflen) {
+		if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
+			return(exit_status);
+		samps_written -= dz->buflen;
+	}	
+	if(samps_written > 0) {
+		if((exit_status = write_samps(dz->sampbuf[0],samps_written,dz))<0)
+			return(exit_status);
+	}	
+	/* CLOSE FILE */
+	dz->outfiletype  = SNDFILE_OUT;			/* allows header to be written  */
+	if((exit_status = headwrite(dz->ofd,dz))<0)
+		return(exit_status);
+	dz->process_type = OTHER_PROCESS;		
+	dz->outfiletype  = NO_OUTPUTFILE;		
+	if((exit_status = reset_peak_finder(dz))<0)
+		return(exit_status);
+	if(sndcloseEx(dz->ofd) < 0) {
+		fprintf(stdout,"WARNING: Can't close output soundfile %s\n",thisfilename);
+		fflush(stdout);
+	}
+	dz->ofd = -1;							
+	return(FINISHED);
+}
+
+/************************** GEN_TEXT_OUTPUT **************************/
+
+int gen_text_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz)
+{
+	int n, j, grping_cnt = 0;
+	int in_group = 0, in_grp = 0;
+
+	for(n=0;n<hfsetcnt;n++) {
+		if(grping!=NULL && grping[0] != -1) {
+			printout_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt,dz);
+		}
+		errstr[0] = ENDOFSTR;
+		for(j=0;j<hfsetlen[n];j++) {
+			set_pitch_to_print((int)hfset[n][j]);
+		}
+		printout_pitchset(dz);
+		if(grping!=NULL && grping[0] != -1) {
+			if(grping[grping_cnt]==n) {
+				in_group = 1;
+				grping_cnt++;
+			} else if(grping[grping_cnt]==-n) {	/* if at end of group */
+				in_group = 0;
+				grping_cnt++;				/* if grp end coincides with gp start */
+				if(grping[grping_cnt]==n) { /* skip a grping value */
+					in_group = 1;
+					grping_cnt++;
+				}
+			}
+		}
+	}
+	if(grping!=NULL && grping[0] != -1) {
+		printout_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt,dz);
+	}
+	display_virtual_time(dz->tempsize,dz);
+	return(FINISHED);
+}
+
+/************************** GEN_MIDI_OUTPUT **************************/
+
+int gen_midi_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz)
+{
+	int n, j, grping_cnt = 0;
+//	int in_group = 0, in_grp = 0;
+	int in_group = 0;
+
+	for(n=0;n<hfsetcnt;n++) {
+		errstr[0] = ENDOFSTR;
+		for(j=0;j<hfsetlen[n];j++)
+			set_midi_to_print((int)hfset[n][j]);
+		printout_pitchset(dz);
+		if(grping!=NULL && grping[0] != -1) {
+			if(grping[grping_cnt]==n) {
+				in_group = 1;
+				grping_cnt++;
+			} else if(grping[grping_cnt]==-n) {	/* if at end of group, or not a grouped chord */
+				in_group = 0;
+				grping_cnt++;				/* if grp end coincides with gp start */
+				if(grping[grping_cnt]==n) { /* skip a grping value */
+					in_group = 1;
+					grping_cnt++;
+				}
+			}
+		}
+	}
+	display_virtual_time(dz->tempsize,dz);
+	return(FINISHED);
+}
+
+/************************** PRINT_GROUPING_STRUCTURE **************************/
+
+void print_grouping_structure(int n,int *grping,int *grping_cnt,int *in_grp,int hfsetcnt)
+{
+	if(grping[*grping_cnt]==-n && (n!=0)) {	  	/* if end of group marked */
+		*in_grp = 0;
+		print_outmessage_flush("))- - - - - - -\n");
+		if(grping[(*grping_cnt)+1]==n) {		/* if start of group ALSO marked */
+			*in_grp = 1;
+			print_outmessage_flush("-------------((\n");
+		}
+	} else if(grping[*grping_cnt]==n) {			/* if start of group marked */
+		*in_grp = 1;
+		print_outmessage_flush("-------------((\n");
+	} else if(!(*in_grp)) {						/* not inside a group */
+		print_outmessage_flush("-----\n");
+	} else if(n >= hfsetcnt) {					/* inside a group at end of whole pass */
+		print_outmessage_flush("))- - - - - - -\n");
+	}
+}
+
+/************************** PRINTOUT_GROUPING_STRUCTURE **************************/
+
+void printout_grouping_structure(int n,int *grping,int *grping_cnt,int *in_grp,int hfsetcnt,dataptr dz)
+{
+	if(grping[*grping_cnt]==-n && (n!=0)) {	  	/* if end of group marked */
+		*in_grp = 0;
+		print_outmessage_flush("))- - - - - - -\n");
+		fprintf(dz->fp,"))- - - - - - -\n");
+		if(grping[(*grping_cnt)+1]==n) {		/* if start of group ALSO marked */
+			*in_grp = 1;
+			print_outmessage_flush("-------------((\n");
+			fprintf(dz->fp,"-------------((\n");
+		}
+	} else if(grping[*grping_cnt]==n) {			/* if start of group marked */
+		*in_grp = 1;
+		print_outmessage_flush("-------------((\n");
+		fprintf(dz->fp,"-------------((\n");
+	} else if(!(*in_grp)) {						/* not inside a group */
+		print_outmessage_flush("-----\n");
+		fprintf(dz->fp,"-----\n");
+	} else if(n >= hfsetcnt) {					/* inside a group at end of whole pass */
+		print_outmessage_flush("))- - - - - - -\n");
+		fprintf(dz->fp,"))- - - - - - -\n");
+	}
+}
+
+/************************** SET_PITCH_TO_PRINT **************************/
+
+void set_pitch_to_print(int midi)
+{
+	int oct =  (midi/12)-5;
+	char temp[12];
+	midi = midi%12;
+	switch(midi) {
+	case(0):	sprintf(temp,"C%d  ",oct);	break;
+	case(1):	sprintf(temp,"C#%d ",oct);	break;
+	case(2):	sprintf(temp,"D%d  ",oct);	break;
+	case(3):	sprintf(temp,"Eb%d ",oct);	break;
+	case(4):	sprintf(temp,"E%d  ",oct);	break;
+	case(5):	sprintf(temp,"F%d  ",oct);	break;
+	case(6):	sprintf(temp,"F#%d ",oct);	break;
+	case(7):	sprintf(temp,"G%d  ",oct);	break;
+	case(8):	sprintf(temp,"Ab%d ",oct);	break;
+	case(9):	sprintf(temp,"A%d  ",oct);	break;
+	case(10):	sprintf(temp,"Bb%d ",oct);	break;
+	case(11):	sprintf(temp,"B%d  ",oct);	break;
+	}
+	if(oct>=0)
+		strcat(temp," ");
+	strcat(errstr,temp);
+}
+
+/************************** SET_MIDI_TO_PRINT **************************/
+
+void set_midi_to_print(int midi)
+{
+	char temp[12];
+	sprintf(temp,"%d  ",midi);
+	strcat(errstr,temp);
+}
+
+/************************** PRINT_PITCHSET **************************/
+
+void print_pitchset(void)
+{
+	char temp[12];
+	sprintf(temp,"\n");
+	strcat(errstr,temp);
+	print_outmessage_flush(errstr);
+}
+
+/************************** PRINTOUT_PITCHSET **************************/
+
+void printout_pitchset(dataptr dz)
+{
+	char temp[12];
+	sprintf(temp,"\n");
+	strcat(errstr,temp);
+	print_outmessage_flush(errstr);
+	fprintf(dz->fp,"%s",errstr);
+}
+
+/************************** SORT_BY_CHORD ***************************
+ *
+ *	Sort size-ordered then pitch-ordered sets, by equivalence of chords they make up.
+ */
+
+int sort_by_chord(double **hfset,int *hfsetlen,double *intv,int *hfsetcnt,int *grping,dataptr dz)
+{
+	int a, b, m, n, j, lastmatch, was_a_match;
+	double *tempoint;
+	int grping_cnt = 0, matching_intervals = 0;
+
+	for(n=0;n<(*hfsetcnt)-1;n++) {		 			
+		for(j = 0; j<hfsetlen[n]-1; j++)
+			intv[j] = hfset[n][j+1] - hfset[n][j];			/* set up intervals of first set as a comparison set */
+		lastmatch = n;
+		was_a_match = 0;
+		for(m = n+1; m<=*hfsetcnt; m++) {
+			if(m==*hfsetcnt || hfsetlen[m] != hfsetlen[n]){	/* if got to end of group-of-sets of same size */
+
+				if(was_a_match) {							/* if a matching-group has just been put together */
+					for(a=n;a<lastmatch;a++) {
+						for(b = a+1; b<=lastmatch; b++) {	/* sort matching chords into pitch-ascending order */
+							if(hfset[b][0] < hfset[a][0]) {
+								tempoint = hfset[a];
+								hfset[a] = hfset[b];
+								hfset[b] = tempoint;
+							}
+						}
+					}	
+					if(grping!=NULL && n!=0) {
+						grping[grping_cnt++] = n;				/* ....mark group start */
+						grping[grping_cnt++] = -(lastmatch+1);		/* mark group end */
+					}
+					if(lastmatch != m-1) {					/* if match-group didn't end at end of last samesize-group */	
+						n = lastmatch+1;					/* baktrak n to position AFTER END of matching set */
+						for(j = 0; j<hfsetlen[n]-1; j++)	/* set this set's intervals as comparison intervals */
+							intv[j] = hfset[n][j+1] - hfset[n][j];	
+						m = n;								/* reset m to run over sets after n */
+						lastmatch = n;
+						was_a_match = 0;					/* search for further matching sets */
+						continue;
+															/* ELSE last match ended at end of group-of-sets */
+					} else if(m < (*hfsetcnt)-1) {			/* SO, if we're not at last set */
+						for(j = 0; j<hfsetlen[m]-1; j++)	/* establish interval comparison set for new setsize */	
+							intv[j] = hfset[m][j+1] - hfset[m][j];	
+						lastmatch = m;						/* reset the base pointer of matching sets */
+						was_a_match = 0;
+						n = m;								/* skip n-index to base of next group samesize sets */
+					}
+				} else {									/* matching set not been made in this pass */
+					m = *hfsetcnt;							/* force n to advance */
+				}
+			} else {
+				matching_intervals = 1;						/* compare samesize (sorted) sets for matching intervals */
+				for(j = 0; j<hfsetlen[m]-1; j++) {			
+					if (!flteq(intv[j],hfset[m][j+1] - hfset[m][j])) {
+						matching_intervals = 0;
+						break;
+					}
+				}
+				if(matching_intervals) {					/* if all intervals match */
+					was_a_match = 1;						/* note tha a match has been found in this pass */
+					lastmatch++;							/* incr pointer to last match position */
+					if(m != lastmatch) {					/* if the matching set is not AT this position */
+						tempoint = hfset[lastmatch];		/* move it to that position */
+						hfset[lastmatch] = hfset[m];
+						hfset[m] = tempoint;
+					}
+				}
+			}
+		}
+	}
+	if(dz->iparam[HP1_SORT1] == CHORD_1) {
+		for(b = 0; b < grping_cnt; b+=2) {
+			m = grping[b] + 1;
+			n = -(grping[b+1]);
+			j = n - m;
+			while(n < *hfsetcnt)
+				hfset[m++] = hfset[n++];
+			*hfsetcnt -= j;
+		}
+		grping_cnt = 0;
+		grping[0] = -1;
+	}
+	return grping_cnt;
+}
+
+/************************** SORT_BY_PITCHCLASS_EQUIVALENCE ***************************
+ *
+ *	Sort size-ordered THEN pitch-ordered sets, by pitch-class equivalence of root note in each size-group.
+ */
+
+
+int sort_by_pitchclass_equivalence
+	(double **hfset,int *hfsetlen,double *pich,int hfsetcnt,int *grping,int *intcnt,
+	double *intv,int *intvcnt,double *intv2,int *intvcnt2,dataptr dz)
+{
+	int j, k, m, n;
+	int in_grp = 0, grping_cnt = 0, matching_pitches, setlen;
+
+	n = 0;
+	setlen = hfsetlen[n];
+	for(j = 0; j<setlen; j++)
+		pich[j] = fmod(hfset[n][j],12.0);			/* set up pitches of first set, as a comparison set */
+	for(m=1;m<hfsetcnt;m++) {
+		if(hfsetlen[m] != setlen) {
+			if(in_grp) {
+				grping[grping_cnt++] = -m;			/* mark end of group */
+				in_grp = 0;
+			}
+			if(intcnt != NULL) {
+				if(dz->vflag[HP1_DENS] == DENSE_SORT)
+					sort_by_density_regardless_of_size(hfset,intv,intvcnt,intv2,intvcnt2,n,m,setlen,1);
+				else
+					sort_by_maxintsize_and_density(hfset,n,m,setlen,0);
+			}
+			n = m;
+			setlen = hfsetlen[n];
+			for(j = 0; j<setlen; j++)
+				pich[j] = fmod(hfset[n][j],12.0);	/* set up pitches of new comparison set */
+			continue;
+		}
+		matching_pitches = 1;			   			/* no pitch-class duplication in sets */
+		for(j=0;j<hfsetlen[m];j++) {
+			matching_pitches = 0;
+			for(k=0;k<hfsetlen[m];k++) {
+				if(flteq(fmod(hfset[m][j],12.0),pich[k])) {
+					matching_pitches = 1;
+					break;
+				}
+			}
+			if(!matching_pitches)
+				break;
+		}
+		if(matching_pitches) {
+			if(!in_grp) {
+				grping[grping_cnt++] = (m-1);		/* mark start of group */
+				in_grp = 1;
+			}
+		} else {
+			if(in_grp) {
+				grping[grping_cnt++] = -m;			/* mark end of group */
+				in_grp = 0;
+			}
+			if(intcnt != NULL) { 
+				if(dz->vflag[HP1_DENS] == DENSE_SORT)
+					sort_by_density_regardless_of_size(hfset,intv,intvcnt,intv2,intvcnt2,n,m,setlen,1);
+				else
+					sort_by_maxintsize_and_density(hfset,n,m,setlen,0);
+			}
+			n = m;
+			setlen = hfsetlen[n];
+			for(j = 0; j<setlen; j++)
+				pich[j] = fmod(hfset[n][j],12.0);	/* set up pitches of new comparison set */
+			continue;
+		}
+	}
+	if(intcnt != NULL) { 
+		if(dz->vflag[HP1_DENS] == DENSE_SORT)
+			sort_by_density_regardless_of_size(hfset,intv,intvcnt,intv2,intvcnt2,n,m,setlen,1);
+		else
+			sort_by_maxintsize_and_density(hfset,n,m,setlen,0);
+	}
+	return(grping_cnt);
+}
+
+/************************** SORT_BY_REFERENCE_NOTE_EQUIVALENCE ***************************
+ *
+ *	Sort pitch-ordered by pitch-class equivalence of root note.
+ */
+
+int sort_by_reference_note_equivalence(double **hfset,int *hfsetlen,int hfsetcnt,int *grping,dataptr dz)
+{
+	int j, k, m, n;
+	int in_grp = 0, grping_cnt = 0, setlen, end, note = 0;
+	double *tempoint, thispitch, thatpitch;
+
+	n = 0;
+	m = n+1;
+	while(m < hfsetcnt) {
+		setlen = hfsetlen[n];
+		end = setlen - 1;
+		switch(dz->iparam[HP1_SORT1]) {
+		case(ROOT):		note = 0; 	break;
+		case(TOP):		note = end;	break;
+		}
+		while(hfsetlen[m] == setlen) {			/* find sets of same size */
+			if(++m >= hfsetcnt)
+				break;
+		}
+		for(j=n;j<m-1;j++) {					/* sort all these samesize sets into root pitchclass order */
+			if(dz->process == HF_PERM1)
+				thispitch = fmod(hfset[j][note],12.0);
+			else
+				thispitch = hfset[j][note];
+			for(k=j+1;k<m;k++) {
+				if(dz->process == HF_PERM1)
+					thatpitch = fmod(hfset[k][note],12.0);
+				else
+					thatpitch = hfset[k][note];
+				if(thatpitch < thispitch) {
+					tempoint = hfset[k];
+					hfset[k] = hfset[j];
+					hfset[j] = tempoint;
+				}
+			}
+		}
+		k = n;										/* sort all these into same-root sets */
+		j = k+1;
+		if(j >= hfsetcnt)
+			break;
+		in_grp = 0;
+		while(j < m) {								
+			if(dz->process == HF_PERM1) {
+				thispitch = fmod(hfset[k][note],12.0);
+				thatpitch = fmod(hfset[j][note],12.0);
+			} else {
+				thispitch = hfset[k][note];
+				thatpitch = hfset[j][note];
+			}
+			while(flteq(thatpitch,thispitch)) {
+				if(!in_grp) {
+					grping[grping_cnt++] = k;		/* mark start of group */
+					in_grp = 1;
+				}
+				if(++j >= m)
+					break;
+				if(dz->process == HF_PERM1) {
+					thispitch = fmod(hfset[k][note],12.0);
+					thatpitch = fmod(hfset[j][note],12.0);
+				} else {
+					thispitch = hfset[k][note];
+					thatpitch = hfset[j][note];
+				}
+			}
+			if(in_grp) {							/* sort all these into density:tessitura order */
+				grping[grping_cnt++] = -j;			/* mark end of group */
+				sort_by_maxint(hfset,k,j,setlen,dz);	
+				in_grp = 0;							/* sort same-root sets into interval size and stack order */
+			}
+			k = j;
+			j = k+1;
+		}		
+		n = m;
+		m = n+1;
+	}
+	return(grping_cnt);
+}
+
+/********************************* SORT_BY_MAXINT *********************************
+ *
+ *	Sort pitch-ordered sets of FIXED SIZE by size of largest interval, then by interval density
+ */
+
+void sort_by_maxint(double **hfset,int n,int m,int setlen,dataptr dz)
+{
+	int j, k;
+	double j_maxint, k_maxint, *tempoint;
+	int end = setlen - 1;
+	int in_grp;
+	
+	for(j=n;j<m-1;j++) {					/* sort all by size of largest interval */
+		j_maxint = hfset[j][end] - hfset[j][0];
+		for(k=j+1;k<m;k++) {
+			k_maxint = hfset[k][end] - hfset[k][0];
+			switch(dz->vflag[HP1_SPAN]) {
+			case(MAXSPAN_FIRST):
+				if(k_maxint < j_maxint) {
+					tempoint = hfset[j];
+					hfset[j] = hfset[k];
+					hfset[k] = tempoint;
+					j_maxint = k_maxint;
+				}
+				break;
+			case(MAXSPAN_LAST):
+				if(k_maxint > j_maxint) {
+					tempoint = hfset[j];
+					hfset[j] = hfset[k];
+					hfset[k] = tempoint;
+					j_maxint = k_maxint;
+				}
+				break;
+			}
+		}
+	}
+	k = n;
+	j = k+1;
+	in_grp = 0;
+	while(j < m) {							/* sort largest-interval sets  by internal interval arrangement */
+		in_grp = 0;
+		k_maxint = hfset[k][end] - hfset[k][0];
+		j_maxint = hfset[j][end] - hfset[j][0];
+		while(flteq(j_maxint,k_maxint)) {
+			in_grp = 1;
+			if(++j >= m)
+				break;
+			j_maxint = hfset[j][end] - hfset[j][0];
+		}
+		if(in_grp) {
+			switch(dz->vflag[HP1_DENS]) {
+			case(DENSE_SORT): 	sort_by_density(hfset,k,j,setlen,0);			break;
+			case(OTHER_SORT):	sort_by_interval_stacking(hfset,k,j,setlen,0);	break;
+			}
+			sort_by_octave_equivalence(hfset,n,m,setlen);
+		}
+		k = j;
+		j = k+1;
+	}
+}
+
+/********************************* SORT_BY_DENSITY *********************************
+ *
+ *	Sort pitch-ordered sets of FIXED SIZE , WITH FIXED MAX INTERVAL by density...
+ *  measure the deviation from the mean inteval size between adjacent notes.
+ *  Minimum deviation = minimum density.
+ */
+
+void sort_by_density(double **hfset,int n,int m,int setlen,int lowest)
+{
+	int j, k, x;
+	double j_deviation, k_deviation, y, average_intsize;
+	double *tempoint;
+
+	average_intsize = (hfset[n][setlen-1] - hfset[n][0])/(setlen-1);
+
+	for(j=n;j<m-1;j++) {
+		j_deviation = 0;
+		for(x = 1; x < setlen; x++) {
+			y = hfset[j][x] - hfset[j][x-1];
+			y = fabs(y - average_intsize);
+			j_deviation += y;		/* no advantage in taking rms */
+		}
+		for(k=j+1;k<m;k++) {
+			k_deviation = 0;
+			for(x = 1; x < setlen; x++) {
+				y = hfset[k][x] - hfset[k][x-1];
+				y = fabs(y - average_intsize);
+				k_deviation += y;	/* no advantage in taking rms */
+			}
+			if(lowest) {
+				if(k_deviation < j_deviation) {
+					tempoint = hfset[k];
+					hfset[k] = hfset[j];
+					hfset[j] = tempoint;
+					j_deviation = k_deviation;
+				}
+			} else {
+				if(k_deviation > j_deviation) {
+					tempoint = hfset[k];
+					hfset[k] = hfset[j];
+					hfset[j] = tempoint;
+					j_deviation = k_deviation;
+				}
+			}
+		}
+	}
+}
+
+/********************************* SORT_BY_MAXINTSIZE_AND_DENSITY *********************************
+ *
+ *	Sort pitch-ordered sets of FIXED SIZE , NOT of FIXED MAX INTERVAL by density...
+ *  measure the deviation from the mean inteval size between adjacent notes.
+ *  Minimum deviation = minimum density.
+ */
+
+void sort_by_maxintsize_and_density(double **hfset,int n,int m,int setlen,int lowest)
+{
+	int j, k, end = setlen - 1, in_grp;
+	double j_intsize, k_intsize;
+	double *tempoint;
+
+	for(j=n;j<m-1;j++) {				  		/* sort by max-intsize */
+		j_intsize = hfset[j][end] - hfset[j][0];
+		for(k=j+1;k<m;k++) {
+			k_intsize = hfset[k][end] - hfset[k][0];
+			if(k_intsize < j_intsize) {
+				tempoint = hfset[k];
+				hfset[k] = hfset[j];
+				hfset[j] = tempoint;
+				j_intsize = k_intsize;
+			}
+		}
+	}
+	j = n;
+	k = j+1;
+	while(k < m) {
+		j_intsize = hfset[j][end] - hfset[j][0];
+		in_grp = 0;
+		while(flteq(hfset[k][end] - hfset[k][0],j_intsize)) {
+			in_grp = 1;
+			if(++k >= m)
+				break;
+		}
+		if(in_grp)
+			sort_by_density(hfset,j,k,setlen,lowest);
+		j = k;
+		k = j+1;
+	}
+}
+
+/********************************* SORT_BY_OCTAVE_EQUIVALENCE *********************************
+ *
+ *	Sort pitch-ordered sets of FIXED SIZE by equivalence at octave transposition, putting lower tessitura item first.
+ */
+
+void sort_by_octave_equivalence
+		(double **hfset,int n,int m,int setlen)
+{
+	int i, j, j_base, j_adj, k, oct_equivalence;
+	double *tempoint, int_diff;
+
+	for(j=n;j<m-1;j++) {
+		j_base = j;
+		j_adj = j+1;								/* if sets are separate by multiple of an octave */
+		for(k=j+1;k<m;k++) {
+			if(flteq(fmod((int_diff = hfset[k][0] - hfset[j][0]),12.0),0.0)) {
+				oct_equivalence = 1;
+				for(n=1;n<setlen;n++) {
+					if(!flteq(hfset[k][n] - hfset[j][n],int_diff)) {
+						oct_equivalence = 0;
+						break;
+					}
+				}
+				if(oct_equivalence) {				/* if oct-equivalent */
+					if(k != j_adj) {				/* if NOT adjacent */
+						tempoint = hfset[j_adj];
+						hfset[j_adj] = hfset[k];	/* move oct-equiv set to be adjacent to j */
+						hfset[k] = tempoint;
+					}
+					i = j;
+					while(hfset[j_adj][0] < hfset[i][0]) {
+						if(--i < j_base)
+							break;
+					}
+					i++;
+					if(i<=j) {
+						tempoint = hfset[i];
+						hfset[i] = hfset[j_adj];	/* move lower register item to correct place in group */
+						hfset[j_adj] = tempoint;
+					}
+					j++;							/* advance to new oct-equiv position */
+					j_adj++;
+				}
+			}
+		}
+	}
+}
+
+/********************************* SORT_BY_INTERVAL_STACKING *********************************
+ *
+ *	Sort pitch-ordered sets of FIXED SIZE , WITH FIXED MAX INTERVAL by sequnce of pitches within...
+ *  NORMALLY - start with chord having the lowest pitches (on average)
+ *  ... if 'highest-first' flag set, start with chord with highest pitches (on average)
+ */
+
+void sort_by_interval_stacking(double **hfset,int n,int m,int setlen,int highest_first)
+{
+	int j, k, x;
+	double j_height, k_height;
+	double *tempoint;
+
+	for(j=n;j<m-1;j++) {
+		j_height = 0;
+		for(x = 1; x < setlen; x++)
+			j_height += hfset[j][x] - hfset[j][0];
+		for(k=j+1;k<m;k++) {
+			k_height = 0;
+			for(x = 1; x < setlen; x++)
+				k_height += hfset[k][x] - hfset[k][0];
+			if(highest_first) {
+				if(k_height > j_height) {
+					tempoint = hfset[k];
+					hfset[k] = hfset[j];
+					hfset[j] = tempoint;
+					j_height = k_height;
+				}
+			} else {
+				if(k_height < j_height) {
+					tempoint = hfset[k];
+					hfset[k] = hfset[j];
+					hfset[j] = tempoint;
+					j_height = k_height;
+				}
+			}
+		}
+	}
+}
+
+/********************************* ELIMINATE_OCT_DUPLICATED_SETS *********************************
+ *
+ *	Sort ordered-by-size, then pitch-ordered sets, eliniating stes dupliated at 8vas.
+ */
+
+void eliminate_oct_duplicated_sets(double **hfset,int *hfsetcnt,int *hfsetlen,int *grping,int *grping_cnt,int type)
+{
+	int a, b, n, m, j, k, oct_equivalence, setlen;
+	double *tempoint, int_diff;
+
+	n=0;
+	m = n+1;
+	setlen = hfsetlen[n];
+	while(n < *hfsetcnt) {
+		while(hfsetlen[m] == setlen) {							/* find equal-size sets */
+			if(++m >= *hfsetcnt)
+				break;
+		}
+		if(m == n+1) {
+			n++;
+			if((m = n+1) >= *hfsetcnt)
+				break;
+			setlen = hfsetlen[n];
+			continue;
+		}
+		for(j=n;j<m-1;j++) {
+			for(k = j+1;k<m;k++) {
+				if(flteq(fmod((int_diff = hfset[k][0] - hfset[j][0]),12.0),0.0)) {
+					oct_equivalence = 1;
+					for(a=1;a<setlen;a++) {
+						if(!flteq(hfset[k][a] - hfset[j][a],int_diff)) {
+							oct_equivalence = 0;
+							break;
+						}
+					}
+					if(oct_equivalence) {					/* if oct-equivalent */
+						if(type == TOPNOTE) {
+							if(hfset[k][0] > hfset[j][0]) {
+								tempoint = hfset[j];
+								hfset[j] = hfset[k];		/* keep the higher-register item */
+								hfset[k] = tempoint;
+							}
+						} else {
+							if(hfset[k][0] < hfset[j][0]) {
+								tempoint = hfset[j];
+								hfset[j] = hfset[k];		/* keep the lower-register item */
+								hfset[k] = tempoint;
+							}
+						}
+						for(a=k,b=k+1;b<*hfsetcnt;a++,b++)	/* delete unwanted set */
+							hfset[a] = hfset[b];
+						if(grping != NULL) {				/* reposition grouping marks */
+							for(a=0;a<*grping_cnt;a++) {		
+															/* if start or end of short group */ 	
+								if(((grping[a] == k)   && (a+1 < *grping_cnt) && (grping[a+1] >= -(k+2)))
+								|| ((grping[a] == k-1) && (a+1 < *grping_cnt) && (grping[a+1] >= -(k+1)))) {
+									if(a+2 < *grping_cnt) {	/* eliminate both */
+										for(b = a+2; b < *grping_cnt;b++)
+											grping[b-2] = grping[b];
+									}
+									*grping_cnt -= 2;
+									a -= 1;					/* step back to resume parse */
+								}
+								else if(grping[a] > k)		/* decrement all markers beyond */
+									grping[a]--;
+								else if(grping[a] < -k)
+									grping[a]++;
+							}
+						}
+						(*hfsetcnt)--;						/* decrement all counters */
+						m--;
+						k--;
+					}
+				}
+			}
+		}
+		n = m;
+		if((m = n+1) >= *hfsetcnt)
+			break;
+		setlen = hfsetlen[n];
+	}
+}
+
+/********************************* SORT_BY_DENSITY_REGARDLESS_OF_SIZE *********************************
+ *
+ *	Sort pitch-ordered sets of FIXED LENGTH . by density, regardless of MAX INTERVAL...
+ *	.... sort on basis of maximum number of minsize intervals.
+ */
+
+void sort_by_density_regardless_of_size
+	(double **hfset,double *interv,int *intervcnt,double *interv2,int *intervcnt2,int n,int m,int setlen,int densest_first)
+{
+	int a, j, k, x, q, do_swap, equivalent;
+	double tempdb, *tempoint;
+	int intsetlen1 = setlen - 1;
+	int intsetlen2 = setlen - 1;
+	int tempoi, end = setlen - 1;
+	double *intv = interv, *intv2 = interv2;
+	int *intvcnt = intervcnt, *intvcnt2 = intervcnt2, *tempii;
+
+	for(j=n;j<m-1;j++) {
+		intsetlen1 = setlen - 1;
+		for(x=1;x<setlen;x++) {
+			intv[x-1] = hfset[j][x] - hfset[j][x-1];   	/* find each interval and count it */
+			intvcnt[x-1] = 1;
+		}
+		for(x=0;x<intsetlen1-1;x++) {
+			for(q=x+1;q<intsetlen1;q++) {
+				if(flteq(intv[q],intv[x])) {			/* compare intervals */
+					intvcnt[x]++;						/* if same, incr count of first */
+					a = q;
+					while(a< intsetlen1-1)	{			/* and eliminate other from set */
+						intv[a] = intv[a+1];
+						a++;
+					}
+					intsetlen1--;
+					q--;
+				}
+			}
+		}
+		for(x=0;x<intsetlen1-1;x++) {					/* sort intervals by size */
+			for(q=x+1;q<intsetlen1;q++) {
+				if(intv[q] < intv[x]) {
+					tempdb = intv[q];
+					intv[q] = intv[x];
+					intv[x] = tempdb;
+					tempoi = intvcnt[q];
+					intvcnt[q] = intvcnt[x];
+					intvcnt[x] = tempoi;
+				}
+			}
+		}
+
+		for(k=j+1;k<m;k++) {
+			intsetlen2 = setlen - 1;
+			for(x=1;x<setlen;x++) {
+				intv2[x-1] = hfset[k][x] - hfset[k][x-1];
+				intvcnt2[x-1] = 1;
+			}
+			for(x=0;x<intsetlen2-1;x++) {
+				for(q=x+1;q<intsetlen2;q++) {
+					if(flteq(intv2[q],intv2[x])) {
+						intvcnt2[x]++;
+						a = q;
+						while(a < intsetlen2-1) {
+							intv2[a] = intv2[a+1];
+							a++;
+						}
+						intsetlen2--;
+						q--;
+					}
+				}
+			}
+			for(x=0;x<intsetlen2-1;x++) {
+				for(q=x+1;q<intsetlen2;q++) {
+					if(intv2[q] < intv2[x]) {
+						tempdb = intv2[q];
+						intv2[q] = intv2[x];
+						intv2[x] = tempdb;
+						tempoi = intvcnt2[q];
+						intvcnt2[q] = intvcnt2[x];
+						intvcnt2[x] = tempoi;
+					}
+				}
+			}
+			do_swap = 0;
+			equivalent = 1;
+			if(densest_first) {
+				for(a=0;a<min(intsetlen1,intsetlen2);a++) {
+					if(intv2[a] > intv[a]) {
+						equivalent = 0;
+						break;
+					} else if(intv2[a] < intv[a]) {
+						equivalent = 0;
+						do_swap = 1;
+						break;
+					} else {
+						 if(intvcnt2[a] > intvcnt[a]) {
+							equivalent = 0;
+							do_swap = 1;
+							break;
+						} else if(intvcnt2[a] < intvcnt[a]) {
+							equivalent = 0;
+							break;
+						}
+					}
+				}
+			} else {
+				for(a=0;a<min(intsetlen1,intsetlen2);a++) {
+					if(intv2[a] < intv[a]) {
+						equivalent = 0;
+						break;
+					} else if(intv2[a] > intv[a]) {
+						equivalent = 0;
+						do_swap = 1;
+						break;
+					} else {
+						if(intvcnt2[a] < intvcnt[a]) {
+							equivalent = 0;
+							do_swap = 1;
+							break;
+						} else if(intvcnt2[a] > intvcnt[a]) {
+							equivalent = 0;
+							break;
+						}
+					}
+				}
+			}
+			if((!do_swap) && equivalent) {	/* swap if total range is greater */
+				if(hfset[j][end] - hfset[j][0] > hfset[k][end] - hfset[k][0])
+					do_swap = 1;
+				else if(hfset[j][0] > hfset[k][0])	/* swap if root is lower */
+					do_swap = 1;
+			}
+			if(do_swap) {
+				tempoint = hfset[k];
+				hfset[k] = hfset[j];
+				hfset[j] = tempoint;
+				tempoint = intv;
+				intv = intv2;
+				intv2 = tempoint;
+				tempii = intvcnt ;
+				intvcnt = intvcnt2;
+				intvcnt2 = tempii;
+			}
+		}
+	}
+}
+
+/******************************* SETUP_NAMING ******************************/
+
+int setup_naming(char **thisfilename,dataptr dz)
+{
+	int innamelen = strlen(dz->wordstor[0]);
+	int numlen = 5;
+// FEB 2010 TW
+	if((*thisfilename = (char *)malloc((innamelen + numlen + 10) * sizeof(char)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for outfilename.\n");
+		return(MEMORY_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********************************** CREATE_OUTFILE_NAME ********************************/
+
+int create_outfile_name(int ccnt,char *thisfilename,dataptr dz)
+{
+	strcpy(thisfilename,dz->wordstor[0]);
+// FEB 2010 TW
+	if(!sloom)
+		insert_separator_on_sndfile_name(thisfilename,1);
+	insert_new_number_at_filename_end(thisfilename,ccnt,1);
+	return(FINISHED);
+}
+
+/********************************** GEN_NOTE ********************************/
+
+void gen_note(int maxjitter,double *tabstart,double *tabend,double **tabmin, double **tabmax,double **hfset,
+	double tabscale,double sintabsize,int splicelen, double *sintab,int n, int j)
+{
+	int jitter, initial_phase, i;
+	double *this_tabend, *startsplice_end, *endsplice_start, *tab; 
+	double sintabpos, sintabincr;
+	int intpos, nxtpos;
+	double frac, vallo, valhi, valdif;
+	
+	jitter = (int)round(drand48() * maxjitter);
+	tab = tabstart + jitter;
+	this_tabend = tabend + jitter;
+	*tabmin = min(tab,*tabmin);
+	*tabmax = max(this_tabend,*tabmax);
+	tab++;			/* 1st val = 0 */
+	/* START POSITION IN TABLE TO READ TO GENERATE SOUND */
+	initial_phase = (int)round(drand48() * HFP_TABSIZE);
+	sintabincr = (miditohz(hfset[n][j]) * tabscale);
+	sintabpos = sintabincr + initial_phase;
+	sintabpos = fmod(sintabpos,sintabsize);
+	startsplice_end = tab + splicelen;
+	endsplice_start = this_tabend - splicelen;
+	/* START OF EACH CONSTITUENT MUST BE SPLICED */
+	i = 0;
+	while(tab < startsplice_end) {		
+		intpos = (int)floor(sintabpos);
+		nxtpos = intpos+1;
+		frac = sintabpos - (double)intpos;
+		vallo = sintab[intpos];
+		valhi = sintab[nxtpos];
+		valdif= valhi - vallo;
+		*tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
+		i++;
+		sintabpos += sintabincr;
+		sintabpos = fmod(sintabpos,sintabsize);
+		tab++;
+	}
+	while(tab < endsplice_start) {		
+		intpos = (int)floor(sintabpos);
+		nxtpos = intpos+1;
+		frac = sintabpos - (double)intpos;
+		vallo = sintab[intpos];
+		valhi = sintab[nxtpos];
+		valdif= valhi - vallo;
+		*tab += vallo + (valdif * frac);
+		sintabpos += sintabincr;
+		sintabpos = fmod(sintabpos,sintabsize);
+		tab++;
+	}
+	/* END OF EACH CONSTITUENT MUST BE SPLICED */
+	i = splicelen - 1;
+	while(tab < this_tabend) {		
+		intpos = (int)floor(sintabpos);
+		nxtpos = intpos+1;
+		frac = sintabpos - (double)intpos;
+		vallo = sintab[intpos];
+		valhi = sintab[nxtpos];
+		valdif= valhi - vallo;
+		*tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
+		i--;
+		sintabpos += sintabincr;
+		sintabpos = fmod(sintabpos,sintabsize);
+		tab++;
+	}
+}
+
+/********************************** NEXT_FILE ********************************/
+
+int next_file(int *samps_written,char *thisfilename,int *ccnt,unsigned int *space_needed, 
+int *samp_space_available,dataptr dz)
+{
+	int exit_status;
+				/* FLUSH BUFS */
+	*samps_written += dz->iparam[HP1_GAP_SIZE];
+	while(*samps_written >= dz->buflen) {
+		if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
+			return(exit_status);
+		*samps_written -= dz->buflen;
+	}	
+	if(*samps_written > 0) {
+		if((exit_status = write_samps(dz->sampbuf[0],*samps_written,dz))<0)
+			return(exit_status);
+	}	
+				/* CLOSE FILE */
+	dz->outfiletype  = SNDFILE_OUT;			/* allows header to be written  */
+	if((exit_status = headwrite(dz->ofd,dz))<0)
+		return(exit_status);
+	dz->process_type = OTHER_PROCESS;		/* restore true status */
+	dz->outfiletype  = NO_OUTPUTFILE;		/* restore true status */
+	superzargo += dz->total_samps_written;	/* accumulator of total samples written */
+	if((exit_status = reset_peak_finder(dz))<0)
+		return(exit_status);
+	if(sndcloseEx(dz->ofd) < 0) {
+		fprintf(stdout,"WARNING: Can't close output soundfile %s\n",thisfilename);
+		fflush(stdout);
+	}
+	dz->ofd = -1;
+	(*ccnt)++;
+				/* OPEN NEW FILE */
+	if((exit_status = create_outfile_name(*ccnt,thisfilename,dz))<0)
+		return(exit_status);
+	dz->process_type = UNEQUAL_SNDFILE;	/* allow sndfile to be created */
+	if((exit_status = create_sized_outfile(thisfilename,dz))<0) {
+		fprintf(stdout, "WARNING: Soundfile %s already exists.\n",thisfilename);
+		fflush(stdout);
+		dz->process_type = OTHER_PROCESS;
+		dz->ofd = -1;
+		return(PROGRAM_ERROR);
+	}							
+	*space_needed -= dz->total_samps_written;
+	if((unsigned int)dz->outfilesize < *space_needed) {
+		 sprintf(errstr,"Insufficient space on the hard disk to store the next output file.\n");
+		 return(MEMORY_ERROR);
+	}
+				/* RESET BUFFERS */
+	dz->total_samps_written = 0;
+	memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
+	*samp_space_available = dz->buflen;
+	*samps_written = 0;
+//NEW TW
+	return(FINISHED);
+}
+
+/********************************** GEN_DP_OUTPUT ********************************/
+
+int gen_dp_output(dataptr dz)
+{
+	int exit_status;
+	float *obuf = dz->sampbuf[0];
+	double *tabend, *tab = (double *)dz->sampbuf[3];
+	double *accumtab = (double *)dz->sampbuf[2];
+	double *perm = dz->parray[1];
+	double tabscale = (double)HFP_TABSIZE/dz->infile->srate;
+	double *sintab = (double *)dz->sampbuf[1];
+	float  *intab = dz->sampbuf[1];
+	double sintabsize, pad;
+	int intabsize;
+	int samps_written = 0, samp_space_available, samps_to_write;
+	int note_being_permed, noteno, index_in_new_perm, index_in_last_perm, i, j, no_of_perms, permcounter, transpos_cnt;
+	int maxjitter = (int)round(drand48() * HFP_MAXJITTER * MS_TO_SECS * (double)dz->infile->srate);
+	unsigned int element_byte_len = dz->iparam[DP_DUR] * sizeof(double);
+	unsigned int element_full_len = element_byte_len + (maxjitter * sizeof(double));
+	double *tabmin = accumtab, *tabmax = accumtab + dz->iparam[DP_DUR] + maxjitter;
+	int splicelen = (int)round(HP1_SPLICELEN * MS_TO_SECS * (double)dz->infile->srate);
+	double ampmult = 1.0/(double)(dz->iparam[DP_CYCCNT] + 1);
+	double *permset, thistranspos;
+	int accumtabstart, accumtabend, a, b;
+	int jitter, endindex_of_last_perm, endindex_of_last_perm_but_one, endindex_in_new_perm = 0, len, thislen;
+
+/* JUNE 2004 */	
+sprintf(errstr,"ERROR: This program is currently malfunctioning.\n");
+return(PROGRAM_ERROR);
+/* JUNE 2004 */	
+	switch(dz->process) {
+	case(DEL_PERM):		
+		sintabsize = (double)HFP_TABSIZE; 
+		ampmult *= MAXSAMP;
+		break;
+	case(DEL_PERM2):	
+		intabsize  = dz->iparam[DP_DUR]; 
+		break;
+	}
+
+	dz->tempsize = dz->iparam[DP_DUR] * (dz->iparam[DP_NOTECNT] + dz->iparam[DP_CYCCNT]);
+
+	if((permset = 
+	(double *)malloc((unsigned int)round(pow(dz->iparam[DP_PERMCNT],dz->iparam[DP_CYCCNT])) * sizeof(double))) == NULL) {
+		sprintf(errstr,"No memory for permutations of notes\n");
+		return(MEMORY_ERROR);
+	}
+	for(noteno = 0; noteno < dz->iparam[DP_NOTECNT]/* + dz->iparam[DP_CYCCNT]*/; noteno++) {
+		sprintf(errstr,"Expanding note %d\n",noteno+1);
+		print_outmessage_flush(errstr);
+		memset(accumtab,0,element_full_len);
+		for(note_being_permed = noteno, no_of_perms = 0; 
+		note_being_permed >= max(0,noteno - dz->iparam[DP_CYCCNT]);
+		note_being_permed--, no_of_perms++) {
+			if(note_being_permed >= dz->iparam[DP_NOTECNT])
+				continue;
+			jitter = (int)(drand48() * maxjitter);
+			accumtabstart = jitter;
+			permset[0] = dz->parray[1][note_being_permed];
+			endindex_of_last_perm = 0;
+			endindex_of_last_perm_but_one = 0;
+			for(permcounter = 0; permcounter < no_of_perms; permcounter++) {
+				index_in_last_perm = endindex_of_last_perm;
+				endindex_in_new_perm = ((index_in_last_perm+1) * dz->iparam[DP_PERMCNT]) - 1;				
+				index_in_new_perm  = endindex_in_new_perm; 
+				while(index_in_last_perm >= 0) {
+					for(transpos_cnt = dz->iparam[DP_PERMCNT]-1; transpos_cnt >= 0; transpos_cnt--)
+						permset[index_in_new_perm--] = permset[index_in_last_perm] + perm[transpos_cnt];
+					index_in_last_perm--;
+				}
+				endindex_of_last_perm_but_one = endindex_of_last_perm;
+				endindex_of_last_perm = endindex_in_new_perm;
+			}
+			tab = (double *)dz->sampbuf[3];
+			if(no_of_perms > 0) {
+				if((len = (int)round((double)dz->iparam[DP_DUR]/(double)(endindex_of_last_perm_but_one+1))) <= splicelen * 2) {
+					sprintf(errstr,"Notes have become too short for splices to be made.\n");
+					return(GOAL_FAILED);
+				}
+				for(i = 0, j = 0; i <= endindex_of_last_perm; i++, j++) {
+					j %= dz->iparam[DP_PERMCNT];
+					switch(dz->process) {
+					case(DEL_PERM):  
+						thislen = (int)round(len * dz->parray[2][j]);
+						if(thislen <= splicelen * 2) {
+							sprintf(errstr,"Notes have become too short for splices to be made.\n");
+							return(GOAL_FAILED);
+						}
+						tabend = tab + thislen;
+						memset((char *)tab,0,element_byte_len);
+						
+						gen_note2(tab,tabend,permset[i],tabscale,sintabsize,splicelen,sintab);	break;
+					case(DEL_PERM2): 
+						thistranspos = pow(2.0,(permset[i]/12.0));
+						thislen = (int)round(len/thistranspos);
+						thislen = min(thislen,len);
+						if(thislen <= splicelen * 2) {
+							sprintf(errstr,"Notes have become too short for splices to be made.\n");
+							return(GOAL_FAILED);
+						}
+						tabend = tab + thislen;
+						memset((char *)tab,0,element_byte_len);
+						gen_note3(tab,tabend,thistranspos,intabsize,splicelen,intab);			break;
+					}
+					accumtabstart = accumtabstart + thislen;
+					accumtabend = accumtabstart + thislen;
+					pad = pow(ROLLOFF,no_of_perms);
+					accumtabstart += thislen;
+				}
+			} else { 
+				len = dz->iparam[DP_DUR];
+				tabend = tab + len;
+				memset(tab,0,element_byte_len);
+				switch(dz->process) {
+				case(DEL_PERM):  gen_note2(tab,tabend,permset[0],tabscale,sintabsize,splicelen,sintab);	break;
+				case(DEL_PERM2): gen_note3(tab,tabend,permset[0],intabsize,splicelen,intab);			break;
+				}
+				accumtabend = accumtabstart + len;
+				for(a=accumtabstart, b = 0; a < accumtabend;a++,b++)
+					accumtab[a] += tab[b]; 
+				accumtabstart += len;
+			}
+		}
+		/* DO OUTPUT */
+		samp_space_available = dz->buflen - samps_written;
+		i = 0;
+		samps_to_write = tabmax - tabmin;
+		while(i < samps_to_write) {
+			if(samp_space_available > samps_to_write) {
+				while(i < samps_to_write)
+					obuf[samps_written++] = (float)(accumtab[i++] * ampmult);
+			} else {
+				while(samps_written < dz->buflen)
+					obuf[samps_written++] = (float)(accumtab[i++] * ampmult);
+				if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
+					return(exit_status);
+				memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
+				samps_written = 0;
+				samp_space_available = dz->buflen;
+			}
+		}
+	}
+	while(samps_written >= dz->buflen) {
+		if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
+			return(exit_status);
+		samps_written -= dz->buflen;
+	}	
+	if(samps_written > 0) {
+		if((exit_status = write_samps(dz->sampbuf[0],samps_written,dz))<0)
+			return(exit_status);
+	}	
+	return(FINISHED);
+}
+
+/********************************** GEN_NOTE2 ********************************/
+
+void gen_note2(double *tabstart,double *tabend,double midival,
+	double tabscale,double sintabsize,int splicelen, double *sintab)
+{
+	int initial_phase, i;
+	double *startsplice_end, *endsplice_start, *tab; 
+	double sintabpos, sintabincr;
+	int intpos, nxtpos;
+	double frac, vallo, valhi, valdif;
+	
+	tab = tabstart;
+	*tab++ = 0;		/* 1st val = 0 */
+	/* START POSITION IN TABLE TO READ TO GENERATE SOUND */
+	initial_phase = (int)round(drand48() * HFP_TABSIZE);
+	sintabincr = (miditohz(midival) * tabscale);
+	sintabpos = sintabincr + initial_phase;
+	sintabpos = fmod(sintabpos,sintabsize);
+	startsplice_end = tab + splicelen;
+	endsplice_start = tabend - splicelen;
+	/* START OF EACH CONSTITUENT MUST BE SPLICED */
+	i = 0;
+	while(tab < startsplice_end) {		
+		intpos = (int)floor(sintabpos);
+		nxtpos = intpos+1;
+		frac = sintabpos - (double)intpos;
+		vallo = sintab[intpos];
+		valhi = sintab[nxtpos];
+		valdif= valhi - vallo;
+		*tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
+		i++;
+		sintabpos += sintabincr;
+		sintabpos = fmod(sintabpos,sintabsize);
+		tab++;
+	}
+	while(tab < endsplice_start) {		
+		intpos = (int)floor(sintabpos);
+		nxtpos = intpos+1;
+		frac = sintabpos - (double)intpos;
+		vallo = sintab[intpos];
+		valhi = sintab[nxtpos];
+		valdif= valhi - vallo;
+		*tab += vallo + (valdif * frac);
+		sintabpos += sintabincr;
+		sintabpos = fmod(sintabpos,sintabsize);
+		tab++;
+	}
+	/* END OF EACH CONSTITUENT MUST BE SPLICED */
+	i = splicelen - 1;
+	while(tab < tabend) {		
+		intpos = (int)floor(sintabpos);
+		nxtpos = intpos+1;
+		frac = sintabpos - (double)intpos;
+		vallo = sintab[intpos];
+		valhi = sintab[nxtpos];
+		valdif= valhi - vallo;
+		*tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
+		i--;
+		sintabpos += sintabincr;
+		sintabpos = fmod(sintabpos,sintabsize);
+		tab++;
+	}
+}
+
+/********************************** GEN_NOTE3 ********************************/
+
+//void gen_note3(double *tabstart,double *tabend,double midival,int intabsize,int splicelen, short *intab)
+void gen_note3(double *tabstart,double *tabend,double midival,int intabsize,int splicelen, float *intab)
+{
+	int i;
+	double *startsplice_end, *endsplice_start, *tab; 
+	double tabpos, tabincr, effective_len;
+	int intpos, nxtpos;
+	double frac, vallo, valhi, valdif;
+	
+	tab = tabstart;
+	*tab++ = 0;		/* 1st val = 0 */
+	tabincr = (miditohz(midival)/miditohz(60.0));
+	effective_len = (double)(tabend - tabstart);
+	if(effective_len * tabincr > (double)intabsize) {
+		effective_len /= tabincr;
+		tabend = tabstart + (int)effective_len;
+	}
+	tabpos = tabincr;
+	startsplice_end = tab + splicelen;
+	endsplice_start = tabend - splicelen;
+	/* START OF EACH CONSTITUENT MUST BE SPLICED */
+	i = 0;
+	while(tab < startsplice_end) {		
+		intpos = (int)floor(tabpos);
+		nxtpos = intpos+1;
+		frac = tabpos - (double)intpos;
+		vallo = intab[intpos];
+		valhi = intab[nxtpos];
+		valdif= valhi - vallo;
+		*tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
+		i++;
+		tabpos += tabincr;
+		tab++;
+	}
+	while(tab < endsplice_start) {		
+		intpos = (int)floor(tabpos);
+		nxtpos = intpos+1;
+		frac = tabpos - (double)intpos;
+		vallo = intab[intpos];
+		valhi = intab[nxtpos];
+		valdif= valhi - vallo;
+		*tab += vallo + (valdif * frac);
+		tabpos += tabincr;
+		tab++;
+	}
+	/* END OF EACH CONSTITUENT MUST BE SPLICED */
+	i = splicelen - 1;
+	while(tab < tabend) {		
+		intpos = (int)floor(tabpos);
+		nxtpos = intpos+1;
+		frac = tabpos - (double)intpos;
+		vallo = intab[intpos];
+		valhi = intab[nxtpos];
+		valdif= valhi - vallo;
+		*tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
+		i--;
+		tabpos += tabincr;
+		tab++;
+	}
+}

+ 239 - 0
dev/hfperm/main.c

@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <synth.h>
+#include <filetype.h>
+#include <processno.h>
+#include <modeno.h>
+#include <formants.h>
+#include <cdpmain.h>
+#include <special.h>
+#include <logic.h>
+#include <globcon.h>
+#include <cdpmain.h>
+#include <sfsys.h>
+#include <ctype.h>
+#include <string.h>
+
+char errstr[2400];
+
+/*extern*/ int sloom = 0;
+/*extern*/ int sloombatch = 0;
+/*extern*/ int anal_infiles = 0;
+/*extern*/ int is_converted_to_stereo = -1;
+const char* cdp_version = "7.1.0";
+
+/**************************************** MAIN *********************************************/
+
+int main(int argc,char *argv[])
+{
+	int exit_status;
+	dataptr dz = NULL;
+//	char *special_data_string = NULL;
+	char **cmdline;
+	int  cmdlinecnt;
+	aplptr ap;
+	int *valid = NULL;
+	int is_launched = FALSE;
+	int  validcnt;
+
+	if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
+		fprintf(stdout,"%s\n",cdp_version);
+		fflush(stdout);
+		return 0;
+	}
+						/* CHECK FOR SOUNDLOOM */
+//	sloom = sound_loom_in_use(&argc,&argv);
+//NEW TW
+	if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
+		sloom = 0;
+		sloombatch = 1;
+	}
+
+	if(!sloom) {
+		if((exit_status = allocate_and_initialise_validity_flags(&valid,&validcnt))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+	}
+
+	if(sflinit("cdp")){
+		sfperror("cdp: initialisation\n");
+		return(FAILED);
+	}
+
+						  /* SET UP THE PRINCIPLE DATASTRUCTURE */
+	if((exit_status = establish_datastructure(&dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+					  
+	if(!sloom) {
+							  /* INITIAL CHECK OF CMDLINE DATA */
+		if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+		cmdline    = argv;	/* GET PRE_DATA, ALLOCATE THE APPLICATION, CHECK FOR EXTRA INFILES */
+		cmdlinecnt = argc;
+		if((exit_status = get_process_and_mode_from_cmdline(&cmdlinecnt,&cmdline,dz))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}		
+		if((exit_status = setup_particular_application(dz))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+		if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+	} else {
+		if((exit_status = parse_tk_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {  	/* includes setup_particular_application()      */
+			exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);/* and cmdlinelength check = sees extra-infiles */
+			return(exit_status);		 
+		}
+	}
+
+	ap = dz->application;
+
+/*********************************************************************************************************************
+	   cmdline[0]				 		  2 vals					   		  ACTIVE		 
+TK 		(infile) (more-infiles) (outfile) (flag val) (formantsqksrch) (special) params  options   variant-params  flags
+CMDLINE	(infile) (more-infiles) (outfile) (formants) (formantsqksrch) (special) params  POSSIBLY  POSSIBLY	  	POSSIBLY
+								 		  1 val
+*********************************************************************************************************************/
+
+	if((exit_status = parse_infile_and_hone_type(cmdline[0],valid,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+	if((exit_status = setup_param_ranges_and_defaults(dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+					/* OPEN FIRST INFILE AND STORE DATA, AND INFORMATION, APPROPRIATELY */
+
+	if(dz->input_data_type!=NO_FILE_AT_ALL) {
+		if((exit_status = open_first_infile(cmdline[0],dz))<0) {	
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);	
+			return(FAILED);
+		}
+//NEW TW
+		cmdlinecnt--;
+		cmdline++;
+
+	}
+//	cmdlinecnt--;
+//	cmdline++;
+
+/*********************************************************************************************************************
+		cmdline[0]				   2 vals				   			   ACTIVE		 
+TK 		(more-infiles) (outfile) (flag val) (formantsqksrch) (special) params  options   variant-params  flags
+CMDLINE	(more-infiles) (outfile) (formants) (formantsqksrch) (special) params  POSSIBLY  POSSIBLY		  POSSIBLY
+								   1 val
+*********************************************************************************************************************/
+
+	if((exit_status = handle_extra_infiles(&cmdline,&cmdlinecnt,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);		
+		return(FAILED);
+	}
+
+/*********************************************************************************************************************
+		cmdline[0]	  2					   			    ACTIVE		 
+TK 		(outfile) (flag val) (formantsqksrch) (special) params  options   variant-params  flags
+CMDLINE	(outfile) (formants) (formantsqksrch) (special) params  POSSIBLY  POSSIBLY		   POSSIBLY
+					  1
+*********************************************************************************************************************/
+
+	if((exit_status = handle_outfile(&cmdlinecnt,&cmdline,is_launched,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+/****************************************************************************************
+		cmdline[0]	  		   			       ACTIVE		 
+TK 		(flag val) (formantsqksrch) (special) params  options   variant-params  flags
+CMDLINE	(formants) (formantsqksrch) (special) params  POSSIBLY  POSSIBLY		POSSIBLY
+*****************************************************************************************/
+
+	if((exit_status = handle_formants(&cmdlinecnt,&cmdline,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	if((exit_status = handle_formant_quiksearch(&cmdlinecnt,&cmdline,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	if((exit_status = handle_special_data(&cmdlinecnt,&cmdline,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+ 
+/****************************************************************************************
+		cmdline[0]	  		   			    
+TK 		active_params  	options   		variant-params  flags
+CMDLINE	active_params  	POSSIBLY  		POSSIBLY		POSSIBLY
+*****************************************************************************************/
+
+	if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+	if((exit_status = check_param_validity_and_consistency(dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+ 	is_launched = TRUE;
+
+	if((exit_status = allocate_large_buffers(dz))<0){
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	if((exit_status = param_preprocess(dz))<0){
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	if((exit_status = groucho_process_file(dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	if((exit_status = complete_output(dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz);
+	free(dz);
+	return(SUCCEEDED);
+}
+

+ 20 - 0
dev/hilite/CMakeLists.txt

@@ -0,0 +1,20 @@
+if(APPLE)
+  set(CMAKE_C_FLAGS "-O2 -Wall -mmacosx-version-min=10.5 -Dunix")
+else()
+  if(MINGW)
+    set(CMAKE_C_FLAGS "-O2 -Wall -DWIN32")
+  else()
+    set(CMAKE_C_FLAGS "-O2 -Wall -Dlinux -Dunix")
+  endif()
+endif()
+
+link_directories(../cdp2k ../sfsys)
+
+include_directories(../../include)
+
+add_executable(hilite main.c ap_hilite.c hilite.c)
+
+target_link_libraries(hilite cdp2k sfsys ${EXTRA_LIBRARIES})
+
+my_install(hilite)
+

+ 1586 - 0
dev/hilite/ap_hilite.c

@@ -0,0 +1,1586 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version TW */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <cdpmain.h>
+#include <tkglobals.h>
+#include <pnames.h>
+#include <highlight.h>
+#include <processno.h>
+#include <modeno.h>
+#include <globcon.h>
+#include <logic.h>
+#include <filetype.h>
+#include <mixxcon.h>
+#include <flags.h>
+#include <speccon.h>
+#include <arrays.h>
+#include <special.h>
+#include <formants.h>
+#include <vowels2.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+#include <srates.h>
+
+#if defined unix || defined __GNUC__
+#define round(x) lround((x))
+#endif
+
+/********************************************************************************************/
+/********************************** FORMERLY IN pconsistency.c ******************************/
+/********************************************************************************************/
+
+static int	check_arpe_parameters_are_compatible(dataptr dz);
+static int	check_validity_of_trace_vals_for_bltr(dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN procspec.c **********************************/
+/********************************************************************************************/
+
+static int  create_and_initialise_array_of_loudest_channel_pointers(int arraysize,dataptr dz);
+static int  make_room_in_loudchans_list_by_moving_later_items_down_a_place(int size_of_list,
+				int index_into_list,dataptr dz);
+static int  prepare_to_do_trace(double *thistime,dataptr dz);
+static int  if_loud_enough_store_in_ring(int cc,int vc,dataptr dz);
+static int	 create_trace(dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+static int  arpe_preprocess(dataptr dz);
+static int  set_arpegtones_sustain_type(dataptr dz);
+static int  gen_arpe_waveform_table(dataptr dz);
+static int  setup_internal_arpe_params_and_preprocess_params(dataptr dz);
+static int  fix_inverted_frqrange_in_arpe(dataptr dz) ;
+static int  establish_arpe_halfband_param(dataptr dz);
+static int  do_log_conversions_for_specfilt(dataptr dz);
+static int  convert_brkpnt_table_vals_to_log(int brktableno,dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN specialin.c *********************************/
+/********************************************************************************************/
+
+static int  generate_filter_data(char *str,int datatype,dataptr dz);
+static int  get_filt_params(char *str,int datatype,double **filtwidth,dataptr dz);
+static int  check_filtfrq(double val, double minval, double maxval);
+static int  check_filtbw(double val, double minval, double maxval);
+static int  sort_peaks_by_frq(double *filtwidth,dataptr dz);
+static int  setup_filter_param_arrays(dataptr dz);
+static int  generate_filter_params(double *filtwidth,dataptr dz);
+static int  read_specsplit_data(char *str,dataptr dz);
+static int  sort_frqbands_into_ascending_order(dataptr dz);
+static void swap_frqbands(int n,int m,dataptr dz);
+
+/***************************************************************************************/
+/****************************** FORMERLY IN aplinit.c **********************************/
+/***************************************************************************************/
+
+/***************************** ESTABLISH_BUFPTRS_AND_EXTRA_BUFFERS **************************/
+
+int establish_bufptrs_and_extra_buffers(dataptr dz)
+{
+	int exit_status;
+	int is_spec = FALSE;
+	dz->extra_bufcnt = -1;	/* ENSURE EVERY CASE HAS A PAIR OF ENTRIES !! */
+	dz->bptrcnt = 0;
+	dz->bufcnt  = 0;
+	switch(dz->process) {
+	case(FILT):       		dz->extra_bufcnt =  0; dz->bptrcnt = 2; 	is_spec = TRUE;		break;
+//TW NEW CASE
+	case(VFILT): 			dz->extra_bufcnt =  0; dz->bptrcnt = 2; 	is_spec = TRUE;		break;
+
+	case(GREQ):       		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(SPLIT):      		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(ARPE):       		dz->extra_bufcnt =  1; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(PLUCK):      		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(S_TRACE):    		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(BLTR):       		dz->extra_bufcnt =  0; dz->bptrcnt = 4; 	is_spec = TRUE;		break;
+	default:
+		sprintf(errstr,"Unknown program type [%d] in establish_bufptrs_and_extra_buffers()\n",dz->process);
+		return(PROGRAM_ERROR);
+	}
+
+	if(dz->extra_bufcnt < 0) {
+		sprintf(errstr,"bufcnts have not been set: establish_bufptrs_and_extra_buffers()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(is_spec)
+		return establish_spec_bufptrs_and_extra_buffers(dz);
+	else if((dz->process==HOUSE_SPEC && dz->mode==HOUSE_CONVERT) || dz->process==INFO_DIFF) {
+		if((exit_status = establish_spec_bufptrs_and_extra_buffers(dz))<0)
+			return(exit_status);
+	}
+	return establish_groucho_bufptrs_and_extra_buffers(dz);
+}
+
+/***************************** SETUP_INTERNAL_ARRAYS_AND_ARRAY_POINTERS **************************/
+
+int setup_internal_arrays_and_array_pointers(dataptr dz)
+{
+	int n;		 
+	dz->ptr_cnt    = -1;		/* base constructor...process */
+	dz->array_cnt  = -1;
+	dz->iarray_cnt = -1;
+	dz->larray_cnt = -1;
+	switch(dz->process) {
+	case(FILT):   	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+//TW NEW CASE
+	case(VFILT):  	dz->array_cnt = 1; dz->iarray_cnt = 1; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+
+	case(GREQ):   	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(SPLIT):  	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(ARPE):   	dz->array_cnt =1;  dz->iarray_cnt =1;  dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(PLUCK):  	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt =1;  dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(S_TRACE):  dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(BLTR):   	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	}
+
+/*** WARNING ***
+ANY APPLICATION DEALING WITH A NUMLIST INPUT: MUST establish AT LEAST 1 double array: i.e. dz->array_cnt = at least 1
+**** WARNING ***/
+
+
+	if(dz->array_cnt < 0 || dz->iarray_cnt < 0 || dz->larray_cnt < 0 || dz->ptr_cnt < 0 || dz->fptr_cnt < 0) {
+		sprintf(errstr,"array_cnt not set in setup_internal_arrays_and_array_pointers()\n");	   
+		return(PROGRAM_ERROR);
+	}
+
+	if(dz->array_cnt > 0) {  
+		if((dz->parray  = (double **)malloc(dz->array_cnt * sizeof(double *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal double arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->array_cnt;n++)
+			dz->parray[n] = NULL;
+	}
+	if(dz->iarray_cnt > 0) {
+		if((dz->iparray = (int     **)malloc(dz->iarray_cnt * sizeof(int *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal int arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->iarray_cnt;n++)
+			dz->iparray[n] = NULL;
+	}
+	if(dz->larray_cnt > 0) {	  
+		if((dz->lparray = (int    **)malloc(dz->larray_cnt * sizeof(int *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal long arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->larray_cnt;n++)
+			dz->lparray[n] = NULL;
+	}
+	if(dz->ptr_cnt > 0)   {  	  
+		if((dz->ptr    	= (double  **)malloc(dz->ptr_cnt  * sizeof(double *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal pointer arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->ptr_cnt;n++)
+			dz->ptr[n] = NULL;
+	}
+	if(dz->fptr_cnt > 0)   {  	  
+		if((dz->fptr = (float  **)malloc(dz->fptr_cnt * sizeof(float *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal float-pointer arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->fptr_cnt;n++)
+			dz->fptr[n] = NULL;
+	}
+	return(FINISHED);
+}
+
+/****************************** ASSIGN_PROCESS_LOGIC *********************************/
+
+int assign_process_logic(dataptr dz)
+{						 
+	switch(dz->process) {
+	case(FILT):			setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+//TW NEW CASE
+	case(VFILT):		setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+
+	case(GREQ):			setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(SPLIT):		setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(ARPE):			setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(PLUCK):		setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(S_TRACE):		setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(BLTR):			setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	default:
+		sprintf(errstr,"Unknown process: assign_process_logic()\n");
+		return(PROGRAM_ERROR);
+		break;
+	}
+	if(dz->has_otherfile) {
+		switch(dz->input_data_type) {
+		case(ALL_FILES):
+		case(TWO_SNDFILES):
+		case(SNDFILE_AND_ENVFILE):
+		case(SNDFILE_AND_BRKFILE):
+		case(SNDFILE_AND_UNRANGED_BRKFILE):
+		case(SNDFILE_AND_DB_BRKFILE):
+			break;
+		case(MANY_SNDFILES):
+			if(dz->process==INFO_TIMELIST)
+				break;
+			/* fall thro */
+		default:
+			sprintf(errstr,"Most processes accepting files with different properties\n"
+						   "can only take 2 sound infiles.\n");
+			return(PROGRAM_ERROR);
+		}
+	}
+	return(FINISHED);
+}
+
+/***************************** SET_LEGAL_INFILE_STRUCTURE **************************
+ *
+ * Allows 2nd infile to have different props to first infile.
+ */
+
+void set_legal_infile_structure(dataptr dz)
+{
+	switch(dz->process) {
+	default:
+		dz->has_otherfile = FALSE;
+		break;
+	}
+}
+
+/***************************************************************************************/
+/****************************** FORMERLY IN internal.c *********************************/
+/***************************************************************************************/
+
+/****************************** SET_LEGAL_INTERNALPARAM_STRUCTURE *********************************/
+
+int set_legal_internalparam_structure(int process,int mode,aplptr ap)
+{
+	int exit_status = FINISHED;
+	switch(process) {
+	case(FILT):	 	  	return(FINISHED);
+//TW NEW CASE
+	case(VFILT):		return(FINISHED);
+
+	case(GREQ):	      	return(FINISHED);
+	case(SPLIT):	  	return(FINISHED);
+	case(ARPE):
+		switch(mode) {
+		case(ON): case(BOOST): case(ABOVE_BOOST): case(BELOW_BOOST):
+					  	exit_status = set_internalparam_data(  "ddid",ap);				break;
+		default:	  	exit_status = set_internalparam_data("00ddid",ap);				break;
+		}
+		break;
+	case(PLUCK): 	  	exit_status = set_internalparam_data("ii",ap);					break;
+	case(S_TRACE):	  	return(FINISHED);
+	case(BLTR):		  	exit_status = set_internalparam_data("ii",ap);					break;
+	default:
+		sprintf(errstr,"Unknown process in set_legal_internalparam_structure()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(exit_status);		
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN specialin.c *********************************/
+/********************************************************************************************/
+
+/********************** READ_SPECIAL_DATA ************************/
+
+int read_special_data(char *str,dataptr dz)	   
+{
+	int exit_status = FINISHED;
+	aplptr ap = dz->application;
+
+	switch(ap->special_data) {
+	case(FILTER_FRQS):
+	case(FILTER_BWS_AND_FRQS):	return generate_filter_data(str,(int)ap->special_data,dz);
+	case(SPECSPLI_DATA):	  	return read_specsplit_data(str,dz);
+//TW NEW CASE
+	case(PITCH_VOWELS):
+		if((exit_status = get_the_vowels(str,&dz->parray[0],&dz->iparray[0],&dz->itemcnt,dz)) < 0)
+			return(exit_status);
+		break;
+
+	default:
+		sprintf(errstr,"Unknown special_data type: read_special_data()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/************************************* GENERATE_FILTER_DATA	**************************************/
+
+int generate_filter_data(char *str,int datatype,dataptr dz)
+{
+	int exit_status;
+	double *filtwidth;
+	if((exit_status = get_filt_params(str,datatype,&filtwidth,dz))<0)
+		return(exit_status);
+	if((exit_status = sort_peaks_by_frq(filtwidth,dz))<0)
+		return(exit_status);
+	if((exit_status = setup_filter_param_arrays(dz))<0)
+		return(exit_status);
+	if((exit_status = generate_filter_params(filtwidth,dz))<0)
+		return(exit_status);
+ 	free(filtwidth);
+	return(FINISHED);
+}
+
+/********************* GET_FILT_PARAMS ************************/
+
+int get_filt_params(char *str,int datatype,double **filtwidth,dataptr dz)
+{
+	int exit_status;
+	char  *p, temp[200];
+	int    gotpair = TRUE, firstime = TRUE;
+	int   arraysize = BIGARRAY;
+	double val, bwidth = 0.0, fpeak = 0.0;
+	aplptr ap = dz->application;
+	FILE *fp;
+	if((fp = fopen(str,"r"))==NULL) {
+		sprintf(errstr,"Cannot open datafile '%s'.\n",str);
+		return(DATA_ERROR);
+	}																									 	
+	if((dz->filtpeak    = (double *)malloc(arraysize * sizeof(double)))==NULL){	/* stores amplitude of filter peaks */ 
+		sprintf(errstr,"INSUFFICIENT MEMORY to store filter peaks.\n");
+		return(MEMORY_ERROR);
+	}
+	if((*filtwidth   = (double *)malloc(arraysize * sizeof(double)))==NULL)	{	/* stores bndwidths of filter peaks */ 
+		sprintf(errstr,"INSUFFICIENT MEMORY to store filter peakwidths.\n");
+		return(MEMORY_ERROR);
+	}
+	while(fgets(temp,200,fp)) {
+		p = temp;
+		while(get_float_from_within_string(&p,&val)) {
+			switch(datatype) {
+			case(FILTER_FRQS):
+				if(firstime) {
+					if((exit_status = check_filtbw(val,ap->min_special,ap->max_special))<0)
+						return(exit_status);
+					bwidth = val;
+					gotpair  = FALSE;
+					firstime = FALSE;
+				} else {
+					if((exit_status = check_filtfrq(val,ap->min_special2,ap->max_special2))<0)
+						return(exit_status);
+					fpeak = val;
+					gotpair = TRUE;
+				}
+				break;
+			case(FILTER_BWS_AND_FRQS):
+				if(gotpair) {
+					if((exit_status = check_filtfrq(val,ap->min_special,ap->max_special))<0)
+						return(exit_status);
+					fpeak  = val;
+				} else {
+					if((exit_status = check_filtbw(val,ap->min_special2,ap->max_special2))<0)
+						return(exit_status);
+					bwidth = val;
+				}
+				gotpair = !gotpair;
+				break;
+			default:
+				sprintf(errstr,"Programming error in get_filt_params()\n");
+				return(PROGRAM_ERROR);
+			}
+			if(gotpair) {
+				if(++dz->itemcnt >= arraysize) {
+					arraysize += BIGARRAY;
+					if((dz->filtpeak = (double *)realloc((char *)dz->filtpeak, arraysize * sizeof(double)))==NULL) {
+						sprintf(errstr,"INSUFFICIENT MEMORY to reallocate filter peaks store.\n");
+						return(MEMORY_ERROR);
+					}
+					if((*filtwidth   = (double *)realloc((char *)(*filtwidth),arraysize * sizeof(double)))==NULL) {
+						sprintf(errstr,"INSUFFICIENT MEMORY to reallocate filter width store.\n");
+						return(MEMORY_ERROR);
+					}
+				}
+				(*filtwidth)[dz->itemcnt-1] = bwidth;
+				dz->filtpeak[dz->itemcnt-1]  = fpeak;	
+			}
+		}
+	}
+	if(!gotpair) {
+		sprintf(errstr,"Filter data not correctly paired in file '%s'.\n",str);
+		return(DATA_ERROR);
+	}
+	if(dz->itemcnt==0) {
+		sprintf(errstr,"No filter data found in file '%s'.\n",str);
+		return(DATA_ERROR);
+	}
+	if(fclose(fp)<0) {
+		fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",str);
+		fflush(stdout);
+	}
+	return(FINISHED);
+}
+
+/************************* CHECK_FILTFRQ *****************************/
+
+int check_filtfrq(double val, double minval, double maxval)
+{
+	if(val < minval || val > maxval) {
+		sprintf(errstr,"Frequency value (%lf) out of range (%lf to %.1lf) in filter data file\n",val,minval,maxval);
+		return(DATA_ERROR);
+	}
+	return(FINISHED);
+}
+
+/************************* CHECK_FILTBW *****************************/
+
+int check_filtbw(double val, double minval, double maxval)
+{
+	if(val < minval || val > maxval) {
+		sprintf(errstr,"Bandwidth value (%lf) out of range (%lf to %.1lf) in filter data file\n",val,minval,maxval);
+		return(DATA_ERROR);
+	}
+	return(FINISHED);
+}
+
+/****************************** SORT_PEAKS_BY_FRQ ***************************/
+
+int sort_peaks_by_frq(double *filtwidth,dataptr dz)		 /* Sort peaks in ascending frequency order */
+{	
+	int m, n;
+	double k;
+	for(n=0;n<dz->itemcnt-1;n++) {
+		for(m=n+1;m<dz->itemcnt;m++) {
+			if(dz->filtpeak[n] > dz->filtpeak[m]) {
+				k         	    = dz->filtpeak[m];
+				dz->filtpeak[m] = dz->filtpeak[n];
+				filtwidth[n]    = k;
+				k         		= filtwidth[m];
+				filtwidth[m]    = filtwidth[n];
+				filtwidth[n]    = k;
+			}
+		}
+	}
+	return(FINISHED);
+}
+
+/****************************** SETUP_FILTER_PARAM_ARRAYS ***************************/
+																					
+int setup_filter_param_arrays(dataptr dz)											
+{																					
+	if((dz->fbandtop   = (double *)malloc((dz->itemcnt+1) * sizeof(double)))==NULL)	 { /* stores top of fiter bands */
+		sprintf(errstr,"INSUFFICIENT MEMORY to store filterband tops.\n");
+		return(MEMORY_ERROR);													
+	}
+	if((dz->fbandbot   = (double *)malloc((dz->itemcnt+1) * sizeof(double)))==NULL)	 { /* stores bottoms of filtbands */
+		sprintf(errstr,"INSUFFICIENT MEMORY to store filterband bottoms.\n");
+		return(MEMORY_ERROR);													
+	}
+	if((dz->fsampbuf   = (float  *)malloc((dz->clength+1) * sizeof(float) ))==NULL)	 { /* stores filter contour */
+		sprintf(errstr,"INSUFFICIENT MEMORY for filter buffer.\n");
+		return(MEMORY_ERROR);
+	}
+	dz->filtpeak[dz->itemcnt] = 0.0;
+    dz->fbandtop[dz->itemcnt] = 0.0;		/* stores top of fiter bands */
+    dz->fbandbot[dz->itemcnt] = 0.0;		/* stores bottoms of filtbands */
+	dz->fsampbuf[dz->clength] = 0.0f;		/* stores filter contour */
+	memset(dz->fsampbuf,0,dz->clength * sizeof(float));	/* initialise filter buf */
+	return(FINISHED);
+}
+
+
+/****************************** GENERATE_FILTER_PARAMS ***************************/
+
+int generate_filter_params(double *filtwidth,dataptr dz)
+{
+	int n;
+	double bratio_up, bratio_dn, halfbwidth;
+	for(n=0;n<dz->itemcnt;n++) {		  /* ESTABLISH BOTTOM AND TOP OF FILTER BANDS */
+		halfbwidth = filtwidth[n]/2.0;
+		dz->scalefact = PI/halfbwidth;	 /* Convert an octave offset from filter centre-frq
+									    to a fraction of the bandwidth X PI */
+		bratio_up = pow(2.0,halfbwidth); /* upward transposition ratio to top of filter band  */
+		bratio_dn = 1.0/bratio_up;	 	 /* Downward transposition ratio to bottom of filter band */
+		dz->fbandbot[n] = dz->filtpeak[n] * bratio_dn;
+		dz->fbandtop[n] = min(dz->filtpeak[n] * bratio_up,dz->nyquist);
+	}
+	return(FINISHED);
+}
+
+/******************************* READ_SPECSPLIT_DATA ***************************
+ *
+ * Read input data from data file and store in structures.
+ */
+
+int read_specsplit_data(char *str,dataptr dz)
+{
+	char temp[200], *p, *q;
+	double otheramp, d1;
+	int mask, n, flags_set = 0, linecnt = 0;
+	int arraysize = BIGARRAY;
+	bandptr bb;
+	FILE *fp;
+	if((fp = fopen(str,"r"))==NULL) {
+  		sprintf(errstr,"Cannot open data file %s\n", str);
+		return(DATA_ERROR);
+	}
+	if((dz->band = (bandptr *)malloc(arraysize * sizeof(bandptr)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to store bands.\n");
+		return(MEMORY_ERROR);
+	}
+	while(fgets(temp,200,fp)!=NULL) {
+		if((dz->band[dz->itemcnt]=(bandptr)malloc(sizeof(struct bandd)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY to store band %d\n",dz->itemcnt+1);
+			return(MEMORY_ERROR);
+		}
+		bb = dz->band[dz->itemcnt];
+		p = temp;
+		while(isspace(*p))
+			p++;
+		if(*p==NEWLINE || *p==ENDOFSTR)
+			continue;
+		linecnt++;
+		if(!get_float_from_within_string(&p,&(bb->bfrqlo))) {
+			sprintf(errstr,"Cannot read lower frequency in line %d in datafile\n",linecnt);
+			return(DATA_ERROR);
+		}
+		if(bb->bfrqlo<0.0 || bb->bfrqlo>dz->nyquist) {
+			sprintf(errstr,"freq %.2lf out of range (>0 to %lf[nyquist]) in line %d in datafile\n",
+			bb->bfrqlo,dz->nyquist,linecnt);
+			return(DATA_ERROR);
+		}
+		if(!get_float_from_within_string(&p,&(bb->bfrqhi))) {
+			sprintf(errstr,"Cannot read higher frequency in line %d in datafile\n",linecnt);
+			return(DATA_ERROR);
+		}
+		if(bb->bfrqhi<0.0) {
+			sprintf(errstr,"freq %.2lf out of range (>0) in line %d in datafile\n",bb->bfrqhi,linecnt);
+			return(DATA_ERROR);
+		}
+		if(bb->bfrqhi>dz->nyquist)
+			bb->bfrqhi = dz->nyquist;
+		if(flteq(bb->bfrqlo,bb->bfrqhi)) {
+			sprintf(errstr,"Cannot proceed, band range zero in line %d in datafile\n",linecnt);
+			return(DATA_ERROR);
+		}
+		if((bb->bfrqdif=bb->bfrqhi - bb->bfrqlo)<0.0){
+			d1        = bb->bfrqlo;
+			bb->bfrqlo = bb->bfrqhi;
+			bb->bfrqhi = d1;
+			bb->bfrqdif = -(bb->bfrqdif);
+		}
+		if(get_word_from_string(&p,&q)==FALSE) {
+			sprintf(errstr,"Cannot read action flag in line %d in datafile\n",linecnt);
+			return(DATA_ERROR);
+		}
+		mask  = 1;
+		bb->bdoflag   = 0;
+		bb->badditive = 0;
+		for(n=0;n<4;n++) {
+			if(q[n] <'0' || q[n] > '1') {
+				sprintf(errstr,"Invalid flag in line %d in datafile\n",linecnt);
+				return(DATA_ERROR);
+			}
+			if(q[n]=='1') {
+				flags_set++;
+				bb->bdoflag |= mask;
+				switch(n) {
+				case(0):
+					if(!get_float_from_within_string(&p,&(bb->bamp))) {
+						sprintf(errstr,"Cannot read amplitude 1 in in line %d in datafile\n",linecnt);
+						return(DATA_ERROR);
+					}
+					break;
+				case(1):
+					if(!(bb->bdoflag & DO_AMPLITUDE_CHANGE)) {
+						sprintf(errstr,"Cannot have amp2 when no amp1 in line %d in datafile\n",linecnt);
+						return(DATA_ERROR);
+					}
+					if(!get_float_from_within_string(&p,&otheramp)) {		 
+						sprintf(errstr,"Cannot read amplitude 1 in line %d in datafile\n",linecnt);
+						return(DATA_ERROR);
+					}
+// FEB 2006
+//					if(otheramp<bb->bamp)
+//						swap(&(bb->bamp),&otheramp);
+					bb->bampdif = otheramp - bb->bamp;
+					break;
+				case(2):
+					while(isspace(*p))
+						p++;
+					if(*p=='+') {
+						bb->badditive = 1;
+						p++;
+					}
+ 					if(!get_float_from_within_string(&p,&(bb->btrans))) {
+						sprintf(errstr,"Cannot read transposition in line %d in datafile\n",linecnt);
+						return(DATA_ERROR);
+					}
+					break;
+				case(3):
+					if(!(bb->bdoflag & DO_TRANSPOSITION)) {
+						sprintf(errstr,"Cannot add_in partials without first transposing: line %d in datafile\n",linecnt);
+						return(DATA_ERROR);
+					}
+					break;
+				}
+			}
+			mask <<= 1;
+		}
+		if(flags_set==0) {
+			sprintf(errstr,"Zero bitflag in line %d in datafile\n",linecnt);
+			return(DATA_ERROR);
+		}
+		if(++dz->itemcnt >= arraysize) {
+			arraysize += BIGARRAY;
+			if((dz->band=(bandptr *)realloc((char *)dz->band,arraysize*sizeof(bandptr)))==NULL) {
+				sprintf(errstr,"INSUFFICIENT MEMORY to reallocate band stores.\n");
+				return(MEMORY_ERROR);
+			}
+		}
+	}
+	if((dz->band=(bandptr *)realloc((char *)dz->band,(dz->itemcnt+1)*sizeof(bandptr)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to reallocate band stores.\n");
+		return(MEMORY_ERROR);
+	}
+	return sort_frqbands_into_ascending_order(dz);
+}
+
+/************************ SORT_FRQBANDS_INTO_ASCENDING_ORDER ********************************
+ *
+ * Sort bands into frequency ascending order.
+ */
+
+int sort_frqbands_into_ascending_order(dataptr dz)
+{
+	double f1, f2;
+	int penult = dz->itemcnt-1, n, m;
+	for(n=0;n<penult;n++) {
+		f1 = dz->band[n]->bfrqlo;
+		for(m=n+1;m<dz->itemcnt;m++) {
+			if((f2 = dz->band[m]->bfrqlo)<f1)
+				swap_frqbands(n,m,dz);
+		}
+	}
+	for(n=0;n<penult;n++) {
+		if(dz->band[n]->bfrqhi > dz->band[n+1]->bfrqlo) {
+			sprintf(errstr,"Frequency bands %d and %d in data file overlap\n%d  %lf..%lf\n%d  %lf..%lf\n",
+			n+1,n+2,n+1,dz->band[n]->bfrqlo,dz->band[n]->bfrqhi,n+2,dz->band[n+1]->bfrqlo,dz->band[n+1]->bfrqhi);
+			return(DATA_ERROR);
+		}
+	}
+	return(FINISHED);
+}
+
+/************************ SWAP_FRQBANDS ********************************
+ *
+ * Swap two bands, using spare band 'banscnt' as temporary store.
+ */
+
+void swap_frqbands(int n,int m,dataptr dz)
+{   bandptr temp;
+
+    temp        = dz->band[n];
+    dz->band[n] = dz->band[m];
+    dz->band[m] = temp;
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+/****************************** PARAM_PREPROCESS *********************************/
+
+int param_preprocess(dataptr dz)	
+{
+	switch(dz->process) {
+	case(ARPE):			return arpe_preprocess(dz);
+	case(FILT):			return do_log_conversions_for_specfilt(dz);
+	case(PLUCK):		return setup_internal_bitflags(PLUK_BFLG,PLUK_LONGPOW2,PLUK_DIVMASK,dz);
+	case(S_TRACE):		return setup_ring(dz);
+
+ 	case(GREQ):	
+	case(SPLIT):	
+	case(BLTR):			
+//TW NEW CASE
+	case(VFILT):
+
+		return(FINISHED);
+	default:
+		sprintf(errstr,"PROGRAMMING PROBLEM: Unknown process in param_preprocess()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/************************** ARPE_PREPROCESS ******************************/
+
+int arpe_preprocess(dataptr dz)
+{
+	int exit_status;
+	if((exit_status = gen_arpe_waveform_table(dz))<0)
+		return(exit_status);
+	if((exit_status = setup_internal_arpe_params_and_preprocess_params(dz))<0)
+		return(exit_status);
+	dz->iparam[ARPE_SUSFLAG] = set_arpegtones_sustain_type(dz);
+	return(FINISHED);
+}
+
+/****************************** SET_ARPEGTONES_SUSTAIN_TYPE ***********************
+ *
+ * this functions establishes the following flag modes for susflag
+ * AP_NORMAL										(0)
+ * AP_SUSTAIN_PITCH									(1)
+ * AP_LIMIT_SUSTAIN									(2)
+ * AP_SUSTAIN_PITCH_AND_LIMIT_SUSTAIN				(3)
+ * AP_NONLIN										(4)
+ * AP_NONLIN_AND_SUSTAIN_PITCH						(5)
+ * AP_NONLIN_AND_LIMIT_SUSTAIN						(6)
+ * AP_NONLIN_AND_SUSTAIN_PITCH_AND_LIMIT_SUSTAIN	(7)
+*/
+int set_arpegtones_sustain_type(dataptr dz)
+{
+	int susflag = 0;
+	if(dz->mode==ON || dz->mode==BOOST || dz->mode==ABOVE_BOOST || dz->mode==BELOW_BOOST) {
+		if(!dz->vflag[ARPE_TRKFRQ])	  	susflag |= 1;	/* Forces pitch-sustain */
+		if(!dz->vflag[ARPE_KEEP_SUST]) 	susflag |= 2;	/* Limits length of sustains */
+		if(dz->vflag[ARPE_IS_NONLIN])   susflag |= 4;	/* forces nonlinear mode */
+	}
+	return(susflag);
+}
+
+/**************************** GEN_ARPE_WAVEFORM_TABLE *******************************/
+
+int gen_arpe_waveform_table(dataptr dz)
+{
+	int n, m, halftab = ARPE_TABSIZE/2;
+	double anglestep = (PI * 2.0)/ARPE_TABSIZE;
+	if((dz->parray[ARPE_TAB] = (double *)malloc(ARPE_TABSIZE * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for arpeg table.\n");
+		return(MEMORY_ERROR);
+	}
+	switch(dz->iparam[ARPE_WTYPE]) {
+	case(SIN):
+		for(n=0;n<ARPE_TABSIZE;n++) {
+			dz->parray[ARPE_TAB][n]  = sin((PI * 1.5) + ((double)n*anglestep));
+			dz->parray[ARPE_TAB][n] += 1.0;
+			dz->parray[ARPE_TAB][n] /= 2.0;
+		}
+		break;
+	case(SAW):
+		for(n=0;n<halftab;n++)
+			dz->parray[ARPE_TAB][n]  = (double)n/(double)halftab;
+		m = halftab;
+		for(n=0;n<halftab;n++)
+			dz->parray[ARPE_TAB][m++]  = 1.0 - dz->parray[ARPE_TAB][n];
+		break;
+	case(DOWNRAMP):
+		for(n=0;n<ARPE_TABSIZE;n++)
+			dz->parray[ARPE_TAB][n]  = 1.0 - (double)n/(double)ARPE_TABSIZE;
+		break;
+	case(UPRAMP):
+		for(n=0;n<ARPE_TABSIZE;n++)
+			dz->parray[ARPE_TAB][n]  = (double)n/(double)ARPE_TABSIZE;
+		break;
+	default:
+		sprintf(errstr,"Programing Problem in gen_arpe_waveform_table()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********************** SETUP_INTERNAL_ARPE_PARAMS_AND_PREPROCESS_PARAMS *********/
+
+int setup_internal_arpe_params_and_preprocess_params(dataptr dz)
+{
+	int exit_status;
+   	dz->param[ARPE_WAVETABPOS] = dz->param[ARPE_PHASE] * (double)ARPE_TABSIZE;
+	if((dz->iparray[ARPE_KEEP] = (int *)malloc(dz->clength * sizeof(int)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for arpe keep array.\n");
+		return(MEMORY_ERROR);
+	}
+	if(dz->brksize[ARPE_LOFRQ]==0 && dz->brksize[ARPE_HIFRQ]==0) {
+		if((exit_status = fix_inverted_frqrange_in_arpe(dz))<0)
+			return(exit_status);
+	}
+	if((exit_status = establish_arpe_halfband_param(dz))<0)
+		return(exit_status);
+	if(dz->brksize[ARPE_AMPL]==0 && dz->brksize[ARPE_SUST]==0)
+		dz->param[ARPE_AMPL]  /= (double)dz->iparam[ARPE_SUST];
+    if(dz->brksize[ARPE_ARPFRQ]) {
+    	if((exit_status = read_value_from_brktable(0.0,ARPE_ARPFRQ,dz))<0)
+			return(exit_status);
+		dz->param[ARPE_LASTARPFRQ] = dz->param[ARPE_ARPFRQ];
+	}
+	return(FINISHED);
+}
+
+/****************************** FIX_INVERTED_FRQRANGE_IN_ARPE ********************/
+
+int fix_inverted_frqrange_in_arpe(dataptr dz) 
+{			   /* cure inverted freq range */
+	double dummy;
+	if(dz->param[ARPE_LOFRQ] >  dz->param[ARPE_HIFRQ]) {
+		dummy = dz->param[ARPE_LOFRQ];
+		dz->param[ARPE_LOFRQ] =	dz->param[ARPE_HIFRQ];
+		dz->param[ARPE_HIFRQ] = dummy;
+	}
+	return(FINISHED);
+}
+
+/********************** ESTABLISH_ARPE_HALFBAND_PARAM **********************/
+
+int establish_arpe_halfband_param(dataptr dz)
+{
+	double *p;
+	int n;
+	if(dz->brksize[ARPE_HBAND]==0)
+		dz->param[ARPE_HBAND] /=  2.0;
+	else {
+		p = dz->brk[ARPE_HBAND] + 1;
+		for(n=0;n<dz->brksize[ARPE_HBAND];n++) {
+			*p /=  2.0;
+			p  += 2;
+		}
+	} 
+	return(FINISHED);
+}
+
+/************ DO_LOG_CONVERSIONS_FOR_SPECFILT *************/
+
+int do_log_conversions_for_specfilt(dataptr dz)	   	/* convert brktables to log vals, for log-interp */
+{			
+	int exit_status;
+	if((exit_status = convert_brkpnt_table_vals_to_log(FILT_QQ,dz))<0)
+		return(exit_status);
+	if((exit_status = convert_brkpnt_table_vals_to_log(FILT_FRQ1,dz))<0)
+		return(exit_status);
+	return convert_brkpnt_table_vals_to_log(FILT_FRQ2,dz);
+}
+
+/******************************* CONVERT_BRKPNT_TABLE_VALS_TO_LOG ****************/
+
+int convert_brkpnt_table_vals_to_log(int brktableno,dataptr dz)
+{
+	int n;
+	double *p;
+	if(dz->brksize[brktableno]) { 	/* convert vals in brkfile to log, so interp in brkfile is log */
+		p = dz->brk[brktableno]+1;	
+		for(n=0;n<dz->brksize[brktableno];n++) {	/* (convert back to exp on special_read) */
+			if(*p <=0.0) {
+				sprintf(errstr,"Error in freq or Q table: 0.0 val: convert_brkpnt_table_vals_to_log()\n");
+				return(PROGRAM_ERROR);
+			}
+			*p = log(*p);
+			p += 2;
+		}
+	}
+	return(FINISHED);
+}
+
+
+/********************************************************************************************/
+/********************************** FORMERLY IN procspec.c **********************************/
+/********************************************************************************************/
+
+/**************************** SPEC_PROCESS_FILE ****************************/
+
+int spec_process_file(dataptr dz)
+{	
+	dz->total_windows = 0;
+
+	display_virtual_time(0L,dz);
+
+	switch(dz->process) {
+	case(FILT):		return outer_loop(dz);
+//TW NEW CASE
+	case(VFILT):	return vowel_filter(dz);
+
+	case(GREQ):		return outer_loop(dz);
+	case(SPLIT):	return outer_loop(dz);
+	case(ARPE):		return outer_loop(dz);
+	case(PLUCK):	return outer_loop(dz);
+	case(S_TRACE):	return outer_loop(dz);
+	case(BLTR):		return spec_blur_and_bltr(dz);
+	default:
+		sprintf(errstr,"Unknown process in procspec()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/**************************** INNER_LOOP ****************************/
+
+int inner_loop
+(int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
+{
+	int exit_status;
+	int local_zero_set = FALSE;
+	int wc;
+	
+   	for(wc=0; wc<windows_in_buf; wc++) {
+		if(dz->total_windows==0) {
+			if((exit_status = skip_or_special_operation_on_window_zero(dz))<0)
+				return(exit_status);
+			if(exit_status==TRUE) {
+				dz->flbufptr[0] += dz->wanted;
+				dz->total_windows++;
+				dz->time = (float)(dz->time + dz->frametime);
+				continue;
+			}
+		}
+		if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0)
+			return(exit_status);
+
+		switch(dz->process) {
+		case(FILT):		exit_status = specfilt(dz);	  						break;
+		case(GREQ):		exit_status = specgreq(dz);	  						break;
+		case(SPLIT): 	exit_status = specsplit(dz);  						break;
+		case(ARPE):		exit_status = specarpe(in_start_portion,dz);		break;
+		case(PLUCK):	exit_status = specpluck(dz);  						break;
+		case(S_TRACE):	exit_status = spectrace(dz);  						break;
+		default:
+			sprintf(errstr,"unknown process in inner_loop()\n");
+			return(PROGRAM_ERROR);
+		}
+		if(exit_status<0)
+			return(exit_status);
+		dz->flbufptr[0] += dz->wanted;
+		dz->total_windows++;
+		dz->time = (float)(dz->time + dz->frametime);
+	}
+	if(!dz->zeroset && local_zero_set==TRUE) {
+		fprintf(stdout,"WARNING: Zero-amp spectral window(s) encountered: orig window(s) substituted.\n"); 
+		fflush(stdout);
+		dz->zeroset = TRUE;
+	}
+	return(FINISHED);
+}
+
+/***************** SKIP_OR_SPECIAL_OPERATION_ON_WINDOW_ZERO ************/
+
+int skip_or_special_operation_on_window_zero(dataptr dz)
+{
+//	int exit_status = FINISHED;
+	switch(dz->process) {
+	case(GREQ):   case(PLUCK): 
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+/*********************************** SPEC_BLUR_AND_BLTR ***********************************/
+
+int spec_blur_and_bltr(dataptr dz)
+{
+	int exit_status;
+	int 	blurcnt = 0, blurfactor = dz->iparam[BLUR_BLURF], w_to_buf, wc;
+  	int	last_total_windows = 0;
+	float 	*ampdif, *freqdif;
+	dz->time = 0.0f;
+	if((exit_status = float_array(&ampdif,dz->clength))<0)
+		return(exit_status);
+	if((exit_status = float_array(&freqdif,dz->clength))<0)
+		return(exit_status);
+	if(dz->process==BLTR
+	&& (exit_status = create_and_initialise_array_of_loudest_channel_pointers(dz->iparam[BLTR_MAXTRACE],dz))<0)
+		return(exit_status);
+	dz->flbufptr[1] = dz->flbufptr[2];
+	if((exit_status = read_samps(dz->bigfbuf, dz)) < 0)
+		return exit_status;
+	while(dz->ssampsread > 0) {
+    	dz->flbufptr[0] = dz->bigfbuf;
+    	w_to_buf       = dz->ssampsread/dz->wanted;  
+    	for(wc=0; wc<w_to_buf; wc++) {
+			if(blurcnt==0) {
+				if(dz->total_windows > 0) {
+ 					if((exit_status = do_the_bltr(&last_total_windows,ampdif,freqdif,blurfactor,dz))<0)
+						return(exit_status);
+				}
+ 				if(dz->brksize[BLUR_BLURF]) {
+ 					if((exit_status = read_value_from_brktable((double)dz->time,BLUR_BLURF,dz))<0)
+						return(exit_status);
+				}
+				blurfactor = dz->iparam[BLUR_BLURF];
+				if(dz->total_windows + blurfactor >= dz->wlength)	  /* number of windows to skip */
+					blurfactor = dz->wlength - dz->total_windows - 1; /* must not exceed total no of windows */
+
+				blurcnt = blurfactor;
+
+					/* SEPARATE THE AMP AND FREQ DATA IN (NEXT) INITIAL WINDOW */
+				if((exit_status = get_amp_and_frq(dz->flbufptr[0],dz))<0)
+					return(exit_status);
+			}
+			blurcnt--;
+			dz->flbufptr[0] += dz->wanted;
+			dz->total_windows++;
+			dz->time = (float)(dz->time + dz->frametime);
+		}
+		if((exit_status = read_samps(dz->bigfbuf, dz)) < 0)
+			return exit_status;
+	}
+	if((exit_status = put_amp_and_frq(dz->flbufptr[1],dz))<0) /* transfer last window to output buffer */
+		return(exit_status);		
+	dz->flbufptr[1] += dz->wanted;
+	return write_exact_samps(dz->flbufptr[2],(dz->flbufptr[1] - dz->flbufptr[2]),dz);
+}
+
+/****************************** DO_THE_BLTR ***************************/
+
+int do_the_bltr(int *last_total_windows,float *ampdif,float *freqdif,int blurfactor,dataptr dz)
+{
+	int exit_status = FINISHED;
+	int thiswindow, j;
+	int cc, vc;
+	double thistime = *last_total_windows * dz->frametime;
+
+	for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2){
+		ampdif[cc]   = dz->flbufptr[0][AMPP] - dz->amp[cc];
+		ampdif[cc]  /= (float)blurfactor;
+		freqdif[cc]  = dz->flbufptr[0][FREQ] - dz->freq[cc];
+		freqdif[cc] /= (float)blurfactor;
+	}
+	for(thiswindow = *last_total_windows,j=0;thiswindow<dz->total_windows;thiswindow++,j++) {
+		if(dz->process == BLTR) {
+			if((exit_status = prepare_to_do_trace(&thistime,dz))<0)
+			return(exit_status);
+		}
+		for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2){  /* BLUR amp AND freq */
+			dz->flbufptr[1][AMPP] = dz->amp[cc]  + ((float)j * ampdif[cc]);
+			dz->flbufptr[1][FREQ] = dz->freq[cc] + ((float)j * freqdif[cc]);
+			if(dz->process == BLTR) {	/* COMPARE amp WITH LOUDEST VALS, AND STORE IF NESS */
+				if((exit_status = if_loud_enough_store_in_ring(cc,vc,dz))<0)
+					return(exit_status);	
+			}
+		}
+		if(dz->process == BLTR) {
+			if((exit_status = create_trace(dz))<0)
+				return(exit_status);
+		}
+		dz->flbufptr[1] += dz->wanted;
+		if(dz->flbufptr[1] >= dz->flbufptr[3]) {
+			if((exit_status = write_exact_samps(dz->flbufptr[2],dz->buflen,dz))<0)
+				return(exit_status);
+			dz->flbufptr[1] = dz->flbufptr[2];
+		}
+	}
+
+	*last_total_windows = dz->total_windows;
+	return(FINISHED);
+}
+
+/****************************** CONSTRUCT_FILTER_ENVELOPE (HILITE) ***************************
+ *
+ * If we reach the top of the channels, and there is another peak to work on,
+ * we must be backtracking to a lower channel. If we are NOT, there is a problem
+ * in my logic ... no peak can have its lowest point higher than the frq in the highest
+ * channel!! That's why we have used CHECKLOGIC to check this out!!!
+ */
+
+int construct_filter_envelope(int pkcnt_here,float *fbuf,dataptr dz)
+{
+#define OVERSHOOT	(8)	/* No of channels to test beyond current ch, for frqs BELOW current frq */
+						/* Guesstimate */
+	int exit_status;
+	double thisfrq, thisamp, filt_centre_frq;
+	int n, m;
+	int  baktrak = -1, activate_baktrak = 0, checklogic = 0;
+	int  beyond_top, band_incremented;
+	int cc , vc;
+    for(cc=0; cc<dz->clength; cc++)	/* PRESET FILTER ENVELOPE TO ZERO */ 
+   		dz->fsampbuf[cc] = 0.0f;
+	n = 0;						/* COUNTER FOR CURRENT PEAK */
+	m = 1;						/* COUNTER FOR NEXT PEAK */
+	cc = 0;
+	vc = 0;
+	beyond_top = 0;
+	while(cc < dz->clength) {
+		switch(dz->process) {
+		case(GREQ):	 filt_centre_frq = dz->filtpeak[n];					break;
+		default:
+			sprintf(errstr,"Invalid application in construct_filter_envelope()\n");
+			return(PROGRAM_ERROR);
+
+		}
+		band_incremented = 0;
+		thisfrq = fabs(fbuf[FREQ]);
+		if(baktrak<0 && (m < pkcnt_here) && (thisfrq > dz->fbandbot[m]))
+			baktrak = cc;						/* IF A FRQ IS ENCOUNTERED WHICH IS IN NEXT BAND
+												   AND FOR THE FIRST TIME : mark this as channel to baktrak to */
+		if(thisfrq < dz->fbandbot[n])	{  			
+			if(beyond_top)						/* IF FRQ BELOW BAND: IGNORE IT */
+				beyond_top++;					/* If beyond possible band_top, count channels beyond */
+		}
+		else if(thisfrq < filt_centre_frq) {		/* IF FRQ IN LOWER HALFBAND: generate filter envel */
+			if((exit_status = gen_amplitude_in_lo_half_filterband(&thisamp,thisfrq,filt_centre_frq,dz))<0)
+				return(exit_status);
+			dz->fsampbuf[cc] = (float)max(dz->fsampbuf[cc],thisamp);
+			if(beyond_top)
+				beyond_top++;				/* If beyond possible band_top, count channels beyond */
+		}
+		else if(thisfrq < dz->fbandtop[n])	{		 /* IF FRQ IN HIGHER HALFBAND: generate filter envel */
+			if((exit_status = gen_amplitude_in_hi_half_filterband(&thisamp,thisfrq,filt_centre_frq,dz))<0)
+				return(exit_status);
+			dz->fsampbuf[cc] = (float)max(dz->fsampbuf[cc],thisamp);
+			if(beyond_top)
+				beyond_top++;				/* If beyond possible band_top, count channels beyond */
+		}
+		else {							/* FREQ is ABOVE TOP OF BAND */
+			if(!beyond_top) {			/* IF only just reached possible bandtop among channel frqs */
+				if(baktrak < 0)			/* If channel to baktrak to has not been set, set it here */
+					baktrak = cc;
+			}
+			if(++beyond_top>OVERSHOOT){/* IF GONE FAR ENOUGH BEYOND POSSIBLE BAND TOP */
+				beyond_top = 0;			/* switch off band_top flag */
+				if(++n >= pkcnt_here)	/* MOVE ON TO NEXT BAND  */			
+					break;				/* IF REACHED END OF ALL BANDS: stop  */
+				m++;
+				band_incremented = 1;	/* Note that band has been incremented */
+				activate_baktrak = 1;	/* activate the baktraking mechanism */
+			}
+		}
+		if(cc == dz->clength-1) {			/* IF REACHED TOP OF CHANNELS ON THIS PASS */
+			checklogic = 1;
+			if(!band_incremented) {		/* IF BAND HAS NOT ALREADY BEEN INCREMENTED */
+				beyond_top = 0;			/* Ensure band_top flag is switched off */
+				if(++n >= pkcnt_here)	/* MOVE ON TO NEXT BAND  */				
+					break;				/* IF REACHED END OF ALL BANDS: stop  */
+				m++;
+				activate_baktrak = 1;	/* activate the baktraking mechanism */
+			}
+		}
+		if(activate_baktrak && baktrak>=0) {/* If necessary, baktrak to channel just inside bottom of next band */
+			if(checklogic)
+				checklogic++;
+			cc = baktrak;
+			vc = cc * 2;
+			baktrak = -1;				 /* Cancel baktrak value */
+			activate_baktrak = 0;		 /* Deactivate baktraking mechanism */
+			continue;
+		}
+		if(checklogic==1) {
+			sprintf(errstr,"Problem with peak-scanning logic. construct_filter_envelope()\n");
+			return(PROGRAM_ERROR);
+		}
+		checklogic = 0;
+		cc++;							/* Otherwise, move on to next channel */
+		vc += 2;
+	}
+	return filter_band_test(dz);
+}
+
+/************* CREATE_AND_INITIALISE_ARRAY_OF_LOUDEST_CHANNEL_POINTERS ************
+ *
+ * Create &initialise an array of k loudest-channel-pointers.
+ */
+
+int create_and_initialise_array_of_loudest_channel_pointers(int arraysize,dataptr dz)
+{
+	int n;
+    if((dz->loudest = (chsptr)malloc(arraysize * (sizeof(struct chanstore))))==NULL) {
+		sprintf(errstr,"create_and_initialise_array_of_loudest_channel_pointers()\n");
+		return(MEMORY_ERROR);
+	}
+	for(n=0;n<arraysize;n++) {
+		(dz->loudest+n)->chan = 0;
+		(dz->loudest+n)->amp  = 0.0F;
+	}
+	return(FINISHED);
+}
+
+/****************************** PREPARE_TO_DO_TRACE ***************************/
+
+int prepare_to_do_trace(double *thistime,dataptr dz)
+{
+	int exit_status;
+	int n;
+	if(dz->brksize[BLTR_TRACE]) {
+		if((exit_status = read_value_from_brktable(*thistime,BLTR_TRACE,dz))<0)
+			return(exit_status);
+
+		*thistime += dz->frametime;
+	}
+	for(n=0;n<dz->iparam[BLTR_TRACE];n++)
+		(dz->loudest+n)->amp = 0.0F;	 /* ZERO LOUDEST VALS */
+	return(FINISHED);
+}
+
+/****************************** IF_LOUD_ENOUGH_STORE_IN_RING ***************************/
+
+int if_loud_enough_store_in_ring(int cc,int vc,dataptr dz)
+{
+	int exit_status;
+	int n;
+	for(n=0;n<dz->iparam[BLTR_TRACE];n++) {
+		if(dz->flbufptr[1][AMPP] > (dz->loudest+n)->amp) {
+			if((exit_status = make_room_in_loudchans_list_by_moving_later_items_down_a_place(dz->iparam[BLTR_TRACE],n,dz))<0)
+				return(exit_status);
+			(dz->loudest+n)->chan = cc;
+			(dz->loudest+n)->amp  = dz->flbufptr[1][AMPP];
+			break;
+		}
+	}	/* RE-INITIALISE CHANNEL AMP TO ZERO */
+	dz->flbufptr[1][AMPP]  = 0.0F;   
+	return(FINISHED);
+}
+
+/******************************** CREATE_TRACE *****************************
+ *
+ * Insert true amplitude in loudest channels only.
+ *
+ * NB array positions of amp-vals in output_buf are *2 true channel position
+ */
+
+int	create_trace(dataptr dz)
+{
+	int n;				
+	for(n=0;n<dz->iparam[BLTR_TRACE];n++)
+		dz->flbufptr[1][((dz->loudest+n)->chan)*2] = (dz->loudest+n)->amp;
+	return(FINISHED);
+}
+
+/************* MAKE_ROOM_IN_LOUDCHANS_LIST_BY_MOVING_LATER_ITEMS_DOWN_A_PLACE *************
+ *
+ * Shuffle the items in the list of loudest channels, down from k towards
+ * end.
+ */
+
+int make_room_in_loudchans_list_by_moving_later_items_down_a_place(int size_of_list,int index_into_list,dataptr dz)
+{
+	int n;
+	if(index_into_list==(size_of_list-1))
+		return(FINISHED);
+	for(n=(size_of_list-1);n>index_into_list;n--) {
+		(dz->loudest+n)->chan = (dz->loudest+n-1)->chan;
+		(dz->loudest+n)->amp  = (dz->loudest+n-1)->amp;
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN pconsistency.c ******************************/
+/********************************************************************************************/
+
+/****************************** CHECK_PARAM_VALIDITY_AND_CONSISTENCY *********************************/
+
+int check_param_validity_and_consistency(dataptr dz)
+{
+//	int exit_status = FINISHED;
+	handle_pitch_zeros(dz);
+	switch(dz->process) {
+	case(ARPE):		   return check_arpe_parameters_are_compatible(dz);
+	case(BLTR):	   	   return check_validity_of_trace_vals_for_bltr(dz);
+	}
+	return(FINISHED);
+}
+
+/*********************** CHECK_ARPE_PARAMETERS_ARE_COMPATIBLE ***********************/
+
+int check_arpe_parameters_are_compatible(dataptr dz)
+{
+	if(dz->mode==ABOVE_BOOST || dz->mode==ONCE_ABOVE) {
+		if((dz->iparam[ARPE_WTYPE]==SIN 
+			|| dz->iparam[ARPE_WTYPE]==SAW) 
+			&& dz->param[ARPE_PHASE] < 0.5) {
+			sprintf(errstr,
+				"startphase of SIN or SAW must be > 0.5 with ABOVE_BOOST & ONCE_ABOVE\n");
+			return(USER_ERROR);
+		}
+	}
+	return(FINISHED);
+}
+
+/********************* CHECK_VALIDITY_OF_TRACE_VALS_FOR_BLTR **********************/
+
+int check_validity_of_trace_vals_for_bltr(dataptr dz)
+{
+	int exit_status;
+	double brkmax;
+	if(dz->brksize[BLTR_TRACE]==0)
+		dz->iparam[BLTR_MAXTRACE] = dz->iparam[BLTR_TRACE];
+	else { 
+		if((exit_status = get_maxvalue_in_brktable(&brkmax,BLTR_TRACE,dz))<0)
+			return(exit_status);
+		dz->iparam[BLTR_MAXTRACE] = round(brkmax);
+	}
+	if(dz->iparam[BLTR_MAXTRACE]<=0) {
+		sprintf(errstr,"Failed to find trace value above zero,\n");
+		return(USER_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN buffers.c ***********************************/
+/********************************************************************************************/
+
+/**************************** ALLOCATE_LARGE_BUFFERS ******************************/
+
+int allocate_large_buffers(dataptr dz)
+{
+	switch(dz->process) {
+	case(FILT):		case(GREQ):		case(SPLIT):	
+	case(ARPE):		case(PLUCK):	case(S_TRACE):	
+		return allocate_single_buffer(dz);
+//TW NEW CASE
+ 	case(VFILT):
+		return allocate_single_buffer_plus_extra_pointer(dz);
+
+	case(BLTR):		
+		return allocate_double_buffer(dz);
+	default:
+		sprintf(errstr,"Unknown program no. in allocate_large_buffers()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN cmdline.c ***********************************/
+/********************************************************************************************/
+
+int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
+{
+	if     (!strcmp(prog_identifier_from_cmdline,"filter"))	   		dz->process = FILT;
+//TW NEW CASE
+	else if(!strcmp(prog_identifier_from_cmdline,"vowels"))	   		dz->process = VFILT;
+
+	else if(!strcmp(prog_identifier_from_cmdline,"greq"))	   		dz->process = GREQ;
+	else if(!strcmp(prog_identifier_from_cmdline,"band"))	   		dz->process = SPLIT;
+	else if(!strcmp(prog_identifier_from_cmdline,"arpeg"))	   		dz->process = ARPE;
+	else if(!strcmp(prog_identifier_from_cmdline,"pluck"))	   		dz->process = PLUCK;
+	else if(!strcmp(prog_identifier_from_cmdline,"trace"))	   		dz->process = S_TRACE;
+	else if(!strcmp(prog_identifier_from_cmdline,"bltr"))	   		dz->process = BLTR;
+	else {
+		sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
+		return(USAGE_ONLY);
+	}
+//TW UPDATE
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN usage.c *************************************/
+/********************************************************************************************/
+
+/******************************** USAGE1 ********************************/
+
+int usage1(void)
+{
+	sprintf(errstr,
+	"\nHIGHLIGHTING OPERATIONS ON A SPECTRAL FILE\n\n"
+	"USAGE: hilite NAME (mode) infile outfile parameters: \n"
+	"\n"
+	"where NAME can be any one of\n"
+	"\n"
+	"filter   greq    band    arpeg    pluck	trace    bltr\n\n"
+//TW NEW CASE
+	"vowels\n\n"
+
+	"Type 'hilite filter' for more info on hilite filter..ETC.\n");
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE2 ********************************/
+
+int usage2(char *str)
+{
+	if(!strcmp(str,"filter")) {
+		fprintf(stdout,
+		"hilite filter 1-4   infile outfile frq1 Q \n"
+		"hilite filter 5-6   infile outfile frq1 Q gain\n"
+		"hilite filter 7-10  infile outfile frq1 frq2 Q\n"
+		"hilite filter 11-12 infile outfile frq1 frq2 Q gain\n"
+		"\n"
+		"FILTER THE SPECTRUM\n"
+		"\n"
+		"MODES:-\n"
+		"1    high pass filter \n"
+		"2    high pass filter (normalised output) \n"
+		"3    low pass filter \n"
+		"4    low pass filter (normalised output) \n"
+		"5    high pass filter with gain \n"
+		"6    low pass filter with gain \n"
+		"7    band pass filter \n"
+		"8    band pass filter (normalised output) \n"
+		"9    notch filter \n"
+		"10   notch filter (normalised output) \n"
+		"11   band pass filter with gain \n"
+		"12   notch filter with gain \n"
+		"\n"
+		"frq1            filter cutoff frq.\n"
+		"frq1 with frq2  limits of filter band.\n"
+		"Q               width of filter skirts, in Hz (Range: >0).\n"
+		"gain            amplification of resulting sound.\n"
+		"\n"
+		"frq1, frq2 and Q may vary over time.\n");
+//TW NEW CASE
+	} else if(!strcmp(str,"vowels")) {
+		fprintf(stdout,
+		"hilite vowels infile outfile vowelfile halfwidth steepness range threshold\n"
+		"\n"
+		"VOWELS......file containing paired times & vowels, where vowels can be....\n"
+		"ee: as in 'heat'  i:  as in 'hit'    e:  as in 'pet'  ai: as in 'hate'\n"
+		"a:  as in 'pat'   ar: as in 'heart'  o:  as in 'hot'  or: as in 'taught'\n"
+		"oa: as in 'boat'  u:  as in 'hood'   oo: as in 'mood'\n"
+		"xx: as in Southern English 'hub'     x:  neutral vowel in 'herb' or 'the'\n"
+		"\n"
+		"Times must start at zero, and increase.\n"
+		"\n"
+		"HALFWIDTH ....half-width of formant peaks as fraction of formant centre-frq.\n"
+		"              (Range 0.01 - 10)\n"
+		"STEEPNESS ....steepness of formant peaks. (Range 0.1 - 10)\n"
+		"RANGE ........the peaks stand above the signal floor. The range of the peaks\n"
+		"..............is therefore a part of the total range of the signal.\n"
+		"..............Range = ratio (max) peakheight to (max) totalrange.(vals 0-1)\n"
+		"THRESHOLD ....spectral window's level is compared with vowel-envelope level.\n"
+		"..............If it exceeds a certain proportion of that level,\n"
+		"..............it is forced to the vowel-envelope level.\n"
+		"..............(Otherwise it remains where it is).\n"
+		"..............threshold defines this proportion.(Range 0-1)\n"
+		"good defaults might be %lf, %d, %lf, 0.5\n",V_HWIDTH,CURVIT,PEAK_RANGE);
+	} else if(!strcmp(str,"greq")) {
+		fprintf(stdout,
+		"hilite greq mode infile outfile filtfile [-r]\n"
+		"\n"
+		"GRAPHIC EQ ON SPECTRUM\n"
+		"\n"
+		"MODES :-\n"
+		"1   single bandwidth for all filter bands.\n"
+		"    FILTFILE has ONE bandwidth (octaves)\n"
+		"    followed by centre frqs of all filter bands (Hz).\n\n"
+		"2   separate bandwidths for each filter band.\n"
+		"    FILTFILE has a pair of values for each filter band.\n"
+		"    These are centre frq of the band (Hz) && bandwidth (octaves).\n"
+		"\n"
+		"-r  Band reject (notch) filter: Default is a bandpass filter.\n");
+	} else if(!strcmp(str,"band")) {	/* SPLIT */
+		fprintf(stdout,
+		"hilite band infile outfile datafile\n"
+		"\n"
+		"SPLIT SPECTRUM INTO BANDS & PROCESS THESE INDIVIDUALLY\n"
+		" \n"
+		"Datafile contains a number of lines with the following info..\n"
+		"\n"
+		"lofrq   hifrq   bitflag   [amp1   amp2   [+]transpose]\n"
+		"\n"
+	   	"bitflag has 4 bits (e.g. '0101' or '1000')\n"
+	   	"bit 1 set: amplitude change to band: put amp multiplier 'amp1' in line.\n"
+	   	"bit 2 set: amplitude ramp: put 2nd amp multiplier 'amp2' in line.\n"
+	   	"           (spectral band will change in amplitude from amp1 to amp2).\n"
+	   	"bit 3 set: partials transpose: prog expects frq multiplier 'transpose' in line.\n"
+	   	"           OR, if val preceeded by '+',val is frq in Hz ADDED to frq in band.\n"
+	   	"bit 4 set: transposed partials ADDED to original spectrum (default: replace)\n\n"
+	    "amp1, amp2 &\\or transpose MUST be present, as required by the bitflag options.\n");
+	} else if(!strcmp(str,"arpeg")) {
+		fprintf(stdout,
+		"hilite arpeg 1-4 infile outfile wave rate [-pU] [-lX] [-hY] [-bZ] [-aA]\n"
+		"                                              [-Nk] [-sS] [-T]  [-K]\n\n"
+//TW JULY 2006
+		"hilite arpeg 5-6 infile outfile wave rate [-pU] [-lX] [-hY] [-aA]\n\n"
+		"hilite arpeg 7-8 infile outfile wave rate [-pU] [-lX] [-hY] [-bZ] [-aA]\n\n"
+		"MODES:-                ARPEGGIATE THE SPECTRUM\n"
+		"1 ON...........Play components inside arpeggiated band ONLY.\n"
+		"2 BOOST........Amplify snds in band. Others play unamplified.\n"
+		"3 BELOW_BOOST..INITIALLY Play components in & below band ONLY.\n"
+		"               THEN amplify snds in band. Others play unamplified.\n"
+		"               (NOT with downramp).\n"
+		"4 ABOVE_BOOST..INITIALLY Play components in & above band ONLY.\n"
+		"               THEN amplify snds in band. Others play unamplified.\n"
+		"              (NOT with upramp: with sin/saw startphase>0.5)\n"
+		"5 BELOW........Play components in & below arpeggiated band ONLY.\n"
+		"6 ABOVE........Play components in & above arpeggiated band ONLY.\n"
+		"7 ONCE_BELOW...INITIALLY Play components in and below band ONLY.\n"
+		"               THEN play whole sound as normal.(NOT with downramp).\n"
+		"8 ONCE_ABOVE...INITIALLY Play components in and above arpeggiated band ONLY.\n"
+		"               THEN play whole sound as normal.\n"
+		"               (NOT with upramp: with sin/saw startphase>0.5)\n"
+		"wave  1 downramp : 2 sin : 3 saw : 4 upramp\n"
+		"rate  sweeps per second.\n"
+		"-p    U = start_phase: range 0-1: (limited range for some cases).\n"
+		"-l    X = lowest  freq arpeg sweeps down to: default 0\n"
+		"-h    Y = highest freq arpeg sweeps up to:   default nyquist\n"
+		"-b    Z = bandwidth of sweep band (in Hz): default = nyquist/channel_cnt\n"
+		"-a    A = amplification of arpegtones : default 10.0\n"
+		"-N    k = Nonlinear decay arpegtones. >1 faster, <1 slower. Must be >0.\n"
+		"-s    S = No. of windows over which arpegtones sustained: Default 3\n"
+		"-T    In sustains, TRACK changing frq of src (default : retain start frq)\n"
+		"-K    Let sustains run to zero before new arpegtone attack accepted\n"
+		"     (Default:Re-attack once sustains fall below current input level)\n"
+		"\n"
+		"all parameters may vary over time, except for wavetype and startphase.\n");
+	} else if(!strcmp(str,"pluck")) {
+		fprintf(stdout,
+		"hilite pluck infile outfile gain\n"
+		"\n"
+		"EMPHASISE SPECTRAL CHANGES (USE e.g. WITH spec arpeg)\n"
+		"\n"
+		"gain   amplitude gain applied to newly prominent spectral components.\n"
+		"\n"
+		"gain may vary over time.\n");
+	} else if(!strcmp(str,"trace")) {
+		fprintf(stdout,
+		"hilite trace 1 infile outfile N\n"
+		"hilite trace 2 infile outfile N lofrq       [-r]\n"
+		"hilite trace 3 infile outfile N       hifrq [-r]\n"
+		"hilite trace 4 infile outfile N lofrq hifrq [-r]\n"
+		"\n"
+		"RETAIN THE N LOUDEST PARTIALS ONLY (ON A WINDOW-BY-WINDOW BASIS)\n"
+		"\n"
+		"MODES :-    \n"
+		"1  Select loudest spectral components.\n"
+		"2  Select loudest from above lofrq: Reject all spectral data below lofrq.\n"
+		"3  Select loudest from below hifrq: Reject all spectral data above hifrq.\n"
+		"4  Select loudest from between lofrq and hifrq: Reject data outside.\n\n"
+		"-r If trace index > no of chans in fltband (defined by lofrq\\hifrq)\n"
+		"   RETAIN loudest chans OUTSIDE fltband.\n"
+		"   (Default: always omit chans outside fltband)\n"
+		"\n"
+		"N   is number of spectral components to retain.\n"
+		"\n"
+		"N, lofrq and hifrq may vary over time.\n");
+	} else if(!strcmp(str,"bltr")) {
+		fprintf(stdout,
+		"hilite bltr infile outfile blurring tracing \n"
+		"\n"
+		"TIME-AVERAGE, AND TRACE, THE SPECTRUM\n"
+		"\n"
+		"blurring   is number of windows over which to average the spectrum.\n"
+		"tracing    is number of (loudest) channels to retain, in each window.\n"
+		"\n"
+		"blurring AND tracing may vary over time. \n");
+	} else
+		fprintf(stdout,"Unknown option '%s'\n",str);
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE3 ********************************/
+
+int usage3(char *str1,char *str2)
+{
+	sprintf(errstr,"Insufficient parameters on command line.\n");
+	return(USAGE_ONLY);
+}
+

+ 1593 - 0
dev/hilite/hilite.c

@@ -0,0 +1,1593 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version TW */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <pnames.h>
+#include <globcon.h>
+#include <processno.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <flags.h>
+#include <highlight.h>
+#include <cdpmain.h>
+#include <formants.h>
+#include <speccon.h>
+#include <sfsys.h>
+#include <osbind.h>
+#include <highlight.h>
+//TW UPDATE
+#include <vowels.h>
+
+#if defined unix || defined __GNUC__
+#define round(x) lround((x))
+#endif
+
+static int  do_filtering(double frq_limit,double hifrq_limit,dataptr dz);
+static int  below_limitfrq_and_zeroed(int vc,double loskirt,dataptr dz);
+static int  below_limitfrq_and_filtered(int vc,double limitfrq,double loskirt,double loskirt_bwidth,dataptr dz);
+static int  above_limitfrq_and_zeroed(int vc,double hiskirt,dataptr dz);
+static int  filter_above_limitfrq(int vc,double limitfrq,double hiskirt,double hiskirt_bwidth,dataptr dz);
+static int  filtered_in_lower_skirt(int vc,double skirttop,double loskirt,double loskirt_bwidth,dataptr dz);
+static int  filtered_in_upper_skirt(int vc,double skirt_bottom,double hiskirt,double hiskirt_bwidth,dataptr dz);
+static int  do_greq_filter(dataptr dz);
+static int  invert_greq_filter_envelope(dataptr dz);
+static int  process_specsplit_channel(int cc,bandptr bb,dataptr dz);
+static int  do_on(double bandhilimit,double bandlolimit,dataptr dz);
+static int  do_below(double bandmid,dataptr dz);
+static int  do_above(double bandmid,dataptr dz);
+static int  do_boost(double bandhilimit,double bandlolimit,dataptr dz);
+static int  do_above_boost(double bandhilimit,double bandlolimit,int *in_start_portion, dataptr dz);
+static int  do_below_boost(double bandhilimit,double bandlolimit,int *in_start_portion,dataptr dz);
+static int  do_once_below(double bandlolimit,int *in_start_portion,dataptr dz);
+static int  do_once_above(double bandhilimit,int *in_start_portion,dataptr dz);
+static int  initiate_new_arpeg_note(int cc,int vc,dataptr dz);
+static int  initiate_new_arpeg_note_with_fixed_pitch(int cc,int vc,dataptr dz);
+static int  temporarily_sustain_arpeg_note(int cc,double thisamp,dataptr dz);
+static int  temporarily_sustain_arpeg_note_with_fixed_pitch(int cc,int vc,double thisamp,dataptr dz);
+static int  get_non_linear_decimation(double *nonlin_dec,int cc,dataptr dz);
+static int  get_decimation(double *dec,int cc,dataptr dz);
+static int  sustain_arpeg_note(int cc,int vc,dataptr dz);
+static int  sustain_arpeg_note_with_fixed_pitch(int cc,int vc,dataptr dz);
+static int  nonlin_sustain_arpeg_note(int cc,int vc, dataptr dz);
+static int  nonlin_sustain_arpeg_note_with_fixed_pitch(int cc, int vc, dataptr dz);
+static int  set_bit_to_zero(int bflagno,int mask,dataptr dz);
+static int  set_bit_to_one(int bflagno,int mask,dataptr dz);
+static int  outside_skirts(int vc,double loskirt,double hiskirt,dataptr dz);
+static int  reset_timechanging_arpe_variables(double *frqrange,double *lofrq, double *hifrq,dataptr dz);
+static int  locate_current_wavetable_position(dataptr dz);
+//TW UPDATE
+static int    do_vowel_filter(double *vamp,double formant1,double formant2,double formant3,double f2atten,double f3atten,
+							double *sensitivity,int senslen,dataptr dz);
+static int get_formant_frqs
+(int vowel,double *formant1, double *formant2, double *formant3, double *f2atten, double *f3atten);
+static int define_sensitivity_curve(double **sensitivity,int *senslen);
+static int adjust_for_sensitivity(double *amp,double frq,double *sensitivity,int senslen);
+
+
+
+/**************************** SPECFILT ***************************/
+
+int specfilt(dataptr dz)
+{
+	int exit_status;
+	int vc;
+	double frq_limit, hifrq_limit = 0.0, pre_amptotal, post_amptotal;
+	if(dz->brksize[FILT_QQ])
+		dz->param[FILT_QQ] 	 = exp(dz->param[FILT_QQ]);
+	if(dz->brksize[FILT_FRQ1])
+		frq_limit = exp(dz->param[FILT_FRQ1]);
+	else
+		frq_limit = dz->param[FILT_FRQ1];
+	switch(dz->mode) {
+	case(F_BND):
+	case(F_BND_NORM):
+	case(F_NOTCH):
+	case(F_NOTCH_NORM):
+	case(F_BAND_GAIN):
+	case(F_NOTCH_GAIN):
+		if(dz->brksize[FILT_FRQ2])
+			hifrq_limit = exp(dz->param[FILT_FRQ2]);
+		else
+			hifrq_limit = dz->param[FILT_FRQ2];
+		if(frq_limit > hifrq_limit)
+			swap(&frq_limit,&hifrq_limit);
+		break;
+	}
+	if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
+			return(exit_status);
+	if((exit_status = do_filtering(frq_limit,hifrq_limit,dz))<0)
+		return(exit_status);
+	if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
+			return(exit_status);
+	switch(dz->mode) {
+	case(F_HI_NORM): 
+	case(F_LO_NORM): 
+	case(F_BND_NORM): 
+	case(F_NOTCH_NORM):   /* normalised output */
+		if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
+			return(exit_status);
+		break;
+	case(F_HI_GAIN): 
+	case(F_LO_GAIN): 
+	case(F_BAND_GAIN): 
+	case(F_NOTCH_GAIN):	/*  post-gain */
+		for(vc = 0; vc < dz->wanted; vc += 2)
+			dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FILT_PG]);
+		break;
+	}
+	return(FINISHED);
+}
+
+/**************************** DO_FILTERING ***************************/
+
+int do_filtering(double frq_limit,double hifrq_limit,dataptr dz)
+{
+	int exit_status;
+	int vc;											   
+	double loskirt, loskirt_bwidth, hiskirt, hiskirt_bwidth;
+	switch(dz->mode) {
+	case(F_HI): 
+	case(F_HI_NORM): 
+	case(F_HI_GAIN):
+		loskirt        = max(0.0,(frq_limit - dz->param[FILT_QQ]));
+		loskirt_bwidth = frq_limit - loskirt;
+		for(vc = 0; vc < dz->wanted; vc += 2) {
+			if((exit_status = below_limitfrq_and_zeroed(vc,loskirt,dz))<0)
+				return(exit_status);
+			if(exit_status==TRUE)
+				continue;
+			if((exit_status = below_limitfrq_and_filtered(vc,frq_limit,loskirt,loskirt_bwidth,dz))<0)
+				return(exit_status);
+		}		    
+		break;
+	case(F_LO): 
+	case(F_LO_NORM): 
+	case(F_LO_GAIN):
+		hiskirt        = min(dz->nyquist,(frq_limit + dz->param[FILT_QQ]));
+		hiskirt_bwidth = hiskirt - frq_limit;
+		for(vc = 0; vc < dz->wanted; vc += 2) {
+			if((exit_status = above_limitfrq_and_zeroed(vc,hiskirt,dz))<0)
+				return(exit_status);
+			if(exit_status==TRUE)
+				continue;
+			if((exit_status = filter_above_limitfrq(vc,frq_limit,hiskirt,hiskirt_bwidth,dz))<0)
+				return(exit_status);
+		}		    
+		break;
+	case(F_BND): 
+	case(F_BND_NORM): 
+	case(F_BAND_GAIN):
+		loskirt        = max(0.0,(frq_limit - dz->param[FILT_QQ]));
+		loskirt_bwidth = frq_limit - loskirt;
+		hiskirt        = min(dz->nyquist,(hifrq_limit + dz->param[FILT_QQ]));
+		hiskirt_bwidth = hiskirt - hifrq_limit;
+		for(vc = 0; vc < dz->wanted; vc += 2) {
+			if((exit_status = below_limitfrq_and_zeroed(vc,loskirt,dz))<0)
+				return(exit_status);
+			if(exit_status==TRUE)
+				continue;
+			if((exit_status = below_limitfrq_and_filtered(vc,frq_limit,loskirt,loskirt_bwidth,dz))<0)
+				return(exit_status);
+			if(exit_status == TRUE) 	
+				continue;
+			if((exit_status = above_limitfrq_and_zeroed(vc,hiskirt,dz))<0)
+				return(exit_status);
+			if(exit_status == TRUE) 	
+				continue;
+			if((exit_status = filter_above_limitfrq(vc,hifrq_limit,hiskirt,hiskirt_bwidth,dz))<0)
+				return(exit_status);
+		}		    
+		break;
+	case(F_NOTCH): 
+	case(F_NOTCH_NORM): 
+	case(F_NOTCH_GAIN):
+		loskirt        = max(0.0,(frq_limit - dz->param[FILT_QQ]));
+		loskirt_bwidth = frq_limit - loskirt;
+		hiskirt        = min(dz->nyquist,(hifrq_limit + dz->param[FILT_QQ]));
+		hiskirt_bwidth = hiskirt - hifrq_limit;
+		for(vc = 0; vc < dz->wanted; vc += 2) {
+			if(outside_skirts(vc,loskirt,hiskirt,dz))
+				continue;
+			if((exit_status = filtered_in_lower_skirt(vc,frq_limit,loskirt,loskirt_bwidth,dz))<0)
+				return(exit_status);
+			if(exit_status==TRUE)	  
+				continue;
+			if((exit_status = filtered_in_upper_skirt(vc,hifrq_limit,hiskirt,hiskirt_bwidth,dz))<0)
+				return(exit_status);
+			if(exit_status==TRUE)	  
+				continue;
+			dz->flbufptr[0][AMPP] = 0.0F;
+		}		    
+		break;
+	default:
+		sprintf(errstr,"unknown mode in do_filtering()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/**************************** BELOW_LIMITFRQ_AND_ZEROED ***************************/
+
+int below_limitfrq_and_zeroed(int vc,double loskirt,dataptr dz)
+{
+	if(dz->flbufptr[0][FREQ] < loskirt) {
+		dz->flbufptr[0][AMPP] = 0.0F;
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+/**************************** BELOW_LIMITFRQ_AND_FILTERED ***************************/
+
+int below_limitfrq_and_filtered(int vc,double limitfrq,double loskirt,double loskirt_bwidth,dataptr dz)
+{
+	if(dz->flbufptr[0][FREQ] < limitfrq) {
+		dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * ((dz->flbufptr[0][FREQ] - loskirt)/loskirt_bwidth));
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+/**************************** FILTER_ABOVE_LIMITFRQ ***************************/
+
+int filter_above_limitfrq(int vc,double limitfrq,double hiskirt,double hiskirt_bwidth,dataptr dz)
+{
+	if(dz->flbufptr[0][FREQ] > limitfrq) {
+		dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * ((hiskirt - dz->flbufptr[0][FREQ])/hiskirt_bwidth));
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+/**************************** ABOVE_LIMITFRQ_AND_ZEROED ***************************/
+
+int above_limitfrq_and_zeroed(int vc,double hiskirt,dataptr dz)
+{
+	if(dz->flbufptr[0][FREQ] > hiskirt) {
+		dz->flbufptr[0][AMPP] = 0.0F;
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+/**************************** FILTER_IN_LOWER_SKIRT ***************************/
+
+int filtered_in_lower_skirt(int vc,double skirttop,double loskirt,double loskirt_bwidth,dataptr dz)
+{
+	if(dz->flbufptr[0][FREQ] < skirttop) {
+		dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * (1.0 - ((dz->flbufptr[0][FREQ] - loskirt)/loskirt_bwidth)));
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+/**************************** FILTER_IN_UPPER_SKIRT ***************************/
+
+int filtered_in_upper_skirt(int vc,double skirt_bottom,double hiskirt,double hiskirt_bwidth,dataptr dz)
+{
+	if(dz->flbufptr[0][FREQ] > skirt_bottom) {
+		dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * (1.0 - ((hiskirt - dz->flbufptr[0][FREQ])/hiskirt_bwidth)));
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+/***********************  SPECGREQ **********************/
+
+int specgreq(dataptr dz)
+{
+	int exit_status;
+	if((exit_status = construct_filter_envelope((int)dz->itemcnt,dz->flbufptr[0],dz))<0)
+		return(exit_status);
+	if(dz->vflag[GREQ_NOTCH]) {
+		if((exit_status = invert_greq_filter_envelope(dz))<0)
+			return(exit_status);
+	}
+	if((exit_status = do_greq_filter(dz))<0)
+		return(exit_status);
+	return(FINISHED);
+}
+
+/****************************** DO_GREQ_FILTER ***************************/
+
+int do_greq_filter(dataptr dz)
+{
+	int cc, vc;
+	for(cc=0, vc=0; cc < dz->clength; cc++, vc += 2)
+		dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->fsampbuf[cc]);
+	return(FINISHED);
+}													 
+
+/****************************** INVERT_GREQ_FILTER_ENVELOPE ***************************/
+
+int invert_greq_filter_envelope(dataptr dz)
+{
+	int cc;
+	for(cc=0; cc<dz->clength; cc++)
+		dz->fsampbuf[cc] = (float)(1.0 - dz->fsampbuf[cc]);
+	return(FINISHED);
+}	
+
+/******************************** SPECSPLIT ******************************/
+
+int specsplit(dataptr dz) 
+{
+	int exit_status;
+	int cc, bno = 0, bottom, top, done = 0, k;
+	bandptr bb;
+	double bandbot, bandtop;
+
+	rectify_window(dz->flbufptr[0],dz);
+	if((exit_status = get_amp_and_frq(dz->flbufptr[0],dz))<0)
+		return(exit_status);		
+	cc   = 0;			/* channel counter */
+	while(bno<dz->itemcnt) {		/* For all bands */
+		bb      = dz->band[bno];
+		bandbot = bb->bfrqlo;	
+		bandtop = bb->bfrqhi;
+		while(dz->freq[cc]<bandbot) {	/* while chan-frq<bandbot: do nothing */
+			if(++cc>=dz->clength) {
+				done = 1;		
+				break;   /* if all channels<bandbot, we.ve finished pass */
+			}
+		}
+		if(done)
+			break;
+		bottom = cc;		/* set bottom channel for inner loop */
+		while(dz->freq[cc]<bandtop) {
+			if(++cc>=dz->clength) {
+				done = 1;	/* find channels up to top of band */
+				break;
+			}
+		}
+		top = min(cc,(dz->clength)-1); 	/* set top channel for inner loop */
+		if((bb->bdoflag & DO_TRANSPOSITION) && bb->btrans>1.0) {
+			for( k = top; k>= bottom; k--) {
+				if((exit_status = process_specsplit_channel(k,bb,dz))<0)
+					return(exit_status);
+			}
+		} else {
+			for( k = bottom; k <= top; k++) {
+				if((exit_status = process_specsplit_channel(k,bb,dz))<0)
+					return(exit_status);
+			}
+		}
+		if(done)
+			break;
+		bno++;
+	}
+	if((exit_status = put_amp_and_frq(dz->flbufptr[0],dz))<0)
+		return(exit_status);
+	return(FINISHED);
+}
+
+/************************ PROCESS_SPECSPLIT_CHANNEL *****************************/
+
+int process_specsplit_channel(int cc,bandptr bb,dataptr dz)
+{
+	int exit_status;
+	double thismult;
+	double newamp = dz->amp[cc];	/* DEFAULT */
+	double newfrq = dz->freq[cc];	/* DEFAULT */
+	int newchan;
+
+	if(bb->bdoflag & DO_AMPLITUDE_CHANGE) {
+		if(bb->bdoflag & DO_RAMPED_AMPLITUDE) {
+			thismult  = (dz->freq[cc] - bb->bfrqlo)/(bb->bfrqdif);
+			thismult *= bb->bampdif;
+			thismult += bb->bamp;
+			newamp    = dz->amp[cc] * thismult;
+		} else
+			newamp   = dz->amp[cc] * bb->bamp;
+	}
+	if(bb->bdoflag & DO_TRANSPOSITION)  {
+		if(bb->badditive) {
+			if((newfrq  = dz->freq[cc] + bb->btrans)<dz->nyquist) {
+				if((exit_status = get_channel_corresponding_to_frq(&newchan,newfrq,dz))<0)
+					return(exit_status);
+				if(newchan!=cc) {
+					dz->freq[newchan] = (float)newfrq;
+					dz->amp[newchan]  = (float)newamp;
+				}  	
+			}
+		} else {
+			if((newfrq  = dz->freq[cc] * bb->btrans)<dz->nyquist) {
+				if((exit_status = get_channel_corresponding_to_frq(&newchan,newfrq,dz))<0)
+					return(exit_status);
+				if(newchan!=cc) {
+					dz->freq[newchan] = (float)newfrq;
+					dz->amp[newchan]  = (float)newamp;
+				}
+			}	
+		}
+		if(!(bb->bdoflag & DO_ADD_TO_SPECTRUM)) {
+			newamp =   	/* set interpolated value on old amp */
+			(dz->amp[max(cc-1,0)] + dz->amp[min(cc+1,(dz->clength-1))])/2.0;
+		}
+	}
+	dz->freq[cc] = (float)newfrq;
+	dz->amp[cc]  = (float)newamp;
+	return(FINISHED);
+}
+
+/********************************** SPECARPE **********************************/
+
+int specarpe(int *in_start_portion,dataptr dz)
+{
+	int exit_status;
+	double	lofrq, hifrq, frqrang;
+	double	bandmid, bandhilimit, bandlolimit;
+	int 	tabindex;
+	if((exit_status = reset_timechanging_arpe_variables(&frqrang,&lofrq,&hifrq,dz))<0)
+		return(exit_status);		
+	if((exit_status = locate_current_wavetable_position(dz))<0)
+		return(exit_status);		
+	tabindex    = round(dz->param[ARPE_WAVETABPOS]);
+											    	/* LOCATE CURRENT FREQUENCY BAND */
+	bandmid     = (dz->parray[ARPE_TAB][tabindex] * frqrang) + lofrq; 
+	bandhilimit = min(bandmid + dz->param[ARPE_HBAND],dz->nyquist);
+	bandlolimit = max(bandmid - dz->param[ARPE_HBAND],0.0);
+	  
+	if((exit_status = get_amp_and_frq(dz->flbufptr[0],dz))<0)		/* SEPARATE THE AMP AND FREQ DATA */
+		return(exit_status);		
+
+	switch(dz->mode) {		 /* ELIMINATE OR MODIFY FREQUENCIES, AS NECESSARY */
+	case(ON):  			exit_status = do_on(bandhilimit,bandlolimit,dz);							break;
+	case(BELOW):  		exit_status = do_below(bandmid,dz);											break;
+	case(ABOVE):  		exit_status = do_above(bandmid,dz);											break;
+	case(BOOST):  		exit_status = do_boost(bandhilimit,bandlolimit,dz); 		   				break;
+	case(ABOVE_BOOST):  exit_status = do_above_boost(bandhilimit,bandlolimit,in_start_portion,dz);	break;
+	case(BELOW_BOOST):  exit_status = do_below_boost(bandhilimit,bandlolimit,in_start_portion,dz);	break;
+	case(ONCE_ABOVE):  	exit_status = do_once_above(bandhilimit,in_start_portion,dz);				break;
+	case(ONCE_BELOW):  	exit_status = do_once_below(bandlolimit,in_start_portion,dz);				break;
+	default:
+		sprintf(errstr,"unknown mode in specarpe()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(exit_status<0)
+		return(exit_status);		
+
+	if((exit_status = put_amp_and_frq(dz->flbufptr[0],dz))<0) /*  WRITE MODIFIED AMP & FREQ BUFF TO SAMP BUFF */
+		return(exit_status);		
+	return(FINISHED);
+}
+
+/*************************** DO_ON ****************************/
+
+int do_on(double bandhilimit,double bandlolimit,dataptr dz)
+{
+	int exit_status;
+	int cc, vc = 0;
+	double dec, nonlin_dec = 0.0, thisamp;
+	switch(dz->iparam[ARPE_SUSFLAG]) {
+	case(AP_NORMAL):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->iparray[ARPE_KEEP][cc]) {
+				if((exit_status = sustain_arpeg_note(cc,vc,dz))<0)
+					return(exit_status);
+			} else {
+				if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+					if((exit_status = initiate_new_arpeg_note(cc,vc,dz))<0)
+						return(exit_status);
+				} else
+					dz->amp[cc]  = 0.0f;
+			}
+	    }
+		break;
+	case(AP_SUSTAIN_PITCH):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->iparray[ARPE_KEEP][cc]) {
+				if((exit_status = sustain_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+					return(exit_status);
+			} else {
+				if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+					if((exit_status = initiate_new_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+						return(exit_status);
+				} else
+					dz->amp[cc]  = 0.0f;
+			}
+	    }
+		break;
+	case(AP_LIMIT_SUSTAIN):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if((exit_status = get_decimation(&dec,cc,dz))<0)
+						return(exit_status);
+				if(dz->iparray[ARPE_KEEP][cc] && ((thisamp = dz->windowbuf[0][AMPP] * dec) > dz->amp[cc])) {
+					if((exit_status = temporarily_sustain_arpeg_note(cc,thisamp,dz))<0)
+						return(exit_status);
+				} else {
+					if((exit_status = initiate_new_arpeg_note(cc,vc,dz))<0)
+						return(exit_status);
+				}
+			} else {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					if((exit_status = sustain_arpeg_note(cc,vc,dz))<0)
+						return(exit_status);
+				} else
+					dz->amp[cc] = 0.0f;
+			}
+	    }
+		break;
+	case(AP_SUSTAIN_PITCH_AND_LIMIT_SUSTAIN):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if((exit_status = get_decimation(&dec,cc,dz))<0)
+					return(exit_status);
+				if(dz->iparray[ARPE_KEEP][cc] && ((thisamp = dz->windowbuf[0][AMPP] * dec) > dz->amp[cc])) {
+					if((exit_status = temporarily_sustain_arpeg_note_with_fixed_pitch(cc,vc,thisamp,dz))<0)
+						return(exit_status);
+				} else {
+					if((exit_status = initiate_new_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+						return(exit_status);
+				}
+			} else {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					if((exit_status = sustain_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+						return(exit_status);
+				} else
+					dz->amp[cc] = 0.0f;
+			}
+	    }										
+		break;
+	case(AP_NONLIN):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->iparray[ARPE_KEEP][cc]) {
+				if((exit_status = nonlin_sustain_arpeg_note(cc,vc,dz))<0)
+					return(exit_status);
+			} else {
+				if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+					if((exit_status = initiate_new_arpeg_note(cc,vc,dz))<0)
+						return(exit_status);
+				} else
+					dz->amp[cc]  = 0.0f;
+			}
+	    }
+		break;
+	case(AP_NONLIN_AND_SUSTAIN_PITCH):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->iparray[ARPE_KEEP][cc]) {
+				if((exit_status = nonlin_sustain_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+					return(exit_status);
+			} else {
+				if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+					if((exit_status = initiate_new_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+						return(exit_status);
+				} else
+					dz->amp[cc]  = 0.0f;
+			}
+	    }
+		break;
+	case(AP_NONLIN_AND_LIMIT_SUSTAIN):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					if((exit_status = get_non_linear_decimation(&nonlin_dec,cc,dz))<0)
+						return(exit_status);
+				}
+				if(dz->iparray[ARPE_KEEP][cc] && ((thisamp = dz->windowbuf[0][AMPP] * nonlin_dec) > dz->amp[cc])) {
+					if((exit_status = temporarily_sustain_arpeg_note(cc,thisamp,dz))<0)
+						return(exit_status);
+				} else {
+					if((exit_status = initiate_new_arpeg_note(cc,vc,dz))<0)
+						return(exit_status);
+				}
+			} else {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					if((exit_status = nonlin_sustain_arpeg_note(cc,vc,dz))<0)
+						return(exit_status);
+				} else
+					dz->amp[cc] = 0.0f;
+			}
+	    }
+		break;
+	case(AP_NONLIN_AND_SUSTAIN_PITCH_AND_LIMIT_SUSTAIN):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					if((exit_status = get_non_linear_decimation(&nonlin_dec,cc,dz))<0)
+						return(exit_status);
+				}
+				if(dz->iparray[ARPE_KEEP][cc] && ((thisamp = dz->windowbuf[0][AMPP] * nonlin_dec) > dz->amp[cc])) {
+					if((exit_status = temporarily_sustain_arpeg_note_with_fixed_pitch(cc,vc,thisamp,dz))<0)
+						return(exit_status);
+				} else {
+					if((exit_status = initiate_new_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+						return(exit_status);
+				}
+			} else {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					if((exit_status = nonlin_sustain_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+						return(exit_status);
+				} else
+					dz->amp[cc] = 0.0f;
+			}
+	    }
+		break;
+	}
+	return(FINISHED);
+}
+
+
+/******************************* DO_BELOW **************************/
+
+int do_below(double bandmid,dataptr dz)
+{	
+	int cc;
+	for(cc=0;cc<dz->clength;cc++) {
+		if(dz->freq[cc]>bandmid)
+			dz->amp[cc] = 0.0f;
+//TW JULY 2006
+		else
+			dz->amp[cc] = (float)(dz->amp[cc] * dz->param[ARPE_AMPL]);
+	}
+	return(FINISHED);
+}
+
+/******************************** DO_ABOVE ***********************/
+
+int do_above(double bandmid,dataptr dz)
+{
+	int cc;
+	for(cc=0;cc<dz->clength;cc++) {
+		if(dz->freq[cc]<bandmid)
+			dz->amp[cc] = 0.0f;
+//TW JULY 2006
+		else
+			dz->amp[cc] = (float)(dz->amp[cc] * dz->param[ARPE_AMPL]);
+	}
+	return(FINISHED);
+}
+
+/**************************** DO_BOOST ****************************/
+
+int do_boost(double bandhilimit,double bandlolimit,dataptr dz)
+{
+	int exit_status;
+	int cc, vc;
+	double dec, nonlin_dec = 0.0,thisamp;
+	switch(dz->iparam[ARPE_SUSFLAG]) {
+	case(AP_NORMAL):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->iparray[ARPE_KEEP][cc]) {
+				if((exit_status = sustain_arpeg_note(cc,vc,dz))<0)
+					return(exit_status);
+			} else if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if((exit_status = initiate_new_arpeg_note(cc,vc,dz))<0)
+					return(exit_status);
+			}
+	    }
+		break;
+	case(AP_SUSTAIN_PITCH):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->iparray[ARPE_KEEP][cc]) {
+				if((exit_status = sustain_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+					return(exit_status);
+			} else if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if((exit_status = initiate_new_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+					return(exit_status);
+			}
+	    }
+		break;
+	case(AP_LIMIT_SUSTAIN):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if((exit_status = get_decimation(&dec,cc,dz))<0)
+					return(exit_status);
+				if(dz->iparray[ARPE_KEEP][cc] && ((thisamp = dz->windowbuf[0][AMPP] * dec) > dz->amp[cc])) {
+					if((exit_status = temporarily_sustain_arpeg_note(cc,thisamp,dz))<0)
+						return(exit_status);
+				} else {
+					if((exit_status = initiate_new_arpeg_note(cc,vc,dz))<0)
+						return(exit_status);
+				}
+			} else {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					 if((exit_status = sustain_arpeg_note(cc,vc,dz))<0)
+						return(exit_status);
+				}
+			}
+	    }
+		break;
+	case(AP_SUSTAIN_PITCH_AND_LIMIT_SUSTAIN):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if((exit_status = get_decimation(&dec,cc,dz))<0)
+					return(exit_status);
+				if(dz->iparray[ARPE_KEEP][cc] && ((thisamp = dz->windowbuf[0][AMPP] * dec) > dz->amp[cc])) {
+					if((exit_status = temporarily_sustain_arpeg_note_with_fixed_pitch(cc,vc,thisamp,dz))<0)
+						return(exit_status);
+				} else {
+					if((exit_status = initiate_new_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+						return(exit_status);
+				}
+			} else {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					if((exit_status = sustain_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+						return(exit_status);
+				}
+			}
+	    }
+		break;
+	case(AP_NONLIN):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if((exit_status = get_non_linear_decimation(&nonlin_dec,cc,dz))<0)
+				return(exit_status);
+			if(dz->iparray[ARPE_KEEP][cc]) {
+				dz->amp[cc] = (float)(dz->windowbuf[0][AMPP] * nonlin_dec);
+				dz->iparray[ARPE_KEEP][cc]--;
+			} else if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if((exit_status = initiate_new_arpeg_note(cc,vc,dz))<0)
+					return(exit_status);
+			}
+	    }
+		break;
+	case(AP_NONLIN_AND_SUSTAIN_PITCH):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->iparray[ARPE_KEEP][cc]) {
+				if((exit_status = nonlin_sustain_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+					return(exit_status);
+			} else if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if((exit_status = initiate_new_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+					return(exit_status);
+			}
+	    }
+		break;
+	case(AP_NONLIN_AND_LIMIT_SUSTAIN):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					if((exit_status = get_non_linear_decimation(&nonlin_dec,cc,dz))<0)
+						return(exit_status);
+				}
+				if(dz->iparray[ARPE_KEEP][cc] && ((thisamp = dz->windowbuf[0][AMPP] * nonlin_dec) > dz->amp[cc])) {
+					if((exit_status = temporarily_sustain_arpeg_note(cc,thisamp,dz))<0)
+						return(exit_status);
+				} else {
+					if((exit_status = initiate_new_arpeg_note(cc,vc,dz))<0)
+						return(exit_status);
+				}
+			} else {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					 if((exit_status = nonlin_sustain_arpeg_note(cc,vc,dz))<0)
+					 	return(exit_status);
+				}
+			}
+	    }
+		break;
+	case(AP_NONLIN_AND_SUSTAIN_PITCH_AND_LIMIT_SUSTAIN):
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->freq[cc]>=bandlolimit && dz->freq[cc]<=bandhilimit) {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					if((exit_status = get_non_linear_decimation(&nonlin_dec,cc,dz))<0)
+						return(exit_status);
+				}
+				if(dz->iparray[ARPE_KEEP][cc] && ((thisamp = dz->windowbuf[0][AMPP] * nonlin_dec) > dz->amp[cc])) {
+					if((exit_status = temporarily_sustain_arpeg_note_with_fixed_pitch(cc,vc,thisamp,dz))<0)
+						return(exit_status);
+				} else {
+					if((exit_status = initiate_new_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+						return(exit_status);
+				}
+			} else {
+				if(dz->iparray[ARPE_KEEP][cc]) {
+					if((exit_status = nonlin_sustain_arpeg_note_with_fixed_pitch(cc,vc,dz))<0)
+						return(exit_status);
+				}
+			}
+	    }
+		break;
+	}
+	return(FINISHED);
+}
+
+/************************* DO_ABOVE_BOOST ****************************/
+
+int do_above_boost(double bandhilimit,double bandlolimit,int *in_start_portion, dataptr dz)
+{
+	int cc;   
+	if(*in_start_portion) {
+		if((dz->iparam[ARPE_WTYPE]==SIN || dz->iparam[ARPE_WTYPE]==SAW)) {
+			if(dz->param[ARPE_WAVETABPOS]>=ARPE_TABSIZE/2)
+				*in_start_portion = FALSE;
+		} else {
+			if(dz->param[ARPE_WAVETABPOS] < dz->param[ARPE_LAST_TABPOS])
+			*in_start_portion = FALSE;
+		}
+	}
+	if(*in_start_portion) {
+		for(cc=0;cc<dz->clength;cc++) {
+			if(dz->freq[cc]>bandlolimit)
+				dz->amp[cc] = 0.0f;
+//TW JULY 2006
+			else
+				dz->amp[cc] = (float)(dz->amp[cc] * dz->param[ARPE_AMPL] * dz->iparam[ARPE_SUST]);
+		}
+	} else
+		return do_boost(bandhilimit,bandlolimit,dz);
+	return(FINISHED);
+}
+
+/**************************** DO_BELOW_BOOST ************************/
+
+int do_below_boost(double bandhilimit,double bandlolimit,int *in_start_portion,dataptr dz)
+{
+	int cc;
+	if(*in_start_portion) {
+		if(dz->param[ARPE_WAVETABPOS] < dz->param[ARPE_LAST_TABPOS])
+			*in_start_portion = FALSE;
+	}
+	if(*in_start_portion) {
+		for(cc=0;cc<dz->clength;cc++) {
+			if(dz->freq[cc]<bandhilimit)
+				dz->amp[cc] = 0.0f;
+//TW JULY 2006
+			else
+				dz->amp[cc] = (float)(dz->amp[cc] * dz->param[ARPE_AMPL] * dz->iparam[ARPE_SUST]);
+		}
+	} else
+		return do_boost(bandhilimit,bandlolimit,dz);
+	return(FINISHED);
+}
+
+/************************** DO_ONCE_BELOW ***************************/
+
+int do_once_below(double bandlolimit,int *in_start_portion,dataptr dz)
+{
+	int cc;
+	if(*in_start_portion) {
+		if((dz->iparam[ARPE_WTYPE]==SIN || dz->iparam[ARPE_WTYPE]==SAW)) {
+			if(dz->param[ARPE_WAVETABPOS] >= ARPE_TABSIZE/2)
+				*in_start_portion = FALSE;
+		} else {
+			if(dz->param[ARPE_WAVETABPOS] < dz->param[ARPE_LAST_TABPOS])
+			*in_start_portion = FALSE;
+		}
+	}
+	if(*in_start_portion) {
+		for(cc=0;cc<dz->clength;cc++) {
+			if(dz->freq[cc]>bandlolimit)
+				dz->amp[cc] = 0.0f;
+//TW JULY 2006
+			else
+				dz->amp[cc] = (float)(dz->amp[cc] * dz->param[ARPE_AMPL]);
+		}
+	}
+	return(FINISHED);
+}
+
+/***************************** DO_ONCE_ABOVE **************************/
+
+int do_once_above(double bandhilimit,int *in_start_portion,dataptr dz)
+{
+	int cc;
+	if(*in_start_portion) {
+		if(dz->param[ARPE_WAVETABPOS] < dz->param[ARPE_LAST_TABPOS])
+			*in_start_portion = FALSE;
+	}
+	if(*in_start_portion) {
+		for(cc=0;cc<dz->clength;cc++) {
+			if(dz->freq[cc]<bandhilimit)
+				dz->amp[cc] = 0.0f;
+//TW JULY 2006
+			else
+				dz->amp[cc] = (float)(dz->amp[cc] * dz->param[ARPE_AMPL]);
+		}
+	}
+	return(FINISHED);
+}
+
+/******************** INITIATE_NEW_ARPEG_NOTE ********************/
+
+int initiate_new_arpeg_note(int cc,int vc,dataptr dz)
+{
+	dz->iparray[ARPE_KEEP][cc] = dz->iparam[ARPE_SUST];
+	dz->amp[cc] *= (float)(dz->param[ARPE_AMPL] * dz->iparray[ARPE_KEEP][cc]);
+	dz->windowbuf[0][AMPP] = dz->amp[cc];
+	(dz->iparray[ARPE_KEEP][cc])--;
+	return(FINISHED);
+}
+
+/******************** INITIATE_NEW_ARPEG_NOTE_WITH_FIXED_PITCH ********************/
+
+int initiate_new_arpeg_note_with_fixed_pitch(int cc,int vc,dataptr dz)
+{
+	dz->iparray[ARPE_KEEP][cc] = dz->iparam[ARPE_SUST];
+	dz->amp[cc] *= (float)(dz->param[ARPE_AMPL] * dz->iparray[ARPE_KEEP][cc]);
+	dz->windowbuf[0][AMPP] = dz->amp[cc];
+	dz->windowbuf[0][FREQ] = dz->freq[cc];
+	dz->iparray[ARPE_KEEP][cc]--;
+	return(FINISHED);
+}
+
+/******************** TEMPORARILY_SUSTAIN_ARPEG_NOTE ********************/
+
+int temporarily_sustain_arpeg_note(int cc,double thisamp,dataptr dz)
+{
+	dz->amp[cc] = (float)thisamp;
+	dz->iparray[ARPE_KEEP][cc]--;
+	return(FINISHED);
+}
+
+
+/******************** TEMPORARILY_SUSTAIN_ARPEG_NOTE_WITH_FIXED_PITCH ********************/
+
+int temporarily_sustain_arpeg_note_with_fixed_pitch(int cc,int vc,double thisamp,dataptr dz)
+{
+	dz->amp[cc]  = (float)thisamp;
+	dz->freq[cc] = dz->windowbuf[0][FREQ];
+	dz->iparray[ARPE_KEEP][cc]--;
+	return(FINISHED);
+}
+
+/******************** GET_NON_LINEAR_DECIMATION ********************/
+
+int get_non_linear_decimation(double *nonlin_dec,int cc,dataptr dz)
+{
+	*nonlin_dec = (double)dz->iparray[ARPE_KEEP][cc]/(double)dz->iparam[ARPE_SUST];
+	*nonlin_dec = pow(*nonlin_dec,dz->param[ARPE_NONLIN]);
+	return(FINISHED);
+}
+
+/******************** GET_DECIMATION ********************/
+
+int get_decimation(double *dec,int cc,dataptr dz)
+{
+	*dec = (double)dz->iparray[ARPE_KEEP][cc]/(double)dz->iparam[ARPE_SUST];
+	return(FINISHED);
+}
+
+/******************** SUSTAIN_ARPEG_NOTE ********************/
+
+int sustain_arpeg_note(int cc,int vc,dataptr dz)
+{
+	double z = (double)dz->iparray[ARPE_KEEP][cc]/(double)dz->iparam[ARPE_SUST];
+	dz->amp[cc] = (float)(dz->windowbuf[0][AMPP] * z);
+	dz->iparray[ARPE_KEEP][cc]--;
+	return(FINISHED);
+}
+
+/******************** SUSTAIN_ARPEG_NOTE_WITH_FIXED_PITCH ********************/
+
+int sustain_arpeg_note_with_fixed_pitch(int cc,int vc,dataptr dz)
+{
+	double z = (double)dz->iparray[ARPE_KEEP][cc]/(double)dz->iparam[ARPE_SUST];
+	dz->amp[cc] = (float)(dz->windowbuf[0][AMPP] * z);
+	dz->freq[cc] = dz->windowbuf[0][FREQ];
+	dz->iparray[ARPE_KEEP][cc]--;
+	return(FINISHED);
+}
+
+/******************** NONLIN_SUSTAIN_ARPEG_NOTE ********************/
+
+int nonlin_sustain_arpeg_note(int cc,int vc, dataptr dz)
+{
+	double z = (double)dz->iparray[ARPE_KEEP][cc]/(double)dz->iparam[ARPE_SUST];
+	z = pow(z,dz->param[ARPE_NONLIN]);
+	dz->amp[cc] = (float)(dz->windowbuf[0][AMPP] * z);
+	dz->iparray[ARPE_KEEP][cc]--;
+	return(FINISHED);
+}
+
+/******************** NONLIN_SUSTAIN_ARPEG_NOTE_WITH_FIXED_PITCH ********************/
+
+int nonlin_sustain_arpeg_note_with_fixed_pitch(int cc, int vc, dataptr dz)
+{
+	double z = (double)dz->iparray[ARPE_KEEP][cc]/(double)dz->iparam[ARPE_SUST];
+	z = pow(z,dz->param[ARPE_NONLIN]);
+	dz->amp[cc]  = (float)(dz->windowbuf[0][AMPP] * z);
+	dz->freq[cc] = dz->windowbuf[0][FREQ];
+	dz->iparray[ARPE_KEEP][cc]--;
+	return(FINISHED);
+}
+
+/****************************** SPECPLUCK ****************************/
+
+int specpluck(dataptr dz)
+{
+	int exit_status;
+	int mask = 1;
+	int cc, vc, bflagno, is_set;
+	if(dz->total_windows==1) {		/* Set up BITFLAGS for current state of chans */
+		for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2){
+			if((exit_status = choose_bflagno_and_reset_mask_if_ness
+			(&bflagno,cc,&mask,dz->iparam[PLUK_LONGPOW2],dz->iparam[PLUK_DIVMASK]))<0)
+				return(exit_status);
+			if(!flteq((double)dz->flbufptr[0][AMPP],0.0))
+				dz->lparray[PLUK_BFLG][bflagno] |= mask;
+			mask <<= 1;		    
+		}
+	} else {		 			/* Check change of state of channels */
+		for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2){
+			if((exit_status = choose_bflagno_and_reset_mask_if_ness
+			(&bflagno,cc,&mask,dz->iparam[PLUK_LONGPOW2],dz->iparam[PLUK_DIVMASK]))<0)
+				return(exit_status);
+			is_set = dz->lparray[PLUK_BFLG][bflagno] & mask;
+			if(!flteq((double)dz->flbufptr[0][vc],0.0)) { 	/* If chan amp NOT zero */
+				if(!is_set) { 						/* if bit previously 0 (for zero amp) */
+					dz->flbufptr[0][vc] = (float)(dz->flbufptr[0][vc] * dz->param[PLUK_GAIN]);
+					exit_status = set_bit_to_one(bflagno,mask,dz);	   /* Give boost to chan amp */
+				}
+			} else {	 		     				/* channel amp IS zero */
+				if(is_set)							/* if bit previously 1 for nonzero amp */
+					exit_status = set_bit_to_zero(bflagno,mask,dz);
+			}
+			mask <<= 1;			    				/* move bitmask upwards */
+		}
+	}		
+	return(FINISHED);
+}
+
+/****************************** SET_BIT_TO_ZERO ****************************/
+
+int set_bit_to_zero(int bflagno,int mask,dataptr dz)
+{
+	mask = ~mask;		 					  /* bit-invert mask */
+	dz->lparray[PLUK_BFLG][bflagno] &= mask;  /* Set bit to 0 */
+	return(FINISHED);
+}
+
+
+/****************************** SET_BIT_TO_ONE ****************************/
+
+int set_bit_to_one(int bflagno,int mask,dataptr dz)
+{
+	dz->lparray[PLUK_BFLG][bflagno] |= mask;  
+	return(FINISHED);
+}
+
+/********************************** SPECTRACE **********************************/
+
+int spectrace(dataptr dz)
+{
+	int exit_status;
+	int invtrindex, cc, vc;
+	int    chans_outside_fltband_to_keep = 0, chans_in_filtband;
+	double	hifrq_limit = 0.0, lofrq_limit = 0.0;
+	chvptr quietest, loudest;
+	if((dz->mode == TRC_ALL || dz->vflag[TRACE_RETAIN]) && dz->iparam[TRAC_INDX] >= dz->clength)
+		return(FINISHED);
+	if(dz->mode != TRC_ALL) {
+		hifrq_limit = dz->param[TRAC_HIFRQ];
+		lofrq_limit = dz->param[TRAC_LOFRQ];
+		if(hifrq_limit < lofrq_limit)
+			swap(&hifrq_limit,&lofrq_limit);
+		if(dz->vflag[TRACE_RETAIN] ) {
+			chans_in_filtband = dz->clength;
+			for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+				if(dz->flbufptr[0][FREQ] < lofrq_limit || dz->flbufptr[0][FREQ] > hifrq_limit)
+					chans_in_filtband--;
+			}
+			if((chans_outside_fltband_to_keep = dz->iparam[TRAC_INDX] - chans_in_filtband) <= 0) {
+				chans_outside_fltband_to_keep = 0;
+				for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+					if(dz->flbufptr[0][FREQ] < lofrq_limit || dz->flbufptr[0][FREQ] > hifrq_limit)
+						dz->flbufptr[0][AMPP] = 0.0f;
+				}
+			}
+		} else {
+			for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+				if(dz->flbufptr[0][FREQ] < lofrq_limit || dz->flbufptr[0][FREQ] > hifrq_limit)
+					dz->flbufptr[0][AMPP] = 0.0f;
+			}
+		}
+	}
+	if(chans_outside_fltband_to_keep>0) {
+		if((exit_status = initialise_ring_vals(chans_outside_fltband_to_keep,-BIGAMP,dz))<0)
+			return(exit_status);
+		for(vc = 0; vc < dz->wanted; vc += 2) {
+			if(dz->flbufptr[0][FREQ] < lofrq_limit || dz->flbufptr[0][FREQ] > hifrq_limit) {
+				if((exit_status = if_one_of_loudest_chans_store_in_ring(vc,dz))<0)
+					return(exit_status);
+				dz->flbufptr[0][AMPP]  = 0.0F;
+			}
+		}
+     /* RESTORE TRUE AMPLITUDE (STORED IN RING) IN LOUDEST OUTSIDER CHANNELS ONLY */
+		loudest = dz->ringhead;		
+		do {
+			dz->flbufptr[0][loudest->loc] = loudest->val;
+		} while((loudest = loudest->next)!=dz->ringhead);
+	} else {
+		if(dz->iparam[TRAC_INDX]>(dz->clength/2)) { 						/* IF MORE CHANS TO KEEP THAN TO REJECT */
+			invtrindex = dz->clength - dz->iparam[TRAC_INDX];   			/* COUNT CHANS TO REJECT */
+			if((exit_status = initialise_ring_vals(invtrindex,BIGAMP,dz))<0)/* MAXIMISE ALL QUIETEST STORES IN RING */
+				return(exit_status);
+			for(vc = 0; vc < dz->wanted; vc += 2) {							/* STORE INDICES OF QUIETEST CHANS */
+				if((exit_status = if_one_of_quietest_chans_store_in_ring(vc,dz))<0)
+					return(exit_status);
+			}
+			quietest = dz->ringhead;		
+			do {								  							/* ZERO ALL QUIETEST CHANS */
+				dz->flbufptr[0][quietest->loc] = 0.0F;
+			} while((quietest = quietest->next)!=dz->ringhead);
+		} else {															/* IF MORE CHANS TO REJECT THAN TO KEEP */
+			if((exit_status = initialise_ring_vals(dz->iparam[TRAC_INDX],-BIGAMP,dz))<0)
+				return(exit_status);										/* MINIMISE ALL LOUDEST STORES IN RING */
+			for(vc = 0; vc < dz->wanted; vc += 2) {
+				if((exit_status = if_one_of_loudest_chans_store_in_ring(vc,dz))<0)
+					return(exit_status);									/* STORE INDICES OF LOUDEST CHANS */
+				dz->flbufptr[0][AMPP]  = 0.0F;  							/* INITIALISE EVERY CHANNEL TO ZERO AMP	 */
+			}
+			loudest = dz->ringhead;	 			
+			do {															/* RESTORE AMPLITUDE IN LOUDEST CHANS ONLY */
+				dz->flbufptr[0][loudest->loc] = loudest->val;
+			} while((loudest = loudest->next)!=dz->ringhead);
+		}
+	}
+	return(FINISHED);
+}
+
+/**************************** OUTSIDE_SKIRTS ***************************/
+
+int outside_skirts(int vc,double loskirt,double hiskirt,dataptr dz)
+{
+	if(dz->flbufptr[0][FREQ] < loskirt || dz->flbufptr[0][FREQ] > hiskirt)
+		return(TRUE);
+	return(FALSE);
+}
+
+/***************************** RESET_TIMECHANGING_ARPE_VARIABLES **************************/
+
+int reset_timechanging_arpe_variables(double *frqrange,double *lofrq, double *hifrq,dataptr dz)
+{
+	double this_arpfrq;
+
+	if(dz->brksize[ARPE_ARPFRQ]) {				  /* RESET ARPFREQ, if ness */
+		this_arpfrq = (dz->param[ARPE_LASTARPFRQ] + dz->param[ARPE_ARPFRQ])/2.0;
+		dz->param[ARPE_LASTARPFRQ] = dz->param[ARPE_ARPFRQ];
+		dz->param[ARPE_ARPFRQ] = this_arpfrq;
+	}
+												  /* RESET arp amplification, if ness */
+//TW JULY 2006
+	if(dz->mode < BELOW) {
+		if(dz->brksize[ARPE_AMPL] || dz->brksize[ARPE_SUST])
+			dz->param[ARPE_AMPL]  /= (double)dz->iparam[ARPE_SUST];
+	}
+
+	*lofrq = dz->param[ARPE_LOFRQ];				  /* RESET arp hi and lo limits */
+	*hifrq = dz->param[ARPE_HIFRQ];
+	if((dz->brksize[ARPE_LOFRQ] || dz->brksize[ARPE_HIFRQ])
+	&& (*hifrq < *lofrq))
+		swap(hifrq,lofrq);
+	*frqrange = *hifrq - *lofrq;
+
+	return(FINISHED);
+}											    	
+
+/******************** LOCATE_CURRENT_WAVETABLE_POSITION ********************/
+
+int locate_current_wavetable_position(dataptr dz)
+{											    	
+	double tabincr;
+	tabincr 					= dz->frametime * dz->param[ARPE_ARPFRQ] * ARPE_TABSIZE;
+	dz->param[ARPE_LAST_TABPOS] = dz->param[ARPE_WAVETABPOS];
+	dz->param[ARPE_WAVETABPOS]  = fmod(dz->param[ARPE_WAVETABPOS] + tabincr,(double)ARPE_TABSIZE);
+	return(FINISHED);
+}
+
+//TW UPDATE: NEW FUNCTIONS (adjusted for float)
+/************************************ VOWEL_FILTER ************************************/
+
+#define NOISEBASE	(0.2)
+
+int vowel_filter(dataptr dz)
+{
+	int *vowels = dz->iparray[0];
+	double *times = dz->parray[0];
+	double startformant1, startformant2, startformant3, endformant1, endformant2, endformant3;
+	double formant1, formant2, formant3;
+	double form1step, form2step, form3step;
+	double starttime, endtime, time, timefrac, timestep, *sensitivity;
+	double f3startatten, f3endatten, f3attenstep, f3atten;
+	double f2startatten, f2endatten, f2attenstep, f2atten;
+	int exit_status, senslen;
+	int n = 0, t = 0;
+	double *amp;
+	int total_windows_got, windows_in_buf;
+
+	if((amp = (double *)malloc(dz->clength * sizeof(double)))==NULL) {
+		sprintf(errstr,"Insufficient memory to store vowel envelope\n");
+		return(MEMORY_ERROR);
+	}
+	if((exit_status = define_sensitivity_curve(&sensitivity,&senslen))<0)
+		return(exit_status);
+
+	dz->flbufptr[0] = dz->bigfbuf;
+	if((exit_status = get_formant_frqs
+	(vowels[t],&startformant1,&startformant2,&startformant3,&f2startatten,&f3startatten))<0)
+		return(exit_status);
+	starttime = times[t++];
+	if((exit_status = get_formant_frqs(vowels[t],&endformant1,&endformant2,&endformant3,&f2endatten,&f3endatten))<0)
+		return(exit_status);
+	endtime = times[t++];
+	form1step = endformant1 - startformant1;
+	form2step = endformant2 - startformant2;
+	form3step = endformant3 - startformant3;
+	f2attenstep = f2endatten - f2startatten; 
+	f3attenstep = f3endatten - f3startatten; 
+	timestep  = endtime-starttime;
+	formant1 = startformant1;	/* works if only one vowel is entered (for time zero) */
+	formant2 = startformant2;
+	formant3 = startformant3;
+	f2atten  = f2startatten;
+	f3atten  = f3startatten;
+
+	total_windows_got = 0;
+
+	while(n < dz->wlength) {
+		if(n >= total_windows_got) {
+			if((exit_status = read_samps(dz->bigfbuf, dz)) < 0) {
+				sprintf(errstr,"Problem reading source analysis data.\n");
+				return(SYSTEM_ERROR);
+			}
+			dz->flbufptr[0] = dz->bigfbuf;
+			windows_in_buf = dz->ssampsread/dz->wanted;
+			total_windows_got += windows_in_buf;
+		}
+		if(dz->itemcnt) {
+			time = n * dz->frametime;
+			while(time >= endtime) {	  	/* advance along vowels */
+				startformant1 = endformant1;
+				startformant2 = endformant2;
+				startformant3 = endformant3;
+				f2startatten  = f2endatten;
+				f3startatten  = f3endatten;
+				starttime = endtime;
+				if(t < dz->itemcnt) {
+					if((exit_status = get_formant_frqs(vowels[t],&endformant1,&endformant2,&endformant3,&f2endatten,&f3endatten))<0)
+						return(exit_status);
+					endtime = times[t++];
+				} else
+					break;
+				form1step = endformant1 - startformant1;
+				form2step = endformant2 - startformant2;
+				form3step = endformant3 - startformant3;
+				f2attenstep = f2endatten - f2startatten; 
+				f3attenstep = f3endatten - f3startatten; 
+				timestep  = endtime-starttime;
+			}
+			if(!flteq(starttime,endtime)) {			   		/* interpolate between vowels : or retain last vowel */
+				timefrac = (time - starttime)/timestep;
+				formant1 = startformant1 + (form1step * timefrac);
+				formant2 = startformant2 + (form2step * timefrac);
+				formant3 = startformant3 + (form3step * timefrac);
+				f2atten  = f2startatten  + (f2attenstep * timefrac);
+				f3atten  = f3startatten  + (f3attenstep * timefrac);
+			}
+		}
+		if((exit_status = do_vowel_filter
+		(amp,formant1,formant2,formant3,f2atten,f3atten,sensitivity,senslen,dz)) <0)
+			return(exit_status);
+
+		if((dz->flbufptr[0] += dz->wanted) >= dz->flbufptr[1]) {
+			if((exit_status = write_samps(dz->bigfbuf,dz->buflen,dz))<0)
+				return(exit_status);
+			dz->flbufptr[0] = dz->bigfbuf;
+		}
+		n++;
+	}
+	if(dz->flbufptr[0] != dz->bigfbuf) {
+		if((exit_status = write_samps(dz->bigfbuf,dz->flbufptr[0] - dz->bigfbuf,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+		
+/************************************ DO_VOWEL_FILTER ************************************
+ *
+ * "sensitivity" compensates for frq sensitivity of ear at low end, and attenuates
+ * formant bands above c3500.
+ */
+
+int do_vowel_filter(double *vamp,double formant1,double formant2,double formant3,double f2atten,double f3atten,
+							double *sensitivity,int senslen,dataptr dz)
+
+{
+	double hfwidth1, hfwidth2, hfwidth3 = 0.0, lolim1, lolim2, lolim3 = 0.0, hilim1, hilim2, hilim3 = 0.0;
+//	double thisfrq, amp, amp2, amp3 = 0.0, totamp = 0.0;
+	double thisfrq, amp, amp2 = 0.0, amp3 = 0.0;
+	int exit_status, cc, vc;
+	int overlapped_formants12 = 0, overlapped_formants23 = 0, overlapped_formants13 = 0;
+	int is_overlap12, is_overlap23, is_overlap13;
+	double toplim, pre_totamp, post_totamp, maxamp, maxvamp, ampscale;
+	int is_third_formant = 0;
+	double signal_base = 1.0 - dz->param[PV_PKRANG];
+
+	if(formant3 > 0.0)
+		is_third_formant = 1;
+	hfwidth1 = formant1 * dz->param[PV_HWIDTH];	/* set limits of formant bands */
+	lolim1  = formant1 - hfwidth1;
+	hilim1  = formant1 + hfwidth1;
+	hfwidth2 = formant2 * dz->param[PV_HWIDTH];
+	lolim2  = formant2 - hfwidth2;
+	hilim2  = formant2 + hfwidth2;
+	if(is_third_formant) {
+		hfwidth3 = formant3 * dz->param[PV_HWIDTH];
+		lolim3  = formant3 - hfwidth3;
+		hilim3  = formant3 + hfwidth3;
+	}
+
+ 	if(hilim1 > lolim2)		/* deal with overlapping formants */
+		overlapped_formants12 = 1;
+	if(is_third_formant) {
+		if(hilim2 > lolim3)
+			overlapped_formants23 = 1;
+		if(hilim1 > lolim3)
+			overlapped_formants13 = 1;
+	}
+	if(is_third_formant)
+		toplim =  hilim3;
+	else
+		toplim =  hilim2;
+	maxamp = 0.0;
+	pre_totamp = 0.0;
+	for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2) {
+		pre_totamp += dz->flbufptr[0][AMPP];
+		maxamp = max(dz->flbufptr[0][AMPP],maxamp);		
+	}
+	maxvamp = 0.0;
+	/* find the formant envelope amplitude at frequency of every window */
+	if(!is_third_formant)
+		hilim3 = hilim2;
+	for(cc = 0, vc = 0;cc <dz->clength; cc++, vc += 2) {
+		thisfrq = dz->flbufptr[0][FREQ];
+		amp = 0.0;
+		is_overlap12 = 0;
+		is_overlap23 = 0;
+		is_overlap13 = 0;
+		if(thisfrq < lolim1 || thisfrq > hilim3)
+			;
+		else if((thisfrq > lolim1) && (thisfrq < hilim1)) {
+ 			if(overlapped_formants12 && (thisfrq > lolim2)) {
+				is_overlap12 = 1;
+				if(thisfrq >= formant2)
+					amp2 = (hilim2 - thisfrq)/hfwidth2;
+				else
+					amp2 = (thisfrq - lolim2)/hfwidth2;
+				amp2 *= f2atten;
+			}
+			if(is_third_formant) {
+				if(overlapped_formants13 && (thisfrq > lolim3)) {
+					is_overlap13 = 1;
+					if(thisfrq >= formant3)
+						amp3 = (hilim3 - thisfrq)/hfwidth3;
+					else
+						amp3 = (thisfrq - lolim3)/hfwidth3;
+					amp3 *= f3atten;
+				}
+			}
+			if(thisfrq >= formant1)
+				amp = (hilim1 - thisfrq)/hfwidth1;
+			else
+				amp = (thisfrq - lolim1)/hfwidth1;
+			if(is_overlap12)
+				amp = max(amp,amp2);
+			if(is_third_formant && is_overlap13)
+				amp = max(amp,amp3);
+		} else if((thisfrq > lolim2) && (thisfrq < hilim2)) {
+			if(is_third_formant && overlapped_formants23 && (thisfrq > lolim3)) {
+				is_overlap23 = 1;
+				if(thisfrq >= formant3)
+					amp3 = (hilim3 - thisfrq)/hfwidth3;
+				else
+					amp3 = (thisfrq - lolim3)/hfwidth3;
+				amp3 *= f3atten;
+			}
+			if(thisfrq >= formant2)
+				amp = (hilim2 - thisfrq)/hfwidth2;
+			else
+				amp = (thisfrq - lolim2)/hfwidth2;
+			amp *= f2atten;
+
+			if(is_third_formant && is_overlap23)
+				amp = max(amp,amp3);
+		} else if(is_third_formant && (thisfrq > lolim3)) {
+			if(thisfrq >= formant3)
+				amp = (hilim3 - thisfrq)/hfwidth3;
+			else
+				amp = (thisfrq - lolim3)/hfwidth3;
+			amp *= f3atten;
+		}
+		amp = pow(amp,dz->param[PV_CURVIT]);
+		amp *= dz->param[PV_PKRANG];
+		amp += signal_base;
+		if((exit_status = adjust_for_sensitivity(&amp,(double)thisfrq,sensitivity,senslen))<0)
+			return(exit_status);
+		vamp[cc] = amp;
+		maxvamp = max(maxvamp,vamp[cc]);
+	}
+	/* set scaling factor to allow for max level of input window */
+	if(flteq(maxvamp,0.0))
+		ampscale = 0.0;
+	else
+		ampscale = (maxamp/maxvamp);
+	post_totamp = 0.0;
+	for(cc = 0,vc = 0;cc <dz->clength; cc++,vc += 2) {
+		vamp[cc] *= ampscale;
+/* force window to formant level ONLY if existing val > a given proportion of formant level */
+		if((double)dz->flbufptr[0][AMPP] > vamp[cc] * dz->param[VF_THRESH])
+			dz->flbufptr[0][AMPP] =  (float)vamp[cc];
+		post_totamp += dz->flbufptr[0][AMPP];
+	}
+/* normalise to overall level of original window */
+	if((exit_status = normalise(pre_totamp,post_totamp,dz))<0)
+		return(exit_status);
+	return(FINISHED);
+}
+
+/************************************ DEFINE_SENSITIVITY_CURVE ************************************
+ *
+ * approximate compensation for aural sensitivity 
+ */
+
+#define	LOFRQ_BOOST		(2.511)		/* 8dB  */
+#define	HIFRQ_LOSS		(0.4)		/* -8dB */
+
+#define	LOFRQ_FOOT		(250.0)
+#define	MIDFRQSHELF_BOT	(2000.0)
+#define	MIDFRQSHELF_TOP	(3000.0)
+#define	HIFRQ_FOOT		(4000.0)
+#define	TOP_OF_SPECTRUM	(96000.0)	/* double maximum nyquist (i.e. >nyquist: for safety margin)  */
+
+int define_sensitivity_curve(double **sensitivity,int *senslen)
+{
+	int arraysize = BIGARRAY;
+	double *p;
+	int n = 0;
+	if((*sensitivity = (double *)malloc(arraysize * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for time data.\n");
+		return(MEMORY_ERROR);
+	}
+	p = *sensitivity;
+	*p++ = 0.0;				*p++ = 1.0;						n+= 2;	/* everything must be in 0-1 range */
+	*p++ = LOFRQ_FOOT;		*p++ = 1.0;						n+= 2;	/* for pow() calculations to work, later */
+	*p++ = MIDFRQSHELF_BOT;	*p++ = 1.0/LOFRQ_BOOST;			n+= 2;
+	*p++ = MIDFRQSHELF_TOP;	*p++ = 1.0/LOFRQ_BOOST;			n+= 2;
+	*p++ = HIFRQ_FOOT;		*p++ = HIFRQ_LOSS/LOFRQ_BOOST;	n+= 2;
+	*p++ = TOP_OF_SPECTRUM;	*p++ = HIFRQ_LOSS/LOFRQ_BOOST;	n+= 2;
+
+	if((*sensitivity = (double *)realloc((char *)(*sensitivity),n * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for sensitivity curve.\n");
+		return(MEMORY_ERROR);
+	}
+	*senslen = n;
+	return(FINISHED);
+}
+
+/************************************ GET_FORMANT_FRQS ************************************/
+
+int get_formant_frqs
+(int vowel,double *formant1, double *formant2, double *formant3, double *f2atten, double *f3atten)
+{
+	switch(vowel) {
+	case(VOWEL_EE):	*formant1= EE_FORMANT1;	*formant2= EE_FORMANT2;	*formant3= EE_FORMANT3;	
+	/* heed  */								*f2atten = EE_F2ATTEN;	*f3atten = EE_F3ATTEN;
+					break;
+	case(VOWEL_I):	*formant1= I_FORMANT1;	*formant2= I_FORMANT2;	*formant3= I_FORMANT3;
+	/* hid  */								*f2atten = I_F2ATTEN;	*f3atten = I_F3ATTEN;
+					break;
+	case(VOWEL_AI):	*formant1= AI_FORMANT1;	*formant2= AI_FORMANT2;	*formant3= AI_FORMANT3;	
+	/* maid  */								*f2atten = AI_F2ATTEN;	*f3atten = AI_F3ATTEN;
+					break;
+	case(VOWEL_AII): *formant1= AII_FORMANT1;	*formant2= AII_FORMANT2;	*formant3= AII_FORMANT3;	
+	/* scottish educAted  */				*f2atten = AII_F2ATTEN;	*f3atten = AII_F3ATTEN;
+					break;
+	case(VOWEL_E):	*formant1= E_FORMANT1;	*formant2= E_FORMANT2;	*formant3= E_FORMANT3;	
+	/* head  */								*f2atten = E_F2ATTEN;	*f3atten = E_F3ATTEN;
+					break;
+	case(VOWEL_A):	*formant1= A_FORMANT1;	*formant2= A_FORMANT2;	*formant3= A_FORMANT3;	
+	/* had  */								*f2atten = A_F2ATTEN;	*f3atten = A_F3ATTEN;
+					break;
+	case(VOWEL_AR):	*formant1= AR_FORMANT1;	*formant2= AR_FORMANT2;	*formant3= AR_FORMANT3;	
+	/* hard  */								*f2atten = AR_F2ATTEN;	*f3atten = AR_F3ATTEN;
+					break;
+	case(VOWEL_O):	*formant1= O_FORMANT1;	*formant2= O_FORMANT2;	*formant3= O_FORMANT3;	
+	/* hod  */								*f2atten = O_F2ATTEN;	*f3atten = O_F3ATTEN;
+					break;
+	case(VOWEL_OR):	*formant1= OR_FORMANT1;	*formant2= OR_FORMANT2;	*formant3= OR_FORMANT3;	
+	/* hoard  */							*f2atten = OR_F2ATTEN;	*f3atten = OR_F3ATTEN;
+					break;
+	case(VOWEL_OA):	*formant1= OA_FORMANT1;	*formant2= OA_FORMANT2;	*formant3= OA_FORMANT3;	
+	/* load (North of England)  */			*f2atten = OA_F2ATTEN;	*f3atten = OA_F3ATTEN;
+					break;
+	case(VOWEL_U):	*formant1= U_FORMANT1;	*formant2= U_FORMANT2;	*formant3= U_FORMANT3;	
+	/* hood, mud (North of England)  */		*f2atten = U_F2ATTEN;	*f3atten = U_F3ATTEN;
+					break;
+	case(VOWEL_UU):	*formant1= UU_FORMANT1;	*formant2= UU_FORMANT2;	*formant3= UU_FORMANT3;	
+	/* Scottish edUcated  */				*f2atten = UU_F2ATTEN;	*f3atten = UU_F3ATTEN;
+					break;
+	case(VOWEL_UI):	*formant1= UI_FORMANT1;	*formant2= UI_FORMANT2;	*formant3= UI_FORMANT3;	
+	/* Scottish 'could'  */					*f2atten = UI_F2ATTEN;	*f3atten = UI_F3ATTEN;
+					break;
+	case(VOWEL_OO):	*formant1= OO_FORMANT1;	*formant2= OO_FORMANT2;	*formant3= OO_FORMANT3;	
+	/* mood  */								*f2atten = OO_F2ATTEN;	*f3atten = OO_F3ATTEN;
+					break;
+	case(VOWEL_XX):	*formant1= XX_FORMANT1;	*formant2= XX_FORMANT2;	*formant3= XX_FORMANT3;	
+	/* mud (South of England)  */			*f2atten = XX_F2ATTEN;	*f3atten = XX_F3ATTEN;
+					break;
+	case(VOWEL_X):	*formant1= X_FORMANT1;	*formant2= X_FORMANT2;	*formant3 = X_FORMANT3;	
+	/* the, herd  */						*f2atten = X_F2ATTEN;	*f3atten = X_F3ATTEN;
+					break;
+	case(VOWEL_N):	*formant1= N_FORMANT1;	*formant2= N_FORMANT2;	*formant3 = N_FORMANT3;	
+	/* 'n'  */								*f2atten = N_F2ATTEN;	*f3atten = N_F3ATTEN;
+					break;
+	case(VOWEL_M):	*formant1= M_FORMANT1;	*formant2= M_FORMANT2;	*formant3 = M_FORMANT3;	
+	/* 'm' */								*f2atten = M_F2ATTEN;	*f3atten = M_F3ATTEN;
+					break;
+	case(VOWEL_R):	*formant1= R_FORMANT1;	*formant2= R_FORMANT2;	*formant3 = R_FORMANT3;	
+	/* dRaws  */							*f2atten = R_F2ATTEN;	*f3atten = R_F3ATTEN;
+					break;
+	case(VOWEL_TH):	*formant1= TH_FORMANT1;	*formant2= TH_FORMANT2;	*formant3 = TH_FORMANT3;	
+	/* 'THe'  */							*f2atten = TH_F2ATTEN;	*f3atten = TH_F3ATTEN;
+					break;
+	default:
+		sprintf(errstr,"Unknown vowel\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/************************************ ADJUST_FOR_SENSITIVITY ************************************/
+
+int adjust_for_sensitivity(double *amp,double frq,double *sensitivity,int senslen)
+{
+	int n = 0;
+	double multiplier, losensfrq, hisensfrq, losens, hisens, frqfrac, sensstep;
+
+	while(frq > sensitivity[n]) {
+		n += 2;
+		if(n > senslen) {
+			sprintf(errstr,"Failed to find sensitivity value (1)\n");
+			return(PROGRAM_ERROR);
+		}
+	}
+	hisensfrq = sensitivity[n]; 
+	n -= 2;
+	if(n < 0) {
+		*amp *= sensitivity[1];
+		return(FINISHED);
+	}
+	losensfrq = sensitivity[n]; 
+	frqfrac = (frq - losensfrq)/(hisensfrq - losensfrq);
+	n++;
+	losens = sensitivity[n];
+	n += 2;
+	if(n >= senslen) {
+		sprintf(errstr,"Failed to find sensitivity value (3)\n");
+		return(PROGRAM_ERROR);
+	}
+	hisens = sensitivity[n];
+	sensstep = hisens - losens;
+
+	multiplier = losens + (sensstep * frqfrac);
+	*amp *= multiplier;
+	return(FINISHED);
+}
+

+ 245 - 0
dev/hilite/main.c

@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version TW */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <highlight.h>
+#include <filetype.h>
+#include <processno.h>
+#include <modeno.h>
+#include <formants.h>
+#include <cdpmain.h>
+#include <special.h>
+#include <logic.h>
+#include <globcon.h>
+#include <cdpmain.h>
+#include <sfsys.h>
+#include <ctype.h>
+//TW UPDATE
+#include <pnames.h>
+#include <string.h>
+
+char errstr[2400];
+
+/*extern*/ int	sloom = 0;
+/*extern*/ int	sloombatch = 0;
+/*extern*/ int anal_infiles = 1;
+/*extern*/ int is_converted_to_stereo = -1;
+const char* cdp_version = "7.1.0";
+
+/**************************************** MAIN *********************************************/
+
+int main(int argc,char *argv[])
+{
+	int exit_status;
+	dataptr dz = NULL;
+//	char *special_data_string = NULL;
+	char **cmdline;
+	int  cmdlinecnt;
+	aplptr ap;
+	int *valid = NULL;
+	int is_launched = FALSE;
+	int  validcnt;
+
+	if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
+		fprintf(stdout,"%s\n",cdp_version);
+		fflush(stdout);
+		return 0;
+	}
+						/* CHECK FOR SOUNDLOOM */
+//TW UPDATE
+	if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
+		sloom = 0;
+		sloombatch = 1;
+	}
+
+	if(!sloom) {
+		if((exit_status = allocate_and_initialise_validity_flags(&valid,&validcnt))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+	}
+
+	if(sflinit("cdp")){
+		sfperror("cdp: initialisation\n");
+		return(FAILED);
+	}
+
+						  /* SET UP THE PRINCIPLE DATASTRUCTURE */
+	if((exit_status = establish_datastructure(&dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+	if(!sloom) {
+							  /* INITIAL CHECK OF CMDLINE DATA */
+		if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+		cmdline    = argv;	/* GET PRE_DATA, ALLOCATE THE APPLICATION, CHECK FOR EXTRA INFILES */
+		cmdlinecnt = argc;
+		if((exit_status = get_process_and_mode_from_cmdline(&cmdlinecnt,&cmdline,dz))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+		if((exit_status = setup_particular_application(dz))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+		if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+	} else {
+		if((exit_status = parse_tk_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {  	/* includes setup_particular_application()      */
+	/* MARCH 1999 */
+			exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);/* and cmdlinelength check = sees extra-infiles */
+			return(exit_status);		 
+		}
+	}
+	ap = dz->application;
+
+/*********************************************************************************************************************
+	   cmdline[0]				 		  2 vals					   		  ACTIVE		 
+TK 		(infile) (more-infiles) (outfile) (flag val) (formantsqksrch) (special) params  options   variant-params  flags
+CMDLINE	(infile) (more-infiles) (outfile) (formants) (formantsqksrch) (special) params  POSSIBLY  POSSIBLY	  	POSSIBLY
+								 		  1 val
+*********************************************************************************************************************/
+
+	if((exit_status = parse_infile_and_hone_type(cmdline[0],valid,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+	if((exit_status = setup_param_ranges_and_defaults(dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+					/* OPEN FIRST INFILE AND STORE DATA, AND INFORMATION, APPROPRIATELY */
+
+	if(dz->input_data_type!=NO_FILE_AT_ALL) {
+		if((exit_status = open_first_infile(cmdline[0],dz))<0) {	
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);	
+			return(FAILED);
+		}
+//TW UPDATE
+		cmdlinecnt--;
+		cmdline++;
+	}
+	
+/*********************************************************************************************************************
+		cmdline[0]				   2 vals				   			   ACTIVE		 
+TK 		(more-infiles) (outfile) (flag val) (formantsqksrch) (special) params  options   variant-params  flags
+CMDLINE	(more-infiles) (outfile) (formants) (formantsqksrch) (special) params  POSSIBLY  POSSIBLY		  POSSIBLY
+								   1 val
+*********************************************************************************************************************/
+
+	if((exit_status = handle_extra_infiles(&cmdline,&cmdlinecnt,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);		
+		return(FAILED);
+	}
+
+/*********************************************************************************************************************
+		cmdline[0]	  2					   			    ACTIVE		 
+TK 		(outfile) (flag val) (formantsqksrch) (special) params  options   variant-params  flags
+CMDLINE	(outfile) (formants) (formantsqksrch) (special) params  POSSIBLY  POSSIBLY		   POSSIBLY
+					  1
+*********************************************************************************************************************/
+
+	if((exit_status = handle_outfile(&cmdlinecnt,&cmdline,is_launched,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+/****************************************************************************************
+		cmdline[0]	  		   			       ACTIVE		 
+TK 		(flag val) (formantsqksrch) (special) params  options   variant-params  flags
+CMDLINE	(formants) (formantsqksrch) (special) params  POSSIBLY  POSSIBLY		POSSIBLY
+*****************************************************************************************/
+
+	if((exit_status = handle_formants(&cmdlinecnt,&cmdline,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	if((exit_status = handle_formant_quiksearch(&cmdlinecnt,&cmdline,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	if((exit_status = handle_special_data(&cmdlinecnt,&cmdline,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+ 
+/****************************************************************************************
+		cmdline[0]	  		   			    
+TK 		active_params  	options   		variant-params  flags
+CMDLINE	active_params  	POSSIBLY  		POSSIBLY		POSSIBLY
+*****************************************************************************************/
+
+	if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+//TW UPDATE
+	if(dz->process == S_TRACE) {
+		if(dz->mode == TRC_ABOVE)
+			dz->param[TRAC_HIFRQ] = ap->default_val[TRAC_HIFRQ];
+		else if(dz->mode == TRC_BELOW)
+			dz->param[TRAC_LOFRQ] = ap->default_val[TRAC_LOFRQ];
+	}
+
+	if((exit_status = check_param_validity_and_consistency(dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+ 	is_launched = TRUE;
+
+	if((exit_status = allocate_large_buffers(dz))<0){
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	if((exit_status = param_preprocess(dz))<0){
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	if((exit_status = spec_process_file(dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	if((exit_status = complete_output(dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz);
+	free(dz);
+	return(SUCCEEDED);
+}