瀏覽代碼

initial commit

richarddobson 3 年之前
父節點
當前提交
0ffe9e02d2
共有 8 個文件被更改,包括 6313 次插入0 次删除
  1. 20 0
      dev/filter/CMakeLists.txt
  2. 1407 0
      dev/filter/ap_filter.c
  3. 1217 0
      dev/filter/filters0-711.c
  4. 1430 0
      dev/filter/filters0.c
  5. 543 0
      dev/filter/filters1.c
  6. 1011 0
      dev/filter/fltpcon.c
  7. 418 0
      dev/filter/fltprepro.c
  8. 267 0
      dev/filter/main.c

+ 20 - 0
dev/filter/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(filter main.c ap_filter.c filters0.c filters1.c fltpcon.c fltprepro.c)
+
+target_link_libraries(filter cdp2k sfsys ${EXTRA_LIBRARIES})
+
+my_install(filter)
+

+ 1407 - 0
dev/filter/ap_filter.c

@@ -0,0 +1,1407 @@
+/*
+ * 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
+ *
+ */
+
+
+
+/* floatsams version*/
+/*RWD Apr 2011 corrected usage message. Rebuilt with fixed (?) library for extra array element */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <cdpmain.h>
+#include <tkglobals.h>
+#include <pnames.h>
+#include <filters.h>
+#include <processno.h>
+#include <modeno.h>
+#include <globcon.h>
+#include <logic.h>
+#include <filetype.h>
+#include <mixxcon.h>
+#include <arrays.h>
+#include <flags.h>
+#include <speccon.h>
+#include <arrays.h>
+#include <special.h>
+#include <filters1.h>
+#include <formants.h>
+#include <sfsys.h>
+#include <osbind.h>
+#include <string.h>
+#include <math.h>
+#include <srates.h>
+/*RWD April 2004*/
+#include <filtcon.h>
+
+#ifndef cdp_round
+extern int cdp_round(double a);
+#endif
+
+#if defined unix || defined __GNUC__
+#define round(x) lround((x))
+#endif
+
+/********************************************************************************************/
+/********************************** FORMERLY IN buffers.c ***********************************/
+/********************************************************************************************/
+
+static int  create_fltiter_buffer(dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN specialin.c *********************************/
+/********************************************************************************************/
+
+static int  read_filter_data(char *filename,dataptr dz);
+static int  read_time_varying_filter_data(char *filename,dataptr dz);
+static int  get_data_from_tvary_infile(char *filename,dataptr dz);
+static int  getmaxlinelen(int *maxcnt,FILE *fp);
+static int  check_filter_data(int wordcnt_in_line,dataptr dz);
+static int  check_seq_and_range_of_filter_data(double *fbrk,int wordcnt_in_line,dataptr dz);
+
+static int	check_seq_and_range_of_filter_data2(double *fbrk,double *hbrk,dataptr dz);
+static int	getmaxlinelen2(int *maxcnt,FILE *fp);
+static int	read_data_from_t_and_p_vary_infile(char *filename,dataptr dz);
+
+/***************************************************************************************/
+/****************************** FORMERLY IN aplinit.c **********************************/
+/***************************************************************************************/
+
+/***************************** 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(EQ):
+	case(LPHP):
+	case(FSTATVAR):
+	case(FLTBANKN):
+	case(FLTBANKC):
+	case(FLTBANKU):
+	case(FLTBANKV):
+	case(FLTBANKV2):
+	case(FLTSWEEP):
+	case(ALLPASS):				dz->extra_bufcnt = 0;	dz->bufcnt = 1;		break;
+
+	case(FLTITER):				dz->extra_bufcnt = 0;	dz->bufcnt = 4;		break;
+	case(MAKE_VFILT):			dz->extra_bufcnt = 0;	dz->bufcnt = 0;		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(FLTBANKC):	dz->array_cnt = 2; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+
+	case(ALLPASS):	dz->array_cnt = 2; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+
+//	case(LPHP):		dz->array_cnt = 11; dz->iarray_cnt= 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break;
+// TW MULTICHAN 2010
+	case(LPHP):		
+		dz->array_cnt = 0; dz->iarray_cnt= 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0; 
+		break;
+	case(EQ):	   	dz->array_cnt = 4; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(FSTATVAR):	dz->array_cnt = 4; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(FLTSWEEP):	dz->array_cnt = 4; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+
+	case(FLTBANKN):	dz->array_cnt = 19; dz->iarray_cnt= 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break;
+	case(FLTBANKU):	dz->array_cnt = 19; dz->iarray_cnt= 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break;
+	case(FLTBANKV):	dz->array_cnt = 19; dz->iarray_cnt= 0; dz->larray_cnt = 1; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break;
+	case(FLTBANKV2):dz->array_cnt = 22; dz->iarray_cnt= 0; dz->larray_cnt = 1; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break;
+	case(FLTITER):	dz->array_cnt = 19; dz->iarray_cnt= 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break;
+	case(MAKE_VFILT): dz->array_cnt= 1; 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(EQ):			  setup_process_logic(SNDFILES_ONLY,		UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(LPHP):			  setup_process_logic(SNDFILES_ONLY,		UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(FSTATVAR):		  setup_process_logic(SNDFILES_ONLY,		UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(FLTBANKN):		  setup_process_logic(SNDFILES_ONLY,		UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(FLTBANKC):		  setup_process_logic(SNDFILES_ONLY,    	TO_TEXTFILE,		TEXTFILE_OUT,	dz);	break;
+	case(FLTBANKU):		  setup_process_logic(SNDFILES_ONLY,		UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(FLTBANKV2):
+	case(FLTBANKV):		  setup_process_logic(SNDFILES_ONLY,		UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(FLTITER):		  setup_process_logic(SNDFILES_ONLY,		UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(FLTSWEEP):		  setup_process_logic(SNDFILES_ONLY,		UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(ALLPASS):		  setup_process_logic(SNDFILES_ONLY,		UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(MAKE_VFILT):	  setup_process_logic(WORDLIST_ONLY,		TO_TEXTFILE,		NO_OUTPUTFILE,	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(EQ):  	 	exit_status = set_internalparam_data( "000dddiddd",ap);			break;	   
+	case(LPHP):    	exit_status = set_internalparam_data(  "000didi",ap);	  		break;	   
+	case(FSTATVAR):	exit_status = set_internalparam_data("0000diiiiididd",ap);		break;
+	case(FLTBANKN):	exit_status = set_internalparam_data( "000diiiiid",ap);			break;
+	case(FLTBANKC):	exit_status = set_internalparam_data( "000di",ap);				break;
+	case(FLTBANKU):	exit_status = set_internalparam_data("0000diiiiid",ap);			break;
+	case(FLTBANKV):	exit_status = set_internalparam_data("00iidiiiiididiiid",ap);	break;
+	case(FLTBANKV2):exit_status = set_internalparam_data("i000iidiiiiididiiidiidd",ap);	break;
+	case(FLTITER):	exit_status = set_internalparam_data(    "diiiiiiiiiiid",ap);	break;
+	case(FLTSWEEP): exit_status = set_internalparam_data( "000diiiiiddddddddd",ap);	break;
+	case(ALLPASS):	exit_status = set_internalparam_data(  "000diiiiiid",ap);		break;
+	case(MAKE_VFILT):	break;
+	default:
+		sprintf(errstr,"Unknown process in set_legal_internalparam_structure()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(exit_status);		
+}
+
+/***************************************************************************************/
+/******************************* FORMERLY IN sndlib.c **********************************/
+/***************************************************************************************/
+
+/*********************** GET_COEFFS1 *************************/
+
+void get_coeffs1(int n,dataptr dz)
+{
+	dz->parray[FLT_WW][n]   = 2.0 * PI * dz->parray[FLT_FRQ][n] * dz->param[FLT_INV_SR];
+	dz->parray[FLT_COSW][n] = cos(dz->parray[FLT_WW][n]);
+	dz->parray[FLT_SINW][n] = sin(dz->parray[FLT_WW][n]);
+}
+
+/*********************** GET_COEFFS2 ***************************/
+
+void get_coeffs2(int n,dataptr dz)
+{
+	double g, r;
+	r    = exp( -(dz->parray[FLT_WW][n])/(2.0 * dz->param[FLT_Q]));
+	dz->parray[FLT_A][n] = 2.0 * r * dz->parray[FLT_COSW][n];
+	dz->parray[FLT_B][n] = -(r) * r;
+	g    = 1.0 / ((1.0  + dz->parray[FLT_B][n]) * dz->parray[FLT_SINW][n]);
+	dz->parray[FLT_AMPL][n] = dz->parray[FLT_AMP][n]/g;
+	if(dz->vflag[FLT_DBLFILT])
+		dz->parray[FLT_AMPL][n] /= g;
+}
+
+/********************************************************************************************/
+/********************************** 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(FILTERBANK):				return read_filter_data(str,dz);
+	case(TIMEVARYING_FILTERBANK):	return read_time_varying_filter_data(str,dz);
+	case(TIMEVARY2_FILTERBANK):		return read_data_from_t_and_p_vary_infile(str,dz);
+	default:
+		sprintf(errstr,"Unknown special_data type: read_special_data()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/************************** READ_FILTER_DATA ********************************/
+
+int read_filter_data(char *filename,dataptr dz)
+{
+	int exit_status;
+	int n = 0, valcnt;
+	char temp[200], *p, *thisword;
+	double *frq, *amp;
+	int is_frq = TRUE;
+
+	if((dz->fp = fopen(filename,"r"))==NULL) {
+		sprintf(errstr,"Cannot open datafile %s\n",filename);
+		return(DATA_ERROR);
+	}
+	while(fgets(temp,200,dz->fp)!=NULL) {
+		p = temp;
+		if(is_an_empty_line_or_a_comment(p))
+			continue;
+		n++;
+	}
+	if(n==0) {
+		sprintf(errstr,"No data in file %s\n",filename);
+		return(DATA_ERROR);
+	}
+	dz->iparam[FLT_CNT] = n;
+	if((exit_status = allocate_filter_frq_amp_arrays(dz->iparam[FLT_CNT],dz))<0)
+		return(exit_status);
+	frq = dz->parray[FLT_FRQ];
+	amp = dz->parray[FLT_AMP];
+	if(fseek(dz->fp,0,0)<0) {
+		sprintf(errstr,"fseek() failed in read_filter_data()\n");
+		return(SYSTEM_ERROR);
+	}
+	n = 0;
+	while(fgets(temp,200,dz->fp)!=NULL) {
+		p = temp;
+		if(is_an_empty_line_or_a_comment(temp))
+			continue;
+		if(n >= dz->iparam[FLT_CNT]) {
+			sprintf(errstr,"Accounting problem reading Frq & Amp: read_filter_data()\n");
+			return(PROGRAM_ERROR);
+		}
+		valcnt = 0;
+		while(get_word_from_string(&p,&thisword)) {
+			if(valcnt>=2) {
+				sprintf(errstr,"Too many values on line %d: file %s\n",n+1,filename);
+				return(DATA_ERROR);
+			}
+			if(is_frq) {
+				if(sscanf(thisword,"%lf",&(frq[n]))!=1) {
+					sprintf(errstr,"Problem reading Frq data: line %d: file %s\n",n+1,filename);
+					return(DATA_ERROR);
+				}
+				if(frq[n]<dz->application->min_special || frq[n]>dz->application->max_special) {
+					sprintf(errstr,"frq (%.3lf) on line %d out of range (%.1lf to %.1lf):file %s\n",
+					frq[n],n+1,dz->application->min_special,dz->application->max_special,filename);
+					return(DATA_ERROR);
+				}
+				if(dz->mode==FLT_MIDI)
+					frq[n] = miditohz(frq[n]);
+			} else {
+				if((exit_status = get_level(thisword,&(amp[n])))<0)
+					return(exit_status);
+				if(amp[n]<FLT_MINGAIN || amp[n]>FLT_MAXGAIN) {
+					sprintf(errstr,"amp (%lf) out of range (%lf to %.1lf) on line %d: file %s\n",
+					amp[n],FLT_MINGAIN,FLT_MAXGAIN,n+1,filename);
+					return(DATA_ERROR);
+				}
+			}
+			is_frq = !is_frq;
+			valcnt++;
+		}
+		if(valcnt<2) {
+			sprintf(errstr,"Not enough values on line %d: file %s\n",n+1,filename);
+			return(DATA_ERROR);
+		}
+		n++;
+	}
+	if(fclose(dz->fp)<0) {
+		fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
+		fflush(stdout);
+	}
+	return(FINISHED);
+}
+
+/**************************** ALLOCATE_FILTER_FRQ_AMP_ARRAYS *******************************/
+
+int allocate_filter_frq_amp_arrays(int fltcnt,dataptr dz)
+{
+//	int chans = dz->infile->channels; 
+	/*RWD 9:2001 must have empty arrays */
+	if((dz->parray[FLT_AMP] = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_FRQ] = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for filter amp and frq arrays.\n");
+		return(MEMORY_ERROR);
+	}
+	return(FINISHED);
+}
+
+/************************** READ_TIME_VARYING_FILTER_DATA ********************************/
+
+int read_time_varying_filter_data(char *filename,dataptr dz)
+{
+	int exit_status;
+//	int cnt = 0;
+	if((exit_status = get_data_from_tvary_infile(filename,dz))<0)
+		return(exit_status);
+	if((exit_status = check_filter_data(dz->iparam[FLT_ENTRYCNT],dz))<0)
+		return(exit_status);
+	return(FINISHED);
+}
+
+/**************************** GET_DATA_FROM_TVARY_INFILE *******************************/
+
+int get_data_from_tvary_infile(char *filename,dataptr dz)
+{
+	int exit_status;
+	char *temp, *p, *thisword;
+	int maxlinelen, frqcnt;
+	int total_wordcnt = 0;
+	int  columns_in_this_row, columns_in_row = 0, number_of_rows = 0;
+/* NEW CODE */
+	int n, m, k, old_wordcnt;
+	double filedur = (double)(dz->insams[0]/dz->infile->channels)/(double)(dz->infile->srate);
+	double far_time = filedur + FLT_TAIL + 1.0;
+/* NEW CODE */
+
+	double val;
+	if((dz->fp = fopen(filename,"r"))==NULL) {
+		sprintf(errstr,"Cannot open datafile %s\n",filename);
+		return(DATA_ERROR);
+	}
+	if((exit_status = getmaxlinelen(&maxlinelen,dz->fp))<0)
+		return(exit_status);
+	if((fseek(dz->fp,0,0))<0) {
+		sprintf(errstr,"Seek failed in get_data_from_tvary_infile()\n");
+		return(SYSTEM_ERROR);
+	}
+	if((temp = (char *)malloc((maxlinelen+2) * sizeof(char)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for temporary line storage.\n");
+		return(MEMORY_ERROR);
+	}
+	while(fgets(temp,maxlinelen,dz->fp)!=NULL) {
+		columns_in_this_row = 0;
+		if(is_an_empty_line_or_a_comment(temp))
+			continue;
+		p = temp;
+		while(get_word_from_string(&p,&thisword)) { 
+			if((exit_status = get_level(thisword,&val))<0) {	/* reads vals or dB vals */
+				free(temp);
+				return(exit_status);
+			}
+			if((total_wordcnt==0 && ((dz->parray[FLT_FBRK] = (double *)malloc(sizeof(double)))==NULL))
+			|| (dz->parray[FLT_FBRK] = (double *)realloc(dz->parray[FLT_FBRK],(total_wordcnt+1) * sizeof(double)))==NULL) {
+				free(temp);
+				sprintf(errstr,"INSUFFICIENT MEMORY to reallocate filter brktable.\n");
+				return(MEMORY_ERROR);
+			}
+			dz->parray[FLT_FBRK][total_wordcnt] = val;
+			columns_in_this_row++;
+			total_wordcnt++;
+		}
+		if(number_of_rows==0) {
+			if((columns_in_row = columns_in_this_row)<3) {
+				sprintf(errstr,"Insufficient filter data in row 1 of file %s.\n",filename);
+				free(temp);
+				return(DATA_ERROR);
+			} else if (ODD(columns_in_row - 1)) {
+				sprintf(errstr,"Frq and Amp data not paired correctly (or no Time) in row 1 of file %s.\n",filename);
+				free(temp);
+				return(DATA_ERROR);
+			}
+		} else if(columns_in_this_row!=columns_in_row) {
+			free(temp);
+			if(columns_in_this_row < columns_in_row)
+				sprintf(errstr,"Not enough entries in row %d of file %s\n",number_of_rows+1,filename);
+			else
+				sprintf(errstr,"Too many entries in row %d of file %s\n",number_of_rows+1,filename);
+			return(DATA_ERROR);
+		}
+		number_of_rows++;
+	}
+	dz->iparam[FLT_WORDCNT] = total_wordcnt;
+	free(temp);
+	if(columns_in_row<3) {
+		sprintf(errstr,"Insufficient data in each row, to define filters.\n");
+		return(DATA_ERROR);
+	}
+	dz->iparam[FLT_ENTRYCNT] = columns_in_row;
+	frqcnt = columns_in_row - 1;
+	if(ODD(frqcnt)) {
+		sprintf(errstr,"amplitude and freq data not correctly paired in rows.\n");
+		return(DATA_ERROR);
+	}
+	dz->iparam[FLT_CNT]       = frqcnt/2;
+	dz->iparam[FLT_TIMESLOTS] = number_of_rows;
+	if(fclose(dz->fp)<0) {
+		fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
+		fflush(stdout);
+	}
+/* NEW CODE */
+	if(dz->parray[FLT_FBRK][0] !=0.0) {
+		if(flteq(dz->parray[FLT_FBRK][0],0.0))
+			dz->parray[FLT_FBRK][0] = 0.0;
+		else {
+			dz->iparam[FLT_TIMESLOTS]++;
+			old_wordcnt = dz->iparam[FLT_WORDCNT];
+			k = old_wordcnt-1;
+			dz->iparam[FLT_WORDCNT] += dz->iparam[FLT_ENTRYCNT];
+			m = dz->iparam[FLT_WORDCNT] - 1;
+			if((dz->parray[FLT_FBRK] = (double *)realloc(dz->parray[FLT_FBRK],dz->iparam[FLT_WORDCNT] * sizeof(double)))==NULL) {
+				sprintf(errstr,"INSUFFICIENT MEMORY to reallocate filter brktable.\n");
+				return(MEMORY_ERROR);
+			}
+			for(n=0;n<old_wordcnt;n++,m--,k--)
+				dz->parray[FLT_FBRK][m] = dz->parray[FLT_FBRK][k];
+			dz->parray[FLT_FBRK][0] = 0.0;
+			total_wordcnt = dz->iparam[FLT_WORDCNT];
+		}
+	}
+
+	if(dz->parray[FLT_FBRK][total_wordcnt - dz->iparam[FLT_ENTRYCNT]] < far_time) {
+		dz->iparam[FLT_TIMESLOTS]++;
+		m = dz->iparam[FLT_WORDCNT];
+		k = m - dz->iparam[FLT_ENTRYCNT];
+		dz->iparam[FLT_WORDCNT] += dz->iparam[FLT_ENTRYCNT];
+		if((dz->parray[FLT_FBRK] = (double *)realloc(dz->parray[FLT_FBRK],dz->iparam[FLT_WORDCNT] * sizeof(double)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY to reallocate filter brktable.\n");
+			return(MEMORY_ERROR);
+		}
+		dz->parray[FLT_FBRK][m] = far_time;
+		m++;
+		k++;
+		for(n=1;n<dz->iparam[FLT_ENTRYCNT];n++,m++,k++)
+			dz->parray[FLT_FBRK][m] = dz->parray[FLT_FBRK][k];
+	}
+/* NEW CODE */
+	return(FINISHED);
+}
+
+/**************************** GETMAXLINELEN *******************************/
+
+int getmaxlinelen(int *maxcnt,FILE *fp)
+{
+	int thiscnt = 0;
+	char c;
+	*maxcnt = 0;
+	while((c= (char)fgetc(fp))!=EOF) {
+		if(c=='\n' || c == ENDOFSTR) {
+			*maxcnt = max(*maxcnt,thiscnt);
+			thiscnt = 0;
+		} else
+			thiscnt++;			
+	}
+	*maxcnt = (int)max(*maxcnt,thiscnt);
+	*maxcnt += 4;	/* NEWLINE, ENDOFSTR and safety!! */
+	return(FINISHED);
+}			
+
+/**************************** CHECK_FILTER_DATA *******************************/
+
+int check_filter_data(int wordcnt_in_line,dataptr dz)
+{
+	int    exit_status;	
+	int   n, lastfilt, new_total_wordcnt;
+	double endtime;
+	int    total_wordcnt = dz->iparam[FLT_WORDCNT];
+	if(dz->parray[FLT_FBRK][0] < 0.0) {
+		sprintf(errstr,"Negative time value (%lf) on line 1.\n",dz->parray[FLT_FBRK][0]);
+		return(DATA_ERROR);
+	}
+	if(flteq(dz->parray[FLT_FBRK][0],0.0))		
+		dz->parray[FLT_FBRK][0] = 0.0;			/* FORCE A FILTER SETTING AT TIME ZERO */
+	else {				 			
+		if((dz->parray[FLT_FBRK] = 
+		(double *)realloc(dz->parray[FLT_FBRK],(total_wordcnt+wordcnt_in_line) * sizeof(double)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY to reallocate filter brktable.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=total_wordcnt-1; n>=0; n--)
+			dz->parray[FLT_FBRK][n + wordcnt_in_line] = dz->parray[FLT_FBRK][n];
+		total_wordcnt += wordcnt_in_line;
+		dz->parray[FLT_FBRK][0] = 0.0;
+		dz->iparam[FLT_TIMESLOTS]++;
+	}
+	dz->iparam[FLT_WORDCNT] = total_wordcnt;
+	if((exit_status = check_seq_and_range_of_filter_data(dz->parray[FLT_FBRK],wordcnt_in_line,dz))<0)
+		return(exit_status);
+								/* FORCE A FILTER SETTING AT (BEYOND) END OF FILE */
+	lastfilt = total_wordcnt - wordcnt_in_line;
+	endtime =  (double)(dz->insams[0]/dz->infile->channels)/(double)dz->infile->srate;
+	if(dz->parray[FLT_FBRK][lastfilt] <= endtime) {
+		if((dz->parray[FLT_FBRK] = 
+		(double *)realloc(dz->parray[FLT_FBRK],(total_wordcnt + wordcnt_in_line) * sizeof(double)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY to reallocate filter brktable.\n");
+			return(MEMORY_ERROR);
+		}
+		new_total_wordcnt = total_wordcnt + wordcnt_in_line;
+		for(n=total_wordcnt;n<new_total_wordcnt;n++)
+			dz->parray[FLT_FBRK][n] = dz->parray[FLT_FBRK][n - wordcnt_in_line];
+		dz->parray[FLT_FBRK][total_wordcnt] = endtime + 1.0;
+		total_wordcnt = new_total_wordcnt;
+		dz->iparam[FLT_TIMESLOTS]++;
+	}
+	if(dz->iparam[FLT_TIMESLOTS]<2) {
+		sprintf(errstr,"Error in timeslot logic: check_filter_data()\n");
+		return(PROGRAM_ERROR);
+	}
+	dz->iparam[FLT_WORDCNT] = total_wordcnt;
+	return(FINISHED);
+}
+
+/**************************** CHECK_SEQ_AND_RANGE_OF_FILTER_DATA *******************************/
+
+int check_seq_and_range_of_filter_data(double *fbrk,int wordcnt_in_line,dataptr dz)
+{
+	double lasttime = 0.0;
+	int n, m, lineno;
+	for(n=1;n<dz->iparam[FLT_WORDCNT];n++) {
+		m = n%wordcnt_in_line;
+		lineno = (n/wordcnt_in_line)+1;	/* original line-no : ignoring comments */
+		if(m==0) {
+			if(fbrk[n] <= lasttime) {
+				sprintf(errstr,"Time is out of sequence on line %d\n",lineno);
+				return(DATA_ERROR);
+//NEW AUGUST 2006
+//			} else if(fbrk[n] > dz->duration) {
+//				fbrk[n] = dz->duration + 1.0;
+//				dz->iparam[FLT_WORDCNT] = lineno * wordcnt_in_line;
+			}
+			lasttime = fbrk[n];
+		} else if(ODD(m)) {
+			if(fbrk[n]<dz->application->min_special || fbrk[n]>dz->application->max_special) {
+				sprintf(errstr,"frq_or_midi value [%.3lf] out of range (%.1f - %.1f) on line %d\n",
+				fbrk[n],dz->application->min_special,dz->application->max_special,lineno);
+					return(DATA_ERROR);
+			}
+			if(dz->mode==FLT_MIDI)
+				fbrk[n] = miditohz(fbrk[n]);
+		} else
+			fbrk[n] = max(fbrk[n],MINFILTAMP);	/* Zero filter amp, forced to +ve, but effectively zero */
+	}
+	return(FINISHED);
+}
+
+
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+/****************************** PARAM_PREPROCESS *********************************/
+
+int param_preprocess(dataptr dz)	
+{
+//	int exit_status = FINISHED;
+
+	switch(dz->process) {
+	case(EQ):			case(LPHP):			case(FSTATVAR):
+	case(FLTBANKN):		case(FLTBANKU):		case(FLTBANKV):
+	case(FLTSWEEP):		case(ALLPASS):		case(FLTITER):
+	case(FLTBANKC):		case(FLTBANKV2):
+		return filter_preprocess(dz);
+	case(MAKE_VFILT):	break;
+	default:
+		sprintf(errstr,"PROGRAMMING PROBLEM: Unknown process in param_preprocess()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+
+/********************************************************************************************/
+/********************************** FORMERLY IN procgrou.c **********************************/
+/********************************************************************************************/
+
+/**************************** GROUCHO_PROCESS_FILE ****************************/
+
+int groucho_process_file(dataptr dz)   /* FUNCTIONS FOUND IN PROCESS.C */
+{	
+//	int exit_status = FINISHED;
+
+	if(dz->process!= FLTBANKC)
+		display_virtual_time(0L,dz);
+
+	switch(dz->process) {
+	case(LPHP):
+	case(EQ):	 		case(FSTATVAR):		case(FLTSWEEP):		case(ALLPASS):
+	case(FLTBANKN):		case(FLTBANKC):		case(FLTBANKU):		case(FLTBANKV):		
+	case(FLTBANKV2):		
+	return filter_process(dz);
+	case(FLTITER):			
+		return iterating_filter(dz);
+	case(MAKE_VFILT):
+		return make_vfilt_data(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;
+	handle_pitch_zeros(dz);
+	switch(dz->process) {
+	case(EQ):		case(LPHP):		case(FSTATVAR):		case(FLTBANKN):
+	case(FLTBANKU):	case(FLTBANKV):	case(FLTSWEEP):		case(ALLPASS):
+	case(FLTITER):	case(FLTBANKC):	case(FLTBANKV2):		
+		return filter_pconsistency(dz);
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN buffers.c ***********************************/
+/********************************************************************************************/
+
+/**************************** ALLOCATE_LARGE_BUFFERS ******************************/
+
+int allocate_large_buffers(dataptr dz)
+{
+	switch(dz->process) {
+	case(EQ):	   		case(LPHP):			case(FSTATVAR):
+	case(FLTBANKN):		case(FLTBANKU):		case(FLTBANKV):		case(FLTBANKV2):
+	case(FLTSWEEP):		case(ALLPASS):			
+		return create_sndbufs(dz);
+
+	case(FLTITER):			
+		return create_fltiter_buffer(dz);
+	case(FLTBANKC):			
+	case(MAKE_VFILT):
+		return(FINISHED);
+	default:
+		sprintf(errstr,"Unknown program no. in allocate_large_buffers()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/*************************** CREATE_FLTITER_BUFFER **************************
+ *
+ * (1)	Create extra spaces for interpolation guard points at end of infile.
+ *
+ * (2) 	Allow for any cumulative addition errors in interpolation.
+ *
+ * (3)	Output buffer must be at least as big as the overflow buffer.
+ *	Output buffer must be big enough for the whole of any possible
+ *	data overflow (in overflow_size buff) to be copied back into it.
+ *	This is because the overflow buffer is ZEROED after such a copy
+ *	and if a 2nd copy of the overflow back into the main buffer
+ *	were necessary, we would be copying zeroes rather than true data.
+ *
+ *	Output buffer must be bigger than the maximum possible delay.
+ * 	When write_start is beyond end of buffer, we copy the overflow buffer
+ *	data back into the true buffer and reset the pointers by subtracting
+ *	buflen (length of output buffer). We must be sure that 'write_start'
+ *	will then be located WITHIN the true buffer. In the worst possible
+ *	case the write_start pointer is at the very end of the true buffer,
+ *	and is then delayed to its maximum possible extent, maxdelay_size (Z),
+ *	which will be Z samps into the overflow buffer. After the copy-back,
+ *	the 'write_start' pointer must lie WITHIN the true buffer.
+ *	Hence the true buflen must be >= maximum delay.
+ *
+ *		true buffer	    			overflow
+ *  |-----------------------------|------------------------------------------|
+ *			    			 worst^					    ^
+ *		    		 possible case^					    ^
+ *		             		      ^----->-delayed by maxdelay_size to ->-----^
+ *			 					  ^<-restored by -buffer_size into truebuf-<-^
+ *  |<-------- BUFFER_SIZE------->
+ *
+ */
+
+int create_fltiter_buffer(dataptr dz)
+{
+	int   big_buffer_size;
+	size_t bigbufsize;
+	double k;
+	int  chans = dz->infile->channels;
+	int bufminimum, infilesamps;
+	dz->iparam[FLT_INFILESPACE] = dz->insams[0];
+	if(dz->param[FLT_PSHIFT]>0.0) {
+		dz->iparam[FLT_INFILESPACE] += chans;		/* 1 */
+		k = pow(2.0,dz->param[FLT_PSHIFT]);
+		dz->iparam[FLT_OVFLWSIZE]  = ((round((dz->insams[0]/chans) * k) * chans) + chans);
+		dz->iparam[FLT_OVFLWSIZE] += FLT_SAFETY;						/* 2 */
+	} else
+		dz->iparam[FLT_OVFLWSIZE] = dz->iparam[FLT_INFILESPACE] + FLT_SAFETY;
+	infilesamps      = dz->iparam[FLT_INFILESPACE];
+	bufminimum       = dz->iparam[FLT_OVFLWSIZE];
+	bigbufsize   = (size_t)Malloc(-1);
+	bigbufsize /= sizeof(float);
+	bigbufsize  -= (dz->iparam[FLT_INFILESPACE] * 2) + dz->iparam[FLT_OVFLWSIZE];
+	if(bigbufsize<bufminimum)
+		bigbufsize = bufminimum;	
+//TW COMMENT: filters don't sfseek: so old buffer protocol can be abandoned
+
+	dz->buflen = (int) bigbufsize;
+	big_buffer_size = (dz->iparam[FLT_INFILESPACE] * 2) + dz->buflen + dz->iparam[FLT_OVFLWSIZE];
+	if((dz->bigbuf = (float *) malloc((size_t)(big_buffer_size * sizeof(float)))) == NULL) {
+		sprintf(errstr, "INSUFFICIENT MEMORY to create sound buffers.\n");
+		return(MEMORY_ERROR);
+	}
+	dz->sampbuf[0]        	  = dz->bigbuf;
+	dz->sampbuf[1]        	  = dz->sampbuf[0] + infilesamps;
+	dz->sampbuf[FLT_OUTBUF]   = dz->sampbuf[1] + infilesamps;
+	dz->sampbuf[FLT_OVFLWBUF] = dz->sampbuf[FLT_OUTBUF] + dz->buflen;
+	memset((char *)dz->bigbuf,0,(size_t)(big_buffer_size * sizeof(float)));
+	return(FINISHED);
+}
+
+
+/********************************************************************************************/
+/********************************** FORMERLY IN cmdline.c ***********************************/
+/********************************************************************************************/
+
+int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
+{
+	if     (!strcmp(prog_identifier_from_cmdline,"fixed"))			dz->process = EQ;
+	else if(!strcmp(prog_identifier_from_cmdline,"lohi"))			dz->process = LPHP;
+	else if(!strcmp(prog_identifier_from_cmdline,"variable"))		dz->process = FSTATVAR;
+	else if(!strcmp(prog_identifier_from_cmdline,"bank"))			dz->process = FLTBANKN;
+	else if(!strcmp(prog_identifier_from_cmdline,"bankfrqs"))		dz->process = FLTBANKC;
+	else if(!strcmp(prog_identifier_from_cmdline,"userbank"))		dz->process = FLTBANKU;
+	else if(!strcmp(prog_identifier_from_cmdline,"varibank"))		dz->process = FLTBANKV;
+	else if(!strcmp(prog_identifier_from_cmdline,"varibank2"))		dz->process = FLTBANKV2;
+	else if(!strcmp(prog_identifier_from_cmdline,"iterated"))		dz->process = FLTITER;
+	else if(!strcmp(prog_identifier_from_cmdline,"sweeping"))		dz->process = FLTSWEEP;
+	else if(!strcmp(prog_identifier_from_cmdline,"phasing"))		dz->process = ALLPASS;
+	else if(!strcmp(prog_identifier_from_cmdline,"vfilters"))		dz->process = MAKE_VFILT;
+	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: filter NAME (mode) infile outfile (datafile) parameters\n"
+	"\n"
+	"where NAME can be any one of\n"
+	"\n"
+	"fixed      lohi         variable\n"
+	"bank       bankfrqs     userbank      varibank      varibank2\n"
+	"iterated   sweeping     phasing	   vfilters\n"
+	"\n"
+	"Type 'filter  userbank'  for more info on filter userbank... ETC.\n");
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE2 ********************************/
+
+int usage2(char *str)
+{
+	if (!strcmp(str,"fixed")) {		 	/* EQ */
+		fprintf(stdout,
+		"CUT OR BOOST, ABOVE, BELOW OR AROUND A GIVEN FRQ\n\n"
+		"USAGE: filter fixed 1-2  infile outfile        boost/cut freq [-ttail] [-sprescale]\n"
+		"OR:    filter fixed 3    infile outfile bwidth boost/cut freq [-ttail] [-sprescale]\n\n"
+		"MODES ARE...\n"
+		"1) BOOST OR CUT BELOW GIVEN FRQ\n"
+		"2) BOOST OR CUT ABOVE GIVEN FRQ\n"
+		"3) BOOST OR CUT A BAND CENTERED ON GIVEN FRQ\n\n"
+		"BWIDTH     is the filter bandwidth in Hz for Mode 3 only\n"
+		"BOOST/CUT  is the boost or cut, in dB\n"
+		"FREQ       is the filter frequency in Hz\n"
+		"TAIL       decay tail duration\n"
+		"PRESCALE   scales the INPUT to the filter.\n");
+
+	} else if (!strcmp(str,"lohi")) {		 /* LOHI */
+		fprintf(stdout,
+    	"FIXED LOW PASS OR HIGH PASS FILTER.\n\n"
+    	"USAGE:\nfilter lohi mode infile outfile attenuation pass-band stop-band [-ttail] [-sprescale]\n\n"
+	    "MODES ARE\n"
+	    "1) Pass-band and stop-band as freq in Hz.\n"
+	    "2) Pass-band and stop-band as (possibly fractional) midi notes.\n\n"
+	    "ATTENUATION Gain reduction of filter, in dB. Range(0 to %.0lf)\n"
+	    "            Greater attenuation, sharper filter, but longer to calculate.\n"
+	    "PASS-BAND   last pitch to be passed by the filter.\n"
+	    "STOP-BAND   first pitch to be stopped by the filter.\n"
+	    "            If stop-band is above pass-band, this is a lopass filter.\n"
+	    "            If stop-band is below pass-band, this is a hipass filter.\n"
+		"TAIL       decay tail duration\n"
+	    "-s          Prescale input: Avoid overflows: Range(%.3lf to %.1lf)\n",
+	    MIN_DB_ON_16_BIT,FLT_MINEQPRESCALE,FLT_MAXEQPRESCALE);
+
+	} else if (!strcmp(str,"variable")) {		 /* FSTATVAR */
+		fprintf(stdout,
+		"LOPASS, HIGH-PASS, BANDPASS, OR NOTCH FILTER WITH VARIABLE FRQ\n\n"
+		"USAGE: filter variable mode infile outfile acuity gain frq [-ttail]\n\n"
+		"MODES ARE..\n"
+		"1) NOTCH (Band Reject)\n\n"
+		"2) BAND-PASS\n"
+		"3) LOW-PASS\n"
+		"4) HIGH-PASS\n"
+	    "ACUITY   acuity of filter: Range(%lf to %.1lf).\n"
+	    "         Smaller vals give tighter filter.\n"
+		"GAIN     overall gain on output:  Range(%lf to %.1lf)\n"
+		"         Rule of thumb:\n"
+		"         if acuity = (1/3)to-power-n: gain = (2/3)-to-power-n\n"
+	    "FRQ      frq of filter:           Range(%.1lf to srate/2)\n\n"	
+		"ACUITY and FRQ can vary over time.\n"
+		"TAIL       decay tail duration\n",MIN_ACUITY,MAX_ACUITY,FLT_MINGAIN,FLT_MAXGAIN,FLT_MINFRQ);
+
+	} else if (!strcmp(str,"bank")) {		 /* FLTBANKN */
+     	fprintf(stdout,
+		"BANK OF FILTERS, WITH TIME-VARIABLE Q\n\n"
+		"USAGE: filter bank 1-3 infile outfile Q gain lof hif       [-ttail] [-sscat] [-d]\n"
+		"OR:    filter bank 4-6 infile outfile Q gain lof hif param [-ttail] [-sscat] [-d]\n\n"
+		"MODES...\n"
+		"1)  HARMONIC SERIES over lofrq.\n"
+		"2)  ALTERNATE HARMONICS over lofrq.\n"
+		"3)  SUBHARMONIC SERIES below hifrq.\n"
+		"4)  HARMONIC SERIES WITH LINEAR OFFSET: param = offset in Hz.\n"
+		"5)  EQUAL INTERVALS BETWEEN lo & hifrq: param = no. of filters.\n"
+		"6)  EQUAL INTERVALS BETWEEN lo & hifrq: param = interval semitone-size.\n\n"
+		"Q      Q (tightness) of filters (Range %lf <= Q < %.1lf)\n"
+		"GAIN   overall gain (Range %lf to %.1lf).\n"
+		"LOF    lofrq limit of filters  (Range: %.0lf to srate/3).\n"
+		"HIF    hifrq limit of filters  (Range: lofrq+ to srate/3).\n"
+		"TAIL   decay tail duration\n"
+		"SCAT   Random scatter of filter frqs (Range 0 to 1: Default 0).\n"
+		"-d     Double filtering.\n\n"
+		"Q may vary over time.\n",MINQ,MAXQ,FLT_MINGAIN,FLT_MAXGAIN,FLT_MINFRQ);
+
+	} else if (!strcmp(str,"bankfrqs")) {		 /* FLTBANKC */
+     	fprintf(stdout,
+		"GENERATE A LIST OF FREQUENCIES FOR USE AS A FILTERBANK\n"
+		"(ADD AMPLITUDES TO THE TEXTFILE FOR USE WITH 'USERBANK')\n\n"
+		"USAGE: filter bankfrqs 1-3 anysndfile outtextfile lof hif\n"
+		"OR:    filter bankfrqs 4-6 anysndfile outtextfile lof hif param\n\n"
+		"MODES...\n"					   
+		"1)  HARMONIC SERIES over lofrq.\n"
+		"2)  ALTERNATE HARMONICS over lofrq.\n"
+		"3)  SUBHARMONIC SERIES below hifrq.\n"
+		"4)  HARMONIC SERIES WITH LINEAR OFFSET: param = offset in Hz.\n"
+		"5)  EQUAL INTERVALS BETWEEN lo & hifrq: param = no. of filters.\n"
+		"6)  EQUAL INTERVALS BETWEEN lo & hifrq: param = interval semitone-size.\n\n"
+		"LOF    lofrq limit of filters  (Range: %.0lf to srate/3).\n"
+		"HIF    hifrq limit of filters  (Range: lofrq+ to srate/3).\n"
+//		"SCAT   Random scatter of filter frqs (Range 0 to 1: Default 0).\n\n" /* RWD Apr 2011 this param not supported here */
+		"NB sampling rate of input soundfile determines frq range\n",FLT_MINFRQ);
+
+	} else if (!strcmp(str,"userbank")) {		 /* FLTBANKU */
+      	fprintf(stdout,
+	   	"USER-DEFINED FILTERBANK,WITH TIME-VARIABLE Q\n\n"
+		"USAGE: filter userbank mode infile outfile datafile Q gain [-ttail] [-d]\n\n"
+		"MODES are\n"
+		"1)  Filter-pitches as frq in Hz.\n"
+		"2)  Filter-pitches as MIDI values.\n\n"
+		"DATAFILE: has Pitch & Amp of filters (paired, one pair on each line).\n"
+		"          Ranges: Pitch (%.0lfHz to sr/3) Amp (%lf to %.1lf)\n"
+		"          Amplitude may also be expressed in decibels.\n"
+		"          Comment-lines (starting with ';') may be used.\n\n"
+		"Q:        Q (tightness) of filter: Range(%lf to %.1lf)\n"
+		"GAIN      overall gain, Range(%lf to %.1lf).\n"
+		"TAIL      decay tail duration\n"
+		"-d        double filtering.\n\n"
+		"Q may vary over time.",FLT_MINFRQ,FLT_MINGAIN,FLT_MAXGAIN,MINQ,MAXQ,FLT_MINGAIN,FLT_MAXGAIN);
+
+	} else if (!strcmp(str,"varibank")) {		 /* FLTBANKV */
+		fprintf(stdout,
+	   	"USER-DEFINED TIME_VARYING FILTERBANK,WITH TIME-VARIABLE Q\n\n"
+		"USAGE:\nfilter varibank mode infile outfile data Q gain [-ttail] [-hhcnt] [-rrolloff] [-d]\n\n"
+		"MODES ARE...\n"
+		"1)  Enter filter-pitches as frq, in Hz.\n"
+		"2)  Enter filter-pitches as MIDI values.\n\n"
+		"DATAFILE: has lines of data for filter bands at successive times.\n"
+		"          Each line contains the following items\n"
+		"                Time:   Pitch1 Amp1   [Pitch2 Amp2    etc....].\n"
+		"          Pitch and Amp values must be paired:\n"
+		"          any number of pairs can be used in a line,\n"
+		"          BUT each line must have SAME number of pairs on it.\n"
+		"          (To eliminate a band in any line(s), set its amplitude to 0.0).\n"
+		"          Time values (in secs) must be in ascending order (and >=0.0)\n"
+		"          Pitch vals may be EITHER frq, OR MIDI, depending on MODE.\n"
+		"          Amp values may be numeric, or dB values (e.g. -4.1dB).\n"
+		"          Comment-lines may be used: start these with ';'.\n\n"
+		"Q         Q (tightness) of filter : Range(%lf to %.1lf).\n"		
+		"GAIN:     overall gain: Range: (%lf to %.1lf)\n"					
+		"TAIL      decay tail duration\n"
+		"HCNT      No of harmonics of each pitch to use: Default 1.\n"
+		"          High harmonics of high pitches may be beyond nyquist.\n"
+		"          (No-of-pitches times no-of-harmonics determines program speed).\n"
+		"ROLLOFF   Level drop (in dB) from one harmonic to next. Range(0 to %.1lf)\n"
+		"-d        double filtering.\n\n"
+		"Q may also vary over time.\n",MINQ,MAXQ,FLT_MINGAIN, FLT_MAXGAIN,MIN_DB_ON_16_BIT);
+
+	} else if (!strcmp(str,"varibank2")) {		 /* FLTBANKV */
+		fprintf(stdout,
+	   	"USER-DEFINED TIME_VARYING FILTERBANK,WITH TIME-VARIABLE Q AND PARTIALS\n"
+		"USAGE:\nfilter varibank2 mode infil outfil data Q gain [-ttail] [-d]\n"
+		"MODES ARE...\n"
+		"1)  Enter filter-pitches as frq, in Hz.\n"
+		"2)  Enter filter-pitches as MIDI values.\n\n"
+		"DATAFILE: has lines of data for filter bands at successive times.\n"
+		"          as varibank filter....\n"
+		"          Followed by a line with a '#' sign at the start.\n"
+		"          Followed by 2nd set of lines, similar to the pitchdata lines\n"
+		"          but now the data is a time followed by any number of pairs of\n"
+		"          partial number (possibly fractional) + amplitude of partial.\n"
+		"          Times for pitch AND for partials data MUST START AT ZERO.\n"
+		"Q         Q (tightness) of filter : Range(%lf to %.1lf).\n"		
+		"GAIN:     overall gain: Range: (%lf to %.1lf)\n"					
+		"TAIL      decay tail duration\n"
+		"-d        double filtering.\n\n"
+		"Q may also vary over time.\n",MINQ,MAXQ,FLT_MINGAIN,FLT_MAXGAIN);
+
+	} else if (!strcmp(str,"iterated")) {		 /* FLTITER */
+		fprintf(stdout,
+    	"ITERATE SOUND, WITH CUMULATIVE FILTERING BY A FILTERBANK.\n\n"
+    	"USAGE: filter iterated mode infile outfile datafile Q gain delay dur \n"
+    	"         [-sprescale] [-rrand] [-ppshift] [-aashift] [-d] [-i] [-e] [-n]\n\n"
+		"MODES ARE...\n"
+		"1)  Enter filter-pitches as frq, in Hz.\n"
+		"2)  Enter filter-pitches as MIDI values.\n\n"
+    	"DATAFILE  has Pitch & Amp of filters (paired, one pair on each line).\n"
+    	"          Pitch, as Hz or MIDI, Range(%.0lfHz to srate/3)\n"		
+    	"          Amp, Range(%lf to %.1lf), can also be entered as dB vals\n\n" 
+    	"Q         Q (tightness) of filter: Range(%lf to %.1lf)\n"    
+    	"GAIN      overrall gain in filtering process (%lf < gain < %.1lf)\n"
+    	"DELAY     (average) delay between iterations (secs).\n"
+    	"          Range(>0 to %.0lf)\n"
+    	"DUR       (min) duration of output file (>infile duration).\n"
+    	"PRESCALE  gain on the INPUT to the filtering process.\n"
+    	"          Range (0.0 - 1.0) Default 1.0\n"
+    	"          If set to 0.0, Program automatically divides input level by\n"
+    	"          the max no. of sound overlays occuring in the iteration process.\n"
+    	"RAND      delaytime-randomisation: Range 0 (none) to 1 (max).\n"
+    	"PSHIFT    max pitchshift of any segment in (fractions of) semitones (>=0).\n"
+    	"ASHIFT    max amplitude reduction of any segment: Range (0.0 - 1.0)\n"
+    	"-d        double filtering.\n"
+	  	"-i        Turn off Interpolation during pitch shift: (fast but dirty).\n"
+    	"-e        Exponential decay added: each seg gets quieter before next enters.\n"
+    	"-n        turns OFF normalisation: segs may grow or fall in level quickly.\n",
+    	FLT_MINFRQ,FLT_MINGAIN,FLT_MAXGAIN,MINQ, MAXQ, FLT_MINGAIN,FLT_MAXGAIN,FLT_MAXDELAY);
+
+	} else if (!strcmp(str,"sweeping")) {		 /* FLTSWEEP */
+		fprintf(stdout,
+	    "FILTER WHOSE FOCUS-FREQUENCY SWEEPS OVER A RANGE OF FREQUENCIES\n\n"
+		"USAGE:\n"
+		"filter sweeping mode infile outfile acuity gain lofrq hifrq sweepfrq [-ttail] [-pphase]\n\n"
+		"MODES ARE...\n"
+		"1) NOTCH (Band-reject). 3) LOW-PASS\n"
+		"2) BAND-PASS            4) HIGH-PASS  \n\n"
+	    "ACUITY   Acuity of filter:  Range(%lf to %.1lf)\n"		
+	    "         Smaller vals give tighter filter.\n"
+		"GAIN     overall gain on output:   Range(%lf to %.1lf)\n"		
+		"         Rule of thumb:\n"
+		"         if acuity = (1/3)to-power-n: gain = (2/3)-to-power-n\n"
+	    "LOFRQ    lowest frq to sweep to:   Range(%.1lf to srate/2)\n"	
+	    "HIFRQ    highest frq to sweep to:  Range(%.1lf to srate/2)\n"	
+	    "SWEEPFRQ frq of the sweep itself:  Range(0.0 to %.1lf)\n"		
+	    "         e.g. to sweep once over range, set sweepfrq to infiledur/2 (default)\n"		
+		"         and set phase to 0 (upsweep) or .5(downsweep)\n"
+		"TAIL      decay tail duration\n"
+		"PHASE    start of sweep: Range(0-1)\n"
+		"         vals are: 0 = (lofrq) rising to .5 = (hifrq) falling to 1 = (lofrq).\n"
+		"         Default value is .25 (midfrq,rising)\n\n"
+		"ACUITY, LOFRQ, HIFRQ and SWEEPFRQ may all vary over time.\n"
+		"This filter is most effective in BAND-PASS or LOW-PASS mode, at low ACUITY.\n",
+		MIN_ACUITY,MAX_ACUITY,FLT_MINGAIN,FLT_MAXGAIN,FLT_MINFRQ,FLT_MINFRQ,FLT_MAXSWEEP);
+
+	} else if (!strcmp(str,"phasing")) {		 /* ALLPASS */
+		fprintf(stdout,
+		"PHASESHIFT SOUND, OR PRODUCE 'PHASING' EFFECT\n\n"
+		"USAGE: filter phasing mode infile outfile gain delay [-ttail] [-sprescale] [-l]\n\n"
+		"MODES ARE..\n"
+		"1) ALLPASS FILTER (PHASE-SHIFTED)\n"
+		"2) PHASING EFFECT\n\n"
+		"GAIN      Range (-1.0 to 1.0)\n"
+		"          In MODE 2, phasing effect increases as gain increases from -1\n"
+		"          BUT a gain of 1.0 will produce complete phase cancellation\n"
+		"          and the output signal will be zero.\n"
+		"DELAY     >0.0 MS\n"
+		"TAIL      decay tail duration\n"
+		"PRESCALE  gain on the INPUT to the filtering process.\n"
+    	"          Range (0.0 - 1.0) Default 1.0\n"
+		"-l        linear interpolation of changing delay vals (default: logarithmic)\n\n"
+		"DELAY may vary over time.\n");
+	} else if (!strcmp(str,"vfilters")) {		 /* MAKE VFILTER FIXED-PITCH DATA FILES */
+		fprintf(stdout,
+		"MAKE FIXED-PITCH DATA-FILES FOR VARIBANK FILTER\n\n"
+		"USAGE: filter vfilters inpitchfile outfile\n\n"
+		"INPITCHFILE     Textfile, contains a list of MIDI or FRQ pitch values\n"
+		"                with one or more values on each line.\n"
+		"Each line is converted to a data file for a fixed pitch(es) filter,\n"
+		"of the 'varibank' type.\n"
+		"Producing outfile0.txt, outfile1.txt etc.\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);
+}
+
+/******************************** 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);
+}
+
+/**************************** CHECK_SEQ_AND_RANGE_OF_FILTER_DATA2 *******************************/
+
+int check_seq_and_range_of_filter_data2(double *fbrk,double *hbrk,dataptr dz)
+{
+	double lasttime = -1.0;
+	double maxpartial = dz->infile->srate/(2.0 * FLT_MINFRQ);
+	double minpartial = 1.0;
+	int n, m, lineno = 0;
+	double frqmax  = dz->infile->srate/2.0;
+	double midimax = unchecked_hztomidi(frqmax);
+	double midimin = unchecked_hztomidi(FLT_MINFRQ);
+
+	int wordcnt_in_line = dz->iparam[FLT_ENTRYCNT];
+	for(n=0;n<dz->iparam[FLT_WORDCNT];n++) {
+		m = n%wordcnt_in_line;
+		if(m==0) {
+			lineno++;				/* original line-no : ignoring comments */
+			if(fbrk[n] <= lasttime) {
+				sprintf(errstr,"Time is out of sequence in pitch data line %d\n",lineno);
+				return(DATA_ERROR);
+			}
+			lasttime = fbrk[n];
+		} else if(ODD(m)) {
+			if(dz->mode==FLT_MIDI) {
+				if(fbrk[n] < midimin || fbrk[n] > midimax) {
+					sprintf(errstr,"midi value [%.3lf] out of range (%.1f - %.1f) on line %d\n",
+					fbrk[n],midimin,midimax,lineno);
+					return(DATA_ERROR);
+				}
+				fbrk[n] = miditohz(fbrk[n]);
+			} else {
+				if(fbrk[n] < FLT_MINFRQ || fbrk[n] > frqmax) {
+					sprintf(errstr,"frq_or_midi value [%.3lf] out of range (%.1f - %.1f) on line %d\n",
+					fbrk[n],FLT_MINFRQ,frqmax,lineno);
+					return(DATA_ERROR);
+				}
+			}
+		} else
+			fbrk[n] = max(fbrk[n],MINFILTAMP);	/* Zero filter amp, forced to +ve, but effectively zero */
+	}
+	wordcnt_in_line = dz->iparam[HRM_ENTRYCNT];
+	lasttime = -1.0;
+	lineno = 0;
+	for(n=0;n<dz->iparam[HRM_WORDCNT];n++) {
+		m = n%wordcnt_in_line;
+		if(m==0) {
+			lineno++;
+			if(hbrk[n] <= lasttime) {
+				sprintf(errstr,"Time is out of sequence in partials data line %d\n",lineno);
+				return(DATA_ERROR);
+			}
+			lasttime = hbrk[n];
+		} else if(ODD(m)) {
+			if(hbrk[n]<minpartial|| hbrk[n]>maxpartial) {
+				sprintf(errstr,"partial value [%.3lf] out of range (%lf - %.1f) on line %d\n",hbrk[n],minpartial,maxpartial,lineno);
+				return(DATA_ERROR);
+			}
+		} else
+			hbrk[n] = max(hbrk[n],MINFILTAMP);	/* Zero filter amp, forced to +ve, but effectively zero */
+	}
+	return(FINISHED);
+}
+
+/**************************** READ_DATA_FROM_T_AND_P_VARY_INFILE *******************************/
+
+int read_data_from_t_and_p_vary_infile(char *filename,dataptr dz)
+{
+	int exit_status;
+	char *temp, *p, *thisword;
+	int maxlinelen, frqcnt = 0, hcnt;
+	int total_wordcnt = 0, number_of_rows = 0, total_number_of_rows = 0,columns_in_this_row,columns_in_row = 0;
+	int  harmdata = 0, ishash = 0, thisarray;
+
+	double val;
+	if((dz->fp = fopen(filename,"r"))==NULL) {
+		sprintf(errstr,"Cannot open datafile %s\n",filename);
+		return(DATA_ERROR);
+	}
+	if((exit_status = getmaxlinelen2(&maxlinelen,dz->fp))<0)
+		return(exit_status);
+	if((fseek(dz->fp,0,0))<0) {
+		sprintf(errstr,"Seek failed in get_data_from_t_and_p_vary_infile()\n");
+		return(SYSTEM_ERROR);
+	}
+	if((temp = (char *)malloc((maxlinelen+2) * sizeof(char)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for temporary line storage.\n");
+		return(MEMORY_ERROR);
+	}
+	while(fgets(temp,maxlinelen,dz->fp)!=NULL) {
+		columns_in_this_row = 0;
+		if(is_an_empty_line_or_a_comment(temp))
+			continue;
+		p = temp;
+		while(get_word_from_string(&p,&thisword)) {
+			if(!strncmp(thisword,"#",1)) {
+				if(harmdata) {
+					sprintf(errstr,"HASH SIGN AT WRONG PLACE IN DATA in LINE %d.\n",total_number_of_rows+1);
+					return(DATA_ERROR);
+				}
+				dz->iparam[FLT_WORDCNT] = total_wordcnt;
+				dz->iparam[FLT_ENTRYCNT] = columns_in_row;
+				total_wordcnt = 0;
+				number_of_rows = 0;
+				frqcnt = columns_in_row - 1;
+				harmdata = 1;
+				ishash = 1;
+				break;
+			}
+			if((exit_status = get_level(thisword,&val))<0) {	/* reads vals */
+				free(temp);
+				return(exit_status);
+			}
+			if(harmdata)
+				thisarray = FLT_HBRK;
+			else
+				thisarray = FLT_FBRK;
+			if(total_wordcnt==0) {
+				if ((dz->parray[thisarray] = (double *)malloc(sizeof(double)))==NULL) {
+					sprintf(errstr,"INSUFFICIENT MEMORY to reallocate filter brktables.\n");
+					return(MEMORY_ERROR);
+				}
+				dz->parray[thisarray][total_wordcnt] = val;
+			} else {
+				if ((dz->parray[thisarray] = (double *)realloc(dz->parray[thisarray],(total_wordcnt+1) * sizeof(double)))==NULL) {
+					sprintf(errstr,"INSUFFICIENT MEMORY to reallocate filter brktables.\n");
+					return(MEMORY_ERROR);
+				}
+			}
+			dz->parray[thisarray][total_wordcnt] = val;
+			columns_in_this_row++;
+			total_wordcnt++;
+		}
+		if(ishash) {
+			ishash = 0;
+			continue;
+		}
+		if(number_of_rows==0) {
+
+			if((columns_in_row = columns_in_this_row)<3) {
+				sprintf(errstr,"Insufficient data in row 1 of file %s.\n",filename);
+				free(temp);
+				return(DATA_ERROR);
+			} else if (ODD(columns_in_row - 1)) {
+				sprintf(errstr,"Value and Amp data not paired correctly (or no Time) in row %d of file %s.\n",total_number_of_rows+1,filename);
+				free(temp);
+				return(DATA_ERROR);
+			}
+		} else if(columns_in_this_row!=columns_in_row) {
+			free(temp);
+			if(columns_in_this_row < columns_in_row)
+				sprintf(errstr,"Not enough entries in row %d of file %s\n",total_number_of_rows+1,filename);
+			else
+				sprintf(errstr,"Too many entries in row %d of file %s\n",total_number_of_rows+1,filename);
+			return(DATA_ERROR);
+		}
+		number_of_rows++;
+		total_number_of_rows++;
+	}
+	dz->iparam[HRM_WORDCNT] = total_wordcnt;
+	free(temp);
+	if(columns_in_row<3) {
+		sprintf(errstr,"Insufficient data in each row, to define filters.\n");
+		return(DATA_ERROR);
+	}
+	dz->iparam[HRM_ENTRYCNT] = columns_in_row;
+	hcnt = columns_in_row - 1;
+	dz->iparam[FLT_CNT]       = frqcnt/2;
+	dz->iparam[FLT_HARMCNT]   = hcnt/2;
+	dz->iparam[FLT_CNT] *= dz->iparam[FLT_HARMCNT];
+	if(fclose(dz->fp)<0) {
+		fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
+		fflush(stdout);
+	}
+	if(dz->parray[FLT_FBRK][0] !=0.0) {
+		sprintf(errstr,"FIRST TIME VALUE FOR PITCHES MUST BE ZERO\n");
+		return(DATA_ERROR);
+	}
+	if(dz->parray[FLT_HBRK][0] !=0.0) {
+		sprintf(errstr,"FIRST TIME VALUE FOR HARMONICS MUST BE ZERO\n");
+		return(DATA_ERROR);
+	}
+	return check_seq_and_range_of_filter_data2(dz->parray[FLT_FBRK],dz->parray[FLT_HBRK],dz);
+}
+
+/**************************** GETMAXLINELEN2 *******************************/
+
+int getmaxlinelen2(int *maxcnt,FILE *fp)
+{
+	int thiscnt = 0;
+	int gothash = 0;
+	int gotdata1 = 0, gotdata2 = 0;
+	char c;
+	*maxcnt = 0;
+
+	while((c= (char)fgetc(fp))!=EOF) {
+		if(!gothash) {
+			if(c=='#') {
+				if(!gotdata1) {
+					sprintf(errstr,"FAILED TO GET FIRST SET OF DATA (PITCH INFORMATION) BEFORE HASH SIGN\n");
+					return(DATA_ERROR);
+				}
+				while((c= (char)fgetc(fp))!=EOF) {
+					if(c == '\n' || c == ENDOFSTR) {
+						gothash = 1;
+						thiscnt = 0;
+						break;
+					}
+				}
+				if(!gothash)
+					break;
+			} else {
+				if(c=='\n' || c == ENDOFSTR) {
+					*maxcnt = max(*maxcnt,thiscnt);
+					thiscnt = 0;
+					gotdata1 = 1;
+				} else {
+					thiscnt++;			
+				}
+			}
+		} else {
+			if(c=='\n' || c == ENDOFSTR) {
+				*maxcnt = max(*maxcnt,thiscnt);
+				thiscnt = 0;
+				gotdata2 = 1;
+			} else {
+				thiscnt++;			
+			}
+		}
+	}
+	if(!gotdata2) {
+		sprintf(errstr,"FAILED TO GET SECOND SET OF DATA (PARTIALS INFORMATION) AFTER HASH SIGN\n");
+		return(DATA_ERROR);
+	}
+	*maxcnt = (int)max(*maxcnt,thiscnt);
+	*maxcnt += 4;	/* NEWLINE, ENDOFSTR and safety!! */
+	return(FINISHED);
+}			
+

+ 1217 - 0
dev/filter/filters0-711.c

@@ -0,0 +1,1217 @@
+/*
+ * 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
+ *
+ */
+
+
+
+/* floatsams version*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <processno.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <filters.h>
+#include <cdpmain.h>
+#include <sfsys.h>
+/*RWD*/
+#include <string.h>
+
+#ifndef cdp_round
+extern int cdp_round(double a);
+#endif
+
+#if defined unix || defined __GNUC__
+#define round(x) lround((x))
+#endif
+
+static void 	filtering(int n,int chans,float *buf,
+					double *a,double *b,double *y,double *z,double *d,double *e,double *ampl,dataptr dz);
+static double	check_float_limits(double sum, dataptr dz);
+static int 		newvalue(int valno,int valincrno, int sampcntno, dataptr dz);
+static int 		newfval(int *fsams,dataptr dz);
+static int 		do_filters(dataptr dz);
+static int 		do_qvary_filters(dataptr dz);
+static int 		do_fvary_filters(dataptr dz);
+static void		print_filter_frqs(dataptr dz);
+static int 		do_varifilter(dataptr dz);
+static int 		do_sweep_filter(dataptr dz);
+static double 	getfrq(double lfrq,double hfrq,double sfrq,dataptr dz);
+static int 		do_allpass_filter(dataptr dz);
+static int 		allpass(float *buf,int chans,double prescale,dataptr dz);
+static int 		varidelay_allpass(float *buf,int chans,double prescale,dataptr dz);
+static int 		do_eq_filter(dataptr dz);
+static float    multifilter(double *dll,double *dbb,double *dnn,double *dhh,double *dpp,
+					double qfac,double coeff,float input,dataptr dz);
+static int 		do_lphp_filter(dataptr dz);
+static int 	my_modulus(int x,int y);
+static void lphp_filt_chan(double *e1,double *e2,double *s1,double *s2,
+					double *den1,double *den2,double *cn,dataptr dz,int chan);
+
+static int		do_fvary2_filters(dataptr dz);
+
+/****************************** FILTER_PROCESS *************************/
+
+int filter_process(dataptr dz)
+{
+	int exit_status = FINISHED;
+	int filter_tail = 0, bufspace;
+	if(dz->process==FLTBANKC) {
+		print_filter_frqs(dz);
+		return(FINISHED);
+	}
+	display_virtual_time(0,dz);
+
+
+/* NEW CODE */
+	if(dz->process==FLTBANKV) {
+		if((exit_status = newfval(&(dz->iparam[FLT_FSAMS]),dz))<0)
+			return(exit_status);
+	} else 	if(dz->process==FLTBANKV2) {
+		dz->iparam[FLT_FSAMS] = dz->iparam[FLT_BLOKSIZE];
+		dz->param[FLT_TIMESTEP] = (double)dz->iparam[FLT_BLOKSIZE]/(double)dz->infile->srate;
+		dz->param[FLT_TOTALTIME] = 0.0;
+		if((exit_status = newfval2(dz->parray[FLT_FBRK],dz->parray[FLT_HBRK],dz))<0)
+			return(exit_status);
+	}
+/* NEW CODE */
+
+	while(dz->samps_left > 0 || filter_tail > 0) {
+		memset((char *)dz->sampbuf[0],0,(size_t) (dz->buflen * sizeof(float)));
+		if(filter_tail) {
+			dz->ssampsread = 0;			
+		} else {
+			if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
+				return(exit_status);
+			if(dz->samps_left <= 0) {
+				if(dz->process==FLTBANKV || dz->process==FLTBANKV2)
+					filter_tail = round(dz->param[FILT_TAILV] * (double)dz->infile->srate) * dz->infile->channels;
+				else 
+					filter_tail = (int)round((dz->param[FILT_TAIL] * (double)dz->infile->srate) * dz->infile->channels);
+            }
+        }
+		if(filter_tail) {
+			bufspace = dz->buflen - dz->ssampsread;
+			if(bufspace >= filter_tail) {
+				dz->ssampsread += filter_tail;				
+				filter_tail = 0;
+			} else {
+				dz->ssampsread = dz->buflen;				
+				filter_tail -= bufspace;
+			}
+		}
+		switch(dz->process) {
+		case(FLTBANKN):
+		case(FLTBANKU):
+			if(dz->brksize[FLT_Q])	
+				exit_status = do_qvary_filters(dz);
+			else					
+				exit_status = do_filters(dz);
+			break;
+		case(FLTBANKV):	exit_status = do_fvary_filters(dz);		break;
+		case(FLTBANKV2):exit_status = do_fvary2_filters(dz);	break;
+		case(FLTSWEEP):	exit_status = do_sweep_filter(dz);		break;
+		case(FSTATVAR):	exit_status = do_varifilter(dz);		break;
+		case(ALLPASS):	exit_status = do_allpass_filter(dz);	break;
+		case(EQ):	    exit_status = do_eq_filter(dz);			break;
+		case(LPHP):	    exit_status = do_lphp_filter(dz);		break;
+		}
+		if(exit_status <0)
+			return(exit_status);
+		if(dz->ssampsread > 0) {
+			if((exit_status = write_samps(dz->sampbuf[0],dz->ssampsread,dz))<0)
+				return(exit_status);
+		}
+	}				
+    if(dz->iparam[FLT_OVFLW] > 0)  {
+		if(!sloom && !sloombatch)
+			fprintf(stdout,"Number of overflows: %d\n",dz->iparam[FLT_OVFLW]);
+		else
+			fprintf(stdout,"INFO: Number of overflows: %d\n",dz->iparam[FLT_OVFLW]);
+		fflush(stdout);
+	}
+	return(FINISHED);
+}
+
+/*************************** DO_FVARY_FILTERS *****************************/
+
+int do_fvary_filters(dataptr dz)
+{
+	int exit_status;
+	int    n, m, fno, chans = dz->infile->channels;
+	float *buf = dz->sampbuf[0];
+
+	double *fincr = dz->parray[FLT_FINCR];
+	double *aincr = dz->parray[FLT_AINCR];
+ 
+ 	double *ampl = dz->parray[FLT_AMPL];
+	double *a = dz->parray[FLT_A];
+	double *b = dz->parray[FLT_B];
+	double *y = dz->parray[FLT_Y];
+	double *z = dz->parray[FLT_Z];
+	double *d = dz->parray[FLT_D];
+	double *e = dz->parray[FLT_E];
+ 	int fsams = dz->iparam[FLT_FSAMS];
+	if (dz->vflag[DROP_OUT_AT_OVFLOW]) {
+		for (n = 0; n < dz->ssampsread; n += chans) { 
+			if(fsams <= 0) {
+				if((exit_status = newfval(&fsams,dz))<0)
+					return(exit_status);
+			}
+			if(dz->brksize[FLT_Q]) {
+				if((dz->iparam[FLT_SAMS] -= chans) <= 0) {
+					if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) {
+						sprintf(errstr,"Ran out of Q values: do_fvary_filters()\n");
+						return(PROGRAM_ERROR);
+					}
+					dz->iparam[FLT_SAMS] *= chans;
+				}
+			}
+			if((dz->iparam[FLT_BLOKCNT] -= chans) <= 0) {
+				for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) {
+					get_coeffs1(fno,dz);
+					get_coeffs2(fno,dz);
+				}
+				if(dz->brksize[FLT_Q])
+					dz->param[FLT_Q] *= dz->param[FLT_Q_INCR];
+				
+				for(m=0;m<dz->iparam[FLT_CNT];m++) {
+					dz->parray[FLT_FRQ][m] *= fincr[m];
+					dz->parray[FLT_AMP][m] *= aincr[m];
+				}
+				dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE] * chans;
+			}
+			filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz);
+			if(dz->iparam[FLT_OVFLW] > 0) {
+				sprintf(errstr,"Filter overflowed\n");
+				return(GOAL_FAILED);
+			}
+			fsams--;
+		}
+	} else {
+		for (n = 0; n < dz->ssampsread; n += chans) { 
+			if(fsams <= 0) {
+				if((exit_status = newfval(&fsams,dz))<0)
+					return(exit_status);
+			}
+			if(dz->brksize[FLT_Q]) {
+				if((dz->iparam[FLT_SAMS] -= chans) <= 0) {
+					if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) {
+			 			sprintf(errstr,"Ran out of Q values: do_fvary_filters()\n");
+						return(PROGRAM_ERROR);
+					}
+					dz->iparam[FLT_SAMS] *= chans;
+				}
+			}
+			if((dz->iparam[FLT_BLOKCNT] -= chans) <= 0) {
+				for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) {
+					get_coeffs1(fno,dz);
+					get_coeffs2(fno,dz);
+				}
+				if(dz->brksize[FLT_Q])
+					dz->param[FLT_Q] *= dz->param[FLT_Q_INCR];
+
+				for(m=0;m<dz->iparam[FLT_CNT];m++) {
+					dz->parray[FLT_FRQ][m] *= fincr[m];
+					dz->parray[FLT_AMP][m] *= aincr[m];
+				}
+				dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE] * chans;
+			}
+			filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz);
+			fsams--;
+		}
+	}
+ 	dz->iparam[FLT_FSAMS] = fsams;
+	return(CONTINUE);
+}
+
+/*************************** DO_FILTERS *******************************/
+
+int do_filters(dataptr dz)
+{
+	int n;
+	int  chans = dz->infile->channels;
+	float *buf = dz->sampbuf[0];
+	double *ampl = dz->parray[FLT_AMPL];
+	double *a = dz->parray[FLT_A];
+	double *b = dz->parray[FLT_B];
+	double *y = dz->parray[FLT_Y];
+	double *z = dz->parray[FLT_Z];
+	double *d = dz->parray[FLT_D];
+	double *e = dz->parray[FLT_E];
+	for (n = 0; n < dz->ssampsread; n += chans)
+		filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz);
+	return(CONTINUE);
+}
+
+/*************************** DO_QVARY_FILTERS *****************************/
+
+int do_qvary_filters(dataptr dz)
+{
+	int   n;
+	int    fno, chans = dz->infile->channels;
+	float *buf = dz->sampbuf[0];
+	double *ampl = dz->parray[FLT_AMPL];
+	double *a = dz->parray[FLT_A];
+	double *b = dz->parray[FLT_B];
+	double *y = dz->parray[FLT_Y];
+	double *z = dz->parray[FLT_Z];
+	double *d = dz->parray[FLT_D];
+	double *e = dz->parray[FLT_E];
+
+	for (n = 0; n < dz->ssampsread; n += chans) { 
+		if((dz->iparam[FLT_SAMS] -= chans) <= 0) {
+			if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) {
+		 		sprintf(errstr,"Ran out of Q values: do_qvary_filters()\n");
+				return(PROGRAM_ERROR);
+			}
+			dz->iparam[FLT_SAMS] *= chans;
+		}
+		if((dz->iparam[FLT_BLOKCNT] -= chans) <= 0) {
+			for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++)
+				get_coeffs2(fno,dz);
+			dz->param[FLT_Q] *= dz->param[FLT_Q_INCR];
+			dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE] * chans;
+		}
+		filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz);
+	}
+	return(CONTINUE);
+}
+
+/******************************* NEWVALUE ***************************
+ *
+ * VAL     is the base value from which we calculate.
+ * VALINCR is the value increment per block of samples.
+ * SAMPCNT is the number of samples from 1 brkpnt val to next.
+ */					   
+
+int newvalue(int valno,int valincrno, int sampcntno, dataptr dz)
+{
+	double *p;				   
+	double ratio, one_over_steps;
+	double thistime;
+	double thisval;
+	int    linear_flag = FALSE;
+	if(dz->process==ALLPASS && valno==FLT_DELAY)	
+		linear_flag = dz->vflag[FLT_LINDELAY];
+	p = dz->brkptr[valno];
+	if(p - dz->brk[valno] >= dz->brksize[valno] * 2)
+		return(FALSE);
+	thistime = (double)round((*p++) * dz->infile->srate);
+	thisval  = *p++;
+	dz->iparam[sampcntno]    = round(thistime - dz->lastind[valno]);
+	/* steps = no_of_samples/sampsize_of_blok: therefore.. */
+	one_over_steps = (double)dz->iparam[FLT_BLOKSIZE]/(double)dz->iparam[sampcntno];	
+	if(linear_flag)
+		dz->param[valincrno] = (thisval - dz->lastval[valno]) * one_over_steps;
+	else {
+		ratio                = (thisval/dz->lastval[valno]);
+		dz->param[valincrno] = pow(ratio,(one_over_steps));
+	}					 
+	dz->param[valno]     = dz->lastval[valno];
+	dz->lastval[valno]   = thisval;
+	dz->lastind[valno]   = thistime;
+	dz->brkptr[valno]    = p;
+	return(TRUE);
+}
+
+/******************************* NEWFVAL ***************************
+ *
+ * VAL is the base value from which we calculate.
+ * VALINCR is the value increment per block of samples.
+ * FSAMS is the number of samples (per channel) from 1 brkpnt val to next.
+ * brk is the particular table we're accessing.
+ */
+
+int newfval(int *fsams,dataptr dz)
+{
+	int   thistime, lasttime;
+	double rratio, one_over_steps;
+	int   n,m,k;
+	double thisval;
+	double *lastfval = dz->parray[FLT_LASTFVAL];
+	double *lastaval = dz->parray[FLT_LASTAVAL];
+	double *aincr    = dz->parray[FLT_AINCR];
+	double *fincr    = dz->parray[FLT_FINCR];
+	int total_frqcnt = dz->iparam[FLT_CNT] * dz->iparam[FLT_TIMESLOTS];
+	
+	if(dz->iparam[FLT_TIMES_CNT]>dz->iparam[FLT_TIMESLOTS]) {
+		sprintf(errstr,"Ran off end of filter data: newfval()\n"); 
+		return(PROGRAM_ERROR);
+	}
+	k = dz->iparam[FLT_TIMES_CNT];
+	lasttime  = dz->lparray[FLT_SAMPTIME][k-1];
+	thistime  = dz->lparray[FLT_SAMPTIME][k];
+	*fsams = thistime - lasttime;
+	/* steps  = fsams/FLT_BLOKSIZE: therefore ... */	
+	one_over_steps  = (double)dz->iparam[FLT_BLOKSIZE]/(double)(*fsams);	
+	if(dz->iparam[FLT_FRQ_INDEX] >= total_frqcnt)
+		return(FINISHED);
+	for(n=0, m= dz->iparam[FLT_FRQ_INDEX];n<dz->iparam[FLT_CNT];n++,m++) {
+	/* FREQUENCY */
+		thisval = dz->parray[FLT_INFRQ][m];
+		if(flteq(lastfval[n],thisval))
+			fincr[n] = 1.0;
+		else {
+			rratio = (thisval/lastfval[n]);
+			fincr[n] = pow(rratio,one_over_steps);
+		}
+		dz->parray[FLT_FRQ][n] = lastfval[n];
+		lastfval[n] = thisval;
+	/* AMPLITUDE */
+		thisval = dz->parray[FLT_INAMP][m];
+		if(flteq(thisval,lastaval[n]))
+			aincr[n] = 1.0;
+		else {
+			rratio = (thisval/lastaval[n]);
+			aincr[n] = pow(rratio,one_over_steps);
+		}
+		dz->parray[FLT_AMP][n] = lastaval[n];
+		lastaval[n] = thisval;
+	}
+	dz->iparam[FLT_FRQ_INDEX] += dz->iparam[FLT_CNT];
+	dz->iparam[FLT_TIMES_CNT]++;
+	return(FINISHED);
+}
+
+/************************** FILTERING ****************************/
+
+void filtering(int n,int chans,float *buf,double *a,double *b,double *y,double *z,
+				double *d,double *e,double *ampl,dataptr dz)
+{
+	double input, sum, xx;
+	int chno, this_samp, fno, i;
+
+	for(chno = 0; chno < chans; chno++) {
+		this_samp = n + chno;
+		input = (double)buf[this_samp];
+		sum   = 0.0;
+		for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) {
+			i    = (fno * chans) + chno;
+			xx   = input + (a[fno] * y[i]) + (b[fno] * z[i]);
+			z[i] = y[i];
+			y[i] = xx;
+			if(dz->vflag[FLT_DBLFILT]) {
+				xx   += (a[fno] * d[i]) + (b[fno] * e[i]);
+				e[i] = d[i];
+				d[i] = xx;
+			}
+			sum += (xx * ampl[fno]);
+		}
+		sum *= dz->param[FLT_GAIN];
+		sum = check_float_limits(sum,dz);
+		buf[this_samp] = (float) sum;
+	}
+}
+
+/************************** IO_FILTERING ****************************/
+
+void io_filtering
+(float *buf1,float *buf2,int chans,int n,
+double *a,double *b,double *y,double *z,double *d,double *z1,double *ampl,dataptr dz)
+{
+	double input, sum, xx;
+	int    chno, this_samp, fno, i;
+	for(chno = 0; chno < chans; chno++) {
+		this_samp = n + chno;
+		input = (double)buf1[this_samp];
+		sum   = 0.0;
+		for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) {
+			i    = (fno * chans) + chno;
+			xx   = input + (a[fno] * y[i]) + (b[fno] * z[i]);
+			z[i] = y[i];
+			y[i] = xx;
+			if(dz->vflag[FLT_DBLFILT]) {
+				xx   += (a[fno] * d[i]) + (b[fno] * z1[i]);
+				z1[i] = d[i];
+				d[i] = xx;
+			}
+			sum += (xx * ampl[fno]);
+		}
+		sum *= dz->param[FLT_GAIN];
+		sum = check_float_limits(sum,dz);
+		buf2[this_samp] = (float) sum;
+	}
+}
+
+/************************ CHECK_FLOAT_LIMITS **************************/
+
+//TODO: if shorts o/p - do clipping; if floatsams, report but don't change!
+double check_float_limits(double sum,dataptr dz)
+{
+	double peak = fabs(sum);
+#ifdef NOTDEF
+	//do this when 'modify loudness' can handle floatsams!
+	if(dz->true_outfile_stype== SAMP_FLOAT){
+		
+		if(peak > 1.0){
+			dz->iparam[FLT_OVFLW]++;
+			dz->peak_fval = max(dz->peak_fval,peak);
+		}		
+	}
+	else {
+#endif
+		if (sum > 1.0) {
+//TW SUGGEST KEEP THIS; prevents FILTER BLOWING UP: see notes
+			dz->param[FLT_GAIN] *= 0.9999;
+			dz->iparam[FLT_OVFLW]++;
+			dz->peak_fval = max(dz->peak_fval,peak);
+			//return(1.0);
+			if(dz->clip_floatsams)
+				sum = 1.0;
+		}
+		if (sum < -1.0) {
+//TW SUGGEST KEEP THIS; prevents FILTER BLOWING UP: see notes
+
+			dz->param[FLT_GAIN] *= 0.9999;
+			dz->iparam[FLT_OVFLW]++;
+			dz->peak_fval = max(dz->peak_fval,peak);
+			//return(-1.0);
+			if(dz->clip_floatsams)
+				sum = -1.0;
+		}
+#ifdef NOTDEF
+	}
+#endif
+	return sum;
+}
+/************************ PRINT_FILTER_FRQS *******************************/
+
+void print_filter_frqs(dataptr dz)
+{
+	int n;
+	double *frq = dz->parray[FLT_FRQ];
+	for(n=0;n<dz->iparam[FLT_CNT];n++)
+		fprintf(dz->fp,"%lf\n",frq[n]);
+}
+	
+/******************************* DO_VARIFILTER ******************************/
+
+int do_varifilter(dataptr dz)
+{
+	double *dls = dz->parray[FLT_DLS];
+ 	double *dbs = dz->parray[FLT_DBS];
+	double *dhs = dz->parray[FLT_DHS];
+	double *dns = dz->parray[FLT_DNS];
+	double *dops[2];
+	double coeff = 0.0;
+	float  *buf  = dz->sampbuf[0];
+	int   n;
+	int    k, chans = dz->infile->channels;
+	int    is_fbrk = FALSE, is_qbrk = FALSE;
+	if(dz->brksize[FLT_ONEFRQ])	is_fbrk = TRUE;
+	if(dz->brksize[FLT_Q])	    is_qbrk = TRUE;
+	for(n=0;n<chans;n++) {
+		switch(dz->mode){
+		case(FSW_HIGH):		dops[n] = &(dz->parray[FLT_DHS][n]);	break;
+		case(FSW_LOW):		dops[n] = &(dz->parray[FLT_DLS][n]);	break;
+		case(FSW_BAND):		dops[n] = &(dz->parray[FLT_DBS][n]);	break;
+		case(FSW_NOTCH):	dops[n] = &(dz->parray[FLT_DNS][n]);	break;
+		}
+	}
+	for (n = 0 ; n < dz->ssampsread; n += chans) {
+		if(is_fbrk && (--dz->iparam[FLT_FSAMS] <= 0)) {
+			if(!newvalue(FLT_ONEFRQ,FLT_F_INCR,FLT_FSAMS,dz)) {
+		 		sprintf(errstr,"Ran out of sweepfrq values: do_varifilter()\n");
+				return(PROGRAM_ERROR);
+			}
+		}
+		if(is_qbrk && (--dz->iparam[FLT_SAMS] <= 0)) {
+			if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) { 
+		 		sprintf(errstr,"Ran out of Q values: do_sweep_filter()\n");
+				return(PROGRAM_ERROR);
+			}
+		}
+		if(--dz->iparam[FLT_BLOKCNT] <= 0){
+			coeff = (2.0 * PI * dz->param[FLT_ONEFRQ]) * dz->param[FLT_INV_SR];
+			if(is_fbrk)    dz->param[FLT_ONEFRQ] *= dz->param[FLT_F_INCR];
+			if(is_qbrk) {
+				dz->param[FLT_QFAC] = 1.0/(1.0 + dz->param[FLT_Q]);
+				dz->param[FLT_Q]   *= dz->param[FLT_Q_INCR];
+			}
+			dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE];
+		}
+		for(k=0;k<chans;k++)
+			buf[n+k] = multifilter(&(dbs[k]),&(dls[k]),&(dhs[k]),&(dns[k]),dops[k],dz->param[FLT_Q],coeff,buf[n+k],dz);
+	}
+	return(CONTINUE);
+}
+
+/******************************* DO_SWEEP_FILTER ******************************/
+
+int do_sweep_filter(dataptr dz)
+{
+	double *dls = dz->parray[FLT_DLS];
+ 	double *dbs = dz->parray[FLT_DBS];
+	double *dhs = dz->parray[FLT_DHS];
+	double *dns = dz->parray[FLT_DNS];
+	double *dops[2];
+	double coeff = 0.0, frq;
+	float  *buf  = dz->sampbuf[0];
+	int   n;
+	int    k, chans = dz->infile->channels;
+	int    is_lbrk = FALSE, is_hbrk = FALSE, is_sbrk = FALSE, is_qbrk = FALSE;
+	if(dz->brksize[FLT_LOFRQ])	is_lbrk = TRUE;
+	if(dz->brksize[FLT_HIFRQ])	is_hbrk = TRUE;
+	if(dz->brksize[FLT_SWPFRQ])	is_sbrk = TRUE;
+	if(dz->brksize[FLT_Q])	    is_qbrk = TRUE;
+	for(n=0;n<chans;n++) {
+		switch(dz->mode){
+		case(FSW_HIGH):		dops[n] = &(dz->parray[FLT_DHS][n]);	break;
+		case(FSW_LOW):		dops[n] = &(dz->parray[FLT_DLS][n]);	break;
+		case(FSW_BAND):		dops[n] = &(dz->parray[FLT_DBS][n]);	break;
+		case(FSW_NOTCH):	dops[n] = &(dz->parray[FLT_DNS][n]);	break;
+		}
+	}
+	for (n = 0 ; n < dz->ssampsread; n += chans) {
+		if(is_lbrk && (--dz->iparam[FLT_LOSAMS] <= 0)) {
+			if(!newvalue(FLT_LOFRQ,FLT_LOINCR,FLT_LOSAMS,dz)) { 
+		 		sprintf(errstr,"Ran out of lofrq values: do_sweep_filter()\n");
+				return(PROGRAM_ERROR);
+			}
+		}
+		if(is_hbrk && (--dz->iparam[FLT_HISAMS] <= 0)) {
+			if(!newvalue(FLT_HIFRQ,FLT_HIINCR,FLT_HISAMS,dz)) { 
+		 		sprintf(errstr,"Ran out of hifrq values: do_sweep_filter()\n");
+				return(PROGRAM_ERROR);
+			}
+		}
+		if(is_sbrk && (--dz->iparam[FLT_SWSAMS] <= 0)) {
+			if(!newvalue(FLT_SWPFRQ,FLT_SWINCR,FLT_SWSAMS,dz)) { 
+		 		sprintf(errstr,"Ran out of sweepfrq values: do_sweep_filter()\n");
+				return(PROGRAM_ERROR);
+			}
+		}
+		if(is_qbrk && (--dz->iparam[FLT_SAMS] <= 0)) {
+			if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) { 
+		 		sprintf(errstr,"Ran out of Q values: do_sweep_filter()\n");
+				return(PROGRAM_ERROR);
+			}
+		}
+		if(--dz->iparam[FLT_BLOKCNT] <= 0){
+			frq   = getfrq(dz->param[FLT_LOFRQ],dz->param[FLT_HIFRQ],dz->param[FLT_SWPFRQ],dz);
+			coeff = (2.0 * PI * frq) * dz->param[FLT_INV_SR];
+			if(is_lbrk)    dz->param[FLT_LOFRQ]  *= dz->param[FLT_LOINCR];
+			if(is_hbrk)    dz->param[FLT_HIFRQ]  *= dz->param[FLT_HIINCR];
+			if(is_sbrk)    dz->param[FLT_SWPFRQ] *= dz->param[FLT_SWINCR];
+			if(is_qbrk) {
+				dz->param[FLT_QFAC] = 1.0/(1.0 + dz->param[FLT_Q]);
+				dz->param[FLT_Q]   *= dz->param[FLT_Q_INCR];
+			}
+			dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE];
+		}
+		for(k=0;k<chans;k++)
+			buf[n+k] = multifilter(&(dbs[k]),&(dls[k]),&(dhs[k]),&(dns[k]),dops[k],dz->param[FLT_Q],coeff,buf[n+k],dz);
+	}
+	return(CONTINUE);
+}
+
+/*************************** GETFRQ ****************************
+ *
+ * NB sfrq is already adjusted to advance over a whole flt_blok.
+ */
+
+double getfrq(double lfrq,double hfrq,double sfrq,dataptr dz)
+{
+	double thispos;
+	double range = hfrq - lfrq;
+	thispos  = (cos(dz->param[FLT_CYCPOS]) + 1.0) * 0.5;
+	dz->param[FLT_CYCPOS]  =  fmod(dz->param[FLT_CYCPOS] + sfrq,TWOPI);
+	return((thispos * range) + lfrq);
+}
+
+/******************************* DO_ALLPASS_FILTER ******************************/
+
+int do_allpass_filter(dataptr dz)
+{
+	int exit_status;
+	int    chans    = dz->infile->channels;
+	float  *buf     = dz->sampbuf[0];
+	double prescale = dz->param[FLT_PRESCALE];
+
+	if(dz->brksize[FLT_DELAY])   
+		exit_status = varidelay_allpass(buf,chans,prescale,dz);
+	else
+		exit_status = allpass(buf,chans,prescale,dz);
+
+	return(exit_status);
+}
+
+/******************************* VARIDELAY_ALLPASS ******************************/
+
+int varidelay_allpass(float *buf,int chans,double prescale,dataptr dz)
+{
+	int   n, thisdelbfpos1, thisdelbfpos2, sampno;
+	int    delay, channo;
+	double frac, ip, op, delval1,delval2, delval;
+	double *delbuf1 = dz->parray[FLT_DELBUF1];
+	double *delbuf2 = dz->parray[FLT_DELBUF2];
+	int    maxdelsamps = dz->iparam[FLT_MAXDELSAMPS] * chans;
+	int	   delbufpos   = dz->iparam[FLT_DELBUFPOS];
+	switch(dz->mode) {
+	case(FLT_PHASESHIFT):
+		for(n=0;n<dz->ssampsread;n+= chans){
+			if(--dz->iparam[FLT_SAMS] <= 0) {
+				if(!newvalue(FLT_DELAY,FLT_D_INCR,FLT_SAMS,dz)) {
+		 			sprintf(errstr,"Ran out of Delay vals: varidelay_allpass()\n");
+					return(PROGRAM_ERROR);
+				}
+			}
+			delay = (int)dz->param[FLT_DELAY];
+			frac  = dz->param[FLT_DELAY] - (double)delay;
+			for(channo = 0;channo < chans; channo++) {
+				sampno = n + channo;
+				thisdelbfpos1 = my_modulus((delbufpos - (delay*chans)),maxdelsamps);
+				thisdelbfpos2 = my_modulus((thisdelbfpos1 + chans)    ,maxdelsamps);
+				ip = (double)buf[sampno]	* prescale;
+				op = (-dz->param[FLT_GAIN]) * ip;
+				delval1     = delbuf1[thisdelbfpos1];
+				delval2     = delbuf1[thisdelbfpos2];
+				delval      = delval1 + ((delval2 - delval1) * frac);
+				op += delval;
+				delval1     = delbuf2[thisdelbfpos1];
+				delval2     = delbuf2[thisdelbfpos2];
+				delval      = delval1 + ((delval2 - delval1) * frac);
+				op += dz->param[FLT_GAIN] * delval;
+				delbuf1[delbufpos] = ip;
+				delbuf2[delbufpos] = op;
+				if(++delbufpos >= maxdelsamps)
+//					delbufpos = 0;
+					delbufpos -= maxdelsamps;		/*RWD 9:2001 */
+//TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time
+//   so (delbufpos -= maxdelsamps) = 0
+				buf[sampno] = (float) (op);
+			}
+			if(dz->vflag[FLT_LINDELAY])
+				dz->param[FLT_DELAY] += dz->param[FLT_D_INCR];
+			else
+				dz->param[FLT_DELAY] *= dz->param[FLT_D_INCR];
+		}
+		break;
+	case(FLT_PHASER):
+		for(n=0;n<dz->ssampsread;n+= chans){
+			if(--dz->iparam[FLT_SAMS] <= 0) {
+				if(!newvalue(FLT_DELAY,FLT_D_INCR,FLT_SAMS,dz)) {
+	 				sprintf(errstr,"Ran out of Delay vals: varidelay_allpass()\n");
+					return(PROGRAM_ERROR);
+				}
+			}
+			delay = (int)dz->param[FLT_DELAY];
+			frac  = dz->param[FLT_DELAY] - (double)delay;
+			for(channo = 0;channo < chans; channo++) {
+				sampno = n + channo;
+				thisdelbfpos1 = my_modulus((delbufpos - (delay*chans)),maxdelsamps);
+				thisdelbfpos2 = my_modulus((thisdelbfpos1 + chans)    ,maxdelsamps);
+				ip = (double)buf[sampno]	* prescale;
+				op = (-dz->param[FLT_GAIN]) * ip;
+				delval1     = delbuf1[thisdelbfpos1];
+				delval2     = delbuf1[thisdelbfpos2];
+				delval      = delval1 + ((delval2 - delval1) * frac);
+				op += delval;
+				delval1     = delbuf2[thisdelbfpos1];
+				delval2     = delbuf2[thisdelbfpos2];
+				delval      = delval1 + ((delval2 - delval1) * frac);
+				op += dz->param[FLT_GAIN] * delval;
+				delbuf1[delbufpos] = ip;
+				delbuf2[delbufpos] = op;
+				if(++delbufpos >= maxdelsamps)
+					//delbufpos = 0;
+					delbufpos -= maxdelsamps;	/*RWD 9:2001 (see e_tmp/cdpfloat ) */
+//TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time
+//   so (delbufpos -= maxdelsamps) = 0
+				buf[sampno] = (float) ((op + (double)buf[sampno]) * 0.5);
+			}
+			if(dz->vflag[FLT_LINDELAY])
+				dz->param[FLT_DELAY] += dz->param[FLT_D_INCR];
+			else
+				dz->param[FLT_DELAY] *= dz->param[FLT_D_INCR];
+		}
+		break;
+	default:
+		sprintf(errstr,"Unknown case:varidelay_allpass()\n");
+		return(PROGRAM_ERROR); 
+  	}
+	dz->iparam[FLT_DELBUFPOS] = delbufpos;
+	return(FINISHED);
+}
+
+/******************************* ALLPASS ******************************/
+
+int allpass(float *buf,int chans,double prescale,dataptr dz)
+{
+	int   n, sampno;
+	int    channo;
+	double *delbuf1 = dz->parray[FLT_DELBUF1];
+	double *delbuf2 = dz->parray[FLT_DELBUF2];
+	int    maxdelsamps = dz->iparam[FLT_MAXDELSAMPS] * chans;
+	int    delbufpos   = dz->iparam[FLT_DELBUFPOS];
+	double ip, op; 
+	switch(dz->mode) {
+	case(FLT_PHASESHIFT):
+		for(n=0;n<dz->ssampsread;n+=chans){
+			for(channo = 0;channo < chans; channo++) {
+				sampno = n + channo;
+				ip = (double)buf[sampno] * prescale;
+				op = (-dz->param[FLT_GAIN]) * ip;
+				op += delbuf1[delbufpos];
+				op += dz->param[FLT_GAIN] * delbuf2[delbufpos];
+				delbuf1[delbufpos] = ip;
+				delbuf2[delbufpos] = op;
+				if(++delbufpos >= maxdelsamps)
+					/*delbufpos = 0;*/
+					delbufpos -= maxdelsamps;			/*RWD */
+//TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time
+//   so (delbufpos -= maxdelsamps) = 0
+				buf[sampno] = (float)(op);
+			}
+		}
+		break;
+	case(FLT_PHASER):
+		for(n=0;n<dz->ssampsread;n+=chans){
+			for(channo = 0;channo < chans; channo++) {
+				sampno = n + channo;
+				ip = (double)buf[sampno] * prescale;
+				op = (-dz->param[FLT_GAIN]) * ip;
+				op += delbuf1[delbufpos];
+				op += dz->param[FLT_GAIN] * delbuf2[delbufpos];
+				delbuf1[delbufpos] = ip;
+				delbuf2[delbufpos] = op;
+				if(++delbufpos >= maxdelsamps)
+					/*delbufpos = 0;*/
+					delbufpos -= maxdelsamps;			/*RWD */
+//TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time
+//   so (delbufpos -= maxdelsamps) = 0
+				buf[sampno] = (float)((op + (double)buf[sampno]) * 0.5);
+			}
+		}
+		break;
+	default:
+		sprintf(errstr,"Unknown case: allpass()\n");
+		return(PROGRAM_ERROR);
+  	}
+	dz->iparam[FLT_DELBUFPOS] = delbufpos;
+	return(FINISHED);
+}
+
+/******************************* DO_EQ_FILTER ******************************/
+
+int do_eq_filter(dataptr dz)
+{
+	double ip, op;
+	int   n, sampno;
+	float  *buf = dz->sampbuf[0];
+	int   chans = dz->infile->channels, chno;
+	double *xx1	= dz->parray[FLT_XX1];
+	double *xx2 = dz->parray[FLT_XX2];
+	double *yy1 = dz->parray[FLT_YY1];
+	double *yy2 = dz->parray[FLT_YY2];
+	double a0   = dz->param[FLT_A0];
+	double a1   = dz->param[FLT_A1];
+	double a2   = dz->param[FLT_A2];
+	double b1   = dz->param[FLT_B1];
+	double b2   = dz->param[FLT_B2];
+	double prescale = dz->param[FLT_PRESCALE];
+	//double inv_of_maxsamp = 1.0/(double)F_MAXSAMP;
+	for(n = 0;n < dz->ssampsread; n+= chans){
+		for(chno = 0;chno < chans; chno++) {
+			sampno = n+chno;
+			ip  = (double)buf[sampno] /* * inv_of_maxsamp*/;
+			ip *= prescale;
+			op  = (a0 * ip) + (a1 * xx1[chno]) + (a2 * xx2[chno]) - (b1 * yy1[chno]) - (b2 * yy2[chno]);
+			xx2[chno] = xx1[chno];
+			xx1[chno] = ip;
+			yy2[chno] = yy1[chno];
+			yy1[chno] = op;
+			buf[sampno] = (float)(op);
+		}
+	}
+	return(FINISHED);
+}
+
+/************************** MULTIFILTER **************************/
+
+float multifilter(double *dll,double *dbb,double *dnn,double *dhh,double *dpp,
+					double qfac,double coeff,float input,dataptr dz)
+{
+	double dya, dsa;
+	dya   = (double)input;
+	*dhh  = (qfac * *dbb) - *dll - dya;
+	*dbb  = *dbb - (coeff * *dhh);
+	*dll  = *dll - (coeff * *dbb);
+	*dnn  = *dll + *dhh;
+	dsa   = (*dpp) * dz->param[FLT_GAIN]; /* dpp points to dhh,dbb,dll,dnn */
+#ifdef NOTDEF
+	if (fabs(dsa) > F_MAXSAMP) {
+		dz->iparam[FLT_OVFLW]++;
+		dz->param[FLT_GAIN] *= .9999;
+		if (dsa  > 0.0) 
+			dsa = (double)F_MAXSAMP;
+		else 
+			dsa = (double)F_MINSAMP;
+	}
+	return((float)dsa);	 /* TRUNCATE */
+#else
+	return (float) check_float_limits(dsa,dz);
+#endif
+}
+
+/***************************** FILTER *************************************/
+/* RWD TODO: add fix for nchans */
+
+//int do_lphp_filter(dataptr dz)
+//{
+//	double *e1s,*e2s,*s1s,*s2s;
+//	double *e1	 = dz->parray[FLT_E1];
+//	double *e2	 = dz->parray[FLT_E2];
+//	double *s1	 = dz->parray[FLT_S1];
+//	double *s2	 = dz->parray[FLT_S2];
+//	double *den1 = dz->parray[FLT_DEN1];
+//	double *den2 = dz->parray[FLT_DEN2];
+//	double *cn	 = dz->parray[FLT_CN];
+//	switch(dz->infile->channels) {
+//	case(STEREO):
+//		e1s	 = dz->parray[FLT_E1S];
+//		e2s	 = dz->parray[FLT_E2S];
+//		s1s	 = dz->parray[FLT_S1S];
+//		s2s	 = dz->parray[FLT_S2S];
+//		lphp_filt_stereo(e1,e2,s1,s2,e1s,e2s,s1s,s2s,den1,den2,cn,dz);
+//		break;
+//	case(MONO):
+//		lphp_filt(e1,e2,s1,s2,den1,den2,cn,dz);
+//		break;
+//	}
+//	return(FINISHED);
+//}
+//		
+// TW MULTICHAN 2010
+int do_lphp_filter(dataptr dz)
+{
+	int i;
+	int index;
+	
+	double *e1,*e2,*s1,*s2;
+	
+	double *den1 = dz->parray[FLT_DEN1];
+	double *den2 = dz->parray[FLT_DEN2];
+	double *cn	 = dz->parray[FLT_CN];	
+
+	for(i=0; i < dz->infile->channels; i++) {
+		index = i * FLT_LPHP_ARRAYS_PER_FILTER;
+	
+		e1	 = dz->parray[FLT_E1_BASE + index];
+		e2	 = dz->parray[FLT_E2_BASE + index];
+		s1	 = dz->parray[FLT_S1_BASE + index];
+		s2	 = dz->parray[FLT_S2_BASE + index];
+		
+		lphp_filt_chan(e1,e2,s1,s2,den1,den2,cn,dz,i);
+
+	}
+	return(FINISHED);
+}
+
+/***************************** LPHP_FILT *************************************/
+
+void lphp_filt(double *e1,double *e2,double *s1,double *s2,
+					double *den1,double *den2,double *cn,dataptr dz)
+{
+	int i;
+	int  k;
+	float *buf = dz->sampbuf[0];
+	double ip, op = 0.0, b1;
+ 	for (i = 0 ; i < dz->ssampsread; i++) {
+		ip = (double) buf[i];
+		for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+			b1    = dz->param[FLT_MUL] * cn[k];
+			op    = (cn[k] * ip) + (den1[k] * s1[k]) + (den2[k] * s2[k]) + (b1 * e1[k]) + (cn[k] * e2[k]);
+			s2[k] = s1[k];
+			s1[k] = op;
+			e2[k] = e1[k];
+			e1[k] = ip;
+		}
+		op *= dz->param[FLT_PRESCALE];
+				//RWD NB gain modification...
+#ifdef NOTDEF
+		if (fabs(op) > 1.0) {
+			dz->iparam[FLT_OVFLW]++;
+//TW SUGGEST KEEP THIS: PREVENTS FILTER BLOWING UP
+			dz->param[FLT_PRESCALE] *= .9999;
+			if (op  > 0.0)
+				op = 1.0;
+			else 
+				op = -1.0;
+		}
+		buf[i] = (float)op;
+#else
+		buf[i] = (float) check_float_limits(op,dz);
+#endif
+	}
+}
+
+/*RWD 4:2000 */
+void lphp_filt_chan(double *e1,double *e2,double *s1,double *s2,
+					double *den1,double *den2,double *cn,dataptr dz,int chan)
+{
+	int i;
+	int  k;
+	float *buf = dz->sampbuf[0];
+	double ip, op = 0.0, b1;
+ 	for (i = chan ; i < dz->ssampsread; i+= dz->infile->channels) {
+		ip = (double) buf[i];
+		for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+			b1    = dz->param[FLT_MUL] * cn[k];
+			op    = (cn[k] * ip) + (den1[k] * s1[k]) + (den2[k] * s2[k]) + (b1 * e1[k]) + (cn[k] * e2[k]);
+			s2[k] = s1[k];
+			s1[k] = op;
+			e2[k] = e1[k];
+			e1[k] = ip;
+		}
+		op *= dz->param[FLT_PRESCALE];
+		//RWD NB gain modification...
+#ifdef NOTDEF
+		if (fabs(op) > 1.0) {
+			dz->iparam[FLT_OVFLW]++;
+//TW SUGGEST KEEP THIS: PREVENTS FILTER BLOWING UP
+			dz->param[FLT_PRESCALE] *= .9999;
+			if (op  > 0.0)
+				op = 1.0;
+			else 
+				op = -1.0;
+		}
+		buf[i] = (float)op;
+#else
+		buf[i] = (float) check_float_limits(op,dz);
+#endif
+	}
+}
+
+/***************************** LPHP_FILT_STEREO *************************************/
+
+void lphp_filt_stereo(double *e1,double *e2,double *s1,double *s2,double *e1s,double *e2s,double *s1s,double *s2s,
+					double *den1,double *den2,double *cn,dataptr dz)
+{
+	int i, j;
+	int  k;
+	float *buf = dz->sampbuf[0];
+	double ip, op = 0.0, b1;
+ 	for (i = 0 ; i < dz->ssampsread; i+=2) {
+		ip = (double)buf[i];
+		for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+			b1    = dz->param[FLT_MUL] * cn[k];
+			op    = (cn[k] * ip) + (den1[k] * s1[k]) + (den2[k] * s2[k]) + (b1 * e1[k]) + (cn[k] * e2[k]);
+			s2[k] = s1[k];
+			s1[k] = op;
+			e2[k] = e1[k];
+			e1[k] = ip;
+		}
+		op *= dz->param[FLT_PRESCALE];
+#ifdef NOTDEF
+		if (fabs(op) > F_MAXSAMP) {
+			dz->iparam[FLT_OVFLW]++;
+			dz->param[FLT_PRESCALE] *= .9999;
+			if (op  > 0.0)
+				op = (double)F_MAXSAMP;
+			else 
+				op = (double)F_MINSAMP;
+		}
+		buf[i] = (float)op;
+#else
+		buf[i] = (float) check_float_limits(op,dz);
+#endif
+		j = i+1;
+		ip = (double)buf[j];
+		for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+			b1     = dz->param[FLT_MUL] * cn[k];
+			op     = (den1[k] * s1s[k]) + (den2[k] * s2s[k]) + (cn[k] * ip) + (b1 * e1s[k]) + (cn[k] * e2s[k]);
+			s2s[k] = s1s[k];
+			s1s[k] = op;
+			e2s[k] = e1s[k];
+			e1s[k] = ip;
+		}
+		op *= dz->param[FLT_PRESCALE];
+#ifdef NOTDEF
+		if (fabs(op) > F_MAXSAMP) {
+			dz->iparam[FLT_OVFLW]++;
+			dz->param[FLT_PRESCALE] *= .9999;
+			if (op  > 0.0)
+				op = (double)F_MAXSAMP;
+			else 
+				op = (double)F_MINSAMP;
+		}
+		buf[j] = (float)op;
+#else
+		buf[j] = (float) check_float_limits(op,dz);
+#endif
+	}
+}
+
+/***************************** MY_MODULUS *************************************/
+
+int my_modulus(int x,int y)
+{
+	if(x>=0)
+		return(x%y);
+	while(x < 0)
+		x += y;
+	return(x);
+}
+
+/**************************** NEWFVAL2 *******************************/
+
+int newfval2(double *fbrk,double *hbrk,dataptr dz)
+{
+	int n, m, k,/* z,*/ timepoint, nextrow;
+	int entrycnt = dz->iparam[FLT_ENTRYCNT];
+	int wordcnt  = dz->iparam[FLT_WORDCNT];
+	int hentrycnt = dz->iparam[HRM_ENTRYCNT];
+	int hwordcnt  = dz->iparam[HRM_WORDCNT];
+	//int srate = dz->infile->srate;
+	double lotime, hitime, timefrac, valdiff;
+	double thistime = dz->param[FLT_TOTALTIME];
+
+	memset((char *)dz->parray[FLT_INFRQ],0,dz->iparam[FLT_CNT] * sizeof(double));
+	memset((char *)dz->parray[FLT_INAMP],0,dz->iparam[FLT_CNT] * sizeof(double));
+	timepoint = 0;
+	while(thistime >= fbrk[timepoint]) {	/* search times in frq array */
+		timepoint += entrycnt;
+		if(timepoint >= wordcnt)
+			break;
+	}
+	timepoint -= entrycnt;
+	lotime = fbrk[timepoint];
+	nextrow = timepoint + entrycnt;
+	for(n = timepoint+1,k = 0; n < nextrow;n+=2,k += dz->iparam[FLT_HARMCNT]) {
+		dz->parray[FLT_INFRQ][k] = fbrk[n];		/* Get frqs of fundamentals into array, leaving space for harmonics */
+		dz->parray[FLT_INAMP][k] = fbrk[n+1];	/* Get amps of fundamentals into array, leaving space for harmonics */
+	}
+	if(nextrow != wordcnt) {					/* if not at end of table, do interpolation */
+		nextrow += entrycnt;
+		timepoint += entrycnt;
+		hitime = fbrk[timepoint];
+		timefrac = (thistime - lotime)/(hitime - lotime);
+		k = 0;
+		for(n = timepoint+1,k=0; n < nextrow;n+=2,k += dz->iparam[FLT_HARMCNT]) {
+			/* FRQ */
+			valdiff = fbrk[n] - dz->parray[FLT_INFRQ][k];
+			valdiff *= timefrac;
+			dz->parray[FLT_INFRQ][k] = dz->parray[FLT_INFRQ][k] + valdiff;
+			/* AMP */
+			valdiff = fbrk[n+1] - dz->parray[FLT_INAMP][k];
+			valdiff *= timefrac;
+			dz->parray[FLT_INAMP][k] = dz->parray[FLT_INAMP][k] + valdiff;
+		}
+	}
+	timepoint = 0;
+	while(thistime >= hbrk[timepoint]) {	/* search times in frq array */
+		timepoint += hentrycnt;
+		if(timepoint >= hwordcnt) {
+			break;
+		}
+	}
+	timepoint -= hentrycnt;
+	lotime = hbrk[timepoint];
+	nextrow = timepoint + hentrycnt;
+	k = 0;
+	for(n = timepoint+1,k=0; n < nextrow;n+=2,k++) {
+		dz->parray[HARM_FRQ_CALC][k] = hbrk[n];
+		dz->parray[HARM_AMP_CALC][k] = hbrk[n+1];
+	}
+	if(nextrow != hwordcnt) {					/* if not at end of table, do interpolation */
+		nextrow += hentrycnt;
+		timepoint += hentrycnt;
+		hitime = hbrk[timepoint];
+		timefrac = (thistime - lotime)/(hitime - lotime);
+		k = 0;
+		for(n = timepoint+1,k=0; n < nextrow;n+=2,k++) {
+			/* PARTIAL MULTIPLIER */
+			valdiff = hbrk[n] - dz->parray[HARM_FRQ_CALC][k];
+			valdiff *= timefrac;
+			dz->parray[HARM_FRQ_CALC][k] = dz->parray[HARM_FRQ_CALC][k] + valdiff;
+			/* PARTIAL AMP */
+			valdiff = hbrk[n+1] - dz->parray[HARM_AMP_CALC][k];
+			valdiff *= timefrac;
+			dz->parray[HARM_AMP_CALC][k] = dz->parray[HARM_AMP_CALC][k] + valdiff;
+		}
+	}
+	for(k=0;k<dz->iparam[FLT_CNT];k+=dz->iparam[FLT_HARMCNT]) {
+//		z = 0;
+		for(m=0; m < dz->iparam[FLT_HARMCNT];m++) {	/* calc vals for partials from basefrq vals */
+			dz->parray[FLT_INFRQ][k+m] = dz->parray[FLT_INFRQ][k] * dz->parray[HARM_FRQ_CALC][m];
+			dz->parray[FLT_INAMP][k+m] = dz->parray[FLT_INAMP][k] * dz->parray[HARM_AMP_CALC][m];
+			dz->parray[FLT_FRQ][k+m] = dz->parray[FLT_INFRQ][k+m];
+			dz->parray[FLT_AMP][k+m] = dz->parray[FLT_INAMP][k+m];
+		}
+	}
+	dz->param[FLT_TOTALTIME] += dz->param[FLT_TIMESTEP];
+	return(FINISHED);
+}
+
+/*************************** DO_FVARY2_FILTERS *****************************/
+
+int do_fvary2_filters(dataptr dz)
+{
+	int exit_status;
+	int    n, fno, chans = dz->infile->channels;
+	float *buf = dz->sampbuf[0];
+
+	//double *fincr = dz->parray[FLT_FINCR];
+	//double *aincr = dz->parray[FLT_AINCR];
+ 
+ 	double *ampl = dz->parray[FLT_AMPL];
+	double *a = dz->parray[FLT_A];
+	double *b = dz->parray[FLT_B];
+	double *y = dz->parray[FLT_Y];
+	double *z = dz->parray[FLT_Z];
+	double *d = dz->parray[FLT_D];
+	double *e = dz->parray[FLT_E];
+ 
+ 	int fsams = dz->iparam[FLT_FSAMS];
+	for (n = 0; n < dz->ssampsread; n += chans) { 
+		if(dz->brksize[FLT_Q]) {
+			if((dz->iparam[FLT_SAMS] -= chans) <= 0) {
+				if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) {
+			 		sprintf(errstr,"Ran out of Q values: do_fvary2_filters()\n");
+					return(PROGRAM_ERROR);
+				}
+				dz->iparam[FLT_SAMS] *= chans;
+			}
+		}
+		if(fsams <= 0) {
+			if((exit_status = newfval2(dz->parray[FLT_FBRK],dz->parray[FLT_HBRK],dz))<0)
+				return(exit_status);
+			fsams = dz->iparam[FLT_FSAMS];
+			for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) {
+				get_coeffs1(fno,dz);
+				get_coeffs2(fno,dz);
+			}
+			if(dz->brksize[FLT_Q])
+				dz->param[FLT_Q] *= dz->param[FLT_Q_INCR];
+		}
+
+		filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz);
+		fsams--;
+	}
+	return(CONTINUE);
+}
+

+ 1430 - 0
dev/filter/filters0.c

@@ -0,0 +1,1430 @@
+/*
+ * 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
+ *
+ */
+
+/* floatsams version*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <processno.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <filters.h>
+#include <cdpmain.h>
+#include <sfsys.h>
+/*RWD*/
+#include <string.h>
+
+#ifndef cdp_round
+extern int cdp_round(double a);
+#endif
+
+#if defined unix || defined __GNUC__
+#define round(x) lround((x))
+#endif
+
+#define MINUS96DB (0.000016)
+
+static void     filtering(int n,int chans,float *buf,
+                    double *a,double *b,double *y,double *z,double *d,double *e,double *ampl,dataptr dz);
+static double   check_float_limits(double sum, dataptr dz);
+static int      newvalue(int valno,int valincrno, int sampcntno, dataptr dz);
+static int      newfval(int *fsams,dataptr dz);
+static int      do_filters(dataptr dz);
+static int      do_qvary_filters(dataptr dz);
+static int      do_fvary_filters(dataptr dz);
+static void     print_filter_frqs(dataptr dz);
+static int      do_varifilter(dataptr dz);
+static int      do_sweep_filter(dataptr dz);
+static double   getfrq(double lfrq,double hfrq,double sfrq,dataptr dz);
+static int      do_allpass_filter(dataptr dz);
+static int      allpass(float *buf,int chans,double prescale,dataptr dz);
+static int      varidelay_allpass(float *buf,int chans,double prescale,dataptr dz);
+static int      do_eq_filter(dataptr dz);
+static float    multifilter(double *dll,double *dbb,double *dnn,double *dhh,double *dpp,
+                    double qfac,double coeff,float input,dataptr dz);
+static int      do_lphp_filter(dataptr dz);
+static int     my_modulus(int x,int y);
+static void lphp_filt_chan(double *e1,double *e2,double *s1,double *s2,
+                    double *den1,double *den2,double *cn,dataptr dz,int chan);
+
+static int      do_fvary2_filters(dataptr dz);
+
+/****************************** FILTER_PROCESS *************************/
+
+int filter_process(dataptr dz)
+{
+    int exit_status = FINISHED;
+    int filter_tail = 0, tail_extend = 0, was_tail_extend = 0, bufspace;
+// NEW MAY 2012
+    int do_norm = 0, chans = dz->infile->channels, sndendset = 0, gotend = 0;
+    double inmaxsamp = 0.0, outmaxsamp = 0.0, maxsamp;
+    float *buf = dz->sampbuf[0];
+    int n, m, k, sndend = 0;
+    int framend, framestart, framesize = F_SECSIZE, framecnt = dz->buflen/framesize;
+    switch(dz->process) {
+    case(FLTBANKV):
+        if(dz->vflag[2])
+            do_norm = 1;
+            break;
+    case(FLTBANKV2):
+        if(dz->vflag[1])
+            do_norm = 1;
+            break;
+    case(FLTBANKN):
+        do_norm = 1;
+        break;
+    }
+// MAY 2012 TO HERE
+    
+    if(dz->process==FLTBANKC) {
+        print_filter_frqs(dz);
+        return(FINISHED);
+    }
+    display_virtual_time(0,dz);
+
+// NEW MAY 2012
+    if(do_norm) {
+        fprintf(stdout,"INFO: Assessing input level.\n");
+        fflush(stdout);
+        while(dz->samps_left > 0) {
+            if((exit_status = read_samps(buf,dz))<0)
+                return(exit_status);
+            for(n = 0;n < dz->ssampsread;n++)
+                inmaxsamp = max(inmaxsamp,fabs(buf[n]));
+        }
+        if(inmaxsamp <= 0.0) {
+            sprintf(errstr,"No level found in input signal\n");
+            return DATA_ERROR;
+        }
+        sndseekEx(dz->ifd[0],0,0);
+        reset_filedata_counters(dz);
+        if(dz->process==FLTBANKV) {
+            if((exit_status = newfval(&(dz->iparam[FLT_FSAMS]),dz))<0)
+                return(exit_status);
+        } else if(dz->process==FLTBANKV2) {
+            dz->iparam[FLT_FSAMS] = dz->iparam[FLT_BLOKSIZE];
+            dz->param[FLT_TIMESTEP] = (double)dz->iparam[FLT_BLOKSIZE]/(double)dz->infile->srate;
+            dz->param[FLT_TOTALTIME] = 0.0;
+            if((exit_status = newfval2(dz->parray[FLT_FBRK],dz->parray[FLT_HBRK],dz))<0)
+                return(exit_status);
+        } else if(dz->process==FLTBANKN) {
+            if(dz->brksize[FLT_Q])
+                exit_status = do_qvary_filters(dz);
+            else
+                exit_status = do_filters(dz);
+        }
+        fprintf(stdout,"INFO: Assessing output level.\n");
+        fflush(stdout);
+        while(dz->samps_left > 0 || filter_tail > 0) {
+            memset((char *)dz->sampbuf[0],0,(size_t) (dz->buflen * sizeof(float)));
+            if(filter_tail || tail_extend) {
+                dz->ssampsread = 0;
+            } else {
+                if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
+                    return(exit_status);
+                if(dz->samps_left <= 0) {
+                    if(dz->process==FLTBANKV || dz->process==FLTBANKV2)
+                        filter_tail = round(dz->param[FILT_TAILV] * (double)dz->infile->srate) * dz->infile->channels;
+                    else 
+                        filter_tail = (int)round((dz->param[FILT_TAIL] * (double)dz->infile->srate) * dz->infile->channels);
+                    if(filter_tail == 0) {
+                        was_tail_extend = 1;
+                        tail_extend = 1;
+                    }
+                }
+            }
+            if(filter_tail) {
+                bufspace = dz->buflen - dz->ssampsread;
+                if(bufspace >= filter_tail) {
+                    dz->ssampsread += filter_tail;
+                    filter_tail = 0;
+                } else {
+                    dz->ssampsread = dz->buflen;
+                    filter_tail -= bufspace;
+                }
+            } else if(tail_extend) {
+                bufspace = dz->buflen;
+                dz->ssampsread = dz->buflen;
+            }
+            switch(dz->process) {
+            case(FLTBANKV): exit_status = do_fvary_filters(dz);     break;
+            case(FLTBANKV2):exit_status = do_fvary2_filters(dz);    break;
+            case(FLTBANKN):
+                if(dz->brksize[FLT_Q])  
+                    exit_status = do_qvary_filters(dz);
+                else
+                    exit_status = do_filters(dz);
+                break;
+            }
+            if(exit_status <0)
+                return(exit_status);
+            if(tail_extend) {
+                sndend = dz->buflen;
+                framend = dz->buflen;
+                for(k = framecnt; k > 0; k--) {                 //  Search backwards thro buffer, frame by frame
+                    framestart = framend - framesize;
+                    maxsamp = 0.0;
+                    for(n = framend-chans;n >= framestart;n-=chans) {   
+                        for(m=0;m<chans;m++) {                  //  Search backwards thro frame, samp-grup by samp-group
+                            if(fabs(buf[n+m]) > maxsamp) {
+                                if(!sndendset) {                //  If samples cease to be zero
+                                    sndend = n + chans;         //  Mark start of end-zeros in buffer
+                                    sndendset = 1;              //  and flag that snd end has been found
+                                }
+                                maxsamp = fabs(buf[n+m]);
+                            }
+                        }
+                        if(maxsamp < MINUS96DB) {               //  If max level in frame falls below -96dB
+                            if(sndendset) {                     //  If we found a place in buffer after which samples were all zero
+                                dz->ssampsread = sndend;        //  Mark this as end of output, and quit the main filtering loop
+                                tail_extend = 0;                //  by setting tail_extend to zero
+                                dz->samps_left = 0; // SAFETY   
+                                break;
+                            } else                              //  If we didn't find place ....    
+                                sndend = framestart;            //  Then all samples in the frame are zero.
+                        }                                       //  So move snd end to start of current frame.
+                    }                                           //  .. and search backwards thro previous frame
+                    if(tail_extend == 0)
+                        break;
+                    framend = framestart;
+                }
+            }
+            if(tail_extend)
+                tail_extend++;
+            if(dz->ssampsread > 0) {
+                for(n = 0;n < dz->ssampsread;n++)
+                    outmaxsamp = max(outmaxsamp,(double)fabs(buf[n]));
+            }
+        }
+        if(outmaxsamp <= 0.0) {
+            sprintf(errstr,"No level found in output signal.\n");
+            return DATA_ERROR;
+        }
+
+        dz->param[FLT_GAIN] *= (inmaxsamp/outmaxsamp);
+
+        sndseekEx(dz->ifd[0],0,0);
+        reset_filedata_counters(dz);
+        if(dz->process==FLTBANKV || dz->process==FLTBANKV2) {
+            for(n = 0;n<dz->iparam[FLT_CNT];n++) {
+                dz->parray[FLT_FRQ][n]      = dz->parray[FLT_INFRQ][n];
+                dz->parray[FLT_AMP][n]      = dz->parray[FLT_INAMP][n];
+                dz->parray[FLT_LASTFVAL][n] = dz->parray[FLT_FRQ][n];
+                dz->parray[FLT_LASTAVAL][n] = dz->parray[FLT_AMP][n];
+            }
+        }
+        dz->iparam[FLT_FRQ_INDEX] = dz->iparam[FLT_CNT];
+        dz->iparam[FLT_TIMES_CNT] = 1;
+        filter_tail = 0;
+        tail_extend = 0;
+        sndendset   = 0;
+        sndend      = 0;
+        tail_extend = 0;
+        was_tail_extend = 0;
+        gotend      = 0;
+        fprintf(stdout,"INFO: Running filter.\n");
+        fflush(stdout);
+    }
+// MAY 2012, TO HERE
+    if(dz->process==FLTBANKV) {
+        if((exit_status = newfval(&(dz->iparam[FLT_FSAMS]),dz))<0)
+            return(exit_status);
+    } else  if(dz->process==FLTBANKV2) {
+        dz->iparam[FLT_FSAMS] = dz->iparam[FLT_BLOKSIZE];
+        dz->param[FLT_TIMESTEP] = (double)dz->iparam[FLT_BLOKSIZE]/(double)dz->infile->srate;
+        dz->param[FLT_TOTALTIME] = 0.0;
+        if((exit_status = newfval2(dz->parray[FLT_FBRK],dz->parray[FLT_HBRK],dz))<0)
+            return(exit_status);
+    }
+    while(dz->samps_left > 0 || filter_tail > 0 || tail_extend) {
+        memset((char *)dz->sampbuf[0],0,(size_t) (dz->buflen * sizeof(float)));
+        if(filter_tail > 0 || tail_extend) {
+            dz->ssampsread = 0;
+        } else {
+            if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
+                return(exit_status);
+            if(dz->samps_left <= 0) {
+                if(dz->process==FLTBANKV || dz->process==FLTBANKV2)
+                    filter_tail = round(dz->param[FILT_TAILV] * (double)dz->infile->srate) * dz->infile->channels;
+                else
+                    filter_tail = (int)round((dz->param[FILT_TAIL] * (double)dz->infile->srate) * dz->infile->channels);
+                if(filter_tail == 0) {
+                    was_tail_extend = 1;
+                    tail_extend = 1;
+                    fprintf(stdout,"INFO: Writing Filter tail.\n");
+                    fflush(stdout);
+                }
+            }
+        }
+        if(filter_tail) {
+            bufspace = dz->buflen - dz->ssampsread;
+            if(bufspace >= filter_tail) {
+                dz->ssampsread += filter_tail;
+                filter_tail = 0;
+            } else {
+                dz->ssampsread = dz->buflen;
+                filter_tail -= bufspace;
+            }
+        } else if(tail_extend) {
+            bufspace = dz->buflen;
+            dz->ssampsread = dz->buflen;
+        }
+        switch(dz->process) {
+        case(FLTBANKN):
+        case(FLTBANKU):
+            if(dz->brksize[FLT_Q])  
+                exit_status = do_qvary_filters(dz);
+            else
+                exit_status = do_filters(dz);
+            break;
+        case(FLTBANKV): exit_status = do_fvary_filters(dz);     break;
+        case(FLTBANKV2):exit_status = do_fvary2_filters(dz);    break;
+        case(FLTSWEEP): exit_status = do_sweep_filter(dz);      break;
+        case(FSTATVAR): exit_status = do_varifilter(dz);        break;
+        case(ALLPASS):  exit_status = do_allpass_filter(dz);    break;
+        case(EQ):       exit_status = do_eq_filter(dz);         break;
+        case(LPHP):     exit_status = do_lphp_filter(dz);       break;
+        }
+        if(exit_status <0)
+            return(exit_status);
+        if(tail_extend) {
+            sndend = dz->buflen;
+            framend = dz->buflen;
+            for(k = framecnt; k > 0; k--) {                 //  Search backwards thro buffer, frame by frame
+                framestart = framend - framesize;
+                maxsamp = 0.0;
+                for(n = framend-chans;n >= framestart;n-=chans) {   
+                    for(m=0;m<chans;m++) {                  //  Search backwards thro frame, samp-grup by samp-group
+                        if(fabs(buf[n+m]) > maxsamp) {
+                            if(!sndendset) {                //  If samples cease to be zero
+                                sndend = n + chans;         //  Mark start of end-zeros in buffer
+                                sndendset = 1;              //  and flag that snd end has been found
+                            }
+                            maxsamp = fabs(buf[n+m]);
+                        }
+                    }
+                    if(maxsamp < MINUS96DB) {               //  If max level in frame falls below -96dB
+                        if(sndendset) {                     //  If we found a place in buffer after which samples were all zero
+                            dz->ssampsread = sndend;        //  Mark this as end of output, and quit the main filtering loop
+                            tail_extend = 0;                //  by setting tail_extend to zero
+                            dz->samps_left = 0; // SAFETY   
+                            break;
+                        } else                              //  If we didn't find place ....
+                            sndend = framestart;            //  Then all samples in the frame are zero.
+                    }                                       //  So move snd end to start of current frame.
+                }                                           //  .. and search backwards thro previous frame
+
+                if(tail_extend == 0)
+                    break;
+                framend = framestart;
+            }
+            if((maxsamp < MINUS96DB) && !sndendset) {       //  Entire buffer is "zero"
+                tail_extend = 0;                            //  Force exit by seting tail_extend to zero
+                dz->samps_left = 0; // SAFETY               //  DO NOT set samps_read to 0, as there may be input samples still to write
+            }
+        }
+        if(tail_extend)
+            tail_extend++;
+        if(dz->ssampsread > 0) {
+            if(sloom && was_tail_extend) {                  //  Force Loom progress bar to respond to tail-write
+                if(!tail_extend)
+                    dz->total_samps_written = dz->insams[0];
+                else
+                    dz->total_samps_written = (long)round((double)dz->insams[0] * ((double)(tail_extend % 8)/8.0));
+                dz->total_samps_written -= dz->ssampsread;
+            }
+            if((exit_status = write_samps(dz->sampbuf[0],dz->ssampsread,dz))<0)
+                return(exit_status);
+        }
+    }               
+    if(dz->iparam[FLT_OVFLW] > 0)  {
+        if(!sloom && !sloombatch)
+            fprintf(stdout,"Number of overflows: %d\n",dz->iparam[FLT_OVFLW]);
+        else
+            fprintf(stdout,"INFO: Number of overflows: %d\n",dz->iparam[FLT_OVFLW]);
+        fflush(stdout);
+    }
+    return(FINISHED);
+}
+
+/*************************** DO_FVARY_FILTERS *****************************/
+
+int do_fvary_filters(dataptr dz)
+{
+    int exit_status;
+    int    n, m, fno, chans = dz->infile->channels;
+    float *buf = dz->sampbuf[0];
+
+    double *fincr = dz->parray[FLT_FINCR];
+    double *aincr = dz->parray[FLT_AINCR];
+ 
+    double *ampl = dz->parray[FLT_AMPL];
+    double *a = dz->parray[FLT_A];
+    double *b = dz->parray[FLT_B];
+    double *y = dz->parray[FLT_Y];
+    double *z = dz->parray[FLT_Z];
+    double *d = dz->parray[FLT_D];
+    double *e = dz->parray[FLT_E];
+    int fsams = dz->iparam[FLT_FSAMS];
+    if (dz->vflag[DROP_OUT_AT_OVFLOW]) {
+        for (n = 0; n < dz->ssampsread; n += chans) { 
+            if(fsams <= 0) {
+                if((exit_status = newfval(&fsams,dz))<0)
+                    return(exit_status);
+            }
+            if(dz->brksize[FLT_Q]) {
+                if((dz->iparam[FLT_SAMS] -= chans) <= 0) {
+                    if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) {
+                        sprintf(errstr,"Ran out of Q values: do_fvary_filters()\n");
+                        return(PROGRAM_ERROR);
+                    }
+                    dz->iparam[FLT_SAMS] *= chans;
+                }
+            }
+            if((dz->iparam[FLT_BLOKCNT] -= chans) <= 0) {
+                for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) {
+                    get_coeffs1(fno,dz);
+                    get_coeffs2(fno,dz);
+                }
+                if(dz->brksize[FLT_Q])
+                    dz->param[FLT_Q] *= dz->param[FLT_Q_INCR];
+                
+                for(m=0;m<dz->iparam[FLT_CNT];m++) {
+                    dz->parray[FLT_FRQ][m] *= fincr[m];
+                    dz->parray[FLT_AMP][m] *= aincr[m];
+                }
+                dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE] * chans;
+            }
+            filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz);
+            if(dz->iparam[FLT_OVFLW] > 0) {
+                sprintf(errstr,"Filter overflowed\n");
+                return(GOAL_FAILED);
+            }
+            fsams--;
+        }
+    } else {
+        for (n = 0; n < dz->ssampsread; n += chans) {
+            if(fsams <= 0) {
+                if((exit_status = newfval(&fsams,dz))<0)
+                    return(exit_status);
+            }
+            if(dz->brksize[FLT_Q]) {
+                if((dz->iparam[FLT_SAMS] -= chans) <= 0) {
+                    if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) {
+                        sprintf(errstr,"Ran out of Q values: do_fvary_filters()\n");
+                        return(PROGRAM_ERROR);
+                    }
+                    dz->iparam[FLT_SAMS] *= chans;
+                }
+            }
+            if((dz->iparam[FLT_BLOKCNT] -= chans) <= 0) {
+                for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) {
+                    get_coeffs1(fno,dz);
+                    get_coeffs2(fno,dz);
+                }
+                if(dz->brksize[FLT_Q])
+                    dz->param[FLT_Q] *= dz->param[FLT_Q_INCR];
+
+                for(m=0;m<dz->iparam[FLT_CNT];m++) {
+                    dz->parray[FLT_FRQ][m] *= fincr[m];
+                    dz->parray[FLT_AMP][m] *= aincr[m];
+                }
+                dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE] * chans;
+            }
+            filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz);
+            fsams--;
+        }
+    }
+    dz->iparam[FLT_FSAMS] = fsams;
+    return(CONTINUE);
+}
+
+/*************************** DO_FILTERS *******************************/
+
+int do_filters(dataptr dz)
+{
+    int n;
+    int  chans = dz->infile->channels;
+    float *buf = dz->sampbuf[0];
+    double *ampl = dz->parray[FLT_AMPL];
+    double *a = dz->parray[FLT_A];
+    double *b = dz->parray[FLT_B];
+    double *y = dz->parray[FLT_Y];
+    double *z = dz->parray[FLT_Z];
+    double *d = dz->parray[FLT_D];
+    double *e = dz->parray[FLT_E];
+    for (n = 0; n < dz->ssampsread; n += chans)
+        filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz);
+    return(CONTINUE);
+}
+
+/*************************** DO_QVARY_FILTERS *****************************/
+
+int do_qvary_filters(dataptr dz)
+{
+    int   n;
+    int    fno, chans = dz->infile->channels;
+    float *buf = dz->sampbuf[0];
+    double *ampl = dz->parray[FLT_AMPL];
+    double *a = dz->parray[FLT_A];
+    double *b = dz->parray[FLT_B];
+    double *y = dz->parray[FLT_Y];
+    double *z = dz->parray[FLT_Z];
+    double *d = dz->parray[FLT_D];
+    double *e = dz->parray[FLT_E];
+
+    for (n = 0; n < dz->ssampsread; n += chans) { 
+        if((dz->iparam[FLT_SAMS] -= chans) <= 0) {
+            if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) {
+                sprintf(errstr,"Ran out of Q values: do_qvary_filters()\n");
+                return(PROGRAM_ERROR);
+            }
+            dz->iparam[FLT_SAMS] *= chans;
+        }
+        if((dz->iparam[FLT_BLOKCNT] -= chans) <= 0) {
+            for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++)
+                get_coeffs2(fno,dz);
+            dz->param[FLT_Q] *= dz->param[FLT_Q_INCR];
+            dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE] * chans;
+        }
+        filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz);
+    }
+    return(CONTINUE);
+}
+
+/******************************* NEWVALUE ***************************
+ *
+ * VAL     is the base value from which we calculate.
+ * VALINCR is the value increment per block of samples.
+ * SAMPCNT is the number of samples from 1 brkpnt val to next.
+ */                    
+
+int newvalue(int valno,int valincrno, int sampcntno, dataptr dz)
+{
+    double *p;
+    double ratio, one_over_steps;
+    double thistime;
+    double thisval;
+    int    linear_flag = FALSE;
+    if(dz->process==ALLPASS && valno==FLT_DELAY)
+        linear_flag = dz->vflag[FLT_LINDELAY];
+    p = dz->brkptr[valno];
+    if(p - dz->brk[valno] >= dz->brksize[valno] * 2)
+        return(FALSE);
+    thistime = (double)round((*p++) * dz->infile->srate);
+    thisval  = *p++;
+    dz->iparam[sampcntno]    = round(thistime - dz->lastind[valno]);
+    /* steps = no_of_samples/sampsize_of_blok: therefore.. */
+    one_over_steps = (double)dz->iparam[FLT_BLOKSIZE]/(double)dz->iparam[sampcntno];
+    if(linear_flag)
+        dz->param[valincrno] = (thisval - dz->lastval[valno]) * one_over_steps;
+    else {
+        ratio                = (thisval/dz->lastval[valno]);
+        dz->param[valincrno] = pow(ratio,(one_over_steps));
+    }
+    dz->param[valno]     = dz->lastval[valno];
+    dz->lastval[valno]   = thisval;
+    dz->lastind[valno]   = thistime;
+    dz->brkptr[valno]    = p;
+    return(TRUE);
+}
+
+/******************************* NEWFVAL ***************************
+ *
+ * VAL is the base value from which we calculate.
+ * VALINCR is the value increment per block of samples.
+ * FSAMS is the number of samples (per channel) from 1 brkpnt val to next.
+ * brk is the particular table we're accessing.
+ */
+
+int newfval(int *fsams,dataptr dz)
+{
+    int   thistime, lasttime;
+    double rratio, one_over_steps;
+    int   n,m,k;
+    double thisval;
+    double *lastfval = dz->parray[FLT_LASTFVAL];
+    double *lastaval = dz->parray[FLT_LASTAVAL];
+    double *aincr    = dz->parray[FLT_AINCR];
+    double *fincr    = dz->parray[FLT_FINCR];
+    int total_frqcnt = dz->iparam[FLT_CNT] * dz->iparam[FLT_TIMESLOTS];
+    
+    if(dz->iparam[FLT_TIMES_CNT]>dz->iparam[FLT_TIMESLOTS]) {
+        sprintf(errstr,"Ran off end of filter data: newfval()\n");
+        return(PROGRAM_ERROR);
+    }
+    k = dz->iparam[FLT_TIMES_CNT];
+    lasttime  = dz->lparray[FLT_SAMPTIME][k-1];
+    thistime  = dz->lparray[FLT_SAMPTIME][k];
+    *fsams = thistime - lasttime;
+    /* steps  = fsams/FLT_BLOKSIZE: therefore ... */
+    one_over_steps  = (double)dz->iparam[FLT_BLOKSIZE]/(double)(*fsams);
+    if(dz->iparam[FLT_FRQ_INDEX] >= total_frqcnt)
+        return(FINISHED);
+    for(n=0, m= dz->iparam[FLT_FRQ_INDEX];n<dz->iparam[FLT_CNT];n++,m++) {
+    /* FREQUENCY */
+        thisval = dz->parray[FLT_INFRQ][m];
+        if(flteq(lastfval[n],thisval))
+            fincr[n] = 1.0;
+        else {
+            rratio = (thisval/lastfval[n]);
+            fincr[n] = pow(rratio,one_over_steps);
+        }
+        dz->parray[FLT_FRQ][n] = lastfval[n];
+        lastfval[n] = thisval;
+    /* AMPLITUDE */
+        thisval = dz->parray[FLT_INAMP][m];
+        if(flteq(thisval,lastaval[n]))
+            aincr[n] = 1.0;
+        else {
+            rratio = (thisval/lastaval[n]);
+            aincr[n] = pow(rratio,one_over_steps);
+        }
+        dz->parray[FLT_AMP][n] = lastaval[n];
+        lastaval[n] = thisval;
+    }
+    dz->iparam[FLT_FRQ_INDEX] += dz->iparam[FLT_CNT];
+    dz->iparam[FLT_TIMES_CNT]++;
+    return(FINISHED);
+}
+
+/************************** FILTERING ****************************/
+
+void filtering(int n,int chans,float *buf,double *a,double *b,double *y,double *z,
+                double *d,double *e,double *ampl,dataptr dz)
+{
+    double input, sum, xx;
+    int chno, this_samp, fno, i;
+
+    for(chno = 0; chno < chans; chno++) {
+        this_samp = n + chno;
+        input = (double)buf[this_samp];
+        sum   = 0.0;
+        for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) {
+            i    = (fno * chans) + chno;
+            xx   = input + (a[fno] * y[i]) + (b[fno] * z[i]);
+            z[i] = y[i];
+            y[i] = xx;
+            if(dz->vflag[FLT_DBLFILT]) {
+                xx   += (a[fno] * d[i]) + (b[fno] * e[i]);
+                e[i] = d[i];
+                d[i] = xx;
+            }
+            sum += (xx * ampl[fno]);
+        }
+        sum *= dz->param[FLT_GAIN];
+        sum = check_float_limits(sum,dz);
+        buf[this_samp] = (float) sum;
+    }
+}
+
+/************************** IO_FILTERING ****************************/
+
+void io_filtering
+(float *buf1,float *buf2,int chans,int n,
+double *a,double *b,double *y,double *z,double *d,double *z1,double *ampl,dataptr dz)
+{
+    double input, sum, xx;
+    int    chno, this_samp, fno, i;
+    for(chno = 0; chno < chans; chno++) {
+        this_samp = n + chno;
+        input = (double)buf1[this_samp];
+        sum   = 0.0;
+        for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) {
+            i    = (fno * chans) + chno;
+            xx   = input + (a[fno] * y[i]) + (b[fno] * z[i]);
+            z[i] = y[i];
+            y[i] = xx;
+            if(dz->vflag[FLT_DBLFILT]) {
+                xx   += (a[fno] * d[i]) + (b[fno] * z1[i]);
+                z1[i] = d[i];
+                d[i] = xx;
+            }
+            sum += (xx * ampl[fno]);
+        }
+        sum *= dz->param[FLT_GAIN];
+        sum = check_float_limits(sum,dz);
+        buf2[this_samp] = (float) sum;
+    }
+}
+
+/************************ CHECK_FLOAT_LIMITS **************************/
+
+//TODO: if shorts o/p - do clipping; if floatsams, report but don't change!
+double check_float_limits(double sum,dataptr dz)
+{
+    double peak = fabs(sum);
+#ifdef NOTDEF
+    //do this when 'modify loudness' can handle floatsams!
+    if(dz->true_outfile_stype== SAMP_FLOAT){
+        
+        if(peak > 1.0){
+            dz->iparam[FLT_OVFLW]++;
+            dz->peak_fval = max(dz->peak_fval,peak);
+        }       
+    }
+    else {
+#endif
+        if (sum > 1.0) {
+//TW SUGGEST KEEP THIS; prevents FILTER BLOWING UP: see notes
+            dz->param[FLT_GAIN] *= 0.9999;
+            dz->iparam[FLT_OVFLW]++;
+            dz->peak_fval = max(dz->peak_fval,peak);
+            //return(1.0);
+            if(dz->clip_floatsams)
+                sum = 1.0;
+        }
+        if (sum < -1.0) {
+//TW SUGGEST KEEP THIS; prevents FILTER BLOWING UP: see notes
+
+            dz->param[FLT_GAIN] *= 0.9999;
+            dz->iparam[FLT_OVFLW]++;
+            dz->peak_fval = max(dz->peak_fval,peak);
+            //return(-1.0);
+            if(dz->clip_floatsams)
+                sum = -1.0;
+        }
+#ifdef NOTDEF
+    }
+#endif
+    return sum;
+}
+/************************ PRINT_FILTER_FRQS *******************************/
+
+void print_filter_frqs(dataptr dz)
+{
+    int n;
+    double *frq = dz->parray[FLT_FRQ];
+    for(n=0;n<dz->iparam[FLT_CNT];n++)
+        fprintf(dz->fp,"%lf\n",frq[n]);
+}
+
+/******************************* DO_VARIFILTER ******************************/
+
+int do_varifilter(dataptr dz)
+{
+    double *dls = dz->parray[FLT_DLS];
+    double *dbs = dz->parray[FLT_DBS];
+    double *dhs = dz->parray[FLT_DHS];
+    double *dns = dz->parray[FLT_DNS];
+    double *dops[2];
+    double coeff = 0.0;
+    float  *buf  = dz->sampbuf[0];
+    int   n;
+    int    k, chans = dz->infile->channels;
+    int    is_fbrk = FALSE, is_qbrk = FALSE;
+    if(dz->brksize[FLT_ONEFRQ]) is_fbrk = TRUE;
+    if(dz->brksize[FLT_Q])      is_qbrk = TRUE;
+    for(n=0;n<chans;n++) {
+        switch(dz->mode){
+        case(FSW_HIGH):     dops[n] = &(dz->parray[FLT_DHS][n]);    break;
+        case(FSW_LOW):      dops[n] = &(dz->parray[FLT_DLS][n]);    break;
+        case(FSW_BAND):     dops[n] = &(dz->parray[FLT_DBS][n]);    break;
+        case(FSW_NOTCH):    dops[n] = &(dz->parray[FLT_DNS][n]);    break;
+        }
+    }
+    for (n = 0 ; n < dz->ssampsread; n += chans) {
+        if(is_fbrk && (--dz->iparam[FLT_FSAMS] <= 0)) {
+            if(!newvalue(FLT_ONEFRQ,FLT_F_INCR,FLT_FSAMS,dz)) {
+                sprintf(errstr,"Ran out of sweepfrq values: do_varifilter()\n");
+                return(PROGRAM_ERROR);
+            }
+        }
+        if(is_qbrk && (--dz->iparam[FLT_SAMS] <= 0)) {
+            if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) { 
+                sprintf(errstr,"Ran out of Q values: do_sweep_filter()\n");
+                return(PROGRAM_ERROR);
+            }
+        }
+        if(--dz->iparam[FLT_BLOKCNT] <= 0){
+            coeff = (2.0 * PI * dz->param[FLT_ONEFRQ]) * dz->param[FLT_INV_SR];
+            if(is_fbrk)    dz->param[FLT_ONEFRQ] *= dz->param[FLT_F_INCR];
+            if(is_qbrk) {
+                dz->param[FLT_QFAC] = 1.0/(1.0 + dz->param[FLT_Q]);
+                dz->param[FLT_Q]   *= dz->param[FLT_Q_INCR];
+            }
+            dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE];
+        }
+        for(k=0;k<chans;k++)
+            buf[n+k] = multifilter(&(dbs[k]),&(dls[k]),&(dhs[k]),&(dns[k]),dops[k],dz->param[FLT_Q],coeff,buf[n+k],dz);
+    }
+    return(CONTINUE);
+}
+
+/******************************* DO_SWEEP_FILTER ******************************/
+
+int do_sweep_filter(dataptr dz)
+{
+    double *dls = dz->parray[FLT_DLS];
+    double *dbs = dz->parray[FLT_DBS];
+    double *dhs = dz->parray[FLT_DHS];
+    double *dns = dz->parray[FLT_DNS];
+    double *dops[2];
+    double coeff = 0.0, frq;
+    float  *buf  = dz->sampbuf[0];
+    int   n;
+    int    k, chans = dz->infile->channels;
+    int    is_lbrk = FALSE, is_hbrk = FALSE, is_sbrk = FALSE, is_qbrk = FALSE;
+    if(dz->brksize[FLT_LOFRQ])  is_lbrk = TRUE;
+    if(dz->brksize[FLT_HIFRQ])  is_hbrk = TRUE;
+    if(dz->brksize[FLT_SWPFRQ]) is_sbrk = TRUE;
+    if(dz->brksize[FLT_Q])      is_qbrk = TRUE;
+    for(n=0;n<chans;n++) {
+        switch(dz->mode){
+        case(FSW_HIGH):     dops[n] = &(dz->parray[FLT_DHS][n]);    break;
+        case(FSW_LOW):      dops[n] = &(dz->parray[FLT_DLS][n]);    break;
+        case(FSW_BAND):     dops[n] = &(dz->parray[FLT_DBS][n]);    break;
+        case(FSW_NOTCH):    dops[n] = &(dz->parray[FLT_DNS][n]);    break;
+        }
+    }
+    for (n = 0 ; n < dz->ssampsread; n += chans) {
+        if(is_lbrk && (--dz->iparam[FLT_LOSAMS] <= 0)) {
+            if(!newvalue(FLT_LOFRQ,FLT_LOINCR,FLT_LOSAMS,dz)) { 
+                sprintf(errstr,"Ran out of lofrq values: do_sweep_filter()\n");
+                return(PROGRAM_ERROR);
+            }
+        }
+        if(is_hbrk && (--dz->iparam[FLT_HISAMS] <= 0)) {
+            if(!newvalue(FLT_HIFRQ,FLT_HIINCR,FLT_HISAMS,dz)) { 
+                sprintf(errstr,"Ran out of hifrq values: do_sweep_filter()\n");
+                return(PROGRAM_ERROR);
+            }
+        }
+        if(is_sbrk && (--dz->iparam[FLT_SWSAMS] <= 0)) {
+            if(!newvalue(FLT_SWPFRQ,FLT_SWINCR,FLT_SWSAMS,dz)) { 
+                sprintf(errstr,"Ran out of sweepfrq values: do_sweep_filter()\n");
+                return(PROGRAM_ERROR);
+            }
+        }
+        if(is_qbrk && (--dz->iparam[FLT_SAMS] <= 0)) {
+            if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) { 
+                sprintf(errstr,"Ran out of Q values: do_sweep_filter()\n");
+                return(PROGRAM_ERROR);
+            }
+        }
+        if(--dz->iparam[FLT_BLOKCNT] <= 0){
+            frq   = getfrq(dz->param[FLT_LOFRQ],dz->param[FLT_HIFRQ],dz->param[FLT_SWPFRQ],dz);
+            coeff = (2.0 * PI * frq) * dz->param[FLT_INV_SR];
+            if(is_lbrk)    dz->param[FLT_LOFRQ]  *= dz->param[FLT_LOINCR];
+            if(is_hbrk)    dz->param[FLT_HIFRQ]  *= dz->param[FLT_HIINCR];
+            if(is_sbrk)    dz->param[FLT_SWPFRQ] *= dz->param[FLT_SWINCR];
+            if(is_qbrk) {
+                dz->param[FLT_QFAC] = 1.0/(1.0 + dz->param[FLT_Q]);
+                dz->param[FLT_Q]   *= dz->param[FLT_Q_INCR];
+            }
+            dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE];
+        }
+        for(k=0;k<chans;k++)
+            buf[n+k] = multifilter(&(dbs[k]),&(dls[k]),&(dhs[k]),&(dns[k]),dops[k],dz->param[FLT_Q],coeff,buf[n+k],dz);
+    }
+    return(CONTINUE);
+}
+
+/*************************** GETFRQ ****************************
+ *
+ * NB sfrq is already adjusted to advance over a whole flt_blok.
+ */
+
+double getfrq(double lfrq,double hfrq,double sfrq,dataptr dz)
+{
+    double thispos;
+    double range = hfrq - lfrq;
+    thispos  = (cos(dz->param[FLT_CYCPOS]) + 1.0) * 0.5;
+    dz->param[FLT_CYCPOS]  =  fmod(dz->param[FLT_CYCPOS] + sfrq,TWOPI);
+    return((thispos * range) + lfrq);
+}
+
+/******************************* DO_ALLPASS_FILTER ******************************/
+
+int do_allpass_filter(dataptr dz)
+{
+    int exit_status;
+    int    chans    = dz->infile->channels;
+    float  *buf     = dz->sampbuf[0];
+    double prescale = dz->param[FLT_PRESCALE];
+
+    if(dz->brksize[FLT_DELAY])   
+        exit_status = varidelay_allpass(buf,chans,prescale,dz);
+    else
+        exit_status = allpass(buf,chans,prescale,dz);
+
+    return(exit_status);
+}
+
+/******************************* VARIDELAY_ALLPASS ******************************/
+
+int varidelay_allpass(float *buf,int chans,double prescale,dataptr dz)
+{
+    int   n, thisdelbfpos1, thisdelbfpos2, sampno;
+    int    delay, channo;
+    double frac, ip, op, delval1,delval2, delval;
+    double *delbuf1 = dz->parray[FLT_DELBUF1];
+    double *delbuf2 = dz->parray[FLT_DELBUF2];
+    int    maxdelsamps = dz->iparam[FLT_MAXDELSAMPS] * chans;
+    int    delbufpos   = dz->iparam[FLT_DELBUFPOS];
+    switch(dz->mode) {
+    case(FLT_PHASESHIFT):
+        for(n=0;n<dz->ssampsread;n+= chans){
+            if(--dz->iparam[FLT_SAMS] <= 0) {
+                if(!newvalue(FLT_DELAY,FLT_D_INCR,FLT_SAMS,dz)) {
+                    sprintf(errstr,"Ran out of Delay vals: varidelay_allpass()\n");
+                    return(PROGRAM_ERROR);
+                }
+            }
+            delay = (int)dz->param[FLT_DELAY];
+            frac  = dz->param[FLT_DELAY] - (double)delay;
+            for(channo = 0;channo < chans; channo++) {
+                sampno = n + channo;
+                thisdelbfpos1 = my_modulus((delbufpos - (delay*chans)),maxdelsamps);
+                thisdelbfpos2 = my_modulus((thisdelbfpos1 + chans)    ,maxdelsamps);
+                ip = (double)buf[sampno]    * prescale;
+                op = (-dz->param[FLT_GAIN]) * ip;
+                delval1     = delbuf1[thisdelbfpos1];
+                delval2     = delbuf1[thisdelbfpos2];
+                delval      = delval1 + ((delval2 - delval1) * frac);
+                op += delval;
+                delval1     = delbuf2[thisdelbfpos1];
+                delval2     = delbuf2[thisdelbfpos2];
+                delval      = delval1 + ((delval2 - delval1) * frac);
+                op += dz->param[FLT_GAIN] * delval;
+                delbuf1[delbufpos] = ip;
+                delbuf2[delbufpos] = op;
+                if(++delbufpos >= maxdelsamps)
+//                  delbufpos = 0;
+                    delbufpos -= maxdelsamps;       /*RWD 9:2001 */
+//TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time
+//   so (delbufpos -= maxdelsamps) = 0
+                buf[sampno] = (float) (op);
+            }
+            if(dz->vflag[FLT_LINDELAY])
+                dz->param[FLT_DELAY] += dz->param[FLT_D_INCR];
+            else
+                dz->param[FLT_DELAY] *= dz->param[FLT_D_INCR];
+        }
+        break;
+    case(FLT_PHASER):
+        for(n=0;n<dz->ssampsread;n+= chans){
+            if(--dz->iparam[FLT_SAMS] <= 0) {
+                if(!newvalue(FLT_DELAY,FLT_D_INCR,FLT_SAMS,dz)) {
+                    sprintf(errstr,"Ran out of Delay vals: varidelay_allpass()\n");
+                    return(PROGRAM_ERROR);
+                }
+            }
+            delay = (int)dz->param[FLT_DELAY];
+            frac  = dz->param[FLT_DELAY] - (double)delay;
+            for(channo = 0;channo < chans; channo++) {
+                sampno = n + channo;
+                thisdelbfpos1 = my_modulus((delbufpos - (delay*chans)),maxdelsamps);
+                thisdelbfpos2 = my_modulus((thisdelbfpos1 + chans)    ,maxdelsamps);
+                ip = (double)buf[sampno]    * prescale;
+                op = (-dz->param[FLT_GAIN]) * ip;
+                delval1     = delbuf1[thisdelbfpos1];
+                delval2     = delbuf1[thisdelbfpos2];
+                delval      = delval1 + ((delval2 - delval1) * frac);
+                op += delval;
+                delval1     = delbuf2[thisdelbfpos1];
+                delval2     = delbuf2[thisdelbfpos2];
+                delval      = delval1 + ((delval2 - delval1) * frac);
+                op += dz->param[FLT_GAIN] * delval;
+                delbuf1[delbufpos] = ip;
+                delbuf2[delbufpos] = op;
+                if(++delbufpos >= maxdelsamps)
+                    //delbufpos = 0;
+                    delbufpos -= maxdelsamps;   /*RWD 9:2001 (see e_tmp/cdpfloat ) */
+//TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time
+//   so (delbufpos -= maxdelsamps) = 0
+                buf[sampno] = (float) ((op + (double)buf[sampno]) * 0.5);
+            }
+            if(dz->vflag[FLT_LINDELAY])
+                dz->param[FLT_DELAY] += dz->param[FLT_D_INCR];
+            else
+                dz->param[FLT_DELAY] *= dz->param[FLT_D_INCR];
+        }
+        break;
+    default:
+        sprintf(errstr,"Unknown case:varidelay_allpass()\n");
+        return(PROGRAM_ERROR); 
+    }
+    dz->iparam[FLT_DELBUFPOS] = delbufpos;
+    return(FINISHED);
+}
+
+/******************************* ALLPASS ******************************/
+
+int allpass(float *buf,int chans,double prescale,dataptr dz)
+{
+    int   n, sampno;
+    int    channo;
+    double *delbuf1 = dz->parray[FLT_DELBUF1];
+    double *delbuf2 = dz->parray[FLT_DELBUF2];
+    int    maxdelsamps = dz->iparam[FLT_MAXDELSAMPS] * chans;
+    int    delbufpos   = dz->iparam[FLT_DELBUFPOS];
+    double ip, op; 
+    switch(dz->mode) {
+    case(FLT_PHASESHIFT):
+        for(n=0;n<dz->ssampsread;n+=chans){
+            for(channo = 0;channo < chans; channo++) {
+                sampno = n + channo;
+                ip = (double)buf[sampno] * prescale;
+                op = (-dz->param[FLT_GAIN]) * ip;
+                op += delbuf1[delbufpos];
+                op += dz->param[FLT_GAIN] * delbuf2[delbufpos];
+                delbuf1[delbufpos] = ip;
+                delbuf2[delbufpos] = op;
+                if(++delbufpos >= maxdelsamps)
+                    /*delbufpos = 0;*/
+                    delbufpos -= maxdelsamps;           /*RWD */
+//TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time
+//   so (delbufpos -= maxdelsamps) = 0
+                buf[sampno] = (float)(op);
+            }
+        }
+        break;
+    case(FLT_PHASER):
+        for(n=0;n<dz->ssampsread;n+=chans){
+            for(channo = 0;channo < chans; channo++) {
+                sampno = n + channo;
+                ip = (double)buf[sampno] * prescale;
+                op = (-dz->param[FLT_GAIN]) * ip;
+                op += delbuf1[delbufpos];
+                op += dz->param[FLT_GAIN] * delbuf2[delbufpos];
+                delbuf1[delbufpos] = ip;
+                delbuf2[delbufpos] = op;
+                if(++delbufpos >= maxdelsamps)
+                    /*delbufpos = 0;*/
+                    delbufpos -= maxdelsamps;           /*RWD */
+//TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time
+//   so (delbufpos -= maxdelsamps) = 0
+                buf[sampno] = (float)((op + (double)buf[sampno]) * 0.5);
+            }
+        }
+        break;
+    default:
+        sprintf(errstr,"Unknown case: allpass()\n");
+        return(PROGRAM_ERROR);
+    }
+    dz->iparam[FLT_DELBUFPOS] = delbufpos;
+    return(FINISHED);
+}
+
+/******************************* DO_EQ_FILTER ******************************/
+
+int do_eq_filter(dataptr dz)
+{
+    double ip, op;
+    int   n, sampno;
+    float  *buf = dz->sampbuf[0];
+    int   chans = dz->infile->channels, chno;
+    double *xx1 = dz->parray[FLT_XX1];
+    double *xx2 = dz->parray[FLT_XX2];
+    double *yy1 = dz->parray[FLT_YY1];
+    double *yy2 = dz->parray[FLT_YY2];
+    double a0   = dz->param[FLT_A0];
+    double a1   = dz->param[FLT_A1];
+    double a2   = dz->param[FLT_A2];
+    double b1   = dz->param[FLT_B1];
+    double b2   = dz->param[FLT_B2];
+    double prescale = dz->param[FLT_PRESCALE];
+    //double inv_of_maxsamp = 1.0/(double)F_MAXSAMP;
+    for(n = 0;n < dz->ssampsread; n+= chans){
+        for(chno = 0;chno < chans; chno++) {
+            sampno = n+chno;
+            ip  = (double)buf[sampno] /* * inv_of_maxsamp*/;
+            ip *= prescale;
+            op  = (a0 * ip) + (a1 * xx1[chno]) + (a2 * xx2[chno]) - (b1 * yy1[chno]) - (b2 * yy2[chno]);
+            xx2[chno] = xx1[chno];
+            xx1[chno] = ip;
+            yy2[chno] = yy1[chno];
+            yy1[chno] = op;
+            buf[sampno] = (float)(op);
+        }
+    }
+    return(FINISHED);
+}
+
+/************************** MULTIFILTER **************************/
+
+float multifilter(double *dll,double *dbb,double *dnn,double *dhh,double *dpp,
+                    double qfac,double coeff,float input,dataptr dz)
+{
+    double dya, dsa;
+    dya   = (double)input;
+    *dhh  = (qfac * *dbb) - *dll - dya;
+    *dbb  = *dbb - (coeff * *dhh);
+    *dll  = *dll - (coeff * *dbb);
+    *dnn  = *dll + *dhh;
+    dsa   = (*dpp) * dz->param[FLT_GAIN]; /* dpp points to dhh,dbb,dll,dnn */
+#ifdef NOTDEF
+    if (fabs(dsa) > F_MAXSAMP) {
+        dz->iparam[FLT_OVFLW]++;
+        dz->param[FLT_GAIN] *= .9999;
+        if (dsa  > 0.0) 
+            dsa = (double)F_MAXSAMP;
+        else 
+            dsa = (double)F_MINSAMP;
+    }
+    return((float)dsa);  /* TRUNCATE */
+#else
+    return (float) check_float_limits(dsa,dz);
+#endif
+}
+
+/***************************** FILTER *************************************/
+/* RWD TODO: add fix for nchans */
+
+//int do_lphp_filter(dataptr dz)
+//{
+//  double *e1s,*e2s,*s1s,*s2s;
+//  double *e1   = dz->parray[FLT_E1];
+//  double *e2   = dz->parray[FLT_E2];
+//  double *s1   = dz->parray[FLT_S1];
+//  double *s2   = dz->parray[FLT_S2];
+//  double *den1 = dz->parray[FLT_DEN1];
+//  double *den2 = dz->parray[FLT_DEN2];
+//  double *cn   = dz->parray[FLT_CN];
+//  switch(dz->infile->channels) {
+//  case(STEREO):
+//      e1s  = dz->parray[FLT_E1S];
+//      e2s  = dz->parray[FLT_E2S];
+//      s1s  = dz->parray[FLT_S1S];
+//      s2s  = dz->parray[FLT_S2S];
+//      lphp_filt_stereo(e1,e2,s1,s2,e1s,e2s,s1s,s2s,den1,den2,cn,dz);
+//      break;
+//  case(MONO):
+//      lphp_filt(e1,e2,s1,s2,den1,den2,cn,dz);
+//      break;
+//  }
+//  return(FINISHED);
+//}
+//      
+// TW MULTICHAN 2010
+int do_lphp_filter(dataptr dz)
+{
+    int i;
+    int index;
+    double *e1,*e2,*s1,*s2;
+    double *den1 = dz->parray[FLT_DEN1];
+    double *den2 = dz->parray[FLT_DEN2];
+    double *cn   = dz->parray[FLT_CN];  
+
+    for(i=0; i < dz->infile->channels; i++) {
+        index = i * FLT_LPHP_ARRAYS_PER_FILTER;
+
+        e1   = dz->parray[FLT_E1_BASE + index];
+        e2   = dz->parray[FLT_E2_BASE + index];
+        s1   = dz->parray[FLT_S1_BASE + index];
+        s2   = dz->parray[FLT_S2_BASE + index];
+
+        lphp_filt_chan(e1,e2,s1,s2,den1,den2,cn,dz,i);
+
+    }
+    return(FINISHED);
+}
+
+/***************************** LPHP_FILT *************************************/
+
+void lphp_filt(double *e1,double *e2,double *s1,double *s2,
+                    double *den1,double *den2,double *cn,dataptr dz)
+{
+    int i;
+    int  k;
+    float *buf = dz->sampbuf[0];
+    double ip, op = 0.0, b1;
+    for (i = 0 ; i < dz->ssampsread; i++) {
+        ip = (double) buf[i];
+        for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+            b1    = dz->param[FLT_MUL] * cn[k];
+            op    = (cn[k] * ip) + (den1[k] * s1[k]) + (den2[k] * s2[k]) + (b1 * e1[k]) + (cn[k] * e2[k]);
+            s2[k] = s1[k];
+            s1[k] = op;
+            e2[k] = e1[k];
+            e1[k] = ip;
+        }
+        op *= dz->param[FLT_PRESCALE];
+                //RWD NB gain modification...
+#ifdef NOTDEF
+        if (fabs(op) > 1.0) {
+            dz->iparam[FLT_OVFLW]++;
+//TW SUGGEST KEEP THIS: PREVENTS FILTER BLOWING UP
+            dz->param[FLT_PRESCALE] *= .9999;
+            if (op  > 0.0)
+                op = 1.0;
+            else 
+                op = -1.0;
+        }
+        buf[i] = (float)op;
+#else
+        buf[i] = (float) check_float_limits(op,dz);
+#endif
+    }
+}
+
+/*RWD 4:2000 */
+void lphp_filt_chan(double *e1,double *e2,double *s1,double *s2,
+                    double *den1,double *den2,double *cn,dataptr dz,int chan)
+{
+    int i;
+    int  k;
+    float *buf = dz->sampbuf[0];
+    double ip, op = 0.0, b1;
+    for (i = chan ; i < dz->ssampsread; i+= dz->infile->channels) {
+        ip = (double) buf[i];
+        for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+            b1    = dz->param[FLT_MUL] * cn[k];
+            op    = (cn[k] * ip) + (den1[k] * s1[k]) + (den2[k] * s2[k]) + (b1 * e1[k]) + (cn[k] * e2[k]);
+            s2[k] = s1[k];
+            s1[k] = op;
+            e2[k] = e1[k];
+            e1[k] = ip;
+        }
+        op *= dz->param[FLT_PRESCALE];
+        //RWD NB gain modification...
+#ifdef NOTDEF
+        if (fabs(op) > 1.0) {
+            dz->iparam[FLT_OVFLW]++;
+//TW SUGGEST KEEP THIS: PREVENTS FILTER BLOWING UP
+            dz->param[FLT_PRESCALE] *= .9999;
+            if (op  > 0.0)
+                op = 1.0;
+            else 
+                op = -1.0;
+        }
+        buf[i] = (float)op;
+#else
+        buf[i] = (float) check_float_limits(op,dz);
+#endif
+    }
+}
+
+/***************************** LPHP_FILT_STEREO *************************************/
+
+void lphp_filt_stereo(double *e1,double *e2,double *s1,double *s2,double *e1s,double *e2s,double *s1s,double *s2s,
+                    double *den1,double *den2,double *cn,dataptr dz)
+{
+    int i, j;
+    int  k;
+    float *buf = dz->sampbuf[0];
+    double ip, op = 0.0, b1;
+    for (i = 0 ; i < dz->ssampsread; i+=2) {
+        ip = (double)buf[i];
+        for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+            b1    = dz->param[FLT_MUL] * cn[k];
+            op    = (cn[k] * ip) + (den1[k] * s1[k]) + (den2[k] * s2[k]) + (b1 * e1[k]) + (cn[k] * e2[k]);
+            s2[k] = s1[k];
+            s1[k] = op;
+            e2[k] = e1[k];
+            e1[k] = ip;
+        }
+        op *= dz->param[FLT_PRESCALE];
+#ifdef NOTDEF
+        if (fabs(op) > F_MAXSAMP) {
+            dz->iparam[FLT_OVFLW]++;
+            dz->param[FLT_PRESCALE] *= .9999;
+            if (op  > 0.0)
+                op = (double)F_MAXSAMP;
+            else 
+                op = (double)F_MINSAMP;
+        }
+        buf[i] = (float)op;
+#else
+        buf[i] = (float) check_float_limits(op,dz);
+#endif
+        j = i+1;
+        ip = (double)buf[j];
+        for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+            b1     = dz->param[FLT_MUL] * cn[k];
+            op     = (den1[k] * s1s[k]) + (den2[k] * s2s[k]) + (cn[k] * ip) + (b1 * e1s[k]) + (cn[k] * e2s[k]);
+            s2s[k] = s1s[k];
+            s1s[k] = op;
+            e2s[k] = e1s[k];
+            e1s[k] = ip;
+        }
+        op *= dz->param[FLT_PRESCALE];
+#ifdef NOTDEF
+        if (fabs(op) > F_MAXSAMP) {
+            dz->iparam[FLT_OVFLW]++;
+            dz->param[FLT_PRESCALE] *= .9999;
+            if (op  > 0.0)
+                op = (double)F_MAXSAMP;
+            else 
+                op = (double)F_MINSAMP;
+        }
+        buf[j] = (float)op;
+#else
+        buf[j] = (float) check_float_limits(op,dz);
+#endif
+    }
+}
+
+/***************************** MY_MODULUS *************************************/
+
+int my_modulus(int x,int y)
+{
+    if(x>=0)
+        return(x%y);
+    while(x < 0)
+        x += y;
+    return(x);
+}
+
+/**************************** NEWFVAL2 *******************************/
+
+int newfval2(double *fbrk,double *hbrk,dataptr dz)
+{
+    int n, m, k, z, timepoint, nextrow;
+    int entrycnt = dz->iparam[FLT_ENTRYCNT];
+    int wordcnt  = dz->iparam[FLT_WORDCNT];
+    int hentrycnt = dz->iparam[HRM_ENTRYCNT];
+    int hwordcnt  = dz->iparam[HRM_WORDCNT];
+    //long srate = dz->infile->srate;
+    double lotime, hitime, timefrac, valdiff;
+    double thistime = dz->param[FLT_TOTALTIME];
+
+    memset((char *)dz->parray[FLT_INFRQ],0,dz->iparam[FLT_CNT] * sizeof(double));
+    memset((char *)dz->parray[FLT_INAMP],0,dz->iparam[FLT_CNT] * sizeof(double));
+    timepoint = 0;
+    while(thistime >= fbrk[timepoint]) {    /* search times in frq array */
+        timepoint += entrycnt;
+        if(timepoint >= wordcnt)
+            break;
+    }
+    timepoint -= entrycnt;
+    lotime = fbrk[timepoint];
+    nextrow = timepoint + entrycnt;
+    for(n = timepoint+1,k = 0; n < nextrow;n+=2,k += dz->iparam[FLT_HARMCNT]) {
+        dz->parray[FLT_INFRQ][k] = fbrk[n];     /* Get frqs of fundamentals into array, leaving space for harmonics */
+        dz->parray[FLT_INAMP][k] = fbrk[n+1];   /* Get amps of fundamentals into array, leaving space for harmonics */
+    }
+    if(nextrow != wordcnt) {                    /* if not at end of table, do interpolation */
+        nextrow += entrycnt;
+        timepoint += entrycnt;
+        hitime = fbrk[timepoint];
+        timefrac = (thistime - lotime)/(hitime - lotime);
+        k = 0;
+        for(n = timepoint+1,k=0; n < nextrow;n+=2,k += dz->iparam[FLT_HARMCNT]) {
+            /* FRQ */
+            valdiff = fbrk[n] - dz->parray[FLT_INFRQ][k];
+            valdiff *= timefrac;
+            dz->parray[FLT_INFRQ][k] = dz->parray[FLT_INFRQ][k] + valdiff;
+            /* AMP */
+            valdiff = fbrk[n+1] - dz->parray[FLT_INAMP][k];
+            valdiff *= timefrac;
+            dz->parray[FLT_INAMP][k] = dz->parray[FLT_INAMP][k] + valdiff;
+        }
+    }
+    timepoint = 0;
+    while(thistime >= hbrk[timepoint]) {    /* search times in frq array */
+        timepoint += hentrycnt;
+        if(timepoint >= hwordcnt) {
+            break;
+        }
+    }
+    timepoint -= hentrycnt;
+    lotime = hbrk[timepoint];
+    nextrow = timepoint + hentrycnt;
+    k = 0;
+    for(n = timepoint+1,k=0; n < nextrow;n+=2,k++) {
+        dz->parray[HARM_FRQ_CALC][k] = hbrk[n];
+        dz->parray[HARM_AMP_CALC][k] = hbrk[n+1];
+    }
+    if(nextrow != hwordcnt) {                   /* if not at end of table, do interpolation */
+        nextrow += hentrycnt;
+        timepoint += hentrycnt;
+        hitime = hbrk[timepoint];
+        timefrac = (thistime - lotime)/(hitime - lotime);
+        k = 0;
+        for(n = timepoint+1,k=0; n < nextrow;n+=2,k++) {
+            /* PARTIAL MULTIPLIER */
+            valdiff = hbrk[n] - dz->parray[HARM_FRQ_CALC][k];
+            valdiff *= timefrac;
+            dz->parray[HARM_FRQ_CALC][k] = dz->parray[HARM_FRQ_CALC][k] + valdiff;
+            /* PARTIAL AMP */
+            valdiff = hbrk[n+1] - dz->parray[HARM_AMP_CALC][k];
+            valdiff *= timefrac;
+            dz->parray[HARM_AMP_CALC][k] = dz->parray[HARM_AMP_CALC][k] + valdiff;
+        }
+    }
+    for(k=0;k<dz->iparam[FLT_CNT];k+=dz->iparam[FLT_HARMCNT]) {
+        z = 0;
+        for(m=0; m < dz->iparam[FLT_HARMCNT];m++) { /* calc vals for partials from basefrq vals */
+            dz->parray[FLT_INFRQ][k+m] = dz->parray[FLT_INFRQ][k] * dz->parray[HARM_FRQ_CALC][m];
+            dz->parray[FLT_INAMP][k+m] = dz->parray[FLT_INAMP][k] * dz->parray[HARM_AMP_CALC][m];
+            dz->parray[FLT_FRQ][k+m] = dz->parray[FLT_INFRQ][k+m];
+            dz->parray[FLT_AMP][k+m] = dz->parray[FLT_INAMP][k+m];
+        }
+    }
+    dz->param[FLT_TOTALTIME] += dz->param[FLT_TIMESTEP];
+    return(FINISHED);
+}
+
+/*************************** DO_FVARY2_FILTERS *****************************/
+
+int do_fvary2_filters(dataptr dz)
+{
+    int exit_status;
+    int    n, fno, chans = dz->infile->channels;
+    float *buf = dz->sampbuf[0];
+
+    //double *fincr = dz->parray[FLT_FINCR];
+    //double *aincr = dz->parray[FLT_AINCR];
+ 
+    double *ampl = dz->parray[FLT_AMPL];
+    double *a = dz->parray[FLT_A];
+    double *b = dz->parray[FLT_B];
+    double *y = dz->parray[FLT_Y];
+    double *z = dz->parray[FLT_Z];
+    double *d = dz->parray[FLT_D];
+    double *e = dz->parray[FLT_E];
+ 
+    int fsams = dz->iparam[FLT_FSAMS];
+    for (n = 0; n < dz->ssampsread; n += chans) { 
+        if(dz->brksize[FLT_Q]) {
+            if((dz->iparam[FLT_SAMS] -= chans) <= 0) {
+                if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) {
+                    sprintf(errstr,"Ran out of Q values: do_fvary2_filters()\n");
+                    return(PROGRAM_ERROR);
+                }
+                dz->iparam[FLT_SAMS] *= chans;
+            }
+        }
+        if(fsams <= 0) {
+            if((exit_status = newfval2(dz->parray[FLT_FBRK],dz->parray[FLT_HBRK],dz))<0)
+                return(exit_status);
+            fsams = dz->iparam[FLT_FSAMS];
+            for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) {
+                get_coeffs1(fno,dz);
+                get_coeffs2(fno,dz);
+            }
+            if(dz->brksize[FLT_Q])
+                dz->param[FLT_Q] *= dz->param[FLT_Q_INCR];
+        }
+
+        filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz);
+        fsams--;
+    }
+    return(CONTINUE);
+}
+

+ 543 - 0
dev/filter/filters1.c

@@ -0,0 +1,543 @@
+/*
+ * Copyright (c) 1983-2020 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 <globcon.h>
+#include <processno.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <filters.h>
+#include <cdpmain.h>
+#include <sfsys.h>
+#include <osbind.h>
+#include <string.h>
+#include <filters.h>
+#include <logic.h>
+
+static int    readsamps_with_wrap(dataptr dz);
+static double get_gain(dataptr dz);
+static double get_pshift(dataptr dz);
+static int   get_next_writestart(int write_start,dataptr dz);
+static int    iterfilt(int write_start,int *write_end,int *atten_index,
+                int thisbuf,double orig_maxsamp,int splicelen,dataptr dz);
+static void   reset_filters(dataptr dz);
+static void   scale_input(dataptr dz);
+static void   amp_smooth(dataptr dz);
+static void   do_attenuation(int atten_index, float *ib2,dataptr dz);
+static void   filter_normalise(float *thisbuf,double orig_maxsamp,dataptr dz);
+static double    get_maxsamp(float *thisbuf,dataptr dz);
+static int    do_shift_gain_and_copy_to_outbuf(float *ibuf,float *obuf,int chans,double step,
+                    double thisgain,int *write_pos,dataptr dz);
+static int    do_iterated_filtering(int atten_index,int write_start,int *write_end,
+                    int thisbuf,double orig_maxsamp,int splicelen,dataptr dz);
+static void   do_end_splice(float *ibuf,int seglen_in_mono,int splicelen,dataptr dz);
+
+/****************************** ITERATING_FILTER *************************/
+
+int iterating_filter(dataptr dz)
+{
+    int exit_status;
+    int tail;
+    float *obuf     = dz->sampbuf[FLT_OUTBUF];
+    float *ovflwbuf = dz->sampbuf[FLT_OVFLWBUF];
+    int write_start = 0, write_end;
+    int atten_index = 2, remaining_dur = dz->iparam[FLT_OUTDUR];
+    int thisbuf = 0;
+    double orig_maxsamp;
+    int splicelen = round(FLT_SPLICELEN * MS_TO_SECS * (double)dz->infile->srate);
+    splicelen = min(splicelen,dz->iparam[FLT_INMSAMPSIZE]/2 );     /*RWD 2 signifies ???? */
+    if((exit_status = readsamps_with_wrap(dz))<0)
+        return(exit_status);
+    if(!flteq(dz->param[FLT_PRESCALE],1.0))
+        scale_input(dz);
+    display_virtual_time(0L,dz);
+    if(dz->vflag[FLT_EXPDEC])
+        amp_smooth(dz);
+    orig_maxsamp = get_maxsamp(dz->sampbuf[0],dz);
+
+    memmove((char *)obuf,(char *)dz->sampbuf[0],(size_t)(dz->insams[0] * sizeof(float)));
+    write_start = get_next_writestart(write_start,dz);
+    write_end = dz->insams[0];
+    while(write_start < remaining_dur) {
+        while(write_start >= dz->buflen) {  /* 'while' allows blank buffers to be copied (where delay > filesize) */
+            if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
+                return(exit_status);
+            tail = write_end - dz->buflen;
+            memset((char *)obuf,0,(size_t)(dz->buflen * sizeof(float)));
+            if(tail > 0) {
+                memmove((char *)obuf,(char *)ovflwbuf,tail * sizeof(float));
+                memset((char *)ovflwbuf,0,(size_t) (dz->iparam[FLT_OVFLWSIZE] * sizeof(float)));
+            }
+            write_start -= dz->buflen;
+            write_end   -= dz->buflen;
+            remaining_dur -= dz->buflen;
+        }
+        if((exit_status= iterfilt(write_start,&write_end,&atten_index,thisbuf,orig_maxsamp,splicelen,dz))<0)
+            return(exit_status);
+        thisbuf = !thisbuf;   /* swap between buf0 and buf1 */
+        write_start = get_next_writestart(write_start,dz);
+    }
+    if(write_end-1 > 0)
+        return write_samps(obuf,write_end-1,dz);
+    return FINISHED;
+}
+
+/*************************** READSAMPS_WITH_WRAP **************************/
+
+int readsamps_with_wrap(dataptr dz)
+{
+    int exit_status;
+    int j;
+    int n;
+    float *buf = dz->sampbuf[0];
+    if((exit_status = read_samps(dz->sampbuf[0],dz)) < 0) {
+//TW MESSAGE TEXT CORRECTED
+        sprintf(errstr, "Can't read samples from input soundfile: readsamps_with_wrap()\n");
+        return(PROGRAM_ERROR);
+    }
+    if(dz->ssampsread!=dz->insams[0]) {
+        sprintf(errstr, "Failed to read all of source file: readsamps_with_wrap()\n");
+        return(PROGRAM_ERROR);
+    }
+    j = dz->ssampsread;
+    for(n=0;n<dz->infile->channels;n++) {
+        buf[j] = 0.0f;
+        j++;            /* INSERT GUARD POINTS FOR INTERPOLATION */
+    }
+    return(FINISHED);
+}
+
+/******************************** GET_GAIN *****************************/
+
+double get_gain(dataptr dz)
+{
+    double scatter;
+    scatter  = drand48() * dz->param[FLT_AMPSHIFT];
+    scatter  = 1.0 - scatter;
+    return scatter;
+}
+
+/******************************** GET_PSHIFT *****************************/
+
+double get_pshift(dataptr dz)
+{
+    double scatter;
+    scatter = (drand48() * 2.0) - 1.0;
+    if(scatter >= 0.0) {
+        scatter *= dz->param[FLT_PSHIFT];
+        return(pow(2.0,scatter));
+    }
+    scatter = -scatter;
+    scatter *= dz->param[FLT_PSHIFT];
+    scatter = pow(2.0,scatter);
+    scatter = 1.0/scatter;
+    return(scatter);
+}
+
+/*************************** GET_NEXT_WRITESTART ****************************/
+
+int get_next_writestart(int write_start,dataptr dz)
+{
+    int this_step;
+    double scatter;  
+    scatter = ((drand48() * 2.0) - 1.0) * dz->param[FLT_RANDDEL];
+    scatter += 1.0;
+    this_step = (int)round((double)dz->iparam[FLT_MSAMPDEL] * scatter);
+    this_step *= dz->infile->channels;
+    write_start += this_step;
+    return(write_start);
+}    
+
+/******************************* ITERFILT *****************************/
+
+int iterfilt(int write_start,int *write_end,int *atten_index,int thisbuf,double orig_maxsamp,int splicelen,dataptr dz)
+{
+    int exit_status;
+    int wr_end;
+    if((exit_status = do_iterated_filtering(*atten_index,write_start,&wr_end,thisbuf,orig_maxsamp,splicelen,dz))<0)
+        return(exit_status);
+    (*atten_index)++;
+    *write_end =  max(wr_end,*write_end);
+    return(FINISHED);
+}
+
+/***************************** RESET_FILTERS *************************/
+
+void reset_filters(dataptr dz)
+{
+    int n, chno, k;
+    int chans = dz->infile->channels;
+    for(n=0;n<dz->iparam[FLT_CNT];n++) {
+        for(chno=0;chno<chans;chno++) {
+            k = (n*chans)+chno;
+            if(dz->vflag[FLT_DBLFILT]) {
+                dz->parray[FLT_D][k]  = 0.0;
+                dz->parray[FLT_E][k]    = 0.0;
+            }
+            dz->parray[FLT_Y][k]  = 0.0;
+            dz->parray[FLT_Z][k]  = 0.0;
+        }
+    }
+}
+
+/******************************* SCALE_INPUT ****************************/
+
+void scale_input(dataptr dz)
+{
+    int i;
+    float *b  = dz->sampbuf[0];
+    int  end = dz->insams[0];
+    if(dz->iparam[FLT_DOFLAG]!=U_MONO && dz->iparam[FLT_DOFLAG]!=U_STEREO)
+        end = dz->insams[0] + dz->infile->channels;
+    for(i=0; i < end; i++)
+        b[i] = (float)(b[i] * dz->param[FLT_PRESCALE]);
+}
+
+/*************************** AMP_SMOOTH ************************
+ *
+ * expomential attenuation to input ensures everything remains equally loud as it decays!!
+ * attenuation when max no of signals overlayed (endatten)  is 1.0/dz->iparam[FLT_MAXOVERLAY].
+ * No of samples before this max overlay (y=attencnt)  
+ * .....is dz->iparam[FLT_MSAMPDEL] * (dz->iparam[FLT_MAXOVERLAY]-1).
+ * If sample by sample atten is x then
+ * pow(x,y) = endatten.
+ * Hence x  = pow(endatten,1/y);
+ */
+
+void amp_smooth(dataptr dz)
+{
+//  int k = 1;
+    register int i = 0, n;
+    register int m;
+    double atten, endatten;
+    int attencnt;
+    int chans = dz->infile->channels;
+    attencnt = dz->iparam[FLT_MSAMPDEL] * (dz->iparam[FLT_MAXOVERLAY]-1);
+    endatten = 1.0/(double)dz->iparam[FLT_MAXOVERLAY];
+    dz->param[FLT_SAMPATTEN] = pow(endatten,(1.0/(double)attencnt));
+    atten = 1.0;
+    for(n = 0;n < dz->insams[0]; n++) {
+        for(m = 0; m < chans; m++) {
+            dz->sampbuf[0][i] = (float)((double)dz->sampbuf[0][i] * atten);
+            i++;
+        }
+        atten *= dz->param[FLT_SAMPATTEN];
+    }
+}
+
+/*************************** DO_ATTENUATION ************************/
+
+void do_attenuation(int atten_index, float *ib2,dataptr dz)
+{
+    double thisgain;
+//  register int n, j = 0;
+    register int n;
+//  int chans = dz->infile->channels;
+    int atten_factor = min(atten_index,dz->iparam[FLT_MAXOVERLAY]);
+    thisgain = pow(dz->param[FLT_SAMPATTEN],(double)(atten_factor * dz->iparam[FLT_MSAMPDEL]));
+    for (n = 0; n < dz->insams[0]; n++) {
+        ib2[n] = (float)((double)ib2[n] * thisgain);
+        //      n++;      /*RWD 12/20: can't be right to increment this twice */
+    }
+}
+
+/************************** FILTER_NORMALISE ************************/
+
+void filter_normalise(float *thisbuf,double orig_maxsamp,dataptr dz)
+{
+    int n;
+    double maxsamp = get_maxsamp(thisbuf,dz);
+    double thisnorm = orig_maxsamp/maxsamp;
+    for (n = 0; n < dz->insams[0]; n++)
+        thisbuf[n] = (float) ((double)thisbuf[n] * thisnorm);
+}
+
+/************************** GET_MAXSAMP ************************/
+
+double get_maxsamp(float *thisbuf,dataptr dz)
+{
+    int n;
+    double  maxsamp = F_MINSAMP, minsamp = F_MAXSAMP;
+    for (n = 0; n < dz->insams[0]; n++) {
+        maxsamp = max(thisbuf[n],maxsamp);
+        minsamp = min(thisbuf[n],minsamp);
+    }
+    maxsamp = max(fabs(maxsamp),fabs(minsamp));
+    return(maxsamp);
+}   
+
+/**************************** DO_ITERATED_FILTERING ***************************/
+
+int do_iterated_filtering(int atten_index,int write_start,int *write_end,
+        int thisbuf,double orig_maxsamp,int splicelen,dataptr dz)
+{
+    int exit_status;
+    register int  n;
+    int   write_pos = write_start;
+    float  *ibuf = dz->sampbuf[thisbuf];
+    float  *ibuf2= dz->sampbuf[!thisbuf];
+    float  *obuf =  dz->sampbuf[FLT_OUTBUF];
+    int    chans = dz->infile->channels;
+    double *ampl = dz->parray[FLT_AMPL];
+    double *a    = dz->parray[FLT_A];
+    double *b    = dz->parray[FLT_B];
+    double *y    = dz->parray[FLT_Y];
+    double *z    = dz->parray[FLT_Z];
+    double *d    = dz->parray[FLT_D];
+    double *z1   = dz->parray[FLT_E];
+    double step     = 1.0;
+    double thisgain = 1.0;
+    int    total_samps = dz->iparam[FLT_INMSAMPSIZE]*chans;
+    if(dz->param[FLT_PSHIFT] > 0.0)     
+        step = get_pshift(dz);
+    if(dz->param[FLT_AMPSHIFT] > 0.0)       
+        thisgain = get_gain(dz);
+
+    reset_filters(dz);
+    for (n = 0; n < total_samps; n+=chans)
+        io_filtering(ibuf,ibuf2,chans,n,a,b,y,z,d,z1,ampl,dz);
+    if(!dz->vflag[FLT_NONORM])
+        filter_normalise(ibuf2,orig_maxsamp,dz);
+    if(dz->vflag[FLT_EXPDEC])
+        do_attenuation(atten_index,ibuf2,dz);
+    do_end_splice(ibuf2,dz->iparam[FLT_INMSAMPSIZE],splicelen,dz);
+    if((exit_status = do_shift_gain_and_copy_to_outbuf(ibuf2,obuf,chans,step,thisgain,&write_pos,dz))<0)
+        return(exit_status);
+
+    memset((char *)ibuf,0,(size_t)(dz->iparam[FLT_INFILESPACE] * sizeof(float)));
+    *write_end = write_pos;
+    return(FINISHED);
+}
+
+/*************************** DO_SHIFT_GAIN_AND_COPY_TO_OUTBUF *******************************/
+
+int do_shift_gain_and_copy_to_outbuf(float *ibuf,float *obuf,int chans,double step,
+                                    double thisgain,int *write_pos,dataptr dz)
+{
+    float  val, nextval, diff;
+    double d = 0.0, part = 0.0, input;
+    int n = 0, z;
+    register int j = *write_pos;
+    register int  chno;
+    int total_samps = dz->iparam[FLT_INMSAMPSIZE] * chans;
+
+    switch(dz->iparam[FLT_DOFLAG]) {
+    case(ITER_MONO): 
+    case(ITER_STEREO):
+        while(n < total_samps) { 
+            for(chno=0;chno<chans;chno++)
+                obuf[j++] += (float)(ibuf[n+chno] * thisgain);
+            n+=chans;
+        }
+        break;
+    case(MN_SHIFT):
+        while(n < dz->iparam[FLT_INMSAMPSIZE]) { 
+            obuf[j++] += (float) (ibuf[n] * thisgain);
+            d       += step;
+            n        = round(d);        /* ROUND */
+        }
+        break;
+    case(ST_SHIFT):
+        while (n < dz->iparam[FLT_INMSAMPSIZE]) { 
+            for(chno = 0; chno < chans; chno++) {
+                z = (n * chans) + chno;
+                obuf[j++] += (float)(ibuf[z] * thisgain);
+            }
+            d   += step;
+            n   = round(d);
+        }
+        break;
+    case(MN_FLT_INTP_SHIFT):
+        while(n < dz->iparam[FLT_INMSAMPSIZE]) {
+            val      = ibuf[n++];
+            nextval  = ibuf[n];
+            diff     = nextval - val;
+            input    = (double)val + ((double)diff * part);
+            obuf[j++] += (float) (input * thisgain);
+            d       += step;
+            n        = (int)d;          /* TRUNCATE */
+            part     = d - (double)n; 
+        }
+        break;
+    case(ST_FLT_INTP_SHIFT):
+        while(n < dz->iparam[FLT_INMSAMPSIZE]) {
+            for(chno = 0; chno < chans; chno++) {
+                z = (n * chans) + chno;
+                val       = ibuf[z];
+                nextval   = ibuf[z+chans];
+                diff      = nextval - val;
+                input     = (double)val + ((double)diff * part);
+                obuf[j++] += (float) (input * thisgain);
+            }
+            d   += step;
+            n    = (int)d;                      /* TRUNCATE */
+            part = d - (double)n;
+        }
+        break;
+    case(U_MONO): 
+    case(U_STEREO):
+        while(n < total_samps) {
+            for(chno=0;chno<chans;chno++) 
+                obuf[j++] += ibuf[n+chno];
+            n+= chans;
+        }
+        break;
+    case(U_MN_SHIFT):
+        while(n < dz->iparam[FLT_INMSAMPSIZE]) { 
+            obuf[j++] = ibuf[n];
+            d      += step;
+            n       = round(d);     /* ROUND */
+        }
+        break;
+    case(U_ST_SHIFT):
+        while(n < dz->iparam[FLT_INMSAMPSIZE]) { 
+            for(chno = 0; chno < chans; chno++) {
+                z = (n * chans) + chno;
+                obuf[j++] += ibuf[z];
+            }
+            d += step;
+            n  = round(d);      /* ROUND */
+        }
+        break;
+    case(U_MN_INTP_SHIFT):
+        while(n < dz->iparam[FLT_INMSAMPSIZE]) {
+            val      = ibuf[n++];
+            nextval  = ibuf[n];
+            diff     = nextval - val;
+            input    = (double)val + ((double)diff * part);
+            obuf[j]  = (float) (input + (double)obuf[j]);
+            j++;
+            d        += step;
+            n         = (int)d;             /* TRUNCATE */
+            part      = d - (double)n; 
+        }
+        break;
+    case(U_ST_INTP_SHIFT):
+        while(n < dz->iparam[FLT_INMSAMPSIZE]) {
+            for(chno = 0; chno < chans; chno++) {
+                z = (n * chans) + chno;
+                val       = ibuf[z];
+                nextval   = ibuf[z+chans];
+                diff      = nextval - val;
+                input     = (double)val + ((double)diff * part);
+                obuf[j]   = (float)(input + (double)obuf[j]);
+                j++;
+            }
+            d   += step;
+            n    = (int)d;             /* TRUNCATE */
+            part = d - (double)n;
+        }
+        break;
+    default:
+        sprintf(errstr,"Unknown case in do_shift_gain_and_copy_to_outbuf()\n");
+        return(PROGRAM_ERROR);
+    }
+    *write_pos = j;
+    return(FINISHED);
+}
+
+/*************************************** DO_END_SPLICE **************************************/
+
+void do_end_splice(float *ibuf,int seglen_in_mono,int splicelen,dataptr dz)
+{
+    int n, m, sampno, chnno, chans = dz->infile->channels;
+    double splicestep = 1.0/(double)splicelen;
+    double splicefact = 0.0;
+    for(n=((seglen_in_mono*chans)-chans), m=0; m<splicelen; n-=chans ,m++) {
+        for(chnno = 0;chnno<chans;chnno++) {
+            sampno = n + chnno;
+            ibuf[sampno] = (float) ((double)ibuf[sampno] * splicefact);
+        }
+        splicefact += splicestep;
+    }
+}
+
+/*************************************** MAKE_VFILT_DATA **************************************/
+
+int make_vfilt_data(dataptr dz)
+{
+    int n,k,m,j;
+    char *q, outname[200], line[200], temp[200];
+    double d;
+    FILE *fp;
+    int *thislinecnt;
+    if((thislinecnt = (int *)malloc(dz->linecnt * sizeof(int)))==NULL) {
+        sprintf(errstr,"No memory to distinguish lines in input data.\n");
+        return(MEMORY_ERROR);
+    }
+    if((fp = fopen(dz->wordstor[0],"r"))==NULL) {
+        sprintf(errstr,"Failed to reopen file %s for checking.\n",dz->wordstor[0]);
+        return(DATA_ERROR);
+    }
+    n = 0;
+    while(fgets(temp,200,fp)!=NULL) {
+        q = temp;
+        thislinecnt[n] = 0;
+        while(get_float_from_within_string(&q,&d)) {
+            thislinecnt[n]++;
+        }
+        n++;
+    }
+    fclose(fp);
+    j = 0;
+    for(n = 0; n < dz->linecnt; n++) {
+        strcpy(outname,dz->wordstor[1]);
+        if(sloom) {
+            replace_filename_extension(outname,"");
+            insert_new_number_at_filename_end(outname,n,1);
+        } else {
+            replace_filename_extension(outname,".txt");
+            insert_new_number_at_filename_end(outname,n,0);
+        }
+        if((fp = fopen(outname,"w"))==NULL) {
+            sprintf(errstr,"Cannot open file %s to store filter data\n",outname);
+            return(SYSTEM_ERROR);
+        }
+        strcpy(line,"0");
+        k = j;
+        for(m=0;m<thislinecnt[n];m++) {
+            strcat(line,"\t");
+            sprintf(temp,"%lf",dz->parray[0][j++]);
+            strcat(line,temp);
+            strcat(line,"\t1");
+        }
+        fprintf(fp,"%s\n",line);
+        strcpy(line,"10000");
+        for(m=0;m<thislinecnt[n];m++) {
+            strcat(line,"\t");
+            sprintf(temp,"%lf",dz->parray[0][k++]);
+            strcat(line,temp);
+            strcat(line,"\t1");
+        }
+        fprintf(fp,"%s\n",line);
+        fclose(fp);
+    }
+    dz->process_type = OTHER_PROCESS;
+    return FINISHED;
+}

+ 1011 - 0
dev/filter/fltpcon.c

@@ -0,0 +1,1011 @@
+/*
+ * 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 <globcon.h>
+#include <processno.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <filters.h>
+#include <sfsys.h>
+#include <osbind.h>
+/*RWD*/
+#include <math.h>
+#include <string.h>
+
+
+static int  force_start_and_end_val(int paramno,dataptr dz);
+static void initialise_filter_table_read(int param,dataptr dz);
+static int  setup_internal_eq_params(dataptr dz);
+static int  setup_internal_fstatvar_params(dataptr dz);
+static int  setup_internal_fltsweep_params(dataptr dz);
+static int  setup_internal_allpass_params_and_delaybufs(dataptr dz);
+static int  setup_internal_fltbankn_params(dataptr dz);
+static void setup_internal_iterfilt_params(dataptr dz);
+static int  allocate_tvarying_filter_arrays(int timeslot_cnt,int harmonics_cnt,dataptr dz);
+static int  put_tvarying_filter_data_in_arrays(double *fbrk,dataptr dz);
+static int  initialise_fltbankv_internal_params(dataptr dz);
+static int  error_name(int paramno,char *paramname,dataptr dz);
+static int  setup_stereo_variables(int a,int b,int c,int d,int chans,dataptr dz);
+static int  setup_eqfilter_coeffs(dataptr dz);
+static int  convert_delay_times_to_samples_and_get_maxdelay(dataptr dz);
+static int  count_filters(dataptr dz);
+static void convert_phase_from_input_range_to_actual_range(dataptr dz);
+static void convert_sfrq(dataptr dz);
+static void set_doflag(dataptr dz);
+/* ANDY MOORER ROUTINES:  for 2nd-order presence and shelving filters */
+/* rationalised slightly  */
+#define PII 	  	(3.141592653589793238462643)
+#define ROOT2OF2 	(0.7071067811965475244)		/* = sqrt(2)/2 */
+#define SPN 1.65436e-24							/* Smallest possible number on DEC VAX-780: but it will work here */
+
+static void   presence(double cf,double boost,double bw,double *a0,double *a1,double *a2,double *b1,double *b2);
+static void   shelve(double cf,double boost,double *a0,double *a1,double *a2,double *b1,double *b2,int mode);
+static double bw2angle(double a,double bw);
+static void   normalise_b0_to_one(double b0,double *a0,double *a1,double *a2,double *b1,double *b2);
+static void   bilinear_transform(double a,double t0,double t1,double t2,double asq,double *x0,double *x1,double *x2);
+static void   set_the_tvars(double gamma,double *t0,double *t1,double *t2);
+static void   establish_a_asq_A_F_F2_tmp(double cf,double boost,
+					double *a,double *asq,double *A,double *F,double *f2,double *temp);
+static int test_pitch_and_spectrum_varying_filterdata(double *fbrk,double *hbrk,dataptr dz);
+static int allocate_tvarying2_filter_arrays(dataptr dz);
+
+/************************************* FILTER_PCONSISTENCY *********************************/
+
+int filter_pconsistency(dataptr dz)
+{
+	int exit_status;
+	initrand48();
+	switch(dz->process) {			/* preset internal counters, or defaulted variables */
+	case(FLTBANKN):
+	case(FSTATVAR):
+	case(FLTBANKU):
+	case(FLTBANKV):
+	case(FLTBANKV2):
+	case(FLTSWEEP):
+		dz->iparam[FLT_SAMS]     = 0;
+		dz->iparam[FLT_OVFLW]    = 0;
+		dz->iparam[FLT_BLOKSIZE] = BSIZE;
+		dz->iparam[FLT_BLOKCNT]  = 0;
+		dz->param[FLT_INV_SR]    = 1.0/(double)dz->infile->srate;
+		if(dz->brksize[FLT_Q]) {
+			if((exit_status = force_start_and_end_val(FLT_Q,dz))<0)
+				return(exit_status);
+			initialise_filter_table_read(FLT_Q,dz);
+		}
+		break;
+	case(FLTBANKC):
+		dz->param[FLT_RANDFACT]	 = 0.0;
+		dz->param[FLT_INV_SR]    = 1.0/(double)dz->infile->srate;
+		break;
+	case(EQ):
+		dz->iparam[FLT_OVFLW]    = 0;
+		dz->param[FLT_INV_SR]    = 1.0/(double)dz->infile->srate;
+		break;
+	case(LPHP):
+		if(dz->mode==FLT_MIDI) {
+			miditohz(dz->param[FLT_PASSFRQ]);
+			miditohz(dz->param[FLT_STOPFRQ]);
+		}
+		dz->iparam[FLT_OVFLW]    = 0;
+		break;
+	case(FLTITER):
+		dz->iparam[FLT_OVFLW]    = 0;
+		dz->param[FLT_INV_SR]    = 1.0/(double)dz->infile->srate;
+		dz->iparam[FLT_SAMS]     = 0;
+		break;
+	case(ALLPASS):
+		dz->iparam[FLT_BLOKSIZE] = 1; /* delay (& strength) incremented on (stereo-pair)sample-by-sample basis */
+		dz->iparam[FLT_OVFLW]    = 0;
+		dz->iparam[FLT_SAMS]     = 0;
+		break;
+	}
+	switch(dz->process) {
+	case(EQ):  		return setup_internal_eq_params(dz);
+	case(FSTATVAR):	return setup_internal_fstatvar_params(dz);
+	case(FLTSWEEP):	return setup_internal_fltsweep_params(dz);
+	case(ALLPASS):	return setup_internal_allpass_params_and_delaybufs(dz);
+	case(FLTBANKN):
+	case(FLTBANKC):	return setup_internal_fltbankn_params(dz);
+	case(FLTITER):
+		setup_internal_iterfilt_params(dz);
+		break;
+	case(FLTBANKV):
+		dz->param[FLT_ROLLOFF] = dbtogain(dz->param[FLT_ROLLOFF]);
+		if((exit_status = allocate_tvarying_filter_arrays(dz->iparam[FLT_TIMESLOTS],dz->iparam[FLT_HARMCNT],dz))<0)
+			return(exit_status);
+		if((exit_status = put_tvarying_filter_data_in_arrays(dz->parray[FLT_FBRK],dz))<0)
+			return(exit_status);
+		if((exit_status = initialise_fltbankv_internal_params(dz))<0)
+			return(exit_status);
+		break;
+	case(FLTBANKV2):
+		if((exit_status = allocate_tvarying2_filter_arrays(dz))<0)
+			return(exit_status);
+		if((exit_status = test_pitch_and_spectrum_varying_filterdata(dz->parray[FLT_FBRK],dz->parray[FLT_HBRK],dz))<0)
+			return(exit_status);
+		if((exit_status = allocate_filter_frq_amp_arrays(dz->iparam[FLT_CNT],dz))<0)
+			return(exit_status);
+		if((exit_status = newfval2(dz->parray[FLT_FBRK],dz->parray[FLT_HBRK],dz))<0)
+			return(exit_status);
+		break;
+	}
+	return(FINISHED);
+}
+
+/*************************************** FORCE_START_AND_END_VAL **************************************/
+
+int force_start_and_end_val(int paramno,dataptr dz)
+{
+	int    exit_status;
+ 	double lasttime, filedur, firsttime, *p;
+	int   k, n;
+	char paramname[10];
+	if((exit_status = error_name(paramno,paramname,dz))<0)
+		return(exit_status);
+
+	firsttime = *(dz->brk[paramno]);
+	if(firsttime < 0.0) {
+		sprintf(errstr,"First time in %s file is -ve: Can't proceed\n",paramname);
+		return(DATA_ERROR);
+	}
+	if(flteq(firsttime,0.0))
+		*(dz->brk[paramno]) = 0.0;
+	else {							/* FORCE VALUE AT TIME 0 */
+	 	dz->brksize[paramno]++;
+		if((dz->brk[paramno] = (double *)realloc(dz->brk[paramno],dz->brksize[paramno] * 2 * sizeof(double)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY to reallocate filter array.\n");
+			return(MEMORY_ERROR);
+		}
+		k = dz->brksize[paramno] * 2;
+		for(n=k-1;n>=2;n--)
+			dz->brk[paramno][n] = dz->brk[paramno][n-2];
+		dz->brk[paramno][0] = 0.0;
+		dz->brk[paramno][1] = dz->brk[paramno][3];
+	}
+
+	lasttime = *(dz->brk[paramno] + ((dz->brksize[paramno]-1) * 2));
+	filedur  = (double)(dz->insams[0]/dz->infile->channels)/(double)dz->infile->srate;
+	if(lasttime >= filedur + FLT_TAIL)
+		return(FINISHED);			/* FORCE Q VALUE AT (BEYOND) END OF FILE */
+	dz->brksize[paramno]++;
+	if((dz->brk[paramno] = (double *)realloc(dz->brk[paramno],dz->brksize[paramno] * 2 * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to reallocate filter array.\n");
+		return(MEMORY_ERROR);
+	}
+	p = (dz->brk[paramno] + ((dz->brksize[paramno]-1) * 2));
+	*p++ = filedur + FLT_TAIL + 1.0;
+	*p = *(p-2);
+	return(FINISHED);
+}
+
+/************************************* INITIALISE_FILTER_TABLE_READ *********************************/
+
+void initialise_filter_table_read(int param,dataptr dz)
+{
+	dz->lastind[param] = (double)round((*dz->brk[param]) * dz->infile->srate);
+	dz->lastval[param] = *(dz->brk[param]+1);
+	dz->brkptr[param]  = dz->brk[param] + 2;
+}
+
+/**************************** SETUP_INTERNAL_EQ_PARAMS **********************/
+
+int setup_internal_eq_params(dataptr dz)
+{
+	int exit_status;
+	dz->param[FLT_ONEFRQ] *= dz->param[FLT_INV_SR];
+	dz->param[FLT_BW]     *= dz->param[FLT_INV_SR];
+	if((exit_status = setup_stereo_variables(FLT_XX1,FLT_XX2,FLT_YY1,FLT_YY2,dz->infile->channels,dz))<0)
+		return(exit_status);
+	return setup_eqfilter_coeffs(dz);
+}
+
+/************************************* SETUP_INTERNAL_FSTATVAR_PARAMS *********************************/
+
+int setup_internal_fstatvar_params(dataptr dz)
+{
+	int exit_status;
+
+	if(dz->brksize[FLT_Q]==0)
+    	dz->param[FLT_QFAC] = 1.0/(1.0 + dz->param[FLT_Q]);
+
+	if(dz->brksize[FLT_Q]) {
+		if((exit_status = force_start_and_end_val(FLT_Q,dz))<0)
+			return(exit_status);
+		initialise_filter_table_read(FLT_Q,dz);
+	}
+	if(dz->brksize[FLT_ONEFRQ]) {
+		if((exit_status = force_start_and_end_val(FLT_ONEFRQ,dz))<0)
+			return(exit_status);
+		initialise_filter_table_read(FLT_ONEFRQ,dz);
+	}
+	return setup_stereo_variables(FLT_DLS,FLT_DBS,FLT_DHS,FLT_DNS,dz->infile->channels,dz);
+}
+
+/************************************* SETUP_INTERNAL_FLTSWEEP_PARAMS *********************************/
+
+int setup_internal_fltsweep_params(dataptr dz)
+{
+	int exit_status;
+	convert_phase_from_input_range_to_actual_range(dz);
+	dz->iparam[FLT_LOSAMS]   = 0;
+	dz->iparam[FLT_HISAMS]   = 0;
+	dz->iparam[FLT_SWSAMS]   = 0;
+	dz->param[FLT_CYCPOS] 	 = dz->param[FLT_SWPPHASE];
+	if(dz->brksize[FLT_Q]==0)
+    	dz->param[FLT_QFAC] = 1.0/(1.0 + dz->param[FLT_Q]);
+
+    convert_sfrq(dz);
+
+	if(dz->brksize[FLT_LOFRQ]) {
+		if((exit_status = force_start_and_end_val(FLT_LOFRQ,dz))<0)
+			return(exit_status);
+		initialise_filter_table_read(FLT_LOFRQ,dz);
+	}
+	if(dz->brksize[FLT_HIFRQ]) {
+		if((exit_status = force_start_and_end_val(FLT_HIFRQ,dz))<0)
+			return(exit_status);
+		initialise_filter_table_read(FLT_HIFRQ,dz);
+	}
+	if(dz->brksize[FLT_SWPFRQ]) {
+		if((exit_status = force_start_and_end_val(FLT_SWPFRQ,dz))<0)
+			return(exit_status);
+		initialise_filter_table_read(FLT_SWPFRQ,dz);
+	}
+	return setup_stereo_variables(FLT_DLS,FLT_DBS,FLT_DHS,FLT_DNS,dz->infile->channels,dz);
+}
+
+/******************** CONVERT_PHASE_FROM_INPUT_RANGE_TO_ACTUAL_RANGE *******************/
+
+void convert_phase_from_input_range_to_actual_range(dataptr dz)
+{
+	dz->param[FLT_SWPPHASE] += .5;
+	if(dz->param[FLT_SWPPHASE] >= 1.0)
+		dz->param[FLT_SWPPHASE] -= 1.0;
+	dz->param[FLT_SWPPHASE] *=  TWOPI;
+}
+
+/**************************** CONVERT_SFRQ ***************************
+ *
+ * (1)	frq is in cycles/sec.
+ * (2)	Divide by SR gives what fraction of a cycle we get through in one sample.
+ * (3)	Multiply by FLT_BLOKSIZE, gives what fraction of a cycle we get through in one sample-blok.
+ * (4)  Multiply by TWOPI gives what part of a TWOPI-cycle do we get through in one sample-blok.
+ */
+
+void convert_sfrq(dataptr dz)
+{
+	double *p, *end;
+	if(dz->brksize[FLT_SWPFRQ]) {
+		p = dz->brk[FLT_SWPFRQ] + 1;
+		end = dz->brk[FLT_SWPFRQ] + (dz->brksize[FLT_SWPFRQ]*2);
+		while(p<end) {
+			if(flteq(*p,0.0))
+				*p = FLT_MINSWEEP;						/* prevent divides by zero */
+			*p *= dz->param[FLT_INV_SR] * dz->iparam[FLT_BLOKSIZE] * TWOPI;	 /* 1,2,3,4 */
+			p += 2;
+		}
+	} else {
+		if(flteq(dz->param[FLT_SWPFRQ],0.0))
+				dz->param[FLT_SWPFRQ] = FLT_MINSWEEP;	/* prevent divides by zero */
+		dz->param[FLT_SWPFRQ] *= dz->param[FLT_INV_SR] * dz->iparam[FLT_BLOKSIZE] * TWOPI;
+	}
+}
+
+/**************************** SETUP_INTERNAL_ALLPASS_PARAMS_AND_DELAYBUFS **********************/
+
+int setup_internal_allpass_params_and_delaybufs(dataptr dz)
+{
+
+#define DELAY_SAFETY (64)
+
+	int exit_status;
+	int delbufsize;
+	dz->iparam[FLT_MAXDELSAMPS]  = convert_delay_times_to_samples_and_get_maxdelay(dz);
+	if(dz->brksize[FLT_DELAY])
+		dz->iparam[FLT_MAXDELSAMPS] += DELAY_SAFETY;
+	delbufsize = dz->iparam[FLT_MAXDELSAMPS] * dz->infile->channels * sizeof(double);
+	/*RWD 9:2001 need calloc */
+	if((dz->parray[FLT_DELBUF1] = (double *)calloc((size_t)delbufsize,sizeof(char)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for 1st delay buffer.\n");
+		return(MEMORY_ERROR);
+	}
+	if((dz->parray[FLT_DELBUF2] = (double *)calloc((size_t)delbufsize,sizeof(char)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for 2nd delay buffer.\n");
+		return(MEMORY_ERROR);
+	}
+	dz->iparam[FLT_DELBUFPOS] = 0;
+
+	if(dz->brksize[FLT_DELAY]) {
+		if((exit_status = force_start_and_end_val(FLT_DELAY,dz))<0)
+			return(exit_status);
+		initialise_filter_table_read(FLT_DELAY,dz);
+	}
+	return(FINISHED);
+}
+
+/************************************* SETUP_INTERNAL_FLTBANKN_PARAMS *********************************/
+
+int setup_internal_fltbankn_params(dataptr dz)
+{
+	int exit_status;
+	double  temp;
+	switch(dz->mode) {
+	case(FLT_EQUALINT):  dz->param[FLT_INTSIZE] = pow(SEMITONE_INTERVAL,dz->param[FLT_INTSIZE]); 	break;
+	case(FLT_HARMONIC):	 dz->param[FLT_OFFSET]  = 0.0;  											break;
+	}
+	if(dz->param[FLT_LOFRQ] > dz->param[FLT_HIFRQ]) {	 /* correct inverted frq range */
+		temp  				 = dz->param[FLT_LOFRQ];
+		dz->param[FLT_LOFRQ] = dz->param[FLT_HIFRQ];
+		dz->param[FLT_HIFRQ] = temp;
+	}
+	if((exit_status = count_filters(dz))<0)
+		return(exit_status);
+	return allocate_filter_frq_amp_arrays(dz->iparam[FLT_CNT],dz);
+}	
+
+/************************************* SETUP_INTERNAL_ITERFILT_PARAMS *********************************/
+
+void setup_internal_iterfilt_params(dataptr dz)
+{
+	int srate = dz->infile->srate;
+	int  chans = dz->infile->channels;
+	dz->iparam[FLT_OUTDUR]  	= max(round(dz->param[FLT_OUTDUR] * (double)(srate * chans)),dz->insams[0]);
+	dz->iparam[FLT_MSAMPDEL] 	= round(dz->param[FLT_DELAY] * (double)srate);
+	dz->iparam[FLT_SMPDEL]   	= dz->iparam[FLT_MSAMPDEL] * chans;
+	dz->iparam[FLT_INMSAMPSIZE] = dz->insams[0]/chans;
+	if(flteq(dz->param[FLT_PRESCALE],0.0)) {								/* set default prescaling of input */
+		dz->iparam[FLT_MAXOVERLAY] = round(((double)dz->iparam[FLT_INMSAMPSIZE]/(double)dz->iparam[FLT_MSAMPDEL])+1.0);
+		if(dz->param[FLT_RANDDEL] > 0.0)
+			dz->iparam[FLT_MAXOVERLAY]++;
+		dz->param[FLT_PRESCALE] = 1.0/(double)dz->iparam[FLT_MAXOVERLAY];	
+	}
+	dz->param[FLT_PSHIFT] /= SEMITONES_PER_OCTAVE;							/* convert semitones to fractions of 8vas */
+	set_doflag(dz);
+}
+
+/************************** SET_DOFLAG ********************************/
+
+void set_doflag(dataptr dz)
+{   
+	if(dz->param[FLT_PSHIFT]>0.0) {
+		if(dz->vflag[FLT_PINTERP_OFF]) {
+			if(dz->infile->channels>1)
+				dz->iparam[FLT_DOFLAG] = ST_SHIFT;
+			else
+				dz->iparam[FLT_DOFLAG] = MN_SHIFT;
+		} else {
+			if(dz->infile->channels>1)
+				dz->iparam[FLT_DOFLAG] = ST_FLT_INTP_SHIFT;
+			else
+				dz->iparam[FLT_DOFLAG] = MN_FLT_INTP_SHIFT;
+		}
+	} else {
+		if(dz->infile->channels>1)
+			dz->iparam[FLT_DOFLAG] = ITER_STEREO;
+		else
+			dz->iparam[FLT_DOFLAG] = ITER_MONO;
+	}
+	if(flteq(dz->param[FLT_AMPSHIFT],0.0))
+	dz->iparam[FLT_DOFLAG] += FIXED_AMP;
+/* ??? */
+	if(dz->iparam[FLT_MSAMPDEL] >= dz->iparam[FLT_INMSAMPSIZE])
+		dz->vflag[FLT_EXPDEC] = 0;
+/* ??? */
+}
+
+/**************************** ALLOCATE_TVARYING_FILTER_ARRAYS *******************************/
+
+int allocate_tvarying_filter_arrays(int timeslot_cnt,int harmonics_cnt,dataptr dz)
+{
+	dz->iparam[FLT_CNT] *= harmonics_cnt;
+
+	if((dz->lparray[FLT_SAMPTIME] = (int *)calloc(timeslot_cnt * sizeof(int),sizeof(char)))==NULL
+	|| (dz->parray[FLT_INFRQ]     = (double *)calloc(dz->iparam[FLT_CNT] * timeslot_cnt * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_INAMP]     = (double *)calloc(dz->iparam[FLT_CNT] * timeslot_cnt * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_FINCR]     = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_AINCR]     = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_LASTFVAL]  = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_LASTAVAL]  = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for filter coefficients.\n");
+		return(MEMORY_ERROR);
+	}
+	return(FINISHED);
+}
+
+/**************************** ALLOCATE_TVARYING2_FILTER_ARRAYS *******************************/
+
+int allocate_tvarying2_filter_arrays(dataptr dz)
+{
+	if((dz->parray[FLT_INFRQ]     = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+	|| (dz->parray[FLT_INAMP]     = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+	|| (dz->parray[FLT_FINCR]     = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+	|| (dz->parray[FLT_AINCR]     = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+	|| (dz->parray[FLT_LASTFVAL]  = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+	|| (dz->parray[FLT_LASTAVAL]  = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for filter coefficients.\n");
+		return(MEMORY_ERROR);
+	}
+	return(FINISHED);
+}
+
+/**************************** PUT_TVARYING_FILTER_DATA_IN_ARRAYS *******************************/
+
+int put_tvarying_filter_data_in_arrays(double *fbrk,dataptr dz)
+{
+	int timescnt = 0, freqcnt = 0, ampcnt = 0, n, m;
+	double atten;
+	int total_frq_cnt = dz->iparam[FLT_CNT] * dz->iparam[FLT_TIMESLOTS];
+	int entrycnt = dz->iparam[FLT_ENTRYCNT];
+	int wordcnt  = dz->iparam[FLT_WORDCNT];
+	int j;
+	int srate = dz->infile->srate;
+	if(dz->parray[FLT_INFRQ]==NULL) {
+		sprintf(errstr,"FLT_INFRQ array not established: put_tvarying_filter_data_in_arrays()\n");
+		return(PROGRAM_ERROR);
+	} 
+	if(dz->parray[FLT_INAMP]==NULL) {
+		sprintf(errstr,"FLT_INAMP array not established: put_tvarying_filter_data_in_arrays()\n");
+		return(PROGRAM_ERROR);
+	} 
+	if(dz->lparray[FLT_SAMPTIME]==NULL) {
+		sprintf(errstr,"FLT_SAMPTIME array not established: put_tvarying_filter_data_in_arrays()\n");
+		return(PROGRAM_ERROR);
+	} 
+	for(n=0;n<wordcnt;n++) {
+		m = n%entrycnt;
+		if(m==0) {
+			if(timescnt >= dz->iparam[FLT_TIMESLOTS]) {
+				sprintf(errstr,"Error 0 in filter counting: put_tvarying_filter_data_in_arrays()\n");
+				return(PROGRAM_ERROR);
+			} 
+			dz->lparray[FLT_SAMPTIME][timescnt++] = round(fbrk[n] * dz->infile->srate);
+
+		} else if(ODD(m)) {
+			for(j=1;j<=dz->iparam[FLT_HARMCNT];j++) {
+				if(freqcnt >= total_frq_cnt) {
+					sprintf(errstr,"Error 1 in filter counting: put_tvarying_filter_data_in_arrays()\n");
+					return(PROGRAM_ERROR);
+				} 
+				if((dz->parray[FLT_INFRQ][freqcnt] = fbrk[n] * (double)j) > FLT_MAXFRQ) {
+					sprintf(errstr,"Filter Harmonic %d of %.1lfHz = %.1lfHz beyond filter limit %.1lf.\n",
+					j,fbrk[n],dz->parray[FLT_INFRQ][freqcnt],FLT_MAXFRQ);
+					return(DATA_ERROR);
+				}
+				freqcnt++;
+			}
+		} else {
+			atten = 1.0;
+			for(j=1;j<=dz->iparam[FLT_HARMCNT];j++) {
+				if(ampcnt >= total_frq_cnt) {
+					sprintf(errstr,"Error 2 in filter counting: put_tvarying_filter_data_in_arrays()\n");
+					return(PROGRAM_ERROR);
+				} 
+				dz->parray[FLT_INAMP][ampcnt] = fbrk[n] * atten;
+				ampcnt++;
+				atten *= dz->param[FLT_ROLLOFF];
+			}
+		}
+	}
+	if(freqcnt != total_frq_cnt || ampcnt != freqcnt || timescnt != dz->iparam[FLT_TIMESLOTS]) {
+		sprintf(errstr,"Filter data accounting problem: read_time_varying_filter_data()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/**************************** INITALISE_FLTBANKV_INTERNAL_PARAMS **********************/
+
+int initialise_fltbankv_internal_params(dataptr dz)
+{
+	int exit_status;
+	int n;
+	if((exit_status = allocate_filter_frq_amp_arrays(dz->iparam[FLT_CNT],dz))<0)
+		return(exit_status);
+	for(n = 0;n<dz->iparam[FLT_CNT];n++) {
+		dz->parray[FLT_FRQ][n]      = dz->parray[FLT_INFRQ][n];
+		dz->parray[FLT_AMP][n]      = dz->parray[FLT_INAMP][n];
+		dz->parray[FLT_LASTFVAL][n] = dz->parray[FLT_FRQ][n];
+		dz->parray[FLT_LASTAVAL][n] = dz->parray[FLT_AMP][n];
+	}
+	dz->iparam[FLT_FRQ_INDEX] = dz->iparam[FLT_CNT];
+	dz->iparam[FLT_TIMES_CNT] = 1;
+	return(FINISHED);
+}
+
+/*************************************** ERROR_NAME **************************************/
+
+int error_name(int paramno,char *paramname,dataptr dz)
+{	
+	switch(dz->process) {
+	case(FLTSWEEP):
+		switch(paramno) {
+		case(FLT_LOFRQ):	strcpy(paramname,"lofrq");		break;
+		case(FLT_HIFRQ):	strcpy(paramname,"hifrq");		break;
+		case(FLT_SWPFRQ):	strcpy(paramname,"sweepfrq");	break;
+		case(FLT_Q):		strcpy(paramname,"Q");			break;
+		default:
+			sprintf(errstr,"Invalid case in error_name()\n");
+			return(PROGRAM_ERROR);
+		}
+		break;
+	case(FLTBANKN):
+	case(FLTBANKU):
+	case(FLTBANKV):
+	case(FLTBANKV2):
+		switch(paramno) {
+		case(FLT_Q):		strcpy(paramname,"Q");			break;
+		default:
+			sprintf(errstr,"Invalid case in error_name()\n");
+			return(PROGRAM_ERROR);
+		}
+		break;
+	case(FLTITER):
+	case(ALLPASS):
+		switch(paramno) {
+		case(FLT_DELAY):	strcpy(paramname,"delay");		break;
+		default:
+			sprintf(errstr,"Invalid case in error_name()\n");
+			return(PROGRAM_ERROR);
+		}
+		break;
+	case(FSTATVAR):
+		switch(paramno) {
+		case(FLT_Q):		strcpy(paramname,"Q");			break;
+		case(FLT_ONEFRQ):	strcpy(paramname,"frq");		break;
+		default:
+			sprintf(errstr,"Invalid case in error_name()\n");
+			return(PROGRAM_ERROR);
+		}
+		break;
+	default:
+		sprintf(errstr,"Invalid case in error_name()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/*************************** SETUP_STEREO_VARIABLES ************************/
+
+int setup_stereo_variables(int a,int b,int c,int d,int chans,dataptr dz)
+{
+	int n;
+	if((dz->parray[a] = (double *)calloc(chans * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[b] = (double *)calloc(chans * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[c] = (double *)calloc(chans * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[d] = (double *)calloc(chans * sizeof(double),sizeof(char)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for stereo coefficients.\n");
+		return(MEMORY_ERROR);
+	}
+	for(n=0;n<chans;n++) {
+		dz->parray[a][n] = 0.0;
+		dz->parray[b][n] = 0.0;
+		dz->parray[c][n] = 0.0;
+		dz->parray[d][n] = 0.0;
+	}
+	return(FINISHED);
+}
+
+/******************************* SETUP_EQFILTER_COEFFS ******************************/
+
+int setup_eqfilter_coeffs(dataptr dz)
+{
+	switch(dz->mode) {
+	case(FLT_LOSHELF):
+	case(FLT_HISHELF):
+		shelve(dz->param[FLT_ONEFRQ],dz->param[FLT_BOOST],
+		&(dz->param[FLT_A0]),&(dz->param[FLT_A1]),&(dz->param[FLT_A2]),
+		&(dz->param[FLT_B1]),&(dz->param[FLT_B2]),dz->mode);
+		break;
+	case(FLT_PEAKING):
+		presence(dz->param[FLT_ONEFRQ],dz->param[FLT_BOOST],dz->param[FLT_BW],
+		&(dz->param[FLT_A0]),&(dz->param[FLT_A1]),&(dz->param[FLT_A2]),
+		&(dz->param[FLT_B1]),&(dz->param[FLT_B2]));
+		break;
+	default:
+		sprintf(errstr,"Unknown mode: setup_eqfilter_coeffs()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/* ANDY MOORER routines, rationalised slightly */
+
+/* Design programs for 2nd-order presence and shelving filters */
+
+#define PII 	  	(3.141592653589793238462643)
+#define ROOT2OF2 	(0.7071067811965475244)		/* = sqrt(2)/2 */
+#define SPN 1.65436e-24							/* Smallest possible number on DEC VAX-780: but it will work here */
+
+/* ----------------------------------------------------------------------------
+  PRESENCE - Design straightforward 2nd-order presence filter.
+Must be given (normalised) centre frequency, bandwidth and boost/cut in dB.
+
+Returns filter of form:
+
+	         -1      -2
+	A0 + A1 Z  + A2 Z					   
+T(z) = ---------------------
+	         -1      -2
+	1 +  B1 Z  + B2 Z
+--------------------------------------------------------------------------- */
+
+void presence(double cf,double boost,double bw,double *a0,double *a1,double *a2,double *b1,double *b2)
+{
+	double a, A, F, xfmbw, C, tmp, alphan, alphad, b0, recipb0, asq, F2, a2plus1, ma2plus1;
+
+ 	establish_a_asq_A_F_F2_tmp(cf,boost,&a,&asq,&A,&F,&F2,&tmp);
+
+	xfmbw = bw2angle(a, bw);
+	C = 1.0 / tan(2 * PII * xfmbw);	/* Co-tangent of angle */
+
+	if(fabs(tmp) <= SPN)
+		alphad = C;
+	else { 
+		alphad = (C * C * (F2 - 1))/tmp;
+		alphad = sqrt(alphad);
+	
+	}
+	alphan = A * alphad;
+	
+	a2plus1  = 1 + asq;
+	ma2plus1 = 1 - asq;
+	*a0 = a2plus1 + alphan * ma2plus1;
+	*a1 = 4 * a;
+	*a2 = a2plus1 - alphan * ma2plus1;
+
+	b0  = a2plus1 + alphad * ma2plus1;
+	*b2 = a2plus1 - alphad * ma2plus1;
+
+	recipb0 = 1.0/b0;
+	*a0 *= recipb0;
+	*a1 *= recipb0;
+	*a2 *= recipb0;
+	*b1 = *a1;		 /* is this correct ?? */
+	*b2 *= recipb0;
+}
+
+/* -------------------------------------------------------------------------
+SHELVE - Design straightforward 2nd-order shelving filter.
+Must be given (normalised) centre frequency, bandwidth and boost/cut in dB.
+This is a LOW shelving filter, in  that the response at z = -1 will be 1.0.
+
+Returns filter of form:
+
+	         -1      -2
+	A0 + A1 Z  + A2 Z
+T(z) = ---------------------			   ANDY MOORER
+	         -1      -2
+	1 +  B1 Z  + B2 Z
+--------------------------------------------------------------------------- */
+
+void shelve(double cf,double boost,double *a0,double *a1,double *a2,double *b1,double *b2,int mode)
+{
+	double a, A, F, tmp, b0, asq, F2, gamman, gammad, ta0, ta1, ta2, tb0, tb1, tb2;
+
+ 	establish_a_asq_A_F_F2_tmp(cf,boost,&a,&asq,&A,&F,&F2,&tmp);
+
+	if(fabs(tmp) <= SPN) 
+		gammad = 1.0;
+/* NB: CHANGED FROM THE ORIGINAL *
+	else
+		gammad = pow((F2 - 1.0)/tmp,0.25);
+AS THIS GAVE A -VE RESULT: SOME KIND OF AIRTHMETIC ERROR INSIDE pow */
+	else {
+		gammad = (F2 - 1.0)/tmp;
+		gammad = pow(gammad,0.25);		   	/* Fourth root */
+	}
+	gamman = sqrt(A) * gammad;
+
+   /* Once for the numerator */
+
+	set_the_tvars(gamman,&ta0,&ta1,&ta2);
+
+	if(mode==FLT_HISHELF)
+		ta1 = -ta1;
+	
+   /* And again for the denominator */
+
+	set_the_tvars(gammad,&tb0,&tb1,&tb2);
+
+	if(mode==FLT_HISHELF)
+		tb1 = -tb1;
+
+   /* Now bilinear transform to proper centre frequency */
+
+	bilinear_transform(a,ta0,ta1,ta2,asq,a0,a1,a2);
+	bilinear_transform(a,tb0,tb1,tb2,asq,&b0,b1,b2);
+	
+   /* Normalise b0 to 1.0 for realisability */
+
+	normalise_b0_to_one(b0,a0,a1,a2,b1,b2);
+}
+
+/* -------------------------------------------------------------------------
+   BW2ANGLE - Given bilinear transform parameter and
+desired bandwidth (as normalised frequency), computes bandedge, e, of filter
+as if it were centred at the frequency .25 (or pi/2, or srate/4). The 
+bandwidth would then 2*(.25-e). e is guaranteed to be between 0 and .25.
+
+To state it differently, given a filter centered on .25 with low bandedge
+e and high bandedge .5-e, the bilinear transform by a 
+will produce a new filter with bandwidth (i.e., difference between the
+high bandedge frequency and low bandedge frequency) of bw	 ANDY MOORER
+------------------------------------------------------------------------- */
+
+double bw2angle(double a,double bw)
+{	
+	double T, d, sn, cs, mag, delta, theta, tmp, a2, a4, asnd;
+
+	T     = tan(2*PII*bw);
+	a2    = a * a;
+	a4    = a2 * a2;
+	d     = 2 * a2 * T;
+	sn    = (1 + a4) * T;
+	cs    = (1 - a4);
+	mag   = sqrt((sn * sn) + (cs * cs));
+	d    /= mag;
+	delta = atan2(sn, cs);
+	asnd  = asin(d);
+	theta = 0.5 * (PII - asnd - delta);	/* Bandedge for prototype */
+	tmp   = 0.5 * (asnd - delta);		/* Take principal branch */
+	if(tmp > 0 && tmp < theta) 
+		theta = tmp;
+	return(theta /(2 * PII));			/* Return normalised frequency */
+}
+
+/********************************* ESTABLISH_A_ASQ_A_F *********************************/
+
+void establish_a_asq_A_F_F2_tmp(double cf,double boost,double *a,double *asq,double *A,double *F,double *F2,double *tmp)
+{
+	double sqrt2 = sqrt(2.0);
+	double cf_less_quarter = cf - 0.25;
+	double b_over20 = boost/20.0;
+	*a   = tan(PII * cf_less_quarter);			/* Warp factor */ 
+	*asq = (*a) * (*a);
+	*A   = pow(10.0, b_over20);					/* Cvt dB to factor */
+	if(boost < 6.0 && boost > -6.0)
+		*F = sqrt(*A);
+	else if(*A > 1.0) 
+		*F = *A/sqrt2;
+	else 
+		*F = (*A) * sqrt2;
+	  /* If |boost/cut| < 6dB, then doesn't make sense to use 3dB point.
+	     Use of root makes bandedge at half the boost/cut amount 
+	  */
+	*F2 = (*F) * (*F);
+	*tmp = ((*A) * (*A)) - (*F2);
+}
+
+/********************************* SET_THE_TVARS *********************************/
+
+void set_the_tvars(double gamma,double *t0,double *t1,double *t2)
+{
+	double gamma2, gam2p1, siggam2;
+	gamma2  = gamma * gamma;
+	gam2p1  = 1.0 + gamma2;
+	siggam2 = 2.0 * ROOT2OF2 * gamma;
+	
+	*t0 = gam2p1 + siggam2;
+	*t1 = -2.0 * (1.0 - gamma2);
+	*t2 = gam2p1 - siggam2;
+}
+
+/********************************* BILINEAR_TRANSFORM *********************************/
+
+void bilinear_transform(double a,double t0,double t1,double t2,double asq,double *x0,double *x1,double *x2)
+{
+	double aa1;
+	aa1 = a * t1;
+	*x0  = t0 + aa1 + (asq * t2);
+	*x1 = (2 * a * (t0 + t2)) + ((1 + asq) * t1);
+	*x2 = (asq * t0) + aa1 + t2;
+}
+
+/********************************* NORMALISE_B0_TO_ONE *********************************/
+
+void normalise_b0_to_one(double b0,double *a0,double *a1,double *a2,double *b1,double *b2)
+{
+	double recipb0 = 1.0/b0;
+	*a0 *= recipb0;
+	*a1 *= recipb0;
+	*a2 *= recipb0;
+	*b1 *= recipb0;
+	*b2 *= recipb0;
+}
+							   
+/******************* CONVERT_DELAY_TIMES_TO_SAMPLES_AND_GET_MAXDELAY *******************/
+
+int convert_delay_times_to_samples_and_get_maxdelay(dataptr dz)
+{
+	double *p, *end;
+	double maxdelay = 0.0;
+	if(dz->brksize[FLT_DELAY]) {
+		p = dz->brk[FLT_DELAY] + 1;
+		end = dz->brk[FLT_DELAY] + (dz->brksize[FLT_DELAY] * 2);
+		while(p < end) {
+			if((*p = (double)round(*p * MS_TO_SECS * (double)dz->infile->srate))<1)
+				*p = 1.0;
+			maxdelay = max(*p,maxdelay);
+			p+= 2;
+		}
+		return(round(maxdelay));
+	}
+	if((dz->param[FLT_DELAY] = (double)round(dz->param[FLT_DELAY] * MS_TO_SECS * (double)dz->infile->srate))<1)
+		dz->param[FLT_DELAY] = 1.0;
+	return(round(dz->param[FLT_DELAY]));
+}
+
+/************************** COUNT_FILTERS ****************************/
+
+int count_filters(dataptr dz)
+{   
+	int f_cnt = 0;
+	double thisfrq;
+	switch(dz->mode) {
+	case(FLT_EQUALSPAN): 
+		f_cnt = dz->iparam[FLT_INCOUNT];
+		break;
+	case(FLT_EQUALINT):
+		thisfrq = dz->param[FLT_LOFRQ]; 
+		while(thisfrq < dz->param[FLT_HIFRQ]) {
+			f_cnt++;
+			thisfrq *= dz->param[FLT_INTSIZE];
+		}
+		break;
+	case(FLT_HARMONIC):	/* offset = 0.0 */
+	case(FLT_LINOFFSET):
+		thisfrq = dz->param[FLT_LOFRQ];
+		while((thisfrq+dz->param[FLT_OFFSET]) < dz->param[FLT_HIFRQ]) {
+			f_cnt++;
+			thisfrq = dz->param[FLT_LOFRQ] * (double)(f_cnt+1);
+		}
+		break;
+	case(FLT_ALTERNATE):
+		thisfrq = dz->param[FLT_LOFRQ];
+		while(thisfrq < dz->param[FLT_HIFRQ]) {
+			f_cnt++;
+			thisfrq = dz->param[FLT_LOFRQ] * (double)((f_cnt*2)+1);
+		}
+		break;
+	case(FLT_SUBHARM):
+		thisfrq = dz->param[FLT_HIFRQ];
+		while(thisfrq > dz->param[FLT_LOFRQ]) {
+			f_cnt++;	
+			thisfrq = dz->param[FLT_HIFRQ]/(double)(f_cnt+1);
+		}
+		break;
+	}
+	if(f_cnt > FLT_MAX_FILTERS || f_cnt < 0) {
+		sprintf(errstr,"Too many filters [%d]: max %d\n",f_cnt,FLT_MAX_FILTERS);
+		return(DATA_ERROR);
+	}
+	if(f_cnt < 1) {
+		sprintf(errstr,"Too few filters in range specified.\n");
+		return(DATA_ERROR);
+	}
+	dz->iparam[FLT_CNT] = (int)f_cnt;
+	return(f_cnt);
+}
+
+/**************************** TEST_PITCH_AND_SPECTRUM_VARYING_FILTERDATA *******************************/
+
+int test_pitch_and_spectrum_varying_filterdata(double *fbrk,double *hbrk,dataptr dz)
+{
+	int n, m, k, timepoint, htimepoint, nextrow;
+	int entrycnt = dz->iparam[FLT_ENTRYCNT];
+	int wordcnt  = dz->iparam[FLT_WORDCNT];
+	int hentrycnt = dz->iparam[HRM_ENTRYCNT];
+	int hwordcnt  = dz->iparam[HRM_WORDCNT];
+	int srate = dz->infile->srate;
+	double thistime, lotime, hitime, timefrac, valdiff;
+	double timestep = (double)dz->iparam[FLT_BLOKSIZE]/(double)dz->infile->srate;
+	double lasttime = fbrk[wordcnt - entrycnt];
+	lasttime = min(lasttime,hbrk[hwordcnt - hentrycnt]);
+
+	dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE] * dz->infile->channels;
+
+	timepoint = 0;
+	htimepoint = 0;
+	fprintf(stdout,"INFO: TESTING PITCH AND HARMONICS DATA.\n");
+	fflush(stdout);
+	if((dz->parray[HARM_FRQ_CALC] = (double *)malloc(dz->iparam[FLT_HARMCNT] * sizeof(double)))==NULL) {
+		sprintf(errstr,"OUT OF MEMORY TO STORE HARMONIC SHIFT DATA\n");
+		return(MEMORY_ERROR);
+	}
+	if((dz->parray[HARM_AMP_CALC] = (double *)malloc(dz->iparam[FLT_HARMCNT] * sizeof(double)))==NULL) {
+		sprintf(errstr,"OUT OF MEMORY TO STORE HARMONICS AMPLITUDE ADJUST DATA\n");
+		return(MEMORY_ERROR);
+	}
+	memset((char *)dz->parray[FLT_INFRQ],0,dz->iparam[FLT_CNT] * sizeof(double));
+
+	
+	for(thistime = 0.0; thistime < lasttime;thistime += timestep) {
+		timepoint = 0;
+		while(thistime >= fbrk[timepoint]) {	/* search times in frq array */
+			if((timepoint += entrycnt)  >= wordcnt)
+				break;
+		}
+		timepoint -= entrycnt;
+		lotime = fbrk[timepoint];
+		nextrow = timepoint + entrycnt;
+		for(n = timepoint+1,k = 0; n < nextrow;n+=2,k += dz->iparam[FLT_HARMCNT])
+			dz->parray[FLT_INFRQ][k] = fbrk[n];		/* Get frqs of fundamentals into array, leaving space for harmonics */
+		if(nextrow != wordcnt) {					/* if not at end of table, do interpolation */
+			nextrow += entrycnt;
+			timepoint += entrycnt;
+			hitime = fbrk[timepoint];
+			timefrac = (thistime - lotime)/(hitime - lotime);
+			k = 0;
+			for(n = timepoint+1,k=0; n < nextrow;n+=2,k += dz->iparam[FLT_HARMCNT]) {
+				valdiff = fbrk[n] - dz->parray[FLT_INFRQ][k];
+				valdiff *= timefrac;
+				dz->parray[FLT_INFRQ][k] = dz->parray[FLT_INFRQ][k] + valdiff;
+			}
+		}
+		htimepoint = 0;
+		while(thistime >= hbrk[htimepoint]) {	/* search times in frq array */
+			if((htimepoint += hentrycnt) >= hwordcnt)
+				break;
+		}
+		htimepoint -= hentrycnt;
+		lotime = hbrk[htimepoint];
+		nextrow = htimepoint + hentrycnt;
+		k = 0;
+		for(n = htimepoint+1,k=0; n < nextrow;n+=2,k++)
+			dz->parray[HARM_FRQ_CALC][k] = hbrk[n];
+		if(nextrow != hwordcnt) {					/* if not at end of table, do interpolation */
+			nextrow += hentrycnt;
+			htimepoint += hentrycnt;
+			hitime = hbrk[htimepoint];
+			timefrac = (thistime - lotime)/(hitime - lotime);
+			k = 0;
+			for(n = htimepoint+1,k=0; n < nextrow;n+=2,k++) {
+				/* PARTIAL MULTIPLIER */
+				valdiff = hbrk[n] - dz->parray[HARM_FRQ_CALC][k];
+				valdiff *= timefrac;
+				dz->parray[HARM_FRQ_CALC][k] = dz->parray[HARM_FRQ_CALC][k] + valdiff;
+				/* PARTIAL AMP */
+			}
+		}
+		for(k=0;k<dz->iparam[FLT_CNT];k+=dz->iparam[FLT_HARMCNT]) {
+			for(m=0; m < dz->iparam[FLT_HARMCNT];m++) {	/* calc vals for partials from basefrq vals */
+				if((dz->parray[FLT_INFRQ][k+m] = dz->parray[FLT_INFRQ][k] * dz->parray[HARM_FRQ_CALC][m]) > FLT_MAXFRQ) {
+					sprintf(errstr,"PARTIAL NO %lf TOO HIGH (Frq %lf Root %lf) AT TIME %lf\n",
+					dz->parray[HARM_FRQ_CALC][m],dz->parray[FLT_INFRQ][k+m],dz->parray[FLT_INFRQ][k]/dz->parray[HARM_FRQ_CALC][0],thistime);
+					return(DATA_ERROR);
+				}
+			}
+		}
+	}
+	fprintf(stdout,"INFO: FINISHED TESTING PITCH AND HARMONICS DATA.\n");
+	fflush(stdout);
+	return(FINISHED);
+}
+

+ 418 - 0
dev/filter/fltprepro.c

@@ -0,0 +1,418 @@
+/*
+ * 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 <memory.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <processno.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <globcon.h>
+#include <filters.h>
+#include <math.h>
+#include <osbind.h>
+
+static int  setup_lphp_filter(dataptr dz);
+static int  calc_frqs(dataptr dz);
+static void randomise_frqs(dataptr dz);
+static int  allocate_internal_params_lphp(int chans,dataptr dz);
+static void calculate_filter_poles_lphp(double signd,int filter_order,dataptr dz);
+static void initialise_filter_coeffs_lphp(int chans,dataptr dz);
+static int  allocate_filter_internalparam_arrays(int fltcnt,dataptr dz);
+static int  initialise_filter_params(dataptr dz);
+static int  establish_order_of_filter(dataptr dz);
+static int  initialise_fltbankv2(dataptr dz);
+
+/************************** FILTER_PREPROCESS **************************/
+
+int filter_preprocess(dataptr dz)
+{
+	int exit_status;
+	int n;
+	if(dz->process == FLTBANKV2) {
+		if((exit_status = initialise_fltbankv2(dz))<0)
+			return exit_status;
+	}
+	switch(dz->process) {
+	case(EQ):
+	case(FSTATVAR):
+	case(FLTSWEEP):
+	case(ALLPASS):
+		break;
+	case(LPHP):
+		if((exit_status = setup_lphp_filter(dz))<0)
+			return(exit_status);
+		break;
+	case(FLTBANKC):			
+		return calc_frqs(dz);
+	case(FLTBANKN):
+		if((exit_status = calc_frqs(dz))<0)
+			return(exit_status);
+		for(n=0;n<dz->iparam[FLT_CNT];n++)
+			dz->parray[FLT_AMP][n] = 1.0;
+		/* fall thro */
+	case(FLTBANKU):
+	case(FLTBANKV2):
+	case(FLTBANKV):
+	case(FLTITER):
+		if((exit_status = allocate_filter_internalparam_arrays(dz->iparam[FLT_CNT],dz))<0)
+			return(exit_status);
+		if((exit_status = initialise_filter_params(dz))<0)
+			return(exit_status);
+		break;
+	default:
+		sprintf(errstr,"Unknown case in filter_preprocess()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********************************* SETUP_LPHP_FILTER *****************************/
+
+int setup_lphp_filter(dataptr dz)
+{
+	int exit_status;
+	int filter_order;
+	double signd = 1.0;
+	if (dz->param[FLT_PASSFRQ] < dz->param[FLT_STOPFRQ])	/* low pass */
+		signd = -1.0;
+	filter_order = establish_order_of_filter(dz);
+
+	if((exit_status = allocate_internal_params_lphp(dz->infile->channels,dz))<0)
+		return(exit_status);
+	calculate_filter_poles_lphp(signd,filter_order,dz);
+	initialise_filter_coeffs_lphp(dz->infile->channels,dz);
+	return(FINISHED);
+}
+
+/***************************** CALC_FRQS **********************************/
+
+int calc_frqs(dataptr dz)
+{
+	double interval, one_over_total_steps;
+	int n;
+	switch(dz->mode) {
+	case(FLT_EQUALSPAN):
+		one_over_total_steps = 1.0/(double)dz->iparam[FLT_CNT];
+		for(n=0;n<dz->iparam[FLT_CNT];n++) {
+			interval = dz->param[FLT_HIFRQ]/dz->param[FLT_LOFRQ];
+			dz->parray[FLT_FRQ][n] = dz->param[FLT_LOFRQ] * pow(interval,(double)n * one_over_total_steps);
+		}
+		break;
+    case(FLT_EQUALINT):
+		dz->parray[FLT_FRQ][0] = dz->param[FLT_LOFRQ];
+		for(n=1;n<dz->iparam[FLT_CNT];n++)   
+			dz->parray[FLT_FRQ][n] =  dz->parray[FLT_FRQ][n-1] * dz->param[FLT_INTSIZE];
+		break;
+    case(FLT_HARMONIC):	/* offset = 0.0 */
+    case(FLT_LINOFFSET):
+		dz->parray[FLT_FRQ][0] = dz->param[FLT_LOFRQ];
+		for(n=1;n<dz->iparam[FLT_CNT];n++)   
+			dz->parray[FLT_FRQ][n] = (dz->param[FLT_LOFRQ] * (double)(n+1))+dz->param[FLT_OFFSET];
+		break;
+    case(FLT_ALTERNATE):
+		dz->parray[FLT_FRQ][0] = dz->param[FLT_LOFRQ];
+		for(n=1;n<dz->iparam[FLT_CNT];n++)   
+			dz->parray[FLT_FRQ][n] =  dz->param[FLT_LOFRQ] * (double)((n*2)+1);
+		break;
+    case(FLT_SUBHARM):	/* dz->param[FLT_LOFRQ] already reset at top */
+		dz->parray[FLT_FRQ][0] = dz->param[FLT_HIFRQ];
+		for(n=1;n<dz->iparam[FLT_CNT];n++)   
+			dz->parray[FLT_FRQ][n] =  dz->param[FLT_HIFRQ]/(double)(n+1);
+		break;
+	default:
+		sprintf(errstr,"Unknown mode in	calc_frqs()\n");
+		return(PROGRAM_ERROR);
+    }
+	if(!flteq(dz->param[FLT_RANDFACT],0.0))
+		randomise_frqs(dz);
+	return(FINISHED);
+}
+
+/************************ RANDOMISE_FRQS *******************************/
+
+void randomise_frqs(dataptr dz)
+{
+	int n;
+	double thisrand, frqratio, interval;
+	for(n=1;n<dz->iparam[FLT_CNT]-1;n++) {
+		thisrand = drand48();						/*  RANGE 0 - 1      */
+		if(thisrand >= 0.5) {						/* IF IN TOP 1/2     */
+			thisrand -= 0.5;						/* REDUCE BY 1/2     */
+			thisrand *= dz->param[FLT_RANDFACT];	/* SCALE BY randfact */
+			frqratio = dz->parray[FLT_FRQ][n+1]/dz->parray[FLT_FRQ][n];
+			interval = log(frqratio) * thisrand;
+			frqratio = exp(interval);
+			dz->parray[FLT_FRQ][n] *= frqratio;
+						/* SCATTER FRQ IN 1/2 INTERVAL ABOVE CURRENT VAL */
+		} else {
+			thisrand *= dz->param[FLT_RANDFACT];	/* SCALE BY randfact */
+			frqratio = dz->parray[FLT_FRQ][n]/dz->parray[FLT_FRQ][n-1];
+			interval = log(frqratio) * (1.0 - thisrand);
+			frqratio = exp(interval);
+			dz->parray[FLT_FRQ][n] = dz->parray[FLT_FRQ][n-1] * frqratio;
+						/* SCATTER FRQ IN 1/2 INTERVAL BELOW CURRENT VAL */
+		}
+	}
+}
+
+/********************************* ALLOCATE_INTERNAL_PARAMS_LPHP *****************************/
+
+//int allocate_internal_params_lphp(int chans,dataptr dz)
+//{
+//	if((dz->parray[FLT_DEN1] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+//	|| (dz->parray[FLT_DEN2] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+//	|| (dz->parray[FLT_CN]   = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+//	|| (dz->parray[FLT_S1]   = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+//	|| (dz->parray[FLT_E1]   = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+//	|| (dz->parray[FLT_S2]   = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+//	|| (dz->parray[FLT_E2]   = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL) {
+//		sprintf(errstr,"INSUFFICIENT MEMORY for arrays of filter parameters.\n");
+//		return(MEMORY_ERROR);
+//	}
+//	if(chans==2) {
+//		if((dz->parray[FLT_S1S]   = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+//		|| (dz->parray[FLT_E1S]   = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+//		|| (dz->parray[FLT_S2S]   = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
+//		|| (dz->parray[FLT_E2S]   = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL) {
+//			sprintf(errstr,"INSUFFICIENT MEMORY for arrays of filter stereo parameters.\n");
+//			return(MEMORY_ERROR);
+//		}
+//	}
+//	return(FINISHED);
+//}
+//
+
+// TW MULTICHAN 2010
+int allocate_internal_params_lphp(int chans,dataptr dz)
+{
+	int i;
+	if((dz->parray[FLT_DEN1] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_DEN2] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_CN]   = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_S1_BASE]   = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_E1_BASE]   = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_S2_BASE]   = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_E2_BASE]   = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for arrays of filter parameters.\n");
+		return(MEMORY_ERROR);
+	}
+	for(i = 1; i < chans;i++) {
+		int index = i*FLT_LPHP_ARRAYS_PER_FILTER;
+		if((dz->parray[FLT_S1_BASE + index]   = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+		|| (dz->parray[FLT_E1_BASE + index]   = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+		|| (dz->parray[FLT_S2_BASE + index]   = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
+		|| (dz->parray[FLT_E2_BASE + index]   = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for arrays of %d-channel filter parameters.\n",chans);
+			return(MEMORY_ERROR);
+		}
+	}
+	return(FINISHED);
+}
+
+/********************************* CALCULATE_FILTER_POLES_LPHP *****************************/
+
+void calculate_filter_poles_lphp(double  signd,int filter_order,dataptr dz)
+{
+	double ss, xx, aa, tppwr, x1, x2, cc;
+	double pii = 4.0 * atan(1.0);
+	double tp = tan(dz->param[FLT_PASSFRQ]);
+	int    k;
+	ss = pii / (double)(2 * filter_order);
+	for (k = 0; k < dz->iparam[FLT_CNT]; k++ ) {
+//TW : RWD CORRECTION TALLIES WITH MY UPDATES
+		xx = (double) ((2.0 * (k+1)) - 1.0);
+		aa = -sin(xx * ss);
+		tppwr = pow(tp,2.0);
+		cc = 1.0 - (2.0 * aa * tp) + tppwr;
+		x1 = 2.0 * (tppwr - 1.0)/cc ;
+		x2 = (1.0 + (2.0 * aa * tp) + tppwr)/cc ;
+		dz->parray[FLT_DEN1][k] = signd * x1;
+		dz->parray[FLT_DEN2][k] = -x2 ;
+		dz->parray[FLT_CN][k]   = pow(tp,2.0)/cc ;
+	}
+}
+
+/********************************* INITIALISE_FILTER_COEFFS_LPHP *****************************/
+
+//void initialise_filter_coeffs_lphp(int chans,dataptr dz)
+//{
+//	int k;
+//	for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+//		dz->parray[FLT_S1][k] = 0.0;
+//		dz->parray[FLT_S2][k] = 0.0;
+//		dz->parray[FLT_E1][k] = 0.0;
+//		dz->parray[FLT_E2][k] = 0.0;
+//	}
+//	if(chans==STEREO)	{
+//		for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+//			dz->parray[FLT_S1S][k] = 0.0;
+//			dz->parray[FLT_S2S][k] = 0.0;
+//			dz->parray[FLT_E1S][k] = 0.0;
+//			dz->parray[FLT_E2S][k] = 0.0;
+//		}
+//	}
+//}
+//
+
+// TW MULTICHAN 2010
+void initialise_filter_coeffs_lphp(int chans,dataptr dz)
+{
+	int k;
+	int i,index;
+	for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+		dz->parray[FLT_S1_BASE][k] = 0.0;
+		dz->parray[FLT_S2_BASE][k] = 0.0;
+		dz->parray[FLT_E1_BASE][k] = 0.0;
+		dz->parray[FLT_E2_BASE][k] = 0.0;
+	}
+	for(i=1;i < chans; i++){
+		index = i *	FLT_LPHP_ARRAYS_PER_FILTER;
+		for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
+			dz->parray[FLT_S1_BASE + i][k] = 0.0;
+			dz->parray[FLT_S2_BASE + i][k] = 0.0;
+			dz->parray[FLT_E1_BASE + i][k] = 0.0;
+			dz->parray[FLT_E2_BASE + i][k] = 0.0;
+		}
+	}
+}
+
+/**************************** ALLOCATE_FILTER_INTERNALPARAM_ARRAYS *******************************/
+
+int allocate_filter_internalparam_arrays(int fltcnt,dataptr dz)
+{
+	int chans = dz->infile->channels;
+	if((dz->parray[FLT_AMPL] = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_A]    = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_B]    = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_WW]   = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_COSW] = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_SINW] = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_Y]    = (double *)calloc(fltcnt * chans * sizeof(double),sizeof(char)))==NULL
+	|| (dz->parray[FLT_Z]    = (double *)calloc(fltcnt * chans * sizeof(double),sizeof(char)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for arrays of filter parameters.\n");
+		return(MEMORY_ERROR);
+	}
+    if(dz->vflag[FLT_DBLFILT]) {
+		if((dz->parray[FLT_D]    = (double *)calloc(fltcnt * chans * sizeof(double),sizeof(char)))==NULL
+		|| (dz->parray[FLT_E]    = (double *)calloc(fltcnt * chans * sizeof(double),sizeof(char)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for double filtering parameters.\n");
+			return(MEMORY_ERROR);
+		}
+	}
+	return(FINISHED);
+}
+
+/************************ INITIALISE_FILTER_PARAMS ***************************/
+
+int initialise_filter_params(dataptr dz)
+{
+	int n, chno, k;
+	int chans = dz->infile->channels;
+	for(n=0;n<dz->iparam[FLT_CNT];n++) {
+		get_coeffs1(n,dz);
+		get_coeffs2(n,dz);
+		for(chno=0;chno<chans;chno++) {
+			k = (n*chans)+chno;
+			if(dz->vflag[FLT_DBLFILT]) {
+				dz->parray[FLT_D][k] = 0.0;
+				dz->parray[FLT_E][k] = 0.0;
+			}
+			dz->parray[FLT_Y][k]  = 0.0;
+			dz->parray[FLT_Z][k]  = 0.0;
+		}	
+	}
+	return(FINISHED);
+}
+
+/********************************* ESTABLISH_ORDER_OF_FILTER *****************************/
+
+int establish_order_of_filter(dataptr dz)
+{
+	int filter_order;
+	double tc, tp, tt, pii, xx, yy;
+	double sr = (double)dz->infile->srate;
+	if (dz->param[FLT_PASSFRQ] < dz->param[FLT_STOPFRQ])		/* low pass */
+		dz->param[FLT_MUL] = 2.0;
+	else {
+		dz->param[FLT_MUL] = -2.0;
+		dz->param[FLT_PASSFRQ] = dz->nyquist - dz->param[FLT_PASSFRQ];
+		dz->param[FLT_STOPFRQ] = dz->nyquist - dz->param[FLT_STOPFRQ];
+	}
+	pii = 4.0 * atan(1.0);
+	dz->param[FLT_PASSFRQ] = pii * dz->param[FLT_PASSFRQ]/sr;
+	tp = tan(dz->param[FLT_PASSFRQ]);
+	dz->param[FLT_STOPFRQ] = pii * dz->param[FLT_STOPFRQ]/sr;
+	tc = tan(dz->param[FLT_STOPFRQ]);
+	tt = tc / tp ;
+	tt = (tt * tt);
+	dz->param[FLT_GAIN] = fabs(dz->param[FLT_GAIN]);
+	dz->param[FLT_GAIN] = dz->param[FLT_GAIN] * log(10.0)/10.0 ;
+	dz->param[FLT_GAIN] = exp(dz->param[FLT_GAIN]) - 1.0 ;
+	xx = log(dz->param[FLT_GAIN])/log(tt) ;
+	yy = floor(xx);
+	if ((xx - yy) == 0.0 )
+		yy = yy - 1.0 ;
+	filter_order = ((int)yy) + 1;
+	if (filter_order <= 1) 
+		filter_order = 2;
+	dz->iparam[FLT_CNT] = filter_order/2 ;
+	filter_order = 2 * dz->iparam[FLT_CNT] ;
+	fprintf(stdout,"INFO: Order of filter is %d\n", filter_order);
+	fflush(stdout);
+	dz->iparam[FLT_CNT] = min(dz->iparam[FLT_CNT],FLT_LBF);
+	filter_order = 2 * dz->iparam[FLT_CNT];
+	return(filter_order);
+}
+
+/**************************** INITIALISE_FLTBANKV2 *******************************/
+
+int initialise_fltbankv2(dataptr dz)
+{
+	int n, k, z;
+
+	memset((char *)dz->parray[FLT_INFRQ],0,dz->iparam[FLT_CNT] * sizeof(double));
+	memset((char *)dz->parray[FLT_INAMP],0,dz->iparam[FLT_CNT] * sizeof(double));
+	for(n = 1,k = 0; n < dz->iparam[FLT_ENTRYCNT];n+=2,k += dz->iparam[FLT_HARMCNT]) {
+		dz->parray[FLT_INFRQ][k] = dz->parray[FLT_FBRK][n];		/* Get frqs of fundamentals into array, leaving space for harmonics */
+		dz->parray[FLT_INAMP][k] = dz->parray[FLT_FBRK][n+1];	/* Get amps of fundamentals into array, leaving space for harmonics */
+	}
+	for(n = 1,k=0; n < dz->iparam[HRM_ENTRYCNT];n+=2,k++) {
+		dz->parray[HARM_FRQ_CALC][k] = dz->parray[FLT_HBRK][n];
+		dz->parray[HARM_AMP_CALC][k] = dz->parray[FLT_HBRK][n+1];
+	}
+	for(n=0;n<dz->iparam[FLT_CNT];n+=dz->iparam[FLT_HARMCNT]) {
+		z = 0;
+		for(k=0; k < dz->iparam[FLT_HARMCNT];k++) {	/* calc vals for partials from basefrq vals */
+			dz->parray[FLT_INFRQ][n+k] = dz->parray[FLT_INFRQ][n] * dz->parray[HARM_FRQ_CALC][k];
+			dz->parray[FLT_INAMP][n+k] = dz->parray[FLT_INAMP][n] * dz->parray[HARM_AMP_CALC][k];
+		}
+	}
+	return(FINISHED);
+}
+

+ 267 - 0
dev/filter/main.c

@@ -0,0 +1,267 @@
+/*
+ * 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 <filters.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>
+#include <arrays.h>
+
+/* RWD Apr 2011 rebuilt to fix bug in filter bankfrqs (memory overrun) */
+/* subject to revision from  TW etc */
+
+
+char errstr[2400];
+
+/*extern*/ int	sloom = 0;
+/* TW May 2001 */
+/*extern*/ int sloombatch = 0;	/*TW may 2001 */
+/*extern*/ int anal_infiles = 0;
+/*extern*/ int is_converted_to_stereo = -1;
+const char* cdp_version = "7.1.0";
+
+// TW MULTICHAN 2010
+static int setup_internal_arrays_and_array_pointers_for_lphp(dataptr dz);
+
+/**************************************** MAIN *********************************************/
+
+int main(int argc,char *argv[])
+{
+	int exit_status;
+/*	FILE *fp   = NULL;*/
+	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 May 2001 */	
+	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);
+		}
+//TW UPDATE
+		cmdlinecnt--;
+		cmdline++;
+	}
+// TW MULTICHAN 2010
+	if(dz->process == LPHP) {
+		if((exit_status = setup_internal_arrays_and_array_pointers_for_lphp(dz))<0) {	
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);	
+			return(FAILED);
+		}
+	}
+	
+/*********************************************************************************************************************
+		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);
+}
+
+// TW MULTICHAN 2010
+/***************************** SETUP_INTERNAL_ARRAYS_AND_ARRAY_POINTERS_FOR_LPHP **************************/
+
+int setup_internal_arrays_and_array_pointers_for_lphp(dataptr dz)
+{
+	int n;		 
+	dz->array_cnt = 3 + (FLT_LPHP_ARRAYS_PER_FILTER * dz->infile->channels); 
+	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;
+	return(FINISHED);
+}
+