richarddobson 3 lat temu
rodzic
commit
27ae0b68cd

+ 22 - 0
dev/distort/CMakeLists.txt

@@ -0,0 +1,22 @@
+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(distort ap_distort.c disprepro.c distdel.c distflt.c distintlv.c distort.c distorta.c 
+	distorte.c distortf.c distorth.c distortion.c distortm.c distorto.c distortp.c 
+	distortr.c distorts.c distresize.c distrpl.c distrpt.c disttel.c main.c pulse.c)
+
+target_link_libraries(distort cdp2k sfsys ${EXTRA_LIBRARIES})
+
+my_install(distort)
+

+ 1398 - 0
dev/distort/ap_distort.c

@@ -0,0 +1,1398 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ctype.h>
+#include <structures.h>
+#include <cdpmain.h>
+#include <tkglobals.h>
+#include <pnames.h>
+#include <distort.h>
+#include <processno.h>
+#include <modeno.h>
+#include <globcon.h>
+#include <logic.h>
+#include <filetype.h>
+//TW REMOVED (duplicated)
+//#include <stdlib.h>
+#include <mixxcon.h>
+//TW UPDATE
+#include <distort1.h>
+#include <flags.h>
+#include <speccon.h>
+#include <arrays.h>
+#include <special.h>
+#include <formants.h>
+#include <sfsys.h>
+#include <osbind.h>
+#include <string.h>
+#include <arrays.h>
+
+
+/********************************************************************************************/
+/********************************** FORMERLY IN buffers.c ***********************************/
+/********************************************************************************************/
+
+static int  create_sndbufs_plus_cyclebuf(int cycbuflen_param,dataptr dz);
+static int  create_avgbufs(dataptr dz);
+//TW UPDATE
+static int	create_pulse_buffers(dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN pconsistency.c ******************************/
+/********************************************************************************************/
+
+static int  check_omit_consistency(dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN specialin.c *********************************/
+/********************************************************************************************/
+
+static int  get_envfile_data(char *filename,dataptr dz);
+//TW UPDATE
+static int  get_pulsefile_data(char *filename,dataptr dz);
+static int  get_harmonic_data(char *filename,dataptr dz);
+
+/***************************** ESTABLISH_BUFPTRS_AND_EXTRA_BUFFERS **************************/
+
+int establish_bufptrs_and_extra_buffers(dataptr dz)
+{
+	int exit_status;
+//TW AGREED DELETION is_spec VARIABLE
+	dz->extra_bufcnt = -1;	/* ENSURE EVERY CASE HAS A PAIR OF ENTRIES !! */
+	dz->bptrcnt = 0;
+	dz->bufcnt  = 0;
+	switch(dz->process) {
+	case(DISTORT):	
+		switch(dz->mode) {
+	    case(DISTORT_EXAGG):	dz->extra_bufcnt = 0;	dz->bufcnt = 3;		break;
+		default:				dz->extra_bufcnt = 0;	dz->bufcnt = 2;		break;
+		}
+		break;
+	case(DISTORT_ENV):			dz->extra_bufcnt = 0;	dz->bufcnt = 2;		break;
+	case(DISTORT_AVG):			dz->extra_bufcnt = 0;	dz->bufcnt = 4;		break;
+	case(DISTORT_OMT):			dz->extra_bufcnt = 0;	dz->bufcnt = 1;		break;
+	case(DISTORT_MLT):			dz->extra_bufcnt = 0;	dz->bufcnt = 6;		break;
+	case(DISTORT_DIV):			dz->extra_bufcnt = 0;	dz->bufcnt = 4;		break;
+	case(DISTORT_HRM):			dz->extra_bufcnt = 0;	dz->bufcnt = 3; 	break;
+	case(DISTORT_FRC):			dz->extra_bufcnt = 0;	dz->bufcnt = 3;		break;
+	case(DISTORT_REV):			dz->extra_bufcnt = 0;	dz->bufcnt = 2;		break;
+	case(DISTORT_SHUF):			dz->extra_bufcnt = 0;	dz->bufcnt = 3;		break;
+	case(DISTORT_RPTFL):
+	case(DISTORT_RPT2):
+	case(DISTORT_RPT):			dz->extra_bufcnt = 0;	dz->bufcnt = 4;		break;
+	case(DISTORT_INTP):			dz->extra_bufcnt = 0;	dz->bufcnt = 5;		break;
+	case(DISTORT_DEL):			dz->extra_bufcnt = 0;	dz->bufcnt = 3;		break;
+	case(DISTORT_RPL):			dz->extra_bufcnt = 0;	dz->bufcnt = 3;		break;
+	case(DISTORT_TEL):			dz->extra_bufcnt = 0;	dz->bufcnt = 3;		break;
+	case(DISTORT_FLT):			dz->extra_bufcnt = 0;	dz->bufcnt = 3;		break;
+	case(DISTORT_INT):
+		switch(dz->mode) {
+		case(DISTINT_INTRLV):	dz->extra_bufcnt = 0;	dz->bufcnt = 3;		break;
+		case(DISTINT_RESIZE):	dz->extra_bufcnt = 0;	dz->bufcnt = 4;		break;
+		default:
+			sprintf(errstr,"Unknown mode for DISTORT_INT in establish_bufptrs_and_extra_buffers()\n");
+			return(PROGRAM_ERROR);
+		}
+		break;
+	case(DISTORT_CYCLECNT):		dz->extra_bufcnt = 0;	dz->bufcnt = 2;		break;
+	case(DISTORT_PCH):			dz->extra_bufcnt = 0;	dz->bufcnt = 4;		break;
+//TW UPDATE NEW CASES
+	case(DISTORT_OVERLOAD):
+		switch(dz->mode) {
+		case(OVER_NOISE):	dz->extra_bufcnt = 0;	dz->bufcnt = 1;		break;
+		case(OVER_SINE):	dz->extra_bufcnt = 0;	dz->bufcnt = 1;		break;
+		}
+		break;
+	case(DISTORT_PULSED):	dz->extra_bufcnt = 0;	dz->bufcnt = 4;		break;
+
+	default:
+		sprintf(errstr,"Unknown program type [%d] in establish_bufptrs_and_extra_buffers()\n",dz->process);
+		return(PROGRAM_ERROR);
+	}
+
+	if(dz->extra_bufcnt < 0) {
+		sprintf(errstr,"bufcnts have not been set: establish_bufptrs_and_extra_buffers()\n");
+		return(PROGRAM_ERROR);
+	}
+	if((dz->process==HOUSE_SPEC && dz->mode==HOUSE_CONVERT) || dz->process==INFO_DIFF) {
+		if((exit_status = establish_spec_bufptrs_and_extra_buffers(dz))<0)
+			return(exit_status);
+	}
+	return establish_groucho_bufptrs_and_extra_buffers(dz);
+}
+
+/***************************** SETUP_INTERNAL_ARRAYS_AND_ARRAY_POINTERS **************************/
+
+int setup_internal_arrays_and_array_pointers(dataptr dz)
+{
+	int n;		 
+	dz->ptr_cnt    = -1;		/* base constructor...process */
+	dz->array_cnt  = -1;
+	dz->iarray_cnt = -1;
+	dz->larray_cnt = -1;
+	switch(dz->process) {
+	case(DISTORT): 	  	dz->array_cnt=1; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_ENV):	dz->array_cnt=1; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 2;	dz->fptr_cnt = 0; break;
+	case(DISTORT_AVG):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 2; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_OMT):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_MLT):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_DIV):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_HRM):	dz->array_cnt=1; dz->iarray_cnt=1; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_FRC):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 2; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_REV):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_SHUF):	dz->array_cnt=0; dz->iarray_cnt=1; dz->larray_cnt = 1; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_RPTFL):
+	case(DISTORT_RPT2):
+	case(DISTORT_RPT):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_INTP):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_DEL):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 2; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_RPL):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 2; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_TEL):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 2; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_FLT):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_INT):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_CYCLECNT):
+						dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+	case(DISTORT_PCH):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+//TW UPDATE NEW CASES
+	case(DISTORT_OVERLOAD):
+		switch(dz->mode) {
+		case(OVER_NOISE):	dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+		case(OVER_SINE):	dz->array_cnt=1; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0;	dz->fptr_cnt = 0; break;
+		}
+		break;
+	case(DISTORT_PULSED):	dz->array_cnt=3; dz->iarray_cnt=1; dz->larray_cnt = 0; dz->ptr_cnt = 2;	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);
+		}
+
+		/*RWD dz->lfarray shadows lparray  for distort del, etc */
+		if((dz->lfarray = (float    **)malloc(dz->larray_cnt * sizeof(float *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal float arrays.\n");
+			return(MEMORY_ERROR);
+		}
+
+		for(n=0;n<dz->larray_cnt;n++){
+			dz->lparray[n] = NULL;
+			dz->lfarray[n] = NULL;		/*RWD*/
+		}
+	}
+	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(DISTORT):		setup_process_logic(SNDFILES_ONLY,		  	EQUAL_SNDFILE,		SNDFILE_OUT,	dz);	break;
+	case(DISTORT_ENV):	setup_process_logic(SNDFILES_ONLY,		  	EQUAL_SNDFILE,		SNDFILE_OUT,	dz);	break;
+	case(DISTORT_AVG):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_OMT):	setup_process_logic(SNDFILES_ONLY,		  	EQUAL_SNDFILE,		SNDFILE_OUT,	dz);	break;
+	case(DISTORT_MLT):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_DIV):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_HRM):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_FRC):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_REV):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_SHUF):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_RPTFL):
+	case(DISTORT_RPT2):
+	case(DISTORT_RPT):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_INTP):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_DEL):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_RPL):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_TEL):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_FLT):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_INT):	setup_process_logic(TWO_SNDFILES,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+	case(DISTORT_CYCLECNT):	
+						setup_process_logic(SNDFILES_ONLY,		  	SCREEN_MESSAGE,		NO_OUTPUTFILE,	dz);	break;
+	case(DISTORT_PCH):	setup_process_logic(SNDFILES_ONLY,		  	UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+//TW UPDATE NEW CASES
+	case(DISTORT_OVERLOAD):	setup_process_logic(SNDFILES_ONLY,		EQUAL_SNDFILE,		SNDFILE_OUT,	dz);	break;
+	case(DISTORT_PULSED):	setup_process_logic(SNDFILES_ONLY,		UNEQUAL_SNDFILE,	SNDFILE_OUT,	dz);	break;
+
+	default:
+		sprintf(errstr,"Unknown process: assign_process_logic()\n");
+		return(PROGRAM_ERROR);
+		break;
+	}
+	if(dz->has_otherfile) {
+		switch(dz->input_data_type) {
+		case(ALL_FILES):
+		case(TWO_SNDFILES):
+		case(SNDFILE_AND_ENVFILE):
+		case(SNDFILE_AND_BRKFILE):
+		case(SNDFILE_AND_UNRANGED_BRKFILE):
+		case(SNDFILE_AND_DB_BRKFILE):
+			break;
+		case(MANY_SNDFILES):
+			if(dz->process==INFO_TIMELIST)
+				break;
+			/* fall thro */
+		default:
+			sprintf(errstr,"Most processes accepting files with different properties\n"
+						   "can only take 2 sound infiles.\n");
+			return(PROGRAM_ERROR);
+		}
+	}
+	return(FINISHED);
+}
+
+/***************************** SET_LEGAL_INFILE_STRUCTURE **************************
+ *
+ * Allows 2nd infile to have different props to first infile.
+ */
+
+void set_legal_infile_structure(dataptr dz)
+{
+	switch(dz->process) {
+	default:
+		dz->has_otherfile = FALSE;
+		break;
+	}
+}
+
+/***************************************************************************************/
+/****************************** FORMERLY IN internal.c *********************************/
+/***************************************************************************************/
+
+/****************************** SET_LEGAL_INTERNALPARAM_STRUCTURE *********************************/
+
+int set_legal_internalparam_structure(int process,int mode,aplptr ap)
+{
+	int exit_status = FINISHED;
+	switch(process) {
+	case(DISTORT):	  	exit_status = set_internalparam_data("i"    ,ap);				break;
+	case(DISTORT_ENV):	exit_status = set_internalparam_data("d"    ,ap);				break;
+	case(DISTORT_AVG):	exit_status = set_internalparam_data("i"    ,ap);				break;
+	case(DISTORT_OMT):	return(FINISHED);												break;
+	case(DISTORT_MLT):	return(FINISHED);												break;
+	case(DISTORT_DIV):	return(FINISHED);												break;
+	case(DISTORT_HRM):	exit_status = set_internalparam_data("iii"  ,ap);				break;
+	case(DISTORT_FRC):	exit_status = set_internalparam_data("i"    ,ap);				break;
+	case(DISTORT_REV):	return(FINISHED);												break;
+	case(DISTORT_SHUF):	exit_status = set_internalparam_data("ii"   ,ap);				break;
+	case(DISTORT_RPTFL):
+	case(DISTORT_RPT2):
+	case(DISTORT_RPT):	return(FINISHED);												break;
+	case(DISTORT_INTP):	return(FINISHED);												break;
+	case(DISTORT_DEL):	return(FINISHED);												break;
+	case(DISTORT_RPL):	return(FINISHED);												break;
+	case(DISTORT_TEL):	return(FINISHED);												break;
+	case(DISTORT_FLT):	exit_status = set_internalparam_data("dd"   ,ap);				break;
+	case(DISTORT_INT):	return(FINISHED);												break;
+	case(DISTORT_CYCLECNT):
+						return(FINISHED);												break;
+	case(DISTORT_PCH):	return(FINISHED);												break;
+//TW NEW CASES
+	case(DISTORT_OVERLOAD):	return(FINISHED);											break;
+	case(DISTORT_PULSED):	exit_status = set_internalparam_data("ii",ap);				break;
+	default:
+		sprintf(errstr,"Unknown process in set_legal_internalparam_structure()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(exit_status);		
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN specialin.c *********************************/
+/********************************************************************************************/
+
+/********************** READ_SPECIAL_DATA ************************/
+
+int read_special_data(char *str,dataptr dz)	   
+{
+//TW CONFIRMED DELETE exit_status = FINISHED;
+	aplptr ap = dz->application;
+
+	switch(ap->special_data) {
+	case(DISTORT_ENVELOPE):		return get_envfile_data(str,dz);
+//TW UPDATE NEW CASE
+	case(PULSE_ENVELOPE):		return get_pulsefile_data(str,dz);
+	case(HARMONIC_DISTORT):		return get_harmonic_data(str,dz);
+	case(SHUFFLE_DATA):			return read_shuffle_data(DISTORTS_DMNCNT,DISTORTS_IMGCNT,DISTORTS_MAP,str,dz);
+	default:
+		sprintf(errstr,"Unknown special_data type: read_special_data()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/************************ GET_ENVFILE_DATA ***************************/
+
+int get_envfile_data(char *filename,dataptr dz)
+{
+	int cnt = 0, n;
+	double maxtime;
+	char temp[200], *p;
+	int arraysize = BIGARRAY;
+//TW CONFIRMED DELETE aplptr ap = dz->application;
+	FILE *fp;
+	if((dz->parray[DISTORTE_ENV] = (double *)malloc(arraysize * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for distortion envelope.\n");
+		return(MEMORY_ERROR);
+	}
+	if((fp = fopen(filename,"r"))==NULL) {			/* 2 */
+		sprintf(errstr,"Failed to open envelope file %s\n",filename);
+		return(DATA_ERROR);
+	}
+	while(fgets(temp,200,fp)!=NULL) {				/* 3 */
+		p = temp;
+		while(get_float_from_within_string(&p,&(dz->parray[DISTORTE_ENV][cnt]))) {
+			if(cnt==0) {		     /* FORCE ZERO-TIME POINT AT TAB START */
+				if(dz->parray[DISTORTE_ENV][cnt]<0.0) {
+					sprintf(errstr,"-ve time (%lf) line %d in file %s\n",dz->parray[DISTORTE_ENV][cnt],(cnt/2)+1,filename);
+					return(DATA_ERROR);
+				}
+				if(flteq(dz->parray[DISTORTE_ENV][cnt],0.0)) {
+					dz->parray[DISTORTE_ENV][cnt] = 0.0;	/* FORCE 0.0 TIME TO exactly 0.0 */
+				} else { 	 								/* Add zero-time values */
+					dz->parray[DISTORTE_ENV][2] = dz->parray[DISTORTE_ENV][0];
+					dz->parray[DISTORTE_ENV][3] = dz->parray[DISTORTE_ENV][1];
+					dz->parray[DISTORTE_ENV][0] = 0.0;
+					cnt += 2;
+				}
+			} else {
+				if(EVEN(cnt)) {	/* Time vals */
+						/* CHECK TIME SEQUENCING */
+					if(dz->parray[DISTORTE_ENV][cnt] <= dz->parray[DISTORTE_ENV][cnt-2]) {
+						sprintf(errstr,"Time values out of sequence (%lf : %lf)in envelope file at line %d\n",
+						dz->parray[DISTORTE_ENV][cnt-2],dz->parray[DISTORTE_ENV][cnt],(cnt/2)+1);
+						return(DATA_ERROR);
+					}
+				} else {		/* Env values */
+					if(dz->parray[DISTORTE_ENV][cnt]<dz->application->min_special 
+					|| dz->parray[DISTORTE_ENV][cnt]>dz->application->max_special) {	/* CHECK RANGE */  
+						sprintf(errstr,"Invalid envelope value (%lf): line %d file %s\n",
+						dz->parray[DISTORTE_ENV][cnt],(cnt/2)+1,filename);
+						return(DATA_ERROR);
+					}
+				}
+			}
+			if(++cnt >= arraysize) {
+				arraysize += BIGARRAY;
+				if((dz->parray[DISTORTE_ENV]=
+				(double *)realloc((char *)dz->parray[DISTORTE_ENV],arraysize*sizeof(double)))==NULL){
+					sprintf(errstr,"INSUFFICIENT MEMORY to reallocate distortion envelope.\n");
+					return(MEMORY_ERROR);
+				}
+			}
+		}
+	}
+	if(ODD(cnt)) {
+		sprintf(errstr,"Envelope vals incorrectly paired in file %s\n",filename);
+		return(DATA_ERROR);
+	}
+	if(cnt==0) {
+		sprintf(errstr,"No envelope values found in file %s\n",filename);
+		return(DATA_ERROR);
+	}
+	
+	if((dz->parray[DISTORTE_ENV]=(double *)realloc(dz->parray[DISTORTE_ENV],cnt * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to reallocate distortion envelope.\n");
+		return(MEMORY_ERROR);
+	}
+
+	dz->ptr[DISTORTE_ENVEND] = &(dz->parray[DISTORTE_ENV][cnt]);    /* MARK END OF ENVELOPE DATA */
+
+	maxtime = dz->parray[DISTORTE_ENV][cnt-2]; 						/* FIND MAXIMUM TIME IN DATA */
+	for(n=2;n<cnt;n +=2)	 					  /* NORMALISE DATA TIMES TO LIE BETWEEN 0 AND 1 */
+		dz->parray[DISTORTE_ENV][n] = (float)(dz->parray[DISTORTE_ENV][n]/maxtime);
+	dz->parray[DISTORTE_ENV][cnt-2] = 1.0;    				  /* FORCE FINAL TIME TO exactly 1.0 */
+	if(fclose(fp)<0) {
+		fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
+		fflush(stdout);
+	}
+	return(FINISHED);
+}    
+
+//TW UPDATE : NEW FUNCTION
+/************************ GET_PULSEFILE_DATA ***************************
+ *
+ * NB DISTORTE_ENV = 0, and so this function works for DISTORT_PULSED,
+ *  putting the data in parray[0]
+ */
+
+int get_pulsefile_data(char *filename,dataptr dz)
+{
+	int cnt = 0, n;
+	double maxtime, dummy;
+	char temp[200], *p;
+	int arraysize = BIGARRAY;
+//	aplptr ap = dz->application;
+	FILE *fp;
+	p = filename;
+	if(sloom) {
+		if(*p == NUMERICVAL_MARKER) {
+			p++;
+			if(sscanf(p,"%lf",&dummy)!=1) {
+				sprintf(errstr,"Invalid numeric value for pulse envelope.\n");
+				return(PROGRAM_ERROR);
+			}
+			if(dummy!=0.0) {
+				sprintf(errstr,"Pulse envelope must be either '0' (for no envelope) or a brkpoint envelope file.\n");
+				return(DATA_ERROR);
+			}
+			if(dz->mode == PULSE_IMP) {
+				sprintf(errstr,"Numeric input for pulse envelope should be impossible in this mode.\n");
+				return(PROGRAM_ERROR);
+			}
+			dz->iparam[PULSE_ENVSIZE] = 0;
+			return(FINISHED);
+		}
+	} else {
+		if(*p == '0') {
+				p++;
+			while(*p=='0')
+				p++;
+			if(*p=='.')
+				p++;
+			while(*p=='0')
+				p++;
+			if(*p==ENDOFSTR) {
+				if(dz->mode == PULSE_IMP) {
+					sprintf(errstr,"You must provide an envelope file for the impulse, for this process\n");
+					return(DATA_ERROR);
+				}
+				dz->iparam[PULSE_ENVSIZE] = 0;
+				return(FINISHED);
+			}
+		}
+	}
+	if((dz->parray[ORIG_PULSENV] = (double *)malloc(arraysize * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for pulse envelope.\n");
+		return(MEMORY_ERROR);
+	}
+	if((fp = fopen(filename,"r"))==NULL) {			/* 2 */
+		sprintf(errstr,"Failed to open envelope file %s\n",filename);
+		return(DATA_ERROR);
+	}
+	while(fgets(temp,200,fp)!=NULL) {				/* 3 */
+		p = temp;
+		while(get_float_from_within_string(&p,&(dz->parray[ORIG_PULSENV][cnt]))) {
+			if(cnt==0) {		     /* FORCE ZERO-TIME POINT AT TAB START */
+				if(dz->parray[ORIG_PULSENV][cnt]<0.0) {
+					sprintf(errstr,"-ve time (%lf) line %d in file %s\n",dz->parray[ORIG_PULSENV][cnt],(cnt/2)+1,filename);
+					return(DATA_ERROR);
+				}
+				if(flteq(dz->parray[ORIG_PULSENV][cnt],0.0)) {
+					dz->parray[ORIG_PULSENV][cnt] = 0.0;	/* FORCE 0.0 TIME TO exactly 0.0 */
+				} else { 	 								/* Add zero-time values */
+					dz->parray[ORIG_PULSENV][2] = dz->parray[ORIG_PULSENV][0];
+					dz->parray[ORIG_PULSENV][3] = dz->parray[ORIG_PULSENV][1];
+					dz->parray[ORIG_PULSENV][0] = 0.0;
+					cnt += 2;
+				}
+			} else {
+				if(EVEN(cnt)) {	/* Time vals */
+						/* CHECK TIME SEQUENCING */
+					if(dz->parray[ORIG_PULSENV][cnt] <= dz->parray[ORIG_PULSENV][cnt-2]) {
+						sprintf(errstr,"Time values out of sequence (%lf : %lf)in pulse envelope file at line %d\n",
+						dz->parray[ORIG_PULSENV][cnt-2],dz->parray[ORIG_PULSENV][cnt],(cnt/2)+1);
+						return(DATA_ERROR);
+					}
+				} else {		/* Env values */
+					if(dz->parray[ORIG_PULSENV][cnt]<dz->application->min_special 
+					|| dz->parray[ORIG_PULSENV][cnt]>dz->application->max_special) {	/* CHECK RANGE */  
+						sprintf(errstr,"Invalid envelope value (%lf): line %d file %s\n",
+						dz->parray[ORIG_PULSENV][cnt],(cnt/2)+1,filename);
+						return(DATA_ERROR);
+					}
+				}
+			}
+			if(++cnt >= arraysize) {
+				arraysize += BIGARRAY;
+				if((dz->parray[ORIG_PULSENV]=
+				(double *)realloc((char *)dz->parray[ORIG_PULSENV],arraysize*sizeof(double)))==NULL){
+					sprintf(errstr,"INSUFFICIENT MEMORY to reallocate pulse envelope.\n");
+					return(MEMORY_ERROR);
+				}
+			}
+		}
+	}
+	if(ODD(cnt)) {
+		sprintf(errstr,"Pulse envelope vals incorrectly paired in file %s\n",filename);
+		return(DATA_ERROR);
+	}
+	if(cnt==0) {
+		sprintf(errstr,"No pulse envelope values found in file %s\n",filename);
+		return(DATA_ERROR);
+	}
+	
+	if((dz->parray[ORIG_PULSENV]=(double *)realloc(dz->parray[ORIG_PULSENV],cnt * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to reallocate pulse envelope.\n");
+		return(MEMORY_ERROR);
+	}
+
+
+	dz->iparam[PULSE_ENVSIZE] = cnt/2;
+	maxtime = dz->parray[ORIG_PULSENV][cnt-2]; 						/* FIND MAXIMUM TIME IN DATA */
+	for(n=2;n<cnt;n +=2)	 					  /* NORMALISE DATA TIMES TO LIE BETWEEN 0 AND 1 */
+		dz->parray[ORIG_PULSENV][n] = (float)(dz->parray[ORIG_PULSENV][n]/maxtime);
+	dz->parray[ORIG_PULSENV][cnt-2] = 1.0;    				  /* FORCE FINAL TIME TO exactly 1.0 */
+	if(fclose(fp)<0) {
+		fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
+		fflush(stdout);
+	}
+	return(FINISHED);
+}    
+
+/************************ GET_HARMONIC_DATA ***************************/
+
+int get_harmonic_data(char *filename,dataptr dz)
+{
+	int n = 0;
+	aplptr ap = dz->application;
+	char temp[200], *p;
+	int arraysize = BIGARRAY;
+	FILE *fp;
+	if((fp = fopen(filename,"r"))==NULL) {			/* 2 */
+		sprintf(errstr,"Cannot open harmonics file %s\n",filename);
+		return(DATA_ERROR);
+	}
+	if((dz->iparray[DISTORTH_HNO]  = (int *)malloc(arraysize * sizeof(int)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to store harmonic numbers.\n");
+		return(MEMORY_ERROR);
+	}
+	if((dz->parray[DISTORTH_AMP] = (double *)malloc(arraysize * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to store harmonic amps.\n");
+		return(MEMORY_ERROR);
+	}
+	while(fgets(temp,200,fp)!=NULL) {				/* 3 */
+		p = temp;
+		while(isspace(*p)) {
+			if(*(++p) == ENDOFSTR)
+				break;
+		}
+		if(*p == ENDOFSTR)		  /* ignore blank lines */
+			continue;
+		if(sscanf(temp,"%d%lf",&(dz->iparray[DISTORTH_HNO][n]),&(dz->parray[DISTORTH_AMP][n]))!=2) {
+			sprintf(errstr,"Cannot read harmonic no/val pair in file %s\n",filename);
+			return(DATA_ERROR);
+		}
+		if(dz->iparray[DISTORTH_HNO][n] < (int)ap->min_special 
+		|| dz->iparray[DISTORTH_HNO][n] > (int)ap->max_special) {	/* TW */
+			sprintf(errstr,"Error in harmonics file - harmonic number [%d] out of range %.0lf - %.0lf\n",
+			dz->iparray[DISTORTH_HNO][n],ap->min_special,ap->max_special);
+			return(DATA_ERROR);
+		} 
+		if(dz->parray[DISTORTH_AMP][n] < (int)ap->min_special2 
+		|| dz->parray[DISTORTH_AMP][n] > (int)ap->max_special2) {	/* TW */
+			sprintf(errstr,"Error in harmonics file - harmonic amp out of range %lf - %lf\n",ap->min_special2,ap->max_special2);
+			return(DATA_ERROR);
+		} 
+		if(++n >= arraysize) {				/* 5 */
+			arraysize += BIGARRAY;
+			if((dz->iparray[DISTORTH_HNO]=(int *)realloc(dz->iparray[DISTORTH_HNO],arraysize*sizeof(int)))==NULL){
+				sprintf(errstr,"INSUFFICIENT MEMORY to reallocate harmonic numbers.\n");
+				return(MEMORY_ERROR);
+			}
+			if((dz->parray[DISTORTH_AMP]=(double *)realloc(dz->parray[DISTORTH_AMP],arraysize*sizeof(double)))==NULL){
+				sprintf(errstr,"INSUFFICIENT MEMORY to reallocate harmonic amps.\n");
+				return(MEMORY_ERROR);
+			}
+		}
+	}
+	if(fclose(fp)<0) {
+		fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
+		fflush(stdout);
+	}
+	if(n==0) {
+		sprintf(errstr,"No harmonics found in file\n");
+		return(DATA_ERROR);
+	}
+	if((dz->iparray[DISTORTH_HNO]=(int *)realloc(dz->iparray[DISTORTH_HNO],n * sizeof(int)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to reallocate harmonic numbers.\n");
+		return(MEMORY_ERROR);
+	}
+	if((dz->parray[DISTORTH_AMP]=(double *)realloc(dz->parray[DISTORTH_AMP],n * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to reallocate harmonic amps.\n");
+		return(MEMORY_ERROR);
+	}
+	dz->iparam[DISTORTH_HCNT] = n;
+	return(FINISHED);
+}    
+
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+
+/****************************** PARAM_PREPROCESS *********************************/
+
+int param_preprocess(dataptr dz)	
+{
+//TW CONFIRMED DELETE int exit_status = FINISHED;
+
+	switch(dz->process) {
+	case(DISTORT):		return distort_preprocess(dz);	
+	case(DISTORT_ENV):	return distortenv_preprocess(dz);	
+	case(DISTORT_MLT):	return distortmlt_preprocess(dz);
+	case(DISTORT_DIV):	return distortdiv_preprocess(dz);
+	case(DISTORT_SHUF): return distortshuf_preprocess(dz);
+ 	case(DISTORT_DEL):	return distortdel_preprocess(dz);
+	case(DISTORT_FLT):	return distortflt_preprocess(dz);
+	case(DISTORT_AVG):	return distorter_preprocess(DISTORTA_CYCLECNT,DISTORTA_STARTCYC,DISTORTA_CYCLEN,dz);
+	case(DISTORT_FRC):	return distorter_preprocess(DISTORTF_SCALE,DISTORTF_STARTCYC,DISTORTF_CYCLEN,dz);
+	case(DISTORT_RPL):	return distorter_preprocess(DISTRPL_CYCLECNT,DISTRPL_STARTCYC,DISTRPL_CYCLEVAL,dz);
+	case(DISTORT_TEL):	return distorter_preprocess(DISTTEL_CYCLECNT,DISTTEL_STARTCYC,DISTTEL_CYCLEVAL,dz);
+
+	case(DISTORT_HRM):	
+		dz->iparam[FOLDOVER_WARNING] = FALSE;	
+		return FINISHED;
+	case(DISTORT_PCH):	
+		initrand48();							
+		return FINISHED;
+
+	case(DISTORT_OMT):	case(DISTORT_REV):	case(DISTORT_RPT):		case(DISTORT_RPTFL):
+	case(DISTORT_INTP):	case(DISTORT_INT):	case(DISTORT_CYCLECNT):	case(DISTORT_RPT2):
+		return FINISHED;
+//TW UPDATE NEW CASES
+	case(DISTORT_OVERLOAD):
+	   	return overload_preprocess(dz);
+	case(DISTORT_PULSED):
+	   	return preprocess_pulse(dz);
+
+	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!=DISTORT_CYCLECNT && dz->process!=DISTORT_PULSED)
+		display_virtual_time(0L,dz);
+	switch(dz->process) {
+	case(DISTORT):
+		if((exit_status = process_with_swapped_bufs_on_single_half_cycles(dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_ENV):
+	case(DISTORT_REV):
+		if((exit_status = process_with_swapped_bufs_on_full_cycles(dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_AVG):
+		if((exit_status = 
+		process_with_swapped_bufs_on_full_cycles_with_newsize_output_and_skipcycles(dz->sampbuf[2],DISTORTA_SKIPCNT,dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_SHUF):
+		if((exit_status = 
+		process_with_swapped_bufs_on_full_cycles_with_newsize_output_and_skipcycles(dz->sampbuf[2],DISTORTS_SKIPCNT,dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_RPTFL):
+	case(DISTORT_RPT):
+	case(DISTORT_RPT2):
+		if((exit_status = 
+		process_with_swapped_bufs_on_full_cycles_with_newsize_output_and_skipcycles(dz->sampbuf[2],DISTRPT_SKIPCNT,dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_INTP):
+		if((exit_status = 
+		process_with_swapped_bufs_on_full_cycles_with_newsize_output_and_skipcycles(dz->sampbuf[2],DISTINTP_SKIPCNT,dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_DEL):
+		if((exit_status = 
+		process_with_swapped_bufs_on_full_cycles_with_newsize_output_and_skipcycles(dz->sampbuf[2],DISTDEL_SKIPCNT,dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_RPL):
+		if((exit_status = 
+		process_with_swapped_bufs_on_full_cycles_with_newsize_output_and_skipcycles(dz->sampbuf[2],DISTRPL_SKIPCNT,dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_TEL):
+		if((exit_status = 
+		process_with_swapped_bufs_on_full_cycles_with_newsize_output_and_skipcycles(dz->sampbuf[2],DISTTEL_SKIPCNT,dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_FLT):
+		if((exit_status = 
+		process_with_swapped_bufs_on_full_cycles_with_newsize_output_and_skipcycles(dz->sampbuf[2],DISTFLT_SKIPCNT,dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_OMT):
+		if((exit_status = process_on_single_buf_with_phase_dependence(dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_MLT):
+	case(DISTORT_DIV):
+		if((exit_status = process_with_swapped_buf_to_swapped_outbufs(dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_HRM):
+	case(DISTORT_FRC):
+		if((exit_status = process_with_swapped_bufs_on_full_cycles_with_optional_prescale(dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_INT):
+		switch(dz->mode) {
+		case(DISTINT_INTRLV):
+			if((exit_status = two_infiles_interleave_process(dz))<0)
+				return(exit_status);
+			break;
+		case(DISTINT_RESIZE):
+			if((exit_status = two_infiles_resize_process(dz))<0)
+				return(exit_status);
+			break;
+		default:
+			sprintf(errstr,"Unknown case in DISTORT_INT mode switch in process_file()\n");
+			return(PROGRAM_ERROR);
+		}
+		break;
+	case(DISTORT_CYCLECNT):
+		if((exit_status = process_cyclecnt(dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_PCH):
+		if((exit_status = distort_pitch(dz))<0)
+			return(exit_status);
+		break;
+//TW UPDATE NEW CASES
+	case(DISTORT_OVERLOAD):
+		if((exit_status = distort_overload(dz))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_PULSED):
+		if((exit_status = do_pulsetrain(dz))<0)
+			return(exit_status);
+		break;
+
+	default:
+		sprintf(errstr,"Unknown case in process_file()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN pconsistency.c ******************************/
+/********************************************************************************************/
+
+/****************************** CHECK_PARAM_VALIDITY_AND_CONSISTENCY *********************************/
+
+int check_param_validity_and_consistency(dataptr dz)
+{
+//TW CONFIRED DELETE int exit_status = FINISHED;
+	handle_pitch_zeros(dz);
+	switch(dz->process) {
+	case(DISTORT_OMT):	return check_omit_consistency(dz); 	
+	}
+	return(FINISHED);
+}
+
+/********************************** CHECK_OMIT_CONSISTENCY **********************************/
+
+int check_omit_consistency(dataptr dz)
+{
+	int exit_status;
+	double brkmax;
+	if(dz->brksize[DISTORTO_OMIT]) {
+		if((exit_status = get_maxvalue_in_brktable(&brkmax,DISTORTO_OMIT,dz))<0)
+			return(exit_status);
+		if(round(brkmax) >= dz->iparam[DISTORTO_KEEP]) {
+			sprintf(errstr,"A in brkfile > or = B at some point: can't proceed.\n");
+			return(USER_ERROR);
+		}
+	} else {
+		if(dz->iparam[DISTORTO_OMIT] >= dz->iparam[DISTORTO_KEEP]) {
+			sprintf(errstr,"A > or = B: can't proceed.\n");
+			return(USER_ERROR);
+		}
+	}
+	return(FINISHED);
+}
+
+
+
+
+
+/********************************************************************************************/
+/********************************** FORMERLY IN buffers.c ***********************************/
+/********************************************************************************************/
+
+/**************************** ALLOCATE_LARGE_BUFFERS ******************************/
+
+int allocate_large_buffers(dataptr dz)
+{
+	switch(dz->process) {
+	case(DISTORT):		case(DISTORT_ENV):	case(DISTORT_OMT):		
+	case(DISTORT_MLT):	case(DISTORT_DIV):	case(DISTORT_REV):		
+	case(DISTORT_SHUF):	case(DISTORT_RPT):	case(DISTORT_INTP):		case(DISTORT_RPT2):
+	case(DISTORT_DEL):	case(DISTORT_RPL):	case(DISTORT_TEL):		
+	case(DISTORT_FLT):	case(DISTORT_INT):	case(DISTORT_CYCLECNT):	
+	case(DISTORT_PCH):	case(DISTORT_OVERLOAD):	case(DISTORT_RPTFL):
+		return create_sndbufs(dz);
+
+	case(DISTORT_AVG):		
+		return create_avgbufs(dz);
+	case(DISTORT_HRM):		
+		return create_sndbufs_plus_cyclebuf(DISTORTH_CYCBUFLEN,dz);
+	case(DISTORT_FRC):		
+		return create_sndbufs_plus_cyclebuf(DISTORTF_CYCBUFLEN,dz);
+//TW UPDATE : NEW CASE
+	case(DISTORT_PULSED):		
+		return create_pulse_buffers(dz);
+	default:
+		sprintf(errstr,"Unknown program no. in allocate_large_buffers()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/************************************* CREATE_PULSE_BUFFERS *************************************/
+
+int create_pulse_buffers(dataptr dz)
+{
+/*  dz->sampbuf[0] = INBUF	has to be extra SECSIZE in length, to allow for rounding samples at end
+	dz->sampbuf[1] = OUTBUF
+	dz->sampbuf[2] = STOREBUF stores set of wavsets for synth option
+	dz->sampbuf[3] = PULSEBUF stores pulse while it's being made
+*/
+	int exit_status;
+	double minfrq, mintrans, k;
+	size_t minbufsize, bigbufsize;
+
+	if(dz->brksize[PULSE_FRQ] > 0) {
+		if((exit_status = get_minvalue_in_brktable(&minfrq,PULSE_FRQ,dz))<0)
+			return(exit_status);
+	} else
+		minfrq = dz->param[PULSE_FRQ];
+	if(dz->param[PULSE_FRQRAND] > 0.0) {				/* if frq could be random-transposed */
+		k = dz->param[PULSE_FRQRAND]/SEMITONES_PER_OCTAVE;
+		k = pow(2.0,k);														
+		minfrq /= k;									/* transpose it down by max amount possible */
+	}
+	if(dz->brksize[PULSE_TRANSPOS] > 0) {
+		if((exit_status = get_minvalue_in_brktable(&mintrans,PULSE_TRANSPOS,dz))<0)
+			return(exit_status);
+	} else
+		mintrans = dz->param[PULSE_TRANSPOS];
+	mintrans /= SEMITONES_PER_OCTAVE;
+	mintrans = pow(2.0,mintrans);
+	minfrq *= mintrans;
+	k = (double)(dz->infile->srate/minfrq);
+	minbufsize = (int)floor(k + 1);
+	bigbufsize = (size_t) Malloc(-1);	/* i.e. grab a big buffer */
+	bigbufsize /= sizeof(float);
+	bigbufsize = (bigbufsize/(4 * F_SECSIZE)) * 4 * F_SECSIZE;
+	bigbufsize /= 4;
+	while(bigbufsize <= minbufsize) {
+		if((bigbufsize += F_SECSIZE) <= 0) {	/* Numeric overflow */
+			sprintf(errstr,"Failed to allocate memory for sound buffers: A.\n");
+			return(MEMORY_ERROR);
+		}
+	}
+	dz->buflen = (int) bigbufsize;
+	if((dz->bigbuf = (float *)malloc((dz->buflen * 4 * sizeof(float)) + F_SECSIZE))==NULL) {
+		sprintf(errstr,"Failed to allocate memory for sound buffers: B.\n");
+		return(MEMORY_ERROR);
+	}
+	dz->sampbuf[0] = dz->bigbuf;
+	dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen + F_SECSIZE;
+	dz->sampbuf[2] = dz->sampbuf[1] + dz->buflen;
+	dz->sampbuf[3] = dz->sampbuf[2] + dz->buflen;
+	return(FINISHED);
+}
+
+/*************************** CREATE_SNDBUFS_PLUS_CYCLEBUF **************************/
+
+int create_sndbufs_plus_cyclebuf(int cycbuflen_param,dataptr dz)
+{
+/*
+ * RWD this would be 12 samples then... 
+ *  #define SAFETY	(24)
+*/
+#define SAFETY	(48)
+	size_t bigbufsize;
+	int n;
+	int  cyclebuf_size;
+	cyclebuf_size = (int)round((double)dz->infile->srate*(double)sizeof(float)*(double)dz->infile->channels*MAXWAVELEN);
+	cyclebuf_size += SAFETY;
+
+	dz->iparam[cycbuflen_param]  = (int)(cyclebuf_size/sizeof(float));
+	dz->bufcnt--;
+	bigbufsize = (size_t) Malloc(-1);
+	dz->buflen = (int)(bigbufsize / sizeof(float));
+	dz->buflen = (dz->buflen / dz->infile->channels) * dz->infile->channels;
+	if((dz->bigbuf = (float *)malloc(sizeof(float) * ((dz->buflen * dz->bufcnt) + dz->iparam[cycbuflen_param]))) == NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
+		return(MEMORY_ERROR);
+	}
+	for(n=0;n<dz->bufcnt;n++)
+		dz->sbufptr[n] = dz->sampbuf[n] = dz->bigbuf + (dz->buflen * n);
+	dz->sampbuf[n] = dz->bigbuf + (dz->buflen * n);	  /* CYCLEBUF */
+	return(FINISHED);
+}
+
+/*************************** CREATE_AVGBUFS **************************/
+#define FSECSIZE (256)
+
+int create_avgbufs(dataptr dz)
+{
+	size_t bigbufsize;
+	long cyclbuf_size;  	
+	cyclbuf_size = round(dz->infile->srate * sizeof(float) * dz->infile->channels * dz->param[DISTORTA_MAXLEN]);
+	if((dz->sampbuf[3] = (float *)malloc(cyclbuf_size))==NULL) {	  /* calculation buffer */
+		sprintf(errstr,"INSUFFICIENT MEMORY to create cycles buffer.\n");
+		return(MEMORY_ERROR);
+	}
+	dz->iparam[DISTORTA_CYCBUFLEN] = (int)(cyclbuf_size/sizeof(float));
+	bigbufsize = (size_t) Malloc(-1);
+	dz->buflen = (int)(bigbufsize / sizeof(float));
+	dz->buflen /= 3;
+	if(dz->buflen==0)
+		dz->buflen = FSECSIZE;
+
+	dz->buflen =  (dz->buflen / dz->infile->channels) * dz->infile->channels;
+
+//TW CHANGED
+//	if((dz->bigbuf = (float *)malloc((dz->buflen * 3))) == NULL) {
+	if((dz->bigbuf = (float *)malloc((dz->buflen * 3 * sizeof(float)))) == NULL) {
+		sprintf(errstr, "INSUFFICIENT MEMORY to create sound buffers.\n");
+		return(MEMORY_ERROR);
+	}
+	dz->sampbuf[0] = dz->bigbuf;					/* pair of input bufs */
+	dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen;
+	dz->sampbuf[2] = dz->sampbuf[1] + dz->buflen;	/* output buffer */
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN cmdline.c ***********************************/
+/********************************************************************************************/
+
+int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
+{
+	if     (!strcmp(prog_identifier_from_cmdline,"reform"))   		dz->process = DISTORT;  
+	else if(!strcmp(prog_identifier_from_cmdline,"envel"))    		dz->process = DISTORT_ENV;
+	else if(!strcmp(prog_identifier_from_cmdline,"average"))  		dz->process = DISTORT_AVG;
+	else if(!strcmp(prog_identifier_from_cmdline,"omit"))  	  		dz->process = DISTORT_OMT;
+	else if(!strcmp(prog_identifier_from_cmdline,"multiply")) 		dz->process = DISTORT_MLT;
+	else if(!strcmp(prog_identifier_from_cmdline,"divide"))   		dz->process = DISTORT_DIV;
+	else if(!strcmp(prog_identifier_from_cmdline,"harmonic")) 		dz->process = DISTORT_HRM;
+	else if(!strcmp(prog_identifier_from_cmdline,"fractal"))  		dz->process = DISTORT_FRC;
+	else if(!strcmp(prog_identifier_from_cmdline,"reverse"))  		dz->process = DISTORT_REV;
+	else if(!strcmp(prog_identifier_from_cmdline,"shuffle"))  		dz->process = DISTORT_SHUF;
+	else if(!strcmp(prog_identifier_from_cmdline,"repeat"))   		dz->process = DISTORT_RPT;
+	else if(!strcmp(prog_identifier_from_cmdline,"repeat2"))   		dz->process = DISTORT_RPT2;
+	else if(!strcmp(prog_identifier_from_cmdline,"replim"))			dz->process = DISTORT_RPTFL;
+	else if(!strcmp(prog_identifier_from_cmdline,"interpolate"))   	dz->process = DISTORT_INTP;
+	else if(!strcmp(prog_identifier_from_cmdline,"delete"))   		dz->process = DISTORT_DEL;
+	else if(!strcmp(prog_identifier_from_cmdline,"replace"))  		dz->process = DISTORT_RPL;
+	else if(!strcmp(prog_identifier_from_cmdline,"telescope"))		dz->process = DISTORT_TEL;
+	else if(!strcmp(prog_identifier_from_cmdline,"filter"))   		dz->process = DISTORT_FLT;
+	else if(!strcmp(prog_identifier_from_cmdline,"interact")) 		dz->process = DISTORT_INT;
+	else if(!strcmp(prog_identifier_from_cmdline,"cyclecnt")) 		dz->process = DISTORT_CYCLECNT;
+	else if(!strcmp(prog_identifier_from_cmdline,"pitch"))    		dz->process = DISTORT_PCH;
+//TW UPDATE NEW CASES
+	else if(!strcmp(prog_identifier_from_cmdline,"overload"))    	dz->process = DISTORT_OVERLOAD;
+	else if(!strcmp(prog_identifier_from_cmdline,"pulsed"))    		dz->process = DISTORT_PULSED;
+	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,
+	"\nUSAGE: distort NAME (mode) infile (infile2) outfile parameters: \n"
+	"\n"
+	"where NAME can be any one of\n"
+	"\n"
+	"    DISTORT OPERATIONS ON A SINGLE SOUND FILE\n\n"
+   	"average   divide    fractal      multiply  repeat    replim     reverse\n"
+	"cyclecnt  envel     harmonic     omit      replace    shuffle\n"
+	"delete    filter    interpolate  pitch     reform     telescope\n"
+	"overload  pulsed    repeat2"
+	"\n"
+	"    DISTORT OPERATIONS ON TWO SOUND FILES\n\n"
+	"interact\n"
+	"\n"
+	"Type 'distort reform' for more info on reform option.. ETC.\n\n"
+	"DISTORT PROCESSES WORK ONLY ON mono FILES.\n");
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE2 ********************************/
+
+int usage2(char *str)
+{
+	if(!strcmp(str,"reform")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort reform 1-7 infile outfile \n"
+		"distort reform 8   infile outfile  exaggeration\n\n"
+		" MODIFY SHAPE OF 'WAVECYCLES'\n\n"
+		"MODES ARE\n"
+		"1 Convert to fixed level square_wave\n"
+		"2 Convert to square wave\n"
+		"3 Convert to fixed level triangular wave\n"
+		"4 Convert to triangular wave\n"
+		"5 Convert to inverted half_cycles\n"
+		"6 Convert to click stream\n"
+		"7 Convert to sinusoid\n"
+		"8 Exaggerate waveform contour\n\n"
+		"EXAGGERATION may vary over time.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"envel")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort envel 1-2 infile outfile         cyclecnt [-ttroughing] [-eexponent]\n"
+		"distort envel 3   infile outfile         cyclecnt troughing     [-eexponent]\n"
+		"distort envel 4   infile outfile envfile cyclecnt \n\n"
+		"IMPOSE ENVELOPE OVER EACH GROUP OF cyclecnt 'WAVECYCLES'\n\n"
+		"MODES (Works on MONO files only)-\n"
+		"1  rising envelope.\n"
+		"2  falling envelope.\n"
+		"3  troughed envelope.\n"
+		"4  user defined envelope.\n"
+		"CYCLECNT  is no of wavecycles under a single envelope.\n"
+		"EXPONENT  is exponent for envelope rise or decay:\n"
+        "          If OMMITED envelope rise/decay is linear.\n"
+		"TROUGHING is trough of envelope (0-1: default 0).\n"
+		"ENVFILE   Defines user envelope as time/val(0-1) pairs.\n"
+		"          (Time units arbitrary, as envelope stretched to each cycle(set) duration.\n\n"
+		"CYCLECNT, TROUGHING and EXPONENT, may vary over time\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"average")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort average infile outfile cyclecnt [-mmaxwavelen] [-sskipcycles]\n\n"
+		"AVERAGE THE WAVESHAPE OVER N 'WAVECYCLES'\n\n"
+		"CYCLECNT   is number of cycles to average over ( > 1)\n"
+		"MAXWAVELEN is max permissible wavelength in seconds. (default %.2lf)\n"
+		"SKIPCYCLES: (integer) is no. of wavecycles to skip at start of file\n",MAXWAVELEN);
+	} else if (!strcmp(str,"omit")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort omit infile outfile A B\n\n"
+		"OMIT A OUT OF EVERY B 'WAVECYCLES' REPLACING THEM BY SILENCE\n\n"
+		"A may vary over time: but must always be less than B.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"multiply")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort multiply infile outfile N [-s]\n\n"
+		"DISTORTION BY MULTIPLYING 'WAVECYCLE' FREQUENCY.\n\n"
+		"N = multiplier (integer only: range 2-16)\n"
+    	"-s smoothing: try if glitches appear.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"divide")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort divide infile outfile N [-i]\n\n"
+		"DISTORTION BY DIVIDING 'WAVECYCLE' FREQUENCY.\n\n"
+		"N = divider (integer only: range 2-16)\n"
+		"-i uses waveform interpolation: slower, but cleaner.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"harmonic")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort harmonic infile outfile harmonics-file [-ppre_attenuation]\n\n"
+		"HARMONIC DISTORTION BY SUPERIMPOSING 'HARMONICS' ONTO 'WAVECYCLES'.\n\n"
+		"HARMONICS-FILE contains harmonic_no/amplitude pairs.\n"
+		"    where amplitude of src sound is taken to be 1.0\n"
+		"    and harmonics range between %.0lf and %.0lf\n\n"
+		"PRE_ATTENUATION is applied to input sound before processing.\n\n"
+		"Works on MONO files only\n",MIN_HARMONIC,MAX_HARMONIC);
+	} else if (!strcmp(str,"fractal")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort fractal infile outfile scaling loudness [-ppre_attenuation]\n\n"
+		"SUPERIMPOSE MINIATURE COPIES OF SRC 'WAVECYCLES' ONTO THEMSELVES.\n\n"
+		"SCALING  = (integer) division of scale of src wave (range: %.0lf to %.2lf*srate)\n"
+		"LOUDNESS = loudness of scaled component, relative to src (loudness 1.0).\n\n"
+		"PRE_ATTENUATION is applied to input sound before processing.\n\n"
+		"scaling and loudness may vary over time\n\n"
+		"Works on MONO files only\n",MIN_SCALE,MAXWAVELEN);
+	} else if (!strcmp(str,"reverse")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort reverse infile outfile cyclecnt\n\n"
+		"CYCLE_REVERSAL DISTORTION.'WAVECYCLES' REVERSED IN GROUPS.\n\n"
+		"CYCLECNT: no. of cycles (>0) in reversed groups.\n\n"
+		"cyclecnt may vary in time\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"shuffle")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort shuffle infile outfile domain-image [-ccylecnt] [-sskipcycles]\n\n"
+		"DISTORTION BY SHUFFLING 'WAVECYCLES'\n\n"
+		"DOMAIN  group of letters representing consecutive (groups of) wavecyles.\n"
+		"IMAGE   group of letters which is some permutation of the domain.\n"
+		"Items from domain may be reordered, ommitted or duplicated.\n"
+		"  N.B. DOMAIN and IMAGE must be connected by a DASH (-).\n"
+		"CYCLECNT is size of wavecycle-groups to operate on. (default 1)\n"
+		"SKIPCYCLES: (integer) is no. of wavecycles to skip at start of file\n\n"
+		"Cyclecnt may vary over time.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"repeat")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort repeat infile outfile multiplier [-ccyleccnt] [-sskipcycles]\n\n"
+		"TIMESTRETCH FILE BY REPEATING 'WAVECYCLES'\n\n"
+		"MULTIPLIER: (integer) is no. of times each wavecycle(grp) repeats.\n"
+    	"CYCLECNT:   (integer) is no. wavecycles in repeated groups.\n"
+		"SKIPCYCLES: (integer) is no. of wavecycles to skip at start of file\n\n"
+		"multiplier and cyclecnt may vary over time.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"repeat2")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort repeat2 infile outfile multiplier [-ccyleccnt] [-sskipcycles]\n\n"
+		"REPEATING 'WAVECYCLES' WITHOUT TIME STRETCHING\n\n"
+		"MULTIPLIER: (integer) is no. of times each wavecycle(grp) repeats.\n"
+    	"CYCLECNT:   (integer) is no. wavecycles in repeated groups.\n"
+		"SKIPCYCLES: (integer) is no. of wavecycles to skip at start of file\n\n"
+		"multiplier and cyclecnt may vary over time.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"replim")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort replim inf outf multiplier [-ccyleccnt] [-sskipcycles] -f[hilim]\n\n"
+		"TIMESTRETCH FILE BY REPEATING 'WAVECYCLES' (BELOW SPECIFIED FRQ)\n\n"
+		"MULTIPLIER: (integer) is no. of times each wavecycle(grp) repeats.\n"
+    	"CYCLECNT:   (integer) is no. wavecycles in repeated groups.\n"
+		"SKIPCYCLES: (integer) is no. of wavecycles to skip at start of file\n"
+		"HILIM:      (float)   is frq below which cycles are counted.\n\n"
+		"multiplier and cyclecnt may vary over time.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"interpolate")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort interpolate infile outfile multiplier [-sskipcycles]\n\n"
+		"TIMESTRETCH FILE BY REPEATING 'WAVECYCLES' & INTERPOLATING BETWEEN THEM.\n\n"
+		"MULTIPLIER: (integer) is no. of times each wavecycle repeats.\n"
+		"SKIPCYCLES: (integer) is no. of wavecycles to skip at start of file\n\n"
+		"multiplier and cyclecnt may vary over time.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"delete")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort delete mode infile outfile cyclecnt [-sskipcycles]\n\n"
+		"TIMECONTRACT FILE BY DELETING 'WAVECYCLES'\n\n"
+		"MODES:\n"
+ 		"1:  1 in CYCLECNT wavecycles retained\n"
+		"2:  Strongest 1 in CYCLECNT wavecycles retained\n\n"
+		"3:  Weakest 1 in CYCLECNT wavecycles deleted\n"
+		"SKIPCYCLES: (integer) is no. of wavecycles to skip at start of file\n\n"
+		"cyclecnt may vary over time.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"replace")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort replace infile outfile cyclecnt [-sskipcycles]\n\n"
+		"STRONGEST 'WAVECYCLE', IN EACH cyclecnt, REPLACES OTHERS\n"
+		"SKIPCYCLES: (integer) is no. of wavecycles to skip at start of file\n\n"
+		"cyclecnt may vary over time.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"telescope")) {		
+		sprintf(errstr,
+		"USAGE:\n"							
+		"distort telescope infile outfile cyclecnt [-sskipcycles] [-a]\n\n"
+		"TIMECONTRACT SOUND BY TELESCOPING cyclecnt 'WAVECYCLES' TO 1\n\n"
+		"SKIPCYCLES: (integer) is no. of wavecycles to skip at start of file\n"
+		"-a          telescope to average cyclelen.(Default: telescope to longest.)\n\n"
+		"cyclecnt may vary over time.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"filter")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort filter 1-2 infile outfile freq        [-sskipcycles]\n"
+		"distort filter 3   infile outfile freq1 freq2 [-sskipcycles]\n\n"
+		"TIMECONTRACT SOUND BY FILTERING OUT 'WAVECYCLES'\n\n"
+		"MODES:\n"
+		"1:  omit cycles below FREQ\n"
+		"2:  omit cycles above FREQ\n"
+		"3:  omit cycles below FREQ1 and above FREQ2\n\n"
+		"skipcycles: (integer) is no. of wavecycles to skip at start of file\n\n"
+		"freq, freq1 and freq2 may vary over time.\n\n"
+		"N.B. timevarying freq1, freq2 may not cross each other, nor be equal.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"interact")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort interact mode infile1 infile2 outfile\n\n"
+		"TIME-DOMAIN INTERACTION OF SOUNDS.\n\n"
+		"MODES:\n"
+		"1:  interleave wavecycles from the two infiles.\n"
+		"2:  impose wavecycle-lengths of 1st file on wavecycles of 2nd\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"cyclecnt")) {		
+		sprintf(errstr,
+		"USAGE:\n"
+		"distort cyclecnt infile\n\n"
+		"COUNT 'WAVECYCLES' IN SNDFILE.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"pitch")) {		
+		sprintf(errstr,
+ 		"USAGE:\n"
+		"distort pitch infile outfile octvary [-ccyclelen] [-sskipcycles]\n\n"
+		"PITCHWARP 'WAVECYCLES' OF SOUND.\n\n"
+     	"octvary:    max possible transposition (up or down) in octaves.\n"
+     	"            Range(>0 - %.1lf)\n"
+		"            pitch of each wavecycle is varied by a random amount\n"
+     	"            within the range octvary 8vas up to octvary 8vas down.\n"
+		"cylelen:    Max no. cycles possible between generation of transpos vals(>1)\n"
+		"            (Default : %d)\n"
+		"            Actual cyclecnt is a random number, less than this maximum.\n"
+		"skipcycles: No of cycles to skip at start of file.\n\n"     	
+		"cyclelen and octvary may vary over time.\n\n"
+		"Works on MONO files only\n",MAXOCTVAR,DEFAULT_RSTEP);
+//TW NEW CASES
+	} else if (!strcmp(str,"overload")) {		
+		sprintf(errstr,
+ 		"USAGE:\n"
+		"distort overload 1 infile outfile clip_level depth\n"
+		"OR\n"
+		"distort overload 2 infile outfile gate depth freq\n\n"
+		"Clip the signal with noise or a (possibly timevarying) waveform.\n\n"
+     	"clip_level: Level at which the signal is clipped.\n"
+     	"            Range(0 - 1)\n"
+		"depth:      Depth of distortion pattern on clipped stretches of signal.\n"
+		"            (Range 0 - 1)\n"
+		"freq:       Frequency of waveform imposed on clipped stretches of signal.\n\n"     	
+		"clip_level, depth and freq may vary over time.\n\n"
+		"Works on MONO files only\n");
+	} else if (!strcmp(str,"pulsed")) {		
+		sprintf(errstr,
+ 		"USAGE:\n"
+		"distort pulsed\n"
+		"1 infil outfil env stime dur frq frand trand arand transp tranrand [-s -e]\n"
+		"OR\n"
+		"2-3 inf outf env stime dur frq frand trand arand cyctime transp tranrand [-s -e]\n"
+		"    Impose impulse-train on source (mode 1), OR\n"
+		"    Use segment of src as looped content of synthetic impulse-train(modes 2,3).\n"
+		"ENV        brkpnt envelope of impulse. Will be scaled to duration needed.\n"
+		"STIME      time in src sound where impulses begin.(In mode 3,time as samplecnt)\n"
+		"DUR        time for which impulses persist.\n"
+		"FRQ        frequency of the impulses, in Hz: range 0.1 to 50\n"
+		"FRAND      randomisation of frequency of impulse (in semitones) (range 0-12).\n"
+		"TRAND      randomisation of relative time-positions of amp peaks & troughs\n"
+		"           from impulse to impulse. (range 0 - 1)\n"
+		"ARAND      randomisation of amplitude shape created by peaks & troughs\n"
+		"           from impulse to impulse. (range 0 - 1)\n"
+		"CYCTIME    duration of wavecycles to grab for sound inside impulses (mode 2)\n"
+		"           OR number of wavecycles to grab as sound inside impulses (mode 3)\n"
+		"TRANSP     transposition contour of sound inside each impulse. Brkpnt file of\n"
+		"           time:semitone-shift pairs,(time will be scaled to impulse dur),\n"
+		"TRANRAND   randomisation transp contour from impulse to impulse.(Range 0-1)\n"
+		"-s         keep start of src sound, before impulses begin (if any).\n"
+		"-e         keep end of src sound, after impulses end (if any)\n"
+		"Works on MONO files only\n");
+	} else
+		sprintf(errstr,"Unknown option '%s'\n",str);
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE3 ********************************/
+
+int usage3(char *str1,char *str2)
+{
+	if(!strcmp(str1,"cyclecnt"))	
+		return(CONTINUE);
+	else
+		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);
+}

+ 399 - 0
dev/distort/disprepro.c

@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version*/
+#include <stdio.h>
+#include <stdlib.h>
+/*RWD*/
+#include <memory.h>
+
+#include <structures.h>
+#include <tkglobals.h>
+#include <cdpmain.h>
+#include <globcon.h>
+#include <distort.h>
+//TW UPDATE
+#include <distort1.h>
+#include <modeno.h>
+#include <arrays.h>
+
+#include <sfsys.h>
+
+
+
+
+static int  gen_distort_sin_table(dataptr dz);
+static int  convert_frq_to_cyclelen(int paramno,dataptr dz);
+static int  reduce_brkvals_by_one(int paramno,dataptr dz);
+static int  frequencies_cross(dataptr dz);
+//TW UPDATE
+static int  make_distorter_tab(dataptr dz);
+
+/****************************** DISTORT_PREPROCESS *********************************/
+
+int distort_preprocess(dataptr dz)
+{
+	int exit_status;
+    dz->iparam[DISTORT_PULSE] = (int)round(PULSEWIDTH * (double)dz->infile->srate);
+	if(dz->mode==DISTORT_SINE && (exit_status = gen_distort_sin_table(dz))<0)
+		return(exit_status);
+	return(FINISHED);
+}
+
+/****************************** GEN_DISTORT_SIN_TABLE *********************************/
+
+int gen_distort_sin_table(dataptr dz)
+{
+	int n;
+	if((dz->parray[DISTORT_SIN] = (double *)malloc(SINETABLEN * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for sinewave table.\n");
+		return(MEMORY_ERROR);
+	}
+	for(n=0;n<SINETABLEN;n++)
+		dz->parray[DISTORT_SIN][n] = sin(PI * (double)n/(double)SINETABLEN);
+	return(FINISHED);
+}
+
+/****************************** DISTORTENV_PREPROCESS *********************************/
+
+int distortenv_preprocess(dataptr dz)
+{
+	int exit_status;
+	if((exit_status = reset_distorte_modes(dz))<0)
+		return(exit_status);
+	dz->param[ONE_LESS_TROF] = 1.0 - dz->param[DISTORTE_TROF];
+	return(FINISHED);
+}
+
+/**************************** RESET_DISTORTE_MODES ************************/
+
+int reset_distorte_modes(dataptr dz)
+{
+	if(dz->mode == DISTORTE_USERDEF)
+		return(FINISHED);
+	if(dz->mode == DISTORTE_TROFFED) {
+		if(!dz->vflag[0]) 			/* Only 1 flag exists in this mode, it is for EXPON, not TROF as in other cases!! */
+			dz->mode = DISTORTE_LINTROF;
+	} else {
+		if(!dz->vflag[DISTORTE_IS_EXPON]) {	/* flag 1 */
+	    	switch(dz->mode) {
+	    	case(DISTORTE_RISING):   dz->mode = DISTORTE_LINRISE;  	break;
+	    	case(DISTORTE_FALLING):  dz->mode = DISTORTE_LINFALL;  	break;
+			default:
+				sprintf(errstr,"Bad case in reset_distorte_modes()\n");
+				return(PROGRAM_ERROR);
+			}
+	    }
+		if(dz->vflag[DISTORTE_IS_TROF]) {		/* flag 0 */
+		    switch(dz->mode) {
+	    	case(DISTORTE_RISING):	dz->mode = DISTORTE_RISING_TR;	break;
+			case(DISTORTE_LINRISE):	dz->mode = DISTORTE_LINRISE_TR;	break;
+	    	case(DISTORTE_FALLING):	dz->mode = DISTORTE_FALLING_TR;	break;
+			case(DISTORTE_LINFALL):	dz->mode = DISTORTE_LINFALL_TR;	break;
+			}
+	    }
+	}
+	return(FINISHED);
+}
+
+/****************************** DISTORTMLT_PREPROCESS *********************************/
+
+int distortmlt_preprocess(dataptr dz)
+{
+	memset((char *)dz->sampbuf[2],0,dz->buflen * sizeof(float));
+	memset((char *)dz->sampbuf[3],0,dz->buflen * sizeof(float));
+	memset((char *)dz->sampbuf[4],0,dz->buflen * sizeof(float));
+	memset((char *)dz->sampbuf[5],0,dz->buflen * sizeof(float));
+	return(FINISHED);
+}
+
+/****************************** DISTORTDIV_PREPROCESS *********************************/
+
+int distortdiv_preprocess(dataptr dz)
+{
+	memset((char *)dz->sampbuf[2],0,dz->buflen * sizeof(float));
+	memset((char *)dz->sampbuf[3],0,dz->buflen * sizeof(float));
+	return(FINISHED);
+}
+
+/****************************** DISTORTER_PREPROCESS *********************************/
+
+int distorter_preprocess(int param1,int param2,int param3,dataptr dz)
+{
+	int exit_status;
+	int   brklen;
+	double brkmax;
+	if(dz->brksize[param1]) {
+		if((exit_status = get_maxvalue_in_brktable(&brkmax,DISTORTA_CYCLECNT,dz))<0)
+			return(exit_status);
+		brklen = round(brkmax);
+	} else
+		brklen = dz->iparam[param1];
+   	if((dz->lparray[param2] = (int *)malloc((brklen+1) * sizeof(int)))==NULL
+   	|| (dz->lparray[param3] = (int *)malloc(brklen     * sizeof(int)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for cycle information arrays.\n");
+		return(MEMORY_ERROR);
+	}
+
+	/*RWD 4:2002 we shadow this with lfarray */
+	if((dz->lfarray[param2] = (float *)malloc((brklen+1) * sizeof(float)))==NULL
+   	|| (dz->lfarray[param3] = (float *)malloc(brklen     * sizeof(float)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for cycle information arrays.\n");
+		return(MEMORY_ERROR);
+	}
+
+	return(FINISHED);
+}
+
+/****************************** DISTORTSHUF_PREPROCESS *********************************/
+
+int distortshuf_preprocess(dataptr dz)
+{
+	int exit_status;
+	int maxval;
+	double brkmax;
+	if(dz->brksize[DISTORTS_CYCLECNT]) {
+		if((exit_status = get_maxvalue_in_brktable(&brkmax,DISTORTS_CYCLECNT,dz))<0)
+			return(exit_status);
+		maxval = round(brkmax);
+	} else
+		maxval = dz->iparam[DISTORTS_CYCLECNT];
+	if((dz->lparray[DISTORTS_STARTCYC] = (int *)malloc((maxval+1)*dz->iparam[DISTORTS_DMNCNT]*sizeof(int)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for cycle information array.\n");
+		return(MEMORY_ERROR);
+	}
+	return(FINISHED);
+}
+
+/****************************** DISTORTDEL_PREPROCESS *********************************/
+
+int distortdel_preprocess(dataptr dz)
+{
+	switch(dz->mode) {
+	case(DELETE_IN_STRICT_ORDER):
+		if(dz->brksize[DISTDEL_CYCLECNT])
+			reduce_brkvals_by_one(DISTDEL_CYCLECNT,dz);	/* becomes number of cycles to delete */
+		else 
+			dz->iparam[DISTDEL_CYCLECNT]--; 
+		break;
+	case(KEEP_STRONGEST):
+	case(DELETE_WEAKEST):
+		return distorter_preprocess(DISTDEL_CYCLECNT,DISTDEL_STARTCYC,DISTDEL_CYCLEVAL,dz);
+	}
+	return(FINISHED);
+}
+
+/****************************** DISTORTFLT_PREPROCESS *********************************/
+
+int distortflt_preprocess(dataptr dz)
+{
+	int exit_status;
+	switch(dz->mode) {
+	case(DISTFLT_HIPASS):
+		convert_frq_to_cyclelen(DISTFLT_LOFRQ_CYCLELEN,dz);
+		break;
+	case(DISTFLT_LOPASS):
+		convert_frq_to_cyclelen(DISTFLT_HIFRQ_CYCLELEN,dz);
+		break;
+	case(DISTFLT_BANDPASS):
+		if(dz->brksize[DISTFLT_LOFRQ_CYCLELEN] && dz->brksize[DISTFLT_HIFRQ_CYCLELEN]) {
+		/* Force both brktables to begin at time zero */
+			if((exit_status = force_value_at_zero_time(DISTFLT_LOFRQ_CYCLELEN,dz))<0)
+				return(exit_status);
+			if((exit_status = force_value_at_zero_time(DISTFLT_HIFRQ_CYCLELEN,dz))<0)
+				return(exit_status);
+		}
+		/* Check brktables against each other: If hifrq < lofrq: reject */
+		if(frequencies_cross(dz)) {
+			sprintf(errstr,"Filter frqs cross: cannot proceed\n");
+			return(DATA_ERROR);
+		}
+		convert_frq_to_cyclelen(DISTFLT_LOFRQ_CYCLELEN,dz);
+		convert_frq_to_cyclelen(DISTFLT_HIFRQ_CYCLELEN,dz);
+		break;
+	default:
+		sprintf(errstr,"Unknown mode for DISTORT_FLT in param_preprocess()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/***************************** CONVERT_FRQ_TO_CYCLELEN ******************************/
+
+int convert_frq_to_cyclelen(int paramno,dataptr dz)
+{
+	double *p, *pend;
+	if(dz->brksize[paramno]) {
+		p = dz->brk[paramno] + 1;
+		pend = p + (dz->brksize[paramno] * 2);
+		while(p < pend) {
+			*p = dz->infile->srate/(*p);
+			p += 2;
+		}
+		dz->is_int[paramno] = TRUE;	/* Force rounding in brktable reads */
+	} else 
+		dz->iparam[paramno] = (int)round(dz->infile->srate/dz->param[paramno]);
+	return(FINISHED);
+}
+
+/**************************** REDUCE_BRKVALS_BY_ONE ************************/
+
+int reduce_brkvals_by_one(int paramno,dataptr dz)
+{
+	double *p = dz->brk[paramno];
+	int n;
+	if(dz->brksize[paramno] <= 0) {
+		sprintf(errstr,"Brktable is empty.\n");
+		return(DATA_ERROR);
+	}
+	p++;
+	for(n=0;n<dz->brksize[paramno];n++) {
+		*p -= 1.0;
+		p += 2;
+	}
+	return(FINISHED);
+}	
+
+/**************************** FREQUENCIES_CROSS ************************/
+
+int frequencies_cross(dataptr dz)
+{
+	int lo_finished = FALSE;
+	int hi_finished = FALSE;
+	double *flo, *fhi, *tlo, *thi, *loend, *hiend;
+	double lasttime,thistime,timediff,timeratio,lastval,thisval,valdiff,val;
+	if(dz->brksize[DISTFLT_LOFRQ_CYCLELEN]) {
+		flo   = dz->brk[DISTFLT_LOFRQ_CYCLELEN] + 1;
+		loend = dz->brk[DISTFLT_LOFRQ_CYCLELEN] + (dz->brksize[DISTFLT_LOFRQ_CYCLELEN] * 2);
+		if(dz->brksize[DISTFLT_HIFRQ_CYCLELEN]) {
+			fhi   = dz->brk[DISTFLT_HIFRQ_CYCLELEN] + 1;
+			hiend = dz->brk[DISTFLT_HIFRQ_CYCLELEN] + (dz->brksize[DISTFLT_HIFRQ_CYCLELEN] * 2);
+			tlo = flo - 1;
+			thi = fhi - 1;
+			while(lo_finished==FALSE && hi_finished==FALSE) {
+				if(*tlo < *thi) {
+					lasttime  = *(thi - 2);
+					thistime  = *thi;
+					timediff  = thistime - lasttime;
+					timeratio = (*tlo - lasttime)/timediff;
+					lastval   = *(fhi - 2);
+					thisval   = *fhi;
+					valdiff   = thisval - lastval;
+					val       = lastval + (valdiff * timeratio);
+					if(*flo >= val)
+						return(TRUE);
+					if((flo += 2) < loend)
+						tlo += 2;
+					else {
+						flo -= 2;
+						lo_finished = TRUE;
+					}
+				} else if (*tlo > *thi) {
+					lasttime  = *(tlo - 2);
+					thistime  = *tlo;
+					timediff  = thistime - lasttime;
+					timeratio = (*thi - lasttime)/timediff;
+					lastval   = *(flo - 2);
+					thisval   = *flo;
+					valdiff   = thisval - lastval;
+					val       = lastval + (valdiff * timeratio);
+					if(val >= *fhi)
+						return(TRUE);
+					if((fhi += 2) < hiend)
+						thi += 2;
+					else {
+						fhi -= 2;
+						hi_finished = TRUE;
+					}
+				} else /* (*tlo == *thi) */ {
+					if(*flo >= *fhi)
+						return(TRUE);
+					if((flo += 2) < loend)
+						tlo += 2;
+					else {
+						flo -= 2;
+						lo_finished = TRUE;
+					}
+					if((fhi += 2) < hiend)
+						thi += 2;
+					else {
+						fhi -= 2;
+						hi_finished = TRUE;
+					}
+				}
+			}
+		} else {
+			while(flo < loend) {
+				if(*flo >= dz->param[DISTFLT_HIFRQ_CYCLELEN])
+					return(TRUE);
+				flo += 2;
+			}
+		}
+	} else if(dz->brksize[DISTFLT_HIFRQ_CYCLELEN]) {
+		fhi   = dz->brk[DISTFLT_HIFRQ_CYCLELEN] + 1;
+		hiend = dz->brk[DISTFLT_HIFRQ_CYCLELEN] + (dz->brksize[DISTFLT_HIFRQ_CYCLELEN] * 2);
+		while(fhi < hiend) {
+			if(*fhi <= dz->param[DISTFLT_LOFRQ_CYCLELEN])
+				return(TRUE);
+			fhi += 2;
+		}
+	}
+	return(FALSE);
+}
+
+//TW UPDATE : NEW FUNCTIONS
+/**************************** OVERLOAD_PREPROCESS ************************/
+
+int overload_preprocess(dataptr dz)
+{
+	int exit_status;
+	if((dz->mode==OVER_SINE) && ((exit_status = make_distorter_tab(dz))<0))
+		return(exit_status);
+//TW NEW CODE UPDATE TO FLOATS
+//	dz->param[DISTORTER_MULT] *= (double)MAXSAMP;
+	return(FINISHED);
+}
+
+/******************************** MAKE_DISTORTER_TAB ********************************
+ *
+ *  cosin table shifted to lie between 0.0 and -1.0
+ */
+ 
+int make_distorter_tab(dataptr dz)
+{
+	int n;
+	double convertor = (double)TWOPI/(double)DISTORTER_TABLEN;
+	double *tab;
+	if((dz->parray[0] = (double *)malloc(DISTORTER_TABLEN * sizeof(double)))==NULL) {
+		sprintf(errstr,"Out of memory for cosine table.");
+		return(MEMORY_ERROR);
+	}
+	tab = dz->parray[0];
+	for(n = 0; n <DISTORTER_TABLEN; n++)
+		tab[n] = (cos((double)n * convertor) - 1.0)/2.0;
+	return(FINISHED);
+}
+

+ 401 - 0
dev/distort/distdel.c

@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+
+static int	do_up_cycle(int keep_or_loose,float **buf,int *current_buf,int *current_pos_in_buf,
+			int *lastzero,int *bufcrosing,int *obufpos,dataptr dz);
+static int	do_dn_cycle(int keep_or_loose,float **buf,int *current_buf,int *current_pos_in_buf,
+			int *lastzero,int *bufcrosing,int *obufpos,dataptr dz);
+static int	do_cycle_loud(float *buf,int cyclecnt,int current_pos_in_buf,int *obufpos,dataptr dz);
+static int	do_cycle_quiet(float *buf,int cyclecnt,int current_pos_in_buf,int *obufpos,dataptr dz);
+static int	do_cycle_loud_crosbuf(int cyclecnt,int current_buf,int current_pos_in_buf,
+			int cycleno_in_group_at_bufcros,int *obufpos,dataptr dz);
+static int	do_cycle_quiet_crosbuf(int cyclecnt,int current_buf,int current_pos_in_buf,
+			int cycleno_in_group_at_bufcros,int *obufpos,dataptr dz);
+static int	get_loudest_cycle(int cyclecnt,dataptr dz);
+static int	get_quietest_cycle(int cyclecnt,dataptr dz);
+static int	write_cycle(int start, int end,float *buf,int *obufpos,dataptr dz);
+
+/********************************** DISTORT_DEL ******************************/
+
+int distort_del
+(int *current_buf,int *current_pos_in_buf,int phase,int *obufpos,int *cnt,dataptr dz)
+{
+	int exit_status;
+	int n;
+	float *b = dz->sampbuf[*current_buf];
+	int bufcrosing = FALSE;
+	int lastzero = *current_pos_in_buf;
+	switch(phase) {
+	case(1):
+		if((exit_status = do_up_cycle(KEEP,&b,current_buf,current_pos_in_buf,&lastzero,&bufcrosing,obufpos,dz))!=CONTINUE)
+			return(exit_status);
+		if((exit_status = do_dn_cycle(KEEP,&b,current_buf,current_pos_in_buf,&lastzero,&bufcrosing,obufpos,dz))!=CONTINUE)
+			return(exit_status);
+		break;
+	case(-1):
+		if((exit_status = do_dn_cycle(KEEP,&b,current_buf,current_pos_in_buf,&lastzero,&bufcrosing,obufpos,dz))!=CONTINUE)
+			return(exit_status);
+		if((exit_status = do_up_cycle(KEEP,&b,current_buf,current_pos_in_buf,&lastzero,&bufcrosing,obufpos,dz))!=CONTINUE)
+			return(exit_status);
+		break;
+	}
+	if((*current_pos_in_buf - lastzero)!=0) {
+		if((exit_status = write_cycle(lastzero,*current_pos_in_buf,b,obufpos,dz))<0)
+			return(exit_status);
+	}
+	lastzero = *current_pos_in_buf;
+	for(n=0;n<dz->iparam[DISTDEL_CYCLECNT];n++) {		  /* FOR NUMBER OF UNWANTED CYCLES */
+		switch(phase) {
+		case(1):
+			if((exit_status = do_up_cycle(LOSE,&b,current_buf,current_pos_in_buf,&lastzero,&bufcrosing,obufpos,dz))!=CONTINUE)
+				return(exit_status);
+			if((exit_status = do_dn_cycle(LOSE,&b,current_buf,current_pos_in_buf,&lastzero,&bufcrosing,obufpos,dz))!=CONTINUE)
+				return(exit_status);
+			break;
+		case(-1):
+			if((exit_status = do_dn_cycle(LOSE,&b,current_buf,current_pos_in_buf,&lastzero,&bufcrosing,obufpos,dz))!=CONTINUE)
+				return(exit_status);
+			if((exit_status = do_up_cycle(LOSE,&b,current_buf,current_pos_in_buf,&lastzero,&bufcrosing,obufpos,dz))!=CONTINUE)
+				return(exit_status);
+			break;
+		}
+	}
+	(*cnt)++;
+	return(CONTINUE);
+}
+
+/******************************* DISTORT_DEL_WITH_LOUDNESS ******************************/
+
+int distort_del_with_loudness(int *current_buf,int phase,int *obufpos,int *current_pos_in_buf,int *cnt,dataptr dz)
+{
+	int exit_status = CONTINUE;
+	int cyclecnt = 0;				/* RWD added init */
+//TW CONFIRM DELETE	*int bufcross = 0;
+	register int i = *current_pos_in_buf;
+//TW CONFIRM DELETE	int cyclestart = i;
+	float *b  = dz->sampbuf[*current_buf];
+	int cycleno_in_group_at_bufcros = -1;
+	switch(phase) {				
+	case(1):
+		for(cyclecnt=0;cyclecnt<dz->iparam[DISTDEL_CYCLECNT];cyclecnt++) {
+			/* RWD 4:2002 use lfarray as this now contains amplitudes */
+			dz->lfarray[DISTDEL_CYCLEVAL][cyclecnt] = 0.0;			
+			dz->lparray[DISTDEL_STARTCYC][cyclecnt] = i;	
+			while(b[i]>=0) {		
+				dz->lfarray[DISTDEL_CYCLEVAL][cyclecnt] += b[i];
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))<0)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = cyclecnt;
+					if(exit_status !=CONTINUE)
+						break;
+					i = 0;
+				}
+			}
+			if(exit_status !=CONTINUE)
+				break;
+			while(b[i]<=0.0) {	
+				dz->lfarray[DISTDEL_CYCLEVAL][cyclecnt] -= b[i];
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))<0)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = cyclecnt;
+					if(exit_status !=CONTINUE)
+						break;
+					i = 0;
+				}
+			}
+			if(exit_status !=CONTINUE)
+				break;
+		}
+		break;
+	case(-1):						
+		for(cyclecnt=0;cyclecnt<dz->iparam[DISTDEL_CYCLECNT];cyclecnt++) {
+			dz->lfarray[DISTDEL_CYCLEVAL][cyclecnt] = 0.0;
+			dz->lparray[DISTDEL_STARTCYC][cyclecnt] = i;
+			while(b[i]<=0.0) {
+				dz->lfarray[DISTDEL_CYCLEVAL][cyclecnt] -= b[i];
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))<0)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = cyclecnt;
+					if(exit_status !=CONTINUE)
+						break;
+					i = 0;
+				}
+			}
+			if(exit_status !=CONTINUE)
+				break;
+			while(b[i]>=0.0) {
+				dz->lfarray[DISTDEL_CYCLEVAL][cyclecnt] += b[i];
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))<0)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = cyclecnt;
+					if(exit_status !=CONTINUE)
+						break;
+					i = 0;
+				}
+			}
+			if(exit_status !=CONTINUE)
+				break;
+		}
+		break;
+	}
+	if(cyclecnt) {
+		if(cycleno_in_group_at_bufcros >= 0) {	/* cycle set crosses between buffers */
+			switch(dz->mode) {
+			case(KEEP_STRONGEST): 
+				if((exit_status = do_cycle_loud_crosbuf(cyclecnt,*current_buf,i,cycleno_in_group_at_bufcros,obufpos,dz))<0)
+					return(exit_status);
+				break;
+			case(DELETE_WEAKEST): 
+				if((exit_status = do_cycle_quiet_crosbuf(cyclecnt,*current_buf,i,cycleno_in_group_at_bufcros,obufpos,dz))<0)
+					return(exit_status);
+				break;
+			}
+		} else {
+			switch(dz->mode) {
+			case(KEEP_STRONGEST):	
+				if((exit_status = do_cycle_loud(b,cyclecnt,i,obufpos,dz))<0)	
+					return(exit_status);
+				break;
+			case(DELETE_WEAKEST):	
+				if((exit_status = do_cycle_quiet(b,cyclecnt,i,obufpos,dz))<0)
+					return(exit_status);
+				break;
+			}
+		}
+	}
+	*current_pos_in_buf = i;
+	(*cnt)++;
+	return(exit_status);
+}
+
+/*************************** DO_UP_CYCLE ******************************/
+
+int do_up_cycle(int keep_or_loose,float **buf,int *current_buf,int *current_pos_in_buf,
+				int *lastzero,int *bufcrosing,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	while((*buf)[*current_pos_in_buf]>=0.0) {
+		if(++(*current_pos_in_buf) >= dz->ssampsread) {
+			if(keep_or_loose ==KEEP) {
+				if((exit_status= write_cycle(*lastzero,*current_pos_in_buf,*buf,obufpos,dz))< 0)
+					return(exit_status);
+			}
+			if((exit_status = change_buf(current_buf,bufcrosing,buf,dz))!=CONTINUE)
+				return(exit_status);
+			*lastzero = *current_pos_in_buf = 0;
+		}
+	}						
+	return(CONTINUE);
+}
+
+/************************* DO_DN_CYCLE ******************************/
+
+int do_dn_cycle(int keep_or_loose,float **buf,int *current_buf,int *current_pos_in_buf,
+				int *lastzero,int *bufcrosing,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	while((*buf)[*current_pos_in_buf]<=0.0) {
+		if(++(*current_pos_in_buf) >= dz->ssampsread) {
+			if(keep_or_loose ==KEEP) {
+				if((exit_status= write_cycle(*lastzero,*current_pos_in_buf,*buf,obufpos,dz))< 0)
+					return(exit_status);
+			}
+			if((exit_status = change_buf(current_buf,bufcrosing,buf,dz))!=CONTINUE)
+				return(exit_status);
+			*lastzero = *current_pos_in_buf = 0;
+		}
+	}						
+	return(CONTINUE);
+}
+
+/************************ DO_CYCLE_LOUD **************************/
+
+int do_cycle_loud(float *buf,int cyclecnt,int current_pos_in_buf,int *obufpos,dataptr dz)
+{
+	int loudest = get_loudest_cycle(cyclecnt,dz);
+	dz->lparray[DISTDEL_STARTCYC][cyclecnt] = current_pos_in_buf;
+	return write_cycle(dz->lparray[DISTDEL_STARTCYC][loudest],dz->lparray[DISTDEL_STARTCYC][loudest+1],buf,obufpos,dz);
+}
+
+
+/************************ DO_CYCLE_LOUD_CROSBUF **************************/
+
+int do_cycle_loud_crosbuf
+(int cyclecnt,int current_buf,int current_pos_in_buf,int cycleno_in_group_at_bufcros,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	int loudest;
+	float *buf;
+	loudest = get_loudest_cycle(cyclecnt,dz);
+	dz->lparray[DISTDEL_STARTCYC][cyclecnt] = current_pos_in_buf;
+	if(cycleno_in_group_at_bufcros == loudest) {
+		buf = dz->sampbuf[!current_buf]; /* GO TO PREVIOUS BUFFER */
+		if((exit_status = write_cycle(dz->lparray[DISTDEL_STARTCYC][loudest],dz->buflen,buf,obufpos,dz))<0)
+			return(exit_status);
+		buf = dz->sampbuf[current_buf];
+		exit_status = write_cycle(0L,dz->lparray[DISTDEL_STARTCYC][loudest+1],buf,obufpos,dz);
+	} else if (cycleno_in_group_at_bufcros > loudest) {
+		buf = dz->sampbuf[!current_buf]; /* GO TO PREVIOUS BUFFER */
+		exit_status = write_cycle(dz->lparray[DISTDEL_STARTCYC][loudest],dz->lparray[DISTDEL_STARTCYC][loudest+1],buf,obufpos,dz);
+	} else {
+		buf = dz->sampbuf[current_buf]; /* GO TO PREVIOUS BUFFER */
+		exit_status = write_cycle(dz->lparray[DISTDEL_STARTCYC][loudest],dz->lparray[DISTDEL_STARTCYC][loudest+1],buf,obufpos,dz);
+	}
+	return(exit_status);
+}
+
+/************************ GET_LOUDEST_CYCLE *******************************
+ *
+ * Find loudest cycle.
+ */
+
+int get_loudest_cycle(int cyclecnt,dataptr dz)
+{
+	int /*ffcycle = 0,*/ position = 0;
+	float ffcycle = 0.0;
+	int n;
+	for(n=0;n<cyclecnt;n++) {
+		if(dz->lfarray[DISTDEL_CYCLEVAL][n] > ffcycle) {
+			ffcycle = dz->lfarray[DISTDEL_CYCLEVAL][n];
+			position = n;
+		}
+	}
+	return(position);
+}
+
+/***************************** DO_CYCLE_QUIET *************************/
+
+int do_cycle_quiet(float *buf,int cyclecnt,int current_pos_in_buf,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	int quietest = get_quietest_cycle(cyclecnt,dz);
+	dz->lparray[DISTDEL_STARTCYC][cyclecnt] = current_pos_in_buf;	
+	if((exit_status = write_cycle(dz->lparray[DISTDEL_STARTCYC][0],dz->lparray[DISTDEL_STARTCYC][quietest],buf,obufpos,dz))<0)
+		return(exit_status);
+	return write_cycle(dz->lparray[DISTDEL_STARTCYC][quietest+1],dz->lparray[DISTDEL_STARTCYC][cyclecnt],buf,obufpos,dz);
+}
+
+/************************** DO_CYCLE_QUIET_CROSBUF *************************/
+
+int do_cycle_quiet_crosbuf
+(int cyclecnt,int current_buf,int current_pos_in_buf,int cycleno_in_group_at_bufcros,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	int quietest = get_quietest_cycle(cyclecnt,dz);
+	float *buf;
+	dz->lparray[DISTDEL_STARTCYC][cyclecnt] = current_pos_in_buf;
+	if(cycleno_in_group_at_bufcros == quietest) {
+		buf = dz->sampbuf[!current_buf];
+		if((exit_status = write_cycle(dz->lparray[DISTDEL_STARTCYC][0],dz->lparray[DISTDEL_STARTCYC][quietest],buf,obufpos,dz))<0)
+			return(exit_status);
+		buf = dz->sampbuf[current_buf];
+		exit_status = write_cycle(dz->lparray[DISTDEL_STARTCYC][quietest+1],dz->lparray[DISTDEL_STARTCYC][cyclecnt],buf,obufpos,dz);
+	} else if(cycleno_in_group_at_bufcros > quietest) {
+		buf = dz->sampbuf[!current_buf];
+		if((exit_status = write_cycle(dz->lparray[DISTDEL_STARTCYC][0],dz->lparray[DISTDEL_STARTCYC][quietest],buf,obufpos,dz))<0)
+			return(exit_status);
+		if((exit_status = write_cycle(dz->lparray[DISTDEL_STARTCYC][quietest+1],dz->buflen,buf,obufpos,dz))<0)
+			return(exit_status);
+		buf = dz->sampbuf[current_buf];
+		exit_status = write_cycle(0L,dz->lparray[DISTDEL_STARTCYC][cyclecnt],buf,obufpos,dz);
+	} else {
+		buf = dz->sampbuf[!current_buf];
+		if((exit_status = write_cycle(dz->lparray[DISTDEL_STARTCYC][0],dz->buflen,buf,obufpos,dz))<0)
+			return(exit_status);
+		buf = dz->sampbuf[current_buf];
+		if((exit_status = write_cycle(0L,dz->lparray[DISTDEL_STARTCYC][quietest],buf,obufpos,dz))<0)
+			return(exit_status);
+		exit_status = write_cycle(dz->lparray[DISTDEL_STARTCYC][quietest+1],dz->lparray[DISTDEL_STARTCYC][cyclecnt],buf,obufpos,dz);
+	}
+	return(exit_status);
+}
+
+/************************ GET_QUIETEST_CYCLE *******************************
+ *
+ * Find quietest cycle.
+ */
+
+int get_quietest_cycle(int cyclecnt,dataptr dz)
+{
+//TW FIXED
+//	int quiestest_cycle = dz->lparray[DISTDEL_CYCLEVAL][0], position = 0;
+	float quiestest_cycle = dz->lfarray[DISTDEL_CYCLEVAL][0];
+	int position = 0;
+	
+	int n;
+	for(n=1;n<cyclecnt;n++) {
+		if(dz->lfarray[DISTDEL_CYCLEVAL][n] < quiestest_cycle) {
+			quiestest_cycle = dz->lfarray[DISTDEL_CYCLEVAL][n];
+			position = n;
+		}
+	}
+	return(position);
+}
+
+/***************************** WRITE_CYCLE **********************************/
+
+int write_cycle(int start,int end,float *buf,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	float *obuf = dz->sampbuf[2] + *obufpos;
+	int partoutbuf  = dz->buflen - *obufpos; 	/* FIND HOW MUCH ROOM LEFT IN OUTBUF */
+	int insamps_to_write = end - start;   		/* FIND HOW MANY SAMPLES TO WRITE */
+	int outoverflow;		     				/* IF SAMPS-TO-WRITE WON'T FIT IN OUTBUF */
+	buf  += start;
+	while((outoverflow = insamps_to_write - partoutbuf) > 0) {
+		memmove((char *)obuf,(char *)buf,partoutbuf * sizeof(float));
+		obuf = dz->sampbuf[2];
+		buf += partoutbuf;
+		if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
+			return(exit_status);
+		*obufpos = 0;
+		insamps_to_write = outoverflow;
+		partoutbuf = dz->buflen;
+	}
+	memmove((char *)obuf,(char *)buf,insamps_to_write * sizeof(float));
+	*obufpos += insamps_to_write; 
+	return(CONTINUE);
+}

+ 170 - 0
dev/distort/distflt.c

@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+static int 	is_filtered_out(int cyclecnt,dataptr dz);
+static int 	copy_cycle_to_output(float *b,int endpos,int startpos,int *obufpos,dataptr dz);
+static int 	copy_crosbuf_cycle_to_output(int endpos,int startpos,int current_buf,int *obufpos,dataptr dz);
+
+/************************** DISTORT_FLT **************************/
+
+int distort_flt(int *current_buf,int initial_phase,int *obufpos,int *current_pos_in_buf,dataptr dz)
+{
+	int exit_status;
+	register int i = *current_pos_in_buf;
+	float *b = dz->sampbuf[*current_buf];
+	int cyclelen;
+	int cyclestart = *current_pos_in_buf;
+	int buffer_overrun = FALSE;
+	switch(initial_phase) {
+	case(1):
+		while(b[i]>=0) {
+			if(++i >= dz->ssampsread) {
+				if((exit_status = change_buf(current_buf,&buffer_overrun,&b,dz))!=CONTINUE) {
+					*current_pos_in_buf = i;
+					return(exit_status);
+				}
+				i = 0;
+			}
+		}
+		while(b[i]<=0) {
+			if(++i >= dz->ssampsread) {
+				if((exit_status = change_buf(current_buf,&buffer_overrun,&b,dz))!=CONTINUE) {
+					*current_pos_in_buf = i;
+					return(exit_status);
+				}
+				i = 0;
+			}
+		}
+		break;
+	case(-1):
+		while(b[i]<=0) {
+			if(++i >= dz->ssampsread) {
+				if((exit_status = change_buf(current_buf,&buffer_overrun,&b,dz))!=CONTINUE) {
+					*current_pos_in_buf = i;
+					return(exit_status);
+				}
+				i = 0;
+			}
+		}
+		while(b[i]>=0) {
+			if(++i >= dz->ssampsread) {
+				if((exit_status = change_buf(current_buf,&buffer_overrun,&b,dz))!=CONTINUE) {
+					*current_pos_in_buf = i;
+					return(exit_status);
+				}
+				i = 0;
+			}
+		}
+		break;
+	}
+	cyclelen = i - cyclestart;
+	if(buffer_overrun==TRUE)
+		cyclelen += dz->buflen;
+	exit_status = is_filtered_out(cyclelen,dz);
+	switch(exit_status) {
+	case(TRUE):	 /* ignore this cycle */ 
+		break;	
+	case(FALSE): /*  keep this cycle  */
+		if(buffer_overrun==TRUE)
+			exit_status = copy_crosbuf_cycle_to_output(i,cyclestart,*current_buf,obufpos,dz);
+		else
+			exit_status = copy_cycle_to_output(b,i,cyclestart,obufpos,dz);	
+		break;
+	}
+	if(exit_status<0)
+		return(exit_status);
+	*current_pos_in_buf = i;
+	return(CONTINUE);
+}
+
+/****************************** IS_FILTERED_OUT ****************************/
+
+int is_filtered_out(int cyclelen,dataptr dz)
+{
+	switch(dz->mode) {
+	case(DISTFLT_HIPASS):
+		if(cyclelen>dz->iparam[DISTFLT_LOFRQ_CYCLELEN])
+			return(TRUE);
+		break;
+	case(DISTFLT_LOPASS):
+		if(cyclelen<dz->iparam[DISTFLT_HIFRQ_CYCLELEN])
+			return(TRUE);
+		break;
+	case(DISTFLT_BANDPASS):
+		if(cyclelen<dz->iparam[DISTFLT_HIFRQ_CYCLELEN] || cyclelen>dz->iparam[DISTFLT_LOFRQ_CYCLELEN])
+			return(TRUE);
+		break;
+	default: 
+		sprintf(errstr,"Unknown mode in is_filtered_out()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FALSE);
+}
+
+/**************************** COPY_CYCLE_TO_OUTPUT *****************************/
+
+int copy_cycle_to_output(float *b,int endpos,int startpos,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	while(startpos < endpos) {
+		if((exit_status = output_val(b[startpos++],obufpos,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/************************* COPY_CROSBUF_CYCLE_TO_OUTPUT ****************************/
+
+int copy_crosbuf_cycle_to_output(int endpos,int startpos,int current_buf,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	float *b = dz->sampbuf[!current_buf];
+	while(startpos < dz->buflen) {
+		if((exit_status = output_val(b[startpos++],obufpos,dz))<0)
+			return(exit_status);
+	}
+	b = dz->sampbuf[current_buf];
+	startpos = 0;
+	while(startpos < endpos) {
+		if((exit_status = output_val(b[startpos++],obufpos,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}

+ 298 - 0
dev/distort/distintlv.c

@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+
+static int read_samps_bb(int k,int *bsamps_left,int *sampsread,dataptr dz);
+static int get_initial_phases(float **sampbuf,int *samps_read,int *initial_phase,int *rephase);
+static int get_cycle(int *p,int *q,int n,int *initial_phase,int rephase,int *bsamps_left,int *samps_read,dataptr dz);
+static int write_inverted_block(float *b,int obuf_endwrite,int *obufpos,int *last_read_marker,dataptr dz);
+static int write_this_block(float *b,int samps_to_copy,int obuf_endwrite,int *obufpos,int *last_read_marker,dataptr dz);
+
+/***************************** TWO_INFILES_PROCESS *****************************/
+
+int two_infiles_interleave_process(dataptr dz)
+{
+	int exit_status;
+ 	int bsamps_left[2], samps_read[2];
+ 	int initial_phase[2];
+	int rephase = FALSE;
+	int i1 = 0, i2 = 0, j = 0;
+	bsamps_left[0] = dz->insams[0];
+	bsamps_left[1] = dz->insams[1];
+	if((exit_status = read_samps_bb(0,bsamps_left,samps_read,dz))<0
+	|| (exit_status = read_samps_bb(1,bsamps_left,samps_read,dz))<0)
+		return(exit_status);
+
+	if((exit_status = get_initial_phases(dz->sampbuf,samps_read,initial_phase,&rephase))<0)
+		return(exit_status);
+	switch(dz->mode) {
+	case(DISTINT_INTRLV):
+		do {
+			if((exit_status = get_cycle(&i1,&j,0,initial_phase,rephase,bsamps_left,samps_read,dz))!=CONTINUE)
+				break;
+			exit_status = get_cycle(&i2,&j,1,initial_phase,rephase,bsamps_left,samps_read,dz);
+		} while(exit_status==CONTINUE);
+		break;
+	default:
+		sprintf(errstr,"Unknown case in two_infiles_interleave_process()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(exit_status<0)
+		return(exit_status);
+	if(j > 0)
+		return write_samps(dz->sampbuf[2],j,dz);
+	return FINISHED;
+}
+
+/**************************** READ_SAMPS_BB ****************************/
+
+int read_samps_bb(int k,int *bsamps_left,int *samps_read,dataptr dz)
+{
+	int /*bytes_read*/sampsread;
+	if(( sampsread = fgetfbufEx(dz->sampbuf[k], dz->buflen,dz->ifd[k],0)) < 0) {
+		sprintf(errstr, "Can't read from input soundfile %d\n",k+1);
+		return(SYSTEM_ERROR);
+	}
+	bsamps_left[k] -= sampsread;
+	if(sloom)
+		dz->total_samps_read = (bsamps_left[0] + bsamps_left[1]) >> 1;
+	samps_read[k]   = sampsread;
+	return(FINISHED);
+}
+
+/********************************** GET_CYCLE ******************************/
+
+int get_cycle(int *p,int *q,int n,int *initial_phase,int rephase,int *bsamps_left,int *samps_read,dataptr dz)
+{
+	int exit_status;
+	int   startphase  = initial_phase[n];
+	float *b          = dz->sampbuf[n];
+	int  samples     = samps_read[n];
+	int  samps_to_copy, obuf_endwrite;
+	register int ibufpos = *p;				
+	int obufpos = *q;
+	int  last_read_marker = ibufpos;				
+	int   in_1st_half_of_cycle = TRUE, OK = TRUE;
+	switch(startphase) {					
+	case(1):
+		while(b[ibufpos]>=0) {
+			if(++ibufpos >= samples) {
+				OK = FALSE;
+				break;
+			}
+		}
+		if(!OK)
+			break;
+		in_1st_half_of_cycle = FALSE;
+		while(b[ibufpos]<=0) {
+			if(++ibufpos >= samples)
+				break;
+		}
+		break;
+	case(-1):
+		while(b[ibufpos]<=0)	{
+			if(++ibufpos >= samples) {
+				OK = FALSE;
+				break;
+			}
+		}
+		if(!OK)
+			break;
+		in_1st_half_of_cycle = FALSE;
+		while(b[ibufpos]>=0) {
+			if(++ibufpos >= samples)
+				break;
+		}
+		break;
+	}
+	samps_to_copy = ibufpos - last_read_marker;	  /* may be only PART of cycle, if end of input buf was encountered */
+	obuf_endwrite = obufpos + samps_to_copy;
+	if(n==1 && rephase)		/* if this is 2nd snd, and phase is different from 1st snd, invert all vals */
+		exit_status = write_inverted_block(b,obuf_endwrite,&obufpos,&last_read_marker,dz);
+	else 							
+		exit_status = write_this_block(b,samps_to_copy,obuf_endwrite,&obufpos,&last_read_marker,dz);
+
+	if(exit_status < 0)
+		return(exit_status);
+		
+	if(ibufpos>=samples) {	 		/* if we reached input buffer end */
+		if(bsamps_left[n] <= 0) {	/* if we reached file end */
+			*q = obufpos;
+			return(FINISHED);
+		}							/* else, deal with part-cycle in next buffer */
+		read_samps_bb(n,bsamps_left,samps_read,dz);
+		last_read_marker = 0;
+		ibufpos  		 = 0;
+		switch(startphase) {
+		case(1):
+			if(in_1st_half_of_cycle)  {
+				while(b[ibufpos]>=0) {
+					if(++ibufpos >= dz->buflen) {
+						sprintf(errstr,"Cyclelen exceeeds buffer_size: cannot proceed\n");
+						return(GOAL_FAILED);
+					}
+				}
+			}
+			while(b[ibufpos]<=0) {
+				if(++ibufpos >= dz->buflen) {
+					sprintf(errstr,"Cyclelen exceeeds buffer_size: cannot proceed\n");
+					return(GOAL_FAILED);
+				}
+			}
+			break;
+		case(-1):
+			if(in_1st_half_of_cycle) {
+				while(b[ibufpos]<=0) {
+					if(++ibufpos >= dz->buflen) {
+						sprintf(errstr,"Cyclelen exceeeds buffer_size: cannot proceed\n");
+						return(GOAL_FAILED);
+					}
+				}
+			}
+			while(b[ibufpos]>=0) {
+				if(++ibufpos >= dz->buflen) {
+					sprintf(errstr,"Cyclelen exceeeds buffer_size: cannot proceed\n");
+					return(GOAL_FAILED);
+				}
+			}
+			break;
+		}
+		samps_to_copy = ibufpos;
+		obuf_endwrite = obufpos + samps_to_copy;   
+		if(n==1 && rephase)
+			exit_status = write_inverted_block(b,obuf_endwrite,&obufpos,&last_read_marker,dz);
+		else 							
+			exit_status = write_this_block(b,samps_to_copy,obuf_endwrite,&obufpos,&last_read_marker,dz);
+	
+		if(exit_status < 0)
+			return(exit_status);
+	}
+	*p = ibufpos;
+	*q = obufpos;
+	return(CONTINUE);
+}
+
+/*************************** GET_INITIAL_PHASES **********************/
+
+int get_initial_phases(float **sampbuf,int *samps_read,int *initial_phase,int *rephase)
+{
+	int bufpos = 0;
+//TW CHANGED
+	while(smpflteq(sampbuf[0][bufpos],0.0) && bufpos < samps_read[0])   
+		bufpos++;
+	if(bufpos >= samps_read[0]) {
+		sprintf(errstr,"No siginificant data in first buffer of file 1\n");
+		return(DATA_ERROR);
+	}
+	if(sampbuf[0][bufpos] > 0)   
+		initial_phase[0] = 1; 
+	else 
+		initial_phase[0] = -1;
+	bufpos = 0;
+//TW CHANGED
+	while(smpflteq(sampbuf[1][bufpos],0.0) && bufpos < samps_read[1])   
+		bufpos++;
+	if(bufpos >= samps_read[1]) {
+		sprintf(errstr,"No siginificant data in first buffer of file 2\n");
+		return(DATA_ERROR);
+	}
+	if(sampbuf[1][bufpos] > 0)   
+		initial_phase[1] = 1; 
+	else 
+		initial_phase[1] = -1;
+	if(initial_phase[0] != initial_phase[1])
+		*rephase = TRUE;
+	return(FINISHED);
+}
+
+/*************************** WRITE_INVERTED_CYCLE **********************/
+
+int write_inverted_block(float *b,int obuf_endwrite,int *obufpos,int *last_read_marker,dataptr dz)
+{
+	int exit_status;
+	int outremain = obuf_endwrite - dz->buflen;
+	register int i = *obufpos;
+	register int j = *last_read_marker;
+	if(outremain>0) {
+		while(i<dz->buflen) 
+			dz->sampbuf[2][i++] = (float) -b[j++];	   /*RWD  added cast, also below */
+		if((exit_status = write_samps(dz->sampbuf[2],dz->buflen,dz))<0) {
+			sprintf(errstr,"Failed to write samps in write_inverted_block()\n");
+			return(SYSTEM_ERROR);
+		}
+		i = 0;
+		while(i<outremain) 	
+			dz->sampbuf[2][i++] = (float)  -b[j++];
+	} else {
+		while(i<obuf_endwrite) 	
+			dz->sampbuf[2][i++] = (float) -b[j++];
+	}
+	*obufpos = i;
+	*last_read_marker = j;
+	return(FINISHED);
+}
+
+/*************************** WRITE_THIS_CYCLE **********************/
+
+int write_this_block(float *b,int samps_to_copy,int obuf_endwrite,int *obufpos,int *last_read_marker,dataptr dz)
+{
+	int exit_status;
+	int outremain = obuf_endwrite - dz->buflen;
+	int part_writelen;
+	if(outremain > 0) {
+		part_writelen = dz->buflen - *obufpos;
+		memmove((char *)(dz->sampbuf[2] + *obufpos),(char *)(b + *last_read_marker),part_writelen * sizeof(float));
+		if((exit_status = write_samps(dz->sampbuf[2],dz->buflen ,dz))<0) {
+			sprintf(errstr,"Failed to write samps in write_this_block()\n");
+			return(SYSTEM_ERROR);
+		}
+		*last_read_marker += part_writelen;
+		samps_to_copy     -= part_writelen;
+		memmove((char *)(dz->sampbuf[2]),(char *)(b + *last_read_marker),samps_to_copy * sizeof(float));
+		*obufpos = outremain;
+		*last_read_marker += samps_to_copy;
+	} else {
+		memmove((char *)(dz->sampbuf[2] + *obufpos),(char *)(b + *last_read_marker),samps_to_copy * sizeof(float));
+		*obufpos = obuf_endwrite;
+		*last_read_marker += samps_to_copy;
+	}
+	return FINISHED;		/*RWD*/
+}

+ 734 - 0
dev/distort/distort.c

@@ -0,0 +1,734 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+#if defined unix || defined __GNUC__
+#define round lround
+#endif
+
+//TW COMMENT : phase as used here, with vals >1 or <-1 (meaning above zero or below zero) in intrinsically 'int' 
+//             phase is also not 'float' elsewhere, 
+//			   To avoid the construction "switch((int)phase)", I've made phase 'int' everywhere, casting in situ where ness.
+
+//static int 	distort_func(float *b,int tthis,int i,float phase,int lastzero,float cyclemax,dataptr dz);
+static int 	distort_func(float *b,int tthis,int i,int phase,int lastzero,float cyclemax,dataptr dz);
+//static int 	distort_func_crosbuf(int tthis,int i,float phase,int lastzero,float cyclemax,int oldbufcnt,dataptr dz);
+static int 	distort_func_crosbuf(int tthis,int i,int phase,int lastzero,float cyclemax,int oldbufcnt,dataptr dz);
+static int 	sinusoid(int tthis,int lastzero,float cyclemax,int endcycle,dataptr dz);
+static int 	end_sinusoid(int tthis,int lastzero,float cyclemax,int newbufcnt,int oldbufcnt,dataptr dz);
+static int 	genpulse(int step,float maxamp,float *bufptr,float *bufend);
+static int 	triangle(float *b,int lastzero,float cyclemax,int endcycle);
+static int 	end_triangle(int tthis,int lastzero,float cyclemax,int newbufcnt,int oldbufcnt,dataptr dz);
+//static int 	exaggerate(int lastzero,int thiszero,float phase,float *b,double powfac);
+static int 	exaggerate(int lastzero,int thiszero,int phase,float *b,double powfac);
+static int 	do_exagg
+			(double lastmax,int lastpos,double thismax,int thispos,double powfac,float *b);
+//static int 	do_exagg2(float phase,int lastpos,int thispos,double powfac,float *b);
+static int 	do_exagg2(int phase,int lastpos,int thispos,double powfac,float *b);
+//static int 	end_exagg(int tthis,int lastzero,int newbufcnt,int oldbufcnt,double powfac,float phase,dataptr dz);
+static int 	end_exagg(int tthis,int lastzero,int newbufcnt,int oldbufcnt,double powfac,int phase,dataptr dz);
+static int 	get_powfac(int lastzero,int thiszero,dataptr dz);
+
+/************************* DO_DISTORT ***********************************
+ *
+ * Works on SINGLE HALF wavecycles.
+ *
+ * This looks for single half-wavecycles, and does not change there
+ * number (or their phase) in the output. It therefore resets the
+ * input & output phase on each entry.
+ */								   
+
+int do_distort(int tthis,int is_last,int *lastzero,float *cyclemax,dataptr dz)
+{
+	int exit_status;
+	register int i = *lastzero;
+	int	oldbufcnt, lastmarker;
+	int 	phase = 1;	   
+	float 	*b 	    = dz->sampbuf[tthis];
+	int 	samples = dz->buflen;
+	if(is_last)
+		samples  = dz->ssampsread;
+//TW CHANGED
+	while(smpflteq(b[i],0.0) && i<samples)
+		i++;
+	lastmarker = i;
+	if(b[i]<0)
+		phase  = -1;
+	while(i < samples)  {				
+		switch(phase) {
+		case(1):	    
+			if(b[i] > 0) {
+				if(b[i]>*cyclemax)
+					*cyclemax=b[i];
+				i++;
+			} else {
+				if((exit_status = distort_func(b,tthis,i,phase,*lastzero,*cyclemax,dz))<0)
+					return(exit_status);
+				i = lastmarker = reset(i,samples,b,lastzero,cyclemax);
+				if(b[i]<0)
+					phase=-1;
+			}
+			break;
+		case(-1):
+			if(b[i] < 0) {
+				if(b[i]<*cyclemax)
+					*cyclemax=b[i];
+				i++;
+			} else {
+				if((exit_status = distort_func(b,tthis,i,phase,*lastzero,*cyclemax,dz))<0)
+					return(exit_status);
+				i = lastmarker = reset(i,samples,b,lastzero,cyclemax);
+				if(b[i]>0)
+					phase=1;
+			}
+			break;
+		}
+	}
+	if(!is_last) {
+		oldbufcnt = dz->buflen - *lastzero;
+		b = dz->sampbuf[!tthis];
+		samples = dz->ssampsread;
+		i = 0;
+		switch(phase) {
+		case(1):	    
+			while(i < samples)  {
+				if(b[i]>0) {
+					if(b[i]>*cyclemax)
+						*cyclemax = b[i];
+					i++;
+				} else
+					break;
+			}
+			break;
+		case(-1):
+			while(i < samples)  {
+				if(b[i]<0) {
+					if(b[i]<*cyclemax)
+						*cyclemax = b[i];
+					i++;
+				} else
+					break;
+			}
+			break;
+		}
+		if((exit_status = distort_func_crosbuf(tthis,i,phase,*lastzero,*cyclemax,oldbufcnt,dz))<0)
+			return(exit_status);
+		i = lastmarker = reset(i,samples,dz->sampbuf[!tthis],lastzero,cyclemax);
+	}
+	return(FINISHED);
+}
+
+/*************************** DISTORT_FUNC ******************************/
+
+int distort_func(float *b,int tthis,int i,int phase,int lastzero,float cyclemax,dataptr dz)
+{
+	int exit_status;
+	register int j;
+	int halfcycle, step;
+	float	 clipmax;
+	switch(dz->mode) {
+	case(DISTORT_SQUARE_FIXED):
+		clipmax = FCLIPMAX * (float)phase;
+		for(j=lastzero;j<i;j++)
+			b[j]=clipmax;			/* 4 */
+		break;
+	case(DISTORT_SQUARE):
+		for(j=lastzero;j<i;j++)
+			b[j]=cyclemax;
+		break;
+	case(DISTORT_TRIANGLE_FIXED):
+		clipmax = FCLIPMAX * (float)phase;
+		if(i - lastzero > 3) {
+			if((exit_status = triangle(b,lastzero,clipmax,i))<0)
+				return(exit_status);
+		}
+		break;
+	case(DISTORT_TRIANGLE):
+		if(i - lastzero > 3) {
+			if((exit_status = triangle(b,lastzero,cyclemax,i))<0)
+				return(exit_status);
+		}
+		break;
+	case(DISTORT_INVERT_HALFCYCLE):
+		for(j=lastzero;j<i;j++)
+			b[j]=cyclemax - b[j];
+		break;
+	case(DISTORT_CLICK):
+		halfcycle = i - lastzero;
+		step = min((int)dz->iparam[DISTORT_PULSE],halfcycle);
+		if((exit_status = genpulse(step,cyclemax,b+lastzero,b+i))<0)
+			return(exit_status);
+		break;
+	case(DISTORT_SINE):
+		if(i - lastzero > 5) {
+			if((exit_status = sinusoid(tthis,lastzero,cyclemax,i,dz))<0)
+				return(exit_status);
+		}
+		break;
+	case(DISTORT_EXAGG):
+		if(dz->brksize[DISTORT_POWFAC] && (exit_status = get_powfac(lastzero,i,dz))<0)
+			return(exit_status);
+		if((exit_status = exaggerate(lastzero,i,phase,dz->sampbuf[tthis],dz->param[DISTORT_POWFAC]))<0)
+			return(exit_status);
+		break;
+	default:
+		sprintf(errstr,"Unknown case in distort_func()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/************************ DISTORT_FUNC_CROSBUF **********************/
+
+int distort_func_crosbuf(int tthis,int i,int phase,int lastzero,float cyclemax,int oldbufcnt,dataptr dz)
+{
+	int exit_status;
+	register int j;
+	int end_bit, halfcycle, step;
+	float *buf = dz->sampbuf[tthis];
+	/*int*/float clipmax;
+	switch(dz->mode) {
+	case(DISTORT_SQUARE_FIXED):
+		clipmax = (float)(FCLIPMAX * (float)phase);
+		for(j=lastzero;j<dz->buflen; j++)
+			buf[j] = clipmax;
+		buf = dz->sampbuf[!tthis];
+		for(j=0;j<i;j++)
+			buf[j] = clipmax;
+		break;
+	case(DISTORT_SQUARE):
+		for(j=lastzero;j<dz->buflen; j++)
+			buf[j] = cyclemax;
+		buf = dz->sampbuf[!tthis];
+		for(j=0;j<i;j++)	      
+			buf[j] = cyclemax;
+		break;
+	case(DISTORT_TRIANGLE_FIXED):
+		clipmax = (float)(FCLIPMAX * (float)phase);
+		if(oldbufcnt + i > 3) {
+			if((exit_status = end_triangle(tthis,lastzero,clipmax,i,oldbufcnt,dz))<0)
+				return(exit_status);
+		}
+		break;
+	case(DISTORT_TRIANGLE):
+		if(oldbufcnt + i > 3) {
+			if((exit_status = end_triangle(tthis,lastzero,cyclemax,i,oldbufcnt,dz))<0)
+				return(exit_status);
+		}
+		break;
+	case(DISTORT_INVERT_HALFCYCLE):
+		for(j=lastzero;j<dz->buflen; j++) 
+			buf[j] = cyclemax - buf[j];
+		buf = dz->sampbuf[!tthis];
+		for(j=0;j<i;j++)	      
+			buf[j] = cyclemax - buf[j];
+		break;
+	case(DISTORT_CLICK):
+		end_bit = dz->buflen - lastzero;
+		halfcycle = i + end_bit;
+		step = min((int)dz->iparam[DISTORT_PULSE],halfcycle);
+		if(step > end_bit) {
+			if((exit_status = genpulse(end_bit,cyclemax,buf+lastzero,buf+dz->buflen))<0)
+				return(exit_status);
+			buf = dz->sampbuf[!tthis];
+			if((exit_status = genpulse(step - end_bit,cyclemax,buf,buf+i))<0)
+				return(exit_status);
+		} else {
+			if((exit_status = genpulse(end_bit,cyclemax,buf + lastzero,buf + dz->buflen))<0)
+				return(exit_status);
+			buf = dz->sampbuf[!tthis];
+			if((exit_status = genpulse(0,cyclemax,buf,buf+i))<0)
+				return(exit_status);
+		}
+		break;
+	case(DISTORT_SINE):
+		if(oldbufcnt + i > 5) {
+			if((exit_status = end_sinusoid(tthis,lastzero,cyclemax,i,oldbufcnt,dz))<0)
+				return(exit_status);
+		}
+		break;
+	case(DISTORT_EXAGG):
+		if(dz->brksize[DISTORT_POWFAC] && (exit_status = get_powfac(lastzero,dz->buflen+i,dz))<0)
+			return(exit_status);
+		if((exit_status = end_exagg(tthis,lastzero,i,oldbufcnt,dz->param[DISTORT_POWFAC],phase,dz))<0)
+			return(exit_status);
+		break;
+	default:
+		sprintf(errstr,"Unknown case in distort_func_crosbuf()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/***************************** SINUSOID ******************************
+ *
+ * Create sinusoidal half-wave, over half-cycle.
+ */
+
+int sinusoid(int tthis,int lastzero,float cyclemax,int endcycle,dataptr dz)
+{
+	float *bb          = dz->sampbuf[tthis]; 
+	int i, j, start   = lastzero;					/* 1 */
+	int half_cyclecnt = endcycle - lastzero;		/* 2 */
+	double index_factor = (double)SINETABLEN/(double)half_cyclecnt;
+	for(j=start, i=0; j<endcycle; j++, i++)
+		bb[j] = /*round*/(float) (dz->parray[DISTORT_SIN][round(i * index_factor)] * cyclemax);
+	return(FINISHED);
+}
+
+/*********************** END_SINUSOID ***************************/
+
+int end_sinusoid(int tthis,int lastzero,float cyclemax,int newbufcnt,int oldbufcnt,dataptr dz)
+{
+	float *bb           = dz->sampbuf[tthis];
+	int i, j, start    = lastzero;
+	int half_cyclecnt  = oldbufcnt + newbufcnt;
+	double index_factor = (double)SINETABLEN/(double)half_cyclecnt;
+	for(j=start, i=0; j<dz->buflen; j++,i++)
+		bb[j] = /*round*/(float)(dz->parray[DISTORT_SIN][round(i * index_factor)] * cyclemax);
+	bb = dz->sampbuf[!tthis];
+	for(j=0; j<newbufcnt; j++, i++)
+		bb[j] = /*round*/(float)(dz->parray[DISTORT_SIN][round(i * index_factor)] * cyclemax);
+	return(FINISHED);
+}
+
+/***************************** GENPULSE ****************************/
+
+int genpulse(int step,float maxamp,float *bufptr,float *bufend)
+{
+	int n, m, z, sum = 0;
+	float ampval =  maxamp;
+	while(sum < step) {
+		n = round(drand48() * MAXWIDTH);	  /* TRUNCATE */
+		n++;
+		sum += n;
+		z = min(n,step-sum);
+		for(m=0;m<z;m++)
+			*bufptr++ = ampval;
+		ampval = -ampval;
+	}
+	while(bufptr<bufend)
+		*bufptr++ = 0;
+	return(FINISHED);
+}
+
+/***************************** TRIANGLE ******************************
+ *
+ * Create triangular half-wave, over half-cycle.
+ *
+ * (0)	Samples values calculated as reals, then approxd to integers.
+ * (1)	establish start of loop after initial sample (set to zero).
+ * (2)  'half_cyclecnt' is number of samples in the half_cycle.
+ * 	'halfcnt' is count to mid-point of triangle form.
+ * (3)	establish midpoint of half_cycle.
+ * (4)	Set initial sample to zero.
+ * (5)	Calculate real increment(decrement) to create triangular form.
+ * (6)	Create triangle from start to middle.
+ * (7)	For even number of samples in half-cycle, add extra peak sample.
+ * (8) 	Create middle sample of triangle.
+ * (9)	Create triangle from middle to end.
+ */
+
+int triangle(float *b,int lastzero,float cyclemax,int endcycle)
+{
+	double realval = 0.0, step;						/* 0 */
+	int start     = lastzero+1;					/* 1 */
+	int half_cyclecnt = endcycle - lastzero;		/* 2 */
+	int halfcnt   = (half_cyclecnt+1)/2;
+	int middle    = lastzero + halfcnt; 			/* 3 */
+	int j;
+	b[lastzero] = 0;								/* 4 */
+	step = (double)cyclemax/(double)halfcnt;		/* 5 */
+	for(j=start; j<middle; j++) {
+		realval += step;							/* 6 */
+		b[j]    = (float)realval;
+	}
+	if(EVEN(half_cyclecnt))
+		realval += step;							/* 7 */
+	b[middle] = (float)/*round*/(realval);				/* 8 */
+	for(j=middle+1; j<endcycle; j++) {
+		realval -= step;							/* 9 */
+		b[j]     = (float)realval;
+	}
+	return(FINISHED);
+}
+
+/*********************** END_TRIANGLE ***************************
+ *
+ * (0)	Sample values calculated as reals, then approximated to integers.
+ * (1)	half_cycle is now that counted in original buffer, plus the part
+ *	counted into the next buffer (newbufcnt).
+ * (1a)	The count as far as middle of half-cycle.
+ * (1b)	middle = actual sample index of midpoint of half-cycle.
+ * (1c) Set inital sample of half-cycle to a zero.
+ * (1d) calculate the increment (=decrement) to create triangle wave.
+ * (2)  If midpoint of triangle is in ORIGINAL buffer...
+ * (3)	..create values from start to middle,
+ * (A)  ..if half_cycle has even number of samples, get extra peak value.
+ * (5)  ..put in middle value.
+ * (6)	..create values from middle to end of buf.
+ * (7)	..switch to other buf.
+ * (8)	..create values from start of new buf, to end of triangle.
+ * (9)  Else, midpoint of triangle is in OTHER buffer...
+ * (10)	..create values from start to end of buffer.
+ * (11)	..decrement location of middle by size of original buffer.
+ * (12)	..switch to other buf.
+ * (13)	..create values from start of new buf, to middle of triangle.
+ * (14) ..if half_cycle has even number of samples, get extra peak value.
+ * (15) ..put in middle value.
+ * (16)	..create values from middle to end of triangle.
+ */
+
+int end_triangle(int tthis,int lastzero,float cyclemax,int newbufcnt,int oldbufcnt,dataptr dz)
+{
+	double realval = 0.0, step;					/* 0 */
+	int start     = lastzero+1;
+	int half_cyclecnt  = oldbufcnt + newbufcnt;/* 1 */
+	int halfcnt   = (half_cyclecnt+1)/2;		/* 1a */
+	int middle    = lastzero + halfcnt;		/* 1b */
+	int j;
+	float *b = dz->sampbuf[tthis];
+	b[lastzero] = 0.0;							/* 1c */
+	step = (double)cyclemax/(double)(halfcnt);
+	if(middle < dz->buflen) {					/* 2 */
+		for(j=start; j<middle; j++) {
+			realval += step;					/* 3 */
+			b[j]    = (float)realval;
+		}
+		if(EVEN(half_cyclecnt))					/* A */
+			realval += step;
+		b[middle] = (float)realval;				/* 5 */
+		for(j=middle+1; j<dz->buflen; j++) {
+			realval -= step;					/* 6 */
+			b[j]    = (float)realval;
+		}
+		b = dz->sampbuf[!tthis];				/* 7 */
+		for(j=0; j<newbufcnt; j++) {
+			realval -= step;					/* 8 */
+			b[j]    = (float)realval;
+		}
+	} else {									/* 9 */
+		for(j=start; j<dz->buflen; j++) {
+			realval += step;					/* 10 */
+			b[j]    = (float)realval;
+		}
+		middle -= dz->buflen;					/* 11 */
+		b = dz->sampbuf[!tthis];				/* 12 */
+		for(j=0; j<middle; j++) {
+			realval += step;					/* 13 */
+			b[j]    = (float)realval;
+		}
+		if(EVEN(half_cyclecnt))					/* 14 */
+			realval += step;
+		b[middle] = (float)realval;				/* 15 */
+		for(j=middle+1; j<newbufcnt; j++) {
+			realval -= step;					/* 16 */
+			b[j]     = (float)realval;
+		}
+	}
+	return(FINISHED);
+}
+
+/************************** RESET ******************************
+ *
+ * (9)	Reset lastzero, marking state of new (half)wavecycle.
+ * (10) Skip any zero samples : drop out if end of samples in buffer reached.
+ * (11)	Reset maximum sample in halfcycle to mimimum (zero).
+ * (12) Return first NON-ZERO sample.
+ */
+
+int reset(int i,int samples,float *bbuf,int *lastzero,float *cyclemax)
+{
+	*lastzero = i;						/* 9 */
+	while(bbuf[i]==0.0 && i < samples)	/* 10 */
+		i++;
+	*cyclemax=0.0;						/* 11 */
+	return(i);							/* 12 */
+}
+
+/****************************** EXAGGERATE *******************************/
+
+int exaggerate(int lastzero,int thiszero,int phase,float *b,double powfac)
+{
+	int exit_status;
+	int n = lastzero + 1;
+	double lastmax, thismax, thismin;
+	int   lastpos, thispos, minpos;
+	int OK = 1;
+	switch(phase) {
+	case(1):
+		while(b[n] >= b[n-1])
+			n++;
+		lastmax = (double)b[n-1];
+		lastpos = n-1;
+		if(powfac < 0.0)
+			exit_status = do_exagg2(phase,lastzero+1,lastpos,powfac,b);
+		else
+			exit_status = do_exagg2(phase,lastzero,lastpos,powfac,b);
+		if(exit_status < 0)
+			return(exit_status);
+		while(n < thiszero) {
+			while(b[n] < b[n-1]) {
+				if(++n >= thiszero) {
+					OK = 0;
+					break;
+				}
+			}
+			if(OK) {
+				thismin = (double)b[n-1];
+				minpos  = n-1;
+				while(b[n] >= b[n-1])
+					n++;
+				thismax = (double)b[n-1];
+				thispos = n-1;
+				if((exit_status = do_exagg(lastmax,lastpos,thismax,thispos,powfac,b))<0)
+					return(exit_status);
+				lastmax = thismax;
+				lastpos = thispos;
+			} else
+				break;
+		}
+		if(powfac < 0.0)
+			exit_status = do_exagg2(phase,lastpos+1,n-1,powfac,b);
+		else
+			exit_status = do_exagg2(phase,lastpos,n-1,powfac,b);
+		if(exit_status < 0)
+			return(exit_status);
+		break;
+	case(-1):
+		while(b[n] <= b[n-1])
+			n++;
+		lastmax = (double)b[n-1];
+		lastpos = n-1;
+		if(powfac < 0.0)
+			exit_status = do_exagg2(phase,lastzero+1,lastpos,powfac,b);
+		else
+			exit_status = do_exagg2(phase,lastzero,lastpos,powfac,b);
+		if(exit_status < 0)
+			return(exit_status);
+		while(n < thiszero) {
+			while(b[n] > b[n-1]) {
+				if(++n >= thiszero) {
+					OK = 0;
+					break;
+				}
+			}
+			if(OK) {
+				thismin = (double)b[n-1];
+				minpos  = n-1;
+				while(b[n] <= b[n-1])
+					n++;
+				thismax = (double)b[n-1];
+				thispos = n-1;
+				if((exit_status = do_exagg(lastmax,lastpos,thismax,thispos,powfac,b))<0)
+					return(exit_status);
+				lastmax = thismax;
+				lastpos = thispos;
+			} else
+				break;
+		}
+		if(powfac < 0.0)
+			exit_status = do_exagg2(phase,lastpos+1,n-1,powfac,b);
+		else
+			exit_status = do_exagg2(phase,lastpos,n-1,powfac,b);
+		if(exit_status < 0)
+			return(exit_status);
+		break;
+	}
+	return(FINISHED);
+}
+
+/****************************** DO_EXAGG ******************************/
+
+int do_exagg
+(double lastmax,int lastpos,double thismax,int thispos,double powfac,float *b)
+{
+	double maxdif = thismax - lastmax;
+	double posdif = thispos - lastpos;
+	double local_max, rati_o;
+	int n, m;
+	for(n = lastpos+1, m = 1; n<thispos; n++, m++) {
+		local_max = lastmax + (maxdif * (double)m/posdif);
+		rati_o    = min(((double)b[n]/local_max),1.0);
+		rati_o    = pow(rati_o,powfac);
+		b[n] 	  = (float)/*round*/((double)b[n] * rati_o);
+	}
+	return(FINISHED);
+}
+
+/*************************** DO_EXAGG2 *******************************/
+
+int do_exagg2(int phase,int lastpos,int thispos,double powfac, float *b)
+{
+	int n;
+	double val, valdiff = (double)max(fabs(b[lastpos]),fabs(b[thispos]));
+	for(n = lastpos; n<=thispos; n++) {
+		val  = (double)b[n]/valdiff;
+		val *= (float)phase;
+		val  = pow(val,powfac);
+		val *= valdiff * (float)phase;
+		b[n] = (float)/*round*/(val);
+	}
+	return(FINISHED);
+}
+
+/************************ END_EXAGG *******************************/
+
+int end_exagg(int tthis,int lastzero,int newbufcnt,int oldbufcnt,double powfac,int phase,dataptr dz)
+{   
+	float *bold  = dz->sampbuf[tthis] + lastzero;
+    float *bnew  = dz->sampbuf[!tthis];
+    float *btemp = dz->sampbuf[2];
+    memmove((char *)btemp,(char *)bold,oldbufcnt * sizeof(float));
+    btemp += oldbufcnt;				
+    memmove((char *)btemp,(char *)bnew,newbufcnt * sizeof(float));
+    exaggerate(0,oldbufcnt+newbufcnt,phase,dz->sampbuf[2],powfac);
+
+    btemp = dz->sampbuf[2];			/* copy the transformed material back to where it came from */
+    memmove((char *)bold,(char *)btemp,oldbufcnt * sizeof(float));
+    btemp += oldbufcnt;
+    memmove((char *)bnew,(char *)btemp,newbufcnt * sizeof(float));
+	return(FINISHED);
+}
+
+/************************ GET_POWFAC *******************************/
+
+int get_powfac(int lastzero,int thiszero,dataptr dz)
+{
+	double thistime;
+	thistime  = (double)(dz->total_samps_read - dz->ssampsread - dz->buflen); 	/* START OF BUF IN USE */
+	thistime += ((double)(thiszero + lastzero)/2.0);  			/* MEAN OFFSET OF CYCLE IN CURRENT BUF */
+	thistime /= (double)dz->infile->srate;
+	return read_value_from_brktable(thistime,DISTORT_POWFAC,dz);
+}
+
+//TW UPDATE : NEW FUNCTION
+/************************ DISTORT_OVERLOAD *******************************/
+
+// NOV 2002: NEED TO FIX buffers to float, MAXSAMP to F_MAXSAP, (short) to THINGY!!
+int distort_overload(dataptr dz)
+{
+	int exit_status, n;
+//	short *buf;
+	float *buf;
+	double *tab = NULL;
+	double maxgate, mingate, inc_ratio, time = 0.0, timestep = 0.01, tabposd = 0.0, normaliser, k;
+	int stepper, tabpos = 0, in_maxgate = 0, in_mingate = 0;
+
+	buf = dz->sampbuf[0];
+	if(dz->mode==OVER_SINE)
+		tab = dz->parray[0];
+	maxgate = dz->param[DISTORTER_MULT];
+	mingate = -maxgate;
+	inc_ratio = (double)DISTORTER_TABLEN/(double)dz->infile->srate;
+	stepper = (int)round((double)dz->infile->srate * timestep);
+	normaliser = ((double)F_MAXSAMP/(maxgate + 1.0)) /* TEST * 0.9 */;
+
+//	while(dz->bytes_left > 0) {
+	while(dz->samps_left > 0) {
+//		if((exit_status = read_bytes((char *)dz->bigbuf,dz))<0)
+		if((exit_status = read_samps(dz->bigbuf,dz))<0)
+			return(exit_status);
+		switch(dz->mode) {
+		case(OVER_NOISE):
+			for(n=0;n<dz->ssampsread;n++) {
+				if(!(n%stepper)) {
+					if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
+						return(exit_status);
+					time += timestep;
+				}
+				if((double)buf[n] >= maxgate) {
+					k = 1.0 - (drand48() * dz->param[DISTORTER_DEPTH]);
+//					buf[n] = (short)round(k * maxgate);
+					buf[n] = (float)(k * maxgate);
+				} else if((double)buf[n] <= mingate) {
+					k = 1.0 - (drand48() * dz->param[DISTORTER_DEPTH]);
+//					buf[n] = (short)round(k * mingate);
+					buf[n] = (float)(k * mingate);
+				}
+//				buf[n] = (short)round(buf[n] * normaliser);	
+				buf[n] = (float)(buf[n] * normaliser);	
+			}
+			break;
+		case(OVER_SINE):
+			for(n=0;n<dz->ssampsread;n++) {
+				if(!(n%stepper)) {
+					if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
+						return(exit_status);
+					time += timestep;
+				}
+				if((double)buf[n] >= maxgate) {
+					if(!in_maxgate) {
+						tabpos = 0;
+						tabposd = 0.0;
+						in_mingate = 0;
+						in_maxgate = 1;
+					}
+					k = 1.0 + (tab[tabpos] * dz->param[DISTORTER_DEPTH]);
+//					buf[n] = (short)round(k * maxgate); 
+					buf[n] = (float)(k * maxgate); 
+				} else if((double)buf[n] <= mingate) {
+					if(!in_mingate)	{
+						tabpos = 0;
+						tabposd = 0.0;
+						in_maxgate = 0;
+						in_mingate = 1;
+					}
+					k = 1.0 + (tab[tabpos] * dz->param[DISTORTER_DEPTH]);
+//					buf[n] = (short)round(k * mingate);
+					buf[n] = (float)(k * mingate);
+				} else {
+					in_maxgate = 0;
+					in_mingate = 0;
+				}
+//				buf[n] = (short)round(buf[n] * normaliser);
+				buf[n] = (float)(buf[n] * normaliser);
+				tabposd = fmod(tabposd + (dz->param[DISTORTER_FRQ] * inc_ratio),(double)DISTORTER_TABLEN);
+				tabpos = round(tabposd) % DISTORTER_TABLEN;
+			}
+			break;
+		}
+		if(dz->ssampsread > 0) {
+			if((exit_status = write_samps(dz->bigbuf,dz->ssampsread,dz))<0)
+				return(exit_status);
+		}
+	}
+	return(FINISHED);
+}

+ 237 - 0
dev/distort/distorta.c

@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+static int	write_cycles(int *obufpos,int cyc_average,dataptr dz);
+static int distorta_func_crosbuf(int,int,int *,int,dataptr);
+static int distorta_func(int current_buf,int cyc_average,int *obufpos,dataptr dz);
+static int get_cyc_average(int *cyc_average,dataptr dz);
+
+/**************************** DISTORT_AVG ******************************
+ *
+ * This works on groups of N input COMPLETE CYCLES, where the output
+ * group is not necessarily the same length as the input group.
+ *
+ * It requires a global current_pos_in_buf & dz->iparam[DISTORTA_OUTCNT].
+ *
+ * change_buff now uses cycleno_in_group_at_bufcros to MARK the cycle number at which
+ * the buff-boundary is crossed.
+ */
+
+int distort_avg(int *current_buf,int initial_phase,int *obufpos,int *current_pos_in_buf,int *cnt,dataptr dz)
+{
+	int exit_status;
+	register int i = *current_pos_in_buf;
+	register int n;
+	int cyc_average;
+	float *b  = dz->sampbuf[*current_buf];
+	int cycleno_in_group_at_bufcros = -1;
+	for(n=0;n<dz->iparam[DISTORTA_CYCLECNT];n++) {
+		dz->lparray[DISTORTA_STARTCYC][n] = i;
+		dz->lparray[DISTORTA_CYCLEN][n]   = 0;
+		switch(initial_phase) {
+		case(1):
+			while(b[i]>=0) {
+				dz->lparray[DISTORTA_CYCLEN][n]++;
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			while(b[i]<=0) {
+				dz->lparray[DISTORTA_CYCLEN][n]++;
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			break;
+		case(-1):
+			while(b[i]<=0) {
+				dz->lparray[DISTORTA_CYCLEN][n]++;
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			while(b[i]>=0) {
+				dz->lparray[DISTORTA_CYCLEN][n]++;
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			break;
+		}
+	}
+	if((exit_status = get_cyc_average(&cyc_average,dz))<0)
+		return(exit_status);
+	if(cycleno_in_group_at_bufcros < 0) 	/* cycle set does not cross between buffers */
+		exit_status = distorta_func(*current_buf,cyc_average,obufpos,dz);
+	else
+		exit_status = distorta_func_crosbuf(cyc_average,*current_buf,obufpos,cycleno_in_group_at_bufcros,dz);
+	if(exit_status < 0)
+		return(exit_status);
+	*current_pos_in_buf = i;
+	(*cnt)++;
+	return(CONTINUE);
+}
+
+/****************************** CHANGE_BUFF *****************************/
+
+int change_buff(float **b,int *cycleno_in_group_at_bufcros,int *current_buf,dataptr dz)
+{
+	int exit_status;
+	if(dz->samps_left <= 0)
+		return(FINISHED);
+	if(*cycleno_in_group_at_bufcros >= 0) {
+		sprintf(errstr,"cycle_search exceeds buffer size\n");
+		return(GOAL_FAILED);
+	}
+	*current_buf = !(*current_buf);
+	*b = dz->sampbuf[*current_buf];
+	if((exit_status = read_samps(*b,dz))<0)
+		return(exit_status);
+	return(CONTINUE);
+}
+
+/*************************** GET_CYC_AVERAGE ***************************/
+
+int get_cyc_average(int *cyc_average,dataptr dz)
+{
+	register int n;
+	int k = 0;
+	for(n=0;n<dz->iparam[DISTORTA_CYCLECNT];n++)
+		k += dz->lparray[DISTORTA_CYCLEN][n];
+	k = round((double)k/(double)dz->iparam[DISTORTA_CYCLECNT]);
+	if(k > dz->iparam[DISTORTA_CYCBUFLEN]) {
+		sprintf(errstr,"wavelength exceeds maximum size\n");
+		return(GOAL_FAILED);
+	}
+	*cyc_average = k;
+	return(FINISHED);
+}
+
+/************************* DISTORT_FUNC ***************************/
+
+int distorta_func(int current_buf,int cyc_average,int *obufpos,dataptr dz)
+{
+	register int n, m;
+	int cycindex;
+	double sum, zorg;
+	int j = 0;
+	float *b = dz->sampbuf[current_buf];
+	for(m=0;m<cyc_average;m++) {
+		sum = 0.0;
+		zorg = (double)m/(double)cyc_average;
+		for(n=0;n<dz->iparam[DISTORTA_CYCLECNT];n++) {
+			cycindex = round(zorg * (double)dz->lparray[DISTORTA_CYCLEN][n]);
+			sum += b[dz->lparray[DISTORTA_STARTCYC][n] + cycindex]; 
+		}
+		/*RWD added cast */
+		dz->sampbuf[3][j++] = (float) /*round*/(sum/(double)dz->iparam[DISTORTA_CYCLECNT]);
+	}
+	return write_cycles(obufpos,cyc_average,dz);
+}
+
+/*************************** DISTORT_FUNC_CROSBUF ***********************/
+
+int distorta_func_crosbuf(int cyc_average,int current_buf,int *obufpos,int cycleno_in_group_at_bufcros,dataptr dz)
+{
+	register int n, m, k;
+	int cycindex;
+	double sum, zorg;
+	int j = 0;
+	float *b;
+	for(m=0;m<cyc_average;m++) {
+		sum = 0.0;
+		b = dz->sampbuf[!current_buf];		/* CYCLES BEFORE CROSSOVER CYCLE */
+		zorg = (double)m/(double)cyc_average;
+		for(n=0;n<cycleno_in_group_at_bufcros;n++) {
+			cycindex = round(zorg * (double)dz->lparray[DISTORTA_CYCLEN][n]);
+			k = dz->lparray[DISTORTA_STARTCYC][n] + cycindex; 
+			sum += b[k]; 
+		}				/* CROSSOVER CYCLE */
+		cycindex = round(zorg * (double)dz->lparray[DISTORTA_CYCLEN][n]);
+		k = dz->lparray[DISTORTA_STARTCYC][n] + cycindex; 
+		if(k >= dz->buflen) {
+			b  = dz->sampbuf[current_buf];
+			k -= dz->buflen;
+		}
+		sum += b[k]; 
+		b = dz->sampbuf[current_buf];		/* CYCLES AFTER CROSSOVER CYCLE */
+		for(n=cycleno_in_group_at_bufcros+1;n<dz->iparam[DISTORTA_CYCLECNT];n++) {
+			cycindex = round(zorg * (double)dz->lparray[DISTORTA_CYCLEN][n]);
+			k = dz->lparray[DISTORTA_STARTCYC][n] + cycindex; 
+			sum += b[k]; 
+		}
+		/*RWD added cast */
+		dz->sampbuf[3][j++] = (float) /*round*/(sum/(double)dz->iparam[DISTORTA_CYCLECNT]);
+	}
+	return write_cycles(obufpos,cyc_average,dz);
+}
+
+/************************* WRITE_CYCLES **************************/
+
+int write_cycles(int *obufpos,int cyc_average,dataptr dz)
+{
+	int exit_status;
+	register int k = *obufpos, n, m, j;  
+	for(m=0;m<dz->iparam[DISTORTA_CYCLECNT];m++) {
+		j = 0;
+		for(n=0;n<cyc_average;n++) {
+			dz->sampbuf[2][k++] = dz->sampbuf[3][j++];
+			if(k >= dz->buflen) {
+				if((exit_status = write_samps(dz->sampbuf[2],dz->buflen,dz))<0)
+					return(exit_status);
+				k = 0;
+			}
+		}
+	}
+	*obufpos = k;
+	return(FINISHED);
+}

+ 883 - 0
dev/distort/distorte.c

@@ -0,0 +1,883 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+#include <stdlib.h>
+#include <sfsys.h>
+#include <osbind.h>
+
+static int		distorte_func(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int		distorte_func_crosbuf(int cyclestart,int cyclend,int current_buf,dataptr dz);
+
+static int  	distorte_rising( int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_falling(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_troffed(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_linrise(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_linfall(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_lintrof(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int 		distorte_userdef(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_rising_troffed( int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_falling_troffed(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_linrise_troffed(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_linfall_troffed(int cyclestart,int cyclend,int current_buf,dataptr dz);
+
+static int 		distorte_rising_bufcross( int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_falling_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_troffed_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_linrise_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_linfall_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_lintrof_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_userdef_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_rising_troffed_bufcross( int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_falling_troffed_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_linrise_troffed_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz);
+static int  	distorte_linfall_troffed_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz);
+
+static double	do_firsthalf_trof(int k,int cyclehlf,dataptr dz);
+static double	do_lasthalf_trof(int k,int cyclehlf,dataptr dz);
+static double	do_rising(int k,int cyclelen,dataptr dz);
+static double	do_falling(int k,int cyclelen,dataptr dz);
+static double	do_lintrof_firsthalf(int k,int cyclehlf,dataptr dz) ;
+static double	do_lintrof_lasthalf(int k,int cyclehlf,dataptr dz);
+static double	do_rising_troffed(int k,int cyclelen,dataptr dz);
+static double	do_falling_troffed(int k,int cyclelen,dataptr dz);
+static double	do_linrise_troffed(int k,int cyclelen,dataptr dz);
+static double	do_linfall_troffed(int k,int cyclelen,dataptr dz);
+
+static int		read_from_user_envelope(double *env_val,double table_index,int init,dataptr dz);
+
+/************************** DISTORT_ENV **************************/
+
+int distort_env(int *current_buf,int initial_phase,int *current_pos,int *buffer_overrun,int *cnt,dataptr dz)
+{
+	int exit_status = CONTINUE;
+	int cyclestart = *current_pos;
+	float *b = dz->sampbuf[*current_buf];
+	dz->param[ONE_LESS_TROF] = 1.0 - dz->param[DISTORTE_TROF];
+	exit_status = get_full_cycle(b,buffer_overrun,current_buf,initial_phase,current_pos,DISTORTE_CYCLECNT,dz);
+	if(*buffer_overrun)
+		distorte_func_crosbuf(cyclestart,*current_pos,*current_buf,dz);
+	else
+		distorte_func(cyclestart,*current_pos,*current_buf,dz);	
+	(*cnt)++;
+	return(exit_status);
+}
+
+/***************************** GET_FULL_CYCLE *******************************/
+
+int get_full_cycle(float *b,int *buffer_overrun,int *current_buf,int initial_phase,int *current_pos,int cyclecnt_param,dataptr dz)
+{
+	int exit_status;
+	register int i = *current_pos;
+	register int n;
+	switch(initial_phase) {
+	case(1):
+		for(n=0;n<dz->iparam[cyclecnt_param];n++) {
+			while(b[i]>=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buf(current_buf,buffer_overrun,&b,dz))!=CONTINUE) {
+						*current_pos = i;
+						return(exit_status);
+					}
+					i = 0;
+				}
+			}
+			while(b[i]<=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buf(current_buf,buffer_overrun,&b,dz))!=CONTINUE) {
+						*current_pos = i;
+						return(exit_status);
+					}
+
+					i = 0;
+				}
+			}
+		}
+		break;
+	case(-1):
+		for(n=0;n<dz->iparam[DISTORTE_CYCLECNT];n++) {
+			while(b[i]<=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buf(current_buf,buffer_overrun,&b,dz))!=CONTINUE) {
+						*current_pos = i;
+						return(exit_status);
+					}
+					i = 0;
+				}
+			}
+			while(b[i]>=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buf(current_buf,buffer_overrun,&b,dz))!=CONTINUE)	 {
+						*current_pos = i;
+						return(exit_status);
+					}
+					i = 0;
+				}
+			}
+		}
+		break;
+	}
+	*current_pos = i;
+	return(CONTINUE);
+}
+
+/***************************** CHANGE_BUF *******************************/
+
+int change_buf(int *current_buf,int *buffer_overrun,float **buf,dataptr dz)
+{
+ 	int exit_status;
+	if(dz->samps_left<=0) 
+		return(FINISHED);
+	if(*buffer_overrun==TRUE) {
+		sprintf(errstr,"Buffer overflow: cycle(set) too long at %lf secs.\n",
+		(double)dz->total_samps_read/(double)dz->infile->srate);
+		return(GOAL_FAILED);
+	}
+	*buffer_overrun = TRUE;
+	*current_buf = !(*current_buf);
+	*buf = dz->sampbuf[*current_buf];
+	if((exit_status = read_samps(*buf,dz))<0)
+		return(exit_status);		
+	return(CONTINUE);
+}
+
+/***************************** DISTORTE_FUNC **************************/
+
+int  distorte_func(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{   
+	switch(dz->mode) {
+	case(DISTORTE_RISING):   		return distorte_rising(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_FALLING):  		return distorte_falling(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_TROFFED):  		return distorte_troffed(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_LINRISE):  		return distorte_linrise(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_LINFALL):  		return distorte_linfall(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_LINTROF):  		return distorte_lintrof(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_USERDEF):  		return distorte_userdef(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_RISING_TR):   	return distorte_rising_troffed(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_FALLING_TR):  	return distorte_falling_troffed(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_LINRISE_TR):  	return distorte_linrise_troffed(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_LINFALL_TR):  	return distorte_linfall_troffed(cyclestart,cyclend,current_buf,dz);
+	default:
+		sprintf(errstr,"Unknown case: distorte_func()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/**************************** DISTORTE_FUNC_CROSBUF ************************/
+
+int distorte_func_crosbuf(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	switch(dz->mode) {
+	case(DISTORTE_RISING):  return distorte_rising_bufcross( cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_FALLING): return distorte_falling_bufcross(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_TROFFED): return distorte_troffed_bufcross(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_LINRISE): return distorte_linrise_bufcross(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_LINFALL): return distorte_linfall_bufcross(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_LINTROF): return distorte_lintrof_bufcross(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_USERDEF): return distorte_userdef_bufcross(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_RISING_TR):  return distorte_rising_troffed_bufcross( cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_FALLING_TR): return distorte_falling_troffed_bufcross(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_LINRISE_TR): return distorte_linrise_troffed_bufcross(cyclestart,cyclend,current_buf,dz);
+	case(DISTORTE_LINFALL_TR): return distorte_linfall_troffed_bufcross(cyclestart,cyclend,current_buf,dz);
+	default:
+		sprintf(errstr,"Unknown case: distorte_func_crosbuf()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/************************** DISTORTE_TROFFED *******************************/
+
+int distorte_troffed(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	register int k = 0, j = cyclestart;
+	int cyclelen = cyclend - cyclestart;
+	int cyclehlf = cyclelen/2;
+	int cyclemid = cyclestart + cyclehlf;
+	float *b = dz->sampbuf[current_buf];
+	while(j<cyclemid) {
+		b[j] = (float)/*ound*/(b[j] * do_firsthalf_trof(k,cyclehlf,dz));
+		j++;
+		k++;
+	}
+	k = 0;
+	cyclehlf = cyclelen - cyclehlf;
+	while(j < cyclend) {
+		b[j] = (float)/*round*/(b[j] * do_lasthalf_trof(k,cyclehlf,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/*************************** DISTORTE_RISING ******************************/
+
+int distorte_rising(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	register int k = 0, j = cyclestart;
+	int cyclelen = cyclend - cyclestart;
+	float *b = dz->sampbuf[current_buf];
+	while(j<cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_rising(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/************************** DISTORTE_FALLING ******************************/
+
+int distorte_falling(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	register int k = 0, j = cyclestart;
+	int cyclelen = cyclend - cyclestart;
+	float *b = dz->sampbuf[current_buf];
+	while(j<cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_falling(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/************************* DISTORTE_LINRISE **************************/
+
+int distorte_linrise(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	register int k = 0, j = cyclestart;
+	double z;
+	int cyclelen = cyclend - cyclestart;
+	float *b = dz->sampbuf[current_buf];
+	while(j<cyclend) {
+		z    = (double)k/(double)cyclelen;
+		b[j] = (float)/*round*/((double)b[j] * z);
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/***************************** DISTORTE_LINFALL ***************************/
+
+int distorte_linfall(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	register int k = 0, j = cyclestart;
+	double z;
+	int cyclelen = cyclend - cyclestart;
+	float *b = dz->sampbuf[current_buf];
+	while(j<cyclend) {
+		z    = 1.0 - ((double)k/(double)cyclelen);
+		b[j] = (float)/*round*/((double)b[j] * z);
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/****************************** DISTORTE_LINTROF ****************************/
+
+int distorte_lintrof(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	register int k = 0, j = cyclestart;
+	int cyclelen = cyclend - cyclestart;
+	int cyclehlf = cyclelen/2;
+	int cyclemid = cyclestart + cyclehlf;
+	float *b = dz->sampbuf[current_buf];
+	while(j<cyclemid) {
+		b[j] = (float)/*round*/((double)b[j] * do_lintrof_firsthalf(k,cyclehlf,dz));
+		j++;
+		k++;
+	}
+	k = 0;
+	cyclehlf = cyclelen - cyclehlf;
+	while(j < cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_lintrof_lasthalf(k,cyclehlf,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/*************************** DISTORTE_USERDEF ***************************/
+
+int distorte_userdef(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 0, j = cyclestart;
+	int cyclelen = cyclend - cyclestart;
+	double index;
+	double z;
+	int init = 1;
+	float *b = dz->sampbuf[current_buf];
+	while(j<cyclend) {
+		index = (double)k/(double)cyclelen;
+		if((exit_status = read_from_user_envelope(&z,index,init,dz))<0)
+			return(exit_status);
+		b[j]  = (float)/*round*/((double)b[j] * z);
+		j++;
+		k++;
+		init = 0;
+	}
+	return(FINISHED);
+}
+
+/*************************** DISTORTE_RISING_TROFFED ***********************/
+
+int distorte_rising_troffed(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	register int k = 0, j = cyclestart;
+	int cyclelen = cyclend - cyclestart;
+	float *b = dz->sampbuf[current_buf];
+	while(j<cyclend) {
+		b[j] = (float) /*round*/((double)b[j] * do_rising_troffed(k,cyclelen,dz));
+		j++;
+		k++;								 
+	}
+	return(FINISHED);
+}
+
+/********************** DISTORTE_FALLING_TROFFED *************************/
+
+int distorte_falling_troffed(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	register int k = 0, j = cyclestart;
+	int cyclelen = cyclend - cyclestart;
+	float *b = dz->sampbuf[current_buf];
+	while(j<cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_falling_troffed(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/************************* DISTORTE_LINRISE_TROFFED **************************/
+
+int distorte_linrise_troffed(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	register int k = 0, j = cyclestart;
+	int cyclelen = cyclend - cyclestart;
+	float *b = dz->sampbuf[current_buf];
+	while(j<cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_linrise_troffed(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/*************************** DISTORTE_LINFALL_TROFFED ***************************/
+
+int distorte_linfall_troffed(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	register int k = 0, j = cyclestart;
+	int cyclelen = cyclend - cyclestart;
+	float *b = dz->sampbuf[current_buf];
+	while(j<cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_linfall_troffed(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/********************** DISTORTE_TROFFED_BUFCROSS ***************************/
+
+int distorte_troffed_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 0, j = cyclestart;
+	int   overspill;
+	int cyclelen = (cyclend + dz->buflen)- cyclestart;
+	int  cyclehlf = cyclelen/2;
+	int cyclemid = cyclestart + cyclehlf;
+	float *b = dz->sampbuf[!current_buf];
+	if((overspill = cyclemid - dz->buflen) < 0) { /* CYCLEMID<BUFLEN */
+		while(j<cyclemid) {
+			b[j] = (float)/*round*/(b[j] * do_firsthalf_trof(k,cyclehlf,dz));
+			j++; k++;
+		}
+		k = 0;
+		cyclehlf = cyclelen - cyclehlf;
+		while(j < dz->buflen) {
+			b[j] = (float)/*round*/(b[j] * do_lasthalf_trof(k,cyclehlf,dz));
+			j++; k++;
+		}
+		if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+			return(exit_status);
+		b = dz->sampbuf[current_buf];
+		j = 0;
+	} else {		/* CYCLEMID >= BUFLEN */
+		while(j<dz->buflen) {
+			b[j] = (float)/*round*/(b[j] * do_firsthalf_trof(k,cyclehlf,dz));
+			j++; k++;
+		}
+		if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+			return(exit_status);
+		b = dz->sampbuf[current_buf];
+		j = 0;
+		while(j<overspill) {
+			b[j] = (float)/*round*/(b[j] * do_firsthalf_trof(k,cyclehlf,dz));
+			j++; k++;
+		}
+		k = 0;
+		cyclehlf = cyclelen - cyclehlf;
+	}
+	while(j < cyclend) {
+		b[j] = (float)/*round*/(b[j] * do_lasthalf_trof(k,cyclehlf,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/********************** DISTORTE_RISING_BUFCROSS **************************/
+
+int distorte_rising_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 0, j = cyclestart;
+	int cyclelen = (cyclend + dz->buflen)- cyclestart;
+	float *b = dz->sampbuf[!current_buf];
+	while(j<dz->buflen) {
+		b[j] = (float)/*round*/((double)b[j] * do_rising(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+		return(exit_status);
+	b = dz->sampbuf[current_buf];
+	j = 0;
+	while(j<cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_rising(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/******************** DISTORTE_FALLING_BUFCROSS *************************/
+
+int distorte_falling_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 0, j = cyclestart;
+	int cyclelen = (cyclend + dz->buflen)- cyclestart;
+	float *b = dz->sampbuf[!current_buf];
+	while(j<dz->buflen) {
+		b[j] = (float)/*round*/((double)b[j] * do_falling(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+		return(exit_status);
+	b = dz->sampbuf[current_buf];
+	j = 0;
+	while(j<cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_falling(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/********************* DISTORTE_LINRISE_BUFCROSS *************************/
+
+int distorte_linrise_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 0, j = cyclestart;
+	double z;
+	int cyclelen = (cyclend + dz->buflen)- cyclestart;
+	float *b = dz->sampbuf[!current_buf];
+	while(j<dz->buflen) {
+		z    = (double)k/(double)cyclelen;
+		b[j] = (float)/*round*/((double)b[j] * z);
+		j++;
+		k++;
+	}
+	if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+		return(exit_status);
+	b = dz->sampbuf[current_buf];
+	j = 0;
+	while(j<cyclend) {
+		z    = (double)k/(double)cyclelen;
+		b[j] = (float)/*round*/((double)b[j] * z);
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/********************* DISTORTE_LINFALL_BUFCROSS **************************/
+
+int distorte_linfall_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 0, j = cyclestart;
+	double z;
+	int cyclelen = (cyclend + dz->buflen)- cyclestart;
+	float *b = dz->sampbuf[!current_buf];
+	while(j<dz->buflen) {
+		z    = 1.0 - ((double)k/(double)cyclelen);
+		b[j] = (float)/*round*/((double)b[j] * z);
+		j++;
+		k++;
+	}
+	if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+		return(exit_status);
+	b = dz->sampbuf[current_buf];
+	j = 0;
+	while(j<cyclend) {
+		z    = 1.0 - ((double)k/(double)cyclelen);
+		b[j] = (float)/*round*/((double)b[j] * z);
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/*********************** DISTORTE_LINTROF_BUFCROSS ****************************/
+
+int distorte_lintrof_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 0, j = cyclestart;
+	int   overspill;
+	int cyclelen = (cyclend + dz->buflen)- cyclestart;
+	int cyclehlf = cyclelen/2;
+	int cyclemid = cyclestart + cyclehlf;
+	float *b = dz->sampbuf[!current_buf];
+	if((overspill = cyclemid - dz->buflen) < 0) { /* CYCLEMID<BUFLEN */
+		while(j<cyclemid) {
+			b[j] = (float)/*round*/((double)b[j] * do_lintrof_firsthalf(k,cyclehlf,dz));
+			j++;
+			k++;
+		}
+		k = 0;
+		cyclehlf = cyclelen - cyclehlf;
+		while(j < dz->buflen) {
+			b[j] = (float)/*round*/((double)b[j] * do_lintrof_lasthalf(k,cyclehlf,dz));
+			j++;
+			k++;
+		}
+		if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+			return(exit_status);
+		b = dz->sampbuf[current_buf];
+		j = 0;
+	} else {		/* CYCLEMID >= BUFLEN */
+		while(j<dz->buflen) {
+			b[j] = (float)/*round*/((double)b[j] * do_lintrof_firsthalf(k,cyclehlf,dz));
+			j++;
+			k++;
+		}
+		if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+			return(exit_status);
+		b = dz->sampbuf[current_buf];
+		j = 0;
+		while(j<overspill) {
+			b[j] = (float)/*round*/((double)b[j] * do_lintrof_firsthalf(k,cyclehlf,dz));
+			j++;
+			k++;
+		}
+		k = 0;
+		cyclehlf = cyclelen - cyclehlf;
+	}
+	while(j < cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_lintrof_lasthalf(k,cyclehlf,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/********************** DISTORTE_USERDEF_BUFCROSS **************************/
+
+int distorte_userdef_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 1, j = cyclestart;
+	int cyclelen = (cyclend + dz->buflen)- cyclestart;
+	double index = 0.0;
+	double z;
+	int init = 1;
+	float *b = dz->sampbuf[!current_buf];
+	while(j<dz->buflen) {
+		index = (double)k/(double)cyclelen;
+		if((exit_status = read_from_user_envelope(&z,index,init,dz))<0)
+			return(exit_status);
+		b[j]  = (float)/*round*/((double)b[j] * z);
+		j++;
+		k++;
+		init = 0;
+	}
+	if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+		return(exit_status);
+	b = dz->sampbuf[current_buf];
+	j = 0;
+	while(j<cyclend) {
+		index = (double)k/(double)cyclelen;
+		if((exit_status = read_from_user_envelope(&z,index,init,dz))<0)
+			return(exit_status);
+		b[j]  = (float)/*round*/((double)b[j] * z);
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/********************** DISTORTE_RISING_TROFFED_BUFCROSS **************************/
+
+int distorte_rising_troffed_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 0, j = cyclestart;
+	int cyclelen = (cyclend + dz->buflen)- cyclestart;
+	float *b = dz->sampbuf[!current_buf];
+	while(j<dz->buflen) {
+		b[j] = (float)/*round*/((double)b[j] * do_rising_troffed(k,cyclelen,dz));
+		j++;
+		k++;								 
+	}
+	if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+		return(exit_status);
+	b = dz->sampbuf[current_buf];
+	j = 0;
+	while(j<cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_rising_troffed(k,cyclelen,dz));
+		j++;
+		k++;								 
+	}
+	return(FINISHED);
+}
+
+/******************** DISTORTE_FALLING_TROFFED_BUFCROSS *************************/
+
+int distorte_falling_troffed_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 0, j = cyclestart;
+	int cyclelen = (cyclend + dz->buflen)- cyclestart;
+	float *b = dz->sampbuf[!current_buf];
+	while(j<dz->buflen) {
+		b[j] = (float)/*round*/((double)b[j] * do_falling_troffed(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+		return(exit_status);
+	b = dz->sampbuf[current_buf];
+	j = 0;
+	while(j<cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_falling_troffed(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/********************* DISTORTE_LINRISE_TROFFED_BUFCROSS *************************/
+
+int distorte_linrise_troffed_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 0, j = cyclestart;
+	int cyclelen = (cyclend + dz->buflen)- cyclestart;
+	float *b = dz->sampbuf[!current_buf];
+	while(j<dz->buflen) {
+		b[j] = (float)/*round*/((double)b[j] * do_linrise_troffed(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+		return(exit_status);
+	b = dz->sampbuf[current_buf];
+	j = 0;
+	while(j<cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_linrise_troffed(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/******************* DISTORTE_LINFALL_TROFFED_BUFCROSS **************************/
+
+int distorte_linfall_troffed_bufcross(int cyclestart,int cyclend,int current_buf,dataptr dz)
+{
+	int exit_status;
+	register int k = 0, j = cyclestart;
+	int cyclelen = (cyclend + dz->buflen)- cyclestart;
+	float *b = dz->sampbuf[!current_buf];
+	while(j<dz->buflen) {
+		b[j] = (float)/*round*/((double)b[j] * do_linfall_troffed(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	if((exit_status = write_samps(dz->sampbuf[!current_buf],dz->buflen,dz))<0)
+		return(exit_status);
+	b = dz->sampbuf[current_buf];
+	j = 0;
+	while(j<cyclend) {
+		b[j] = (float)/*round*/((double)b[j] * do_linfall_troffed(k,cyclelen,dz));
+		j++;
+		k++;
+	}
+	return(FINISHED);
+}
+
+/******************* DO_FIRSTHALF_TROF **************************/
+
+double do_firsthalf_trof(int k,int cyclehlf,dataptr dz)
+{
+	double z = 1.0 - ((double)k/(double)cyclehlf);
+	z = (pow(z,dz->param[DISTORTE_EXPON]) * dz->param[ONE_LESS_TROF]) + dz->param[DISTORTE_TROF];
+	return (z);
+}
+
+/******************* DO_LASTHALF_TROF **************************/
+
+double do_lasthalf_trof(int k,int cyclehlf,dataptr dz)
+{
+	double z = (double)k/(double)cyclehlf;
+	z    = (pow(z,dz->param[DISTORTE_EXPON]) * dz->param[ONE_LESS_TROF]) + dz->param[DISTORTE_TROF];
+	return(z);
+}
+
+/******************* DO_RISING **************************/
+
+double do_rising(int k,int cyclelen,dataptr dz)
+{
+	double z = (double)k/(double)cyclelen;
+	z = pow(z,dz->param[DISTORTE_EXPON]);
+	return z;
+}
+
+/******************* DO_FALLING **************************/
+
+double do_falling(int k,int cyclelen,dataptr dz)
+{
+	double z = 1.0 - ((double)k/(double)cyclelen);
+	z    = pow(z,dz->param[DISTORTE_EXPON]);
+	return z;
+}
+
+/************************ DO_LINTROF_FIRSTHALF *******************************/
+
+double do_lintrof_firsthalf(int k,int cyclehlf,dataptr dz) 
+{
+	double z = 1.0 - ((double)k/(double)cyclehlf);
+	z = (z * dz->param[ONE_LESS_TROF]) + dz->param[DISTORTE_TROF];
+	return z;
+}
+
+/************************ DO_LINTROF_LASTHALF *******************************/
+
+double do_lintrof_lasthalf(int k,int cyclehlf,dataptr dz)
+{
+	double z = (double)k/(double)cyclehlf;
+	z = (z * dz->param[ONE_LESS_TROF]) + dz->param[DISTORTE_TROF];
+	return z;
+}
+
+/************************ DO_RISING_TROFFED *******************************/
+
+double do_rising_troffed(int k,int cyclelen,dataptr dz)
+{
+	double z = (double)k/(double)cyclelen;
+	z  = pow(z,dz->param[DISTORTE_EXPON]);
+	z *= dz->param[ONE_LESS_TROF];
+	z += dz->param[DISTORTE_TROF];
+	return(z);
+}
+
+/************************ DO_FALLING_TROFFED *******************************/
+
+double do_falling_troffed(int k,int cyclelen,dataptr dz)
+{
+	double z = 1.0 - ((double)k/(double)cyclelen);
+	z = (pow(z,dz->param[DISTORTE_EXPON]) * dz->param[ONE_LESS_TROF]) + dz->param[DISTORTE_TROF];
+	return z;
+}
+
+/************************ DO_LINRISE_TROFFED *******************************/
+
+double do_linrise_troffed(int k,int cyclelen,dataptr dz)
+{
+	double z = (double)k/(double)cyclelen;
+	z = (z * dz->param[ONE_LESS_TROF]) + dz->param[DISTORTE_TROF];
+	return z;
+}
+
+/************************ DO_LINFALL_TROFFED *******************************/
+
+double do_linfall_troffed(int k,int cyclelen,dataptr dz)
+{
+	double z = 1.0 - ((double)k/(double)cyclelen);
+	z = (z * dz->param[ONE_LESS_TROF]) + dz->param[DISTORTE_TROF];
+	return z;
+}
+
+/************************ READ_FROM_USER_ENVELOPE *******************************/
+
+int read_from_user_envelope(double *env_val,double table_index,int init,dataptr dz)
+{
+	double *p;
+	double hi_env, lo_env, hi_index, lo_index;
+	double env;
+	if(init)
+		dz->ptr[DISTORTE_ENV] = dz->parray[DISTORTE_ENV];
+	p = dz->ptr[DISTORTE_ENV];
+	while(table_index > *p) {
+		if((p += 2) >= dz->ptr[DISTORTE_ENVEND]) {
+			sprintf(errstr,"Problem reading user envelope data: read_from_user_envelope()\n");
+			return(PROGRAM_ERROR);
+		}
+	}
+	if(p != dz->parray[DISTORTE_ENV]) {
+		hi_env   = *(p+1);
+		hi_index = *p;
+		lo_env   = *(p-1);
+		lo_index = *(p-2);
+		env      = (double)((table_index - lo_index)/(hi_index - lo_index));
+		env     *= (double)(hi_env - lo_env);
+		env     += (double)lo_env;
+	} else
+		env = *(p+1);
+	dz->ptr[DISTORTE_ENV] = p;
+	*env_val = env;
+	return(FINISHED);
+}		

+ 220 - 0
dev/distort/distortf.c

@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+#define	FCYCBUF	(2)
+
+static void do_fractal(int grouplen,int current_buf,dataptr dz);
+static void do_fractal_crosbuf(int grouplen,int bufcros_cycle,int current_buf,dataptr dz);
+static int 	get_scaled_halfcycle(int n,int *cnt,float **buf,int *bufpos,int *grouplen,int *current_buf,
+			int *is_bufcros,int *bufcros_cycle,int prescale_param,int *last_total_samps,dataptr dz);
+static int 	change_buf_marking_crossing_cycle_no(int n,float **buf,int *is_bufcross,int *bufcros_cycle,int *current_buf,dataptr dz);
+
+/**************************** DISTORTF ******************************
+ *
+ * Distort file by adding smaller scale perturbations modelled on large.
+ */
+
+int distortf(int *bufpos,int phase,int *last_total_samps,int *current_buf,dataptr dz)
+{
+	int exit_status;
+	int grouplen = 0;
+	int cnt = 0, n;
+	int firstime = 1;   
+	float *buf  = dz->sampbuf[*current_buf];
+	int bufcros_cycle = 0;
+	int is_bufcros = 0;
+	double thistime = (double)(dz->total_samps_written + *bufpos)/(double)(dz->infile->srate);
+	if((exit_status = read_values_from_all_existing_brktables(thistime,dz))<0)
+		return(exit_status);
+	switch(phase) {
+	case(1):
+		for(n=0;n<dz->iparam[DISTORTF_SCALE];n++) {
+			dz->lparray[DISTORTF_STARTCYC][n] = *bufpos;
+			while(buf[*bufpos]>=0.0) {
+				if((exit_status = get_scaled_halfcycle(n,&cnt,&buf,bufpos,&grouplen,current_buf,&is_bufcros,&bufcros_cycle,DISTORTF_PRESCALE,last_total_samps,dz))!=CONTINUE)
+					return(exit_status);
+			}
+			while(buf[*bufpos]<=0.0) {
+				if((exit_status = get_scaled_halfcycle(n,&cnt,&buf,bufpos,&grouplen,current_buf,&is_bufcros,&bufcros_cycle,DISTORTF_PRESCALE,last_total_samps,dz))!=CONTINUE)
+					return(exit_status);
+			}
+			if(is_bufcros && firstime) {
+				dz->lparray[DISTORTF_CYCLEN][n] = dz->buflen - dz->lparray[DISTORTF_STARTCYC][n] + *bufpos;
+				firstime = 0;
+			} else
+				dz->lparray[DISTORTF_CYCLEN][n] = *bufpos - dz->lparray[DISTORTF_STARTCYC][n];
+		}
+		break;
+	case(-1):
+		for(n=0;n<dz->iparam[DISTORTF_SCALE];n++) {
+			dz->lparray[DISTORTF_STARTCYC][n] = *bufpos;
+			while(buf[*bufpos]<=0.0) {
+				if((exit_status = get_scaled_halfcycle(n,&cnt,&buf,bufpos,&grouplen,current_buf,&is_bufcros,&bufcros_cycle,DISTORTF_PRESCALE,last_total_samps,dz))!=CONTINUE)
+					return(exit_status);
+			}
+			while(buf[*bufpos]>=0.0) {
+				if((exit_status = get_scaled_halfcycle(n,&cnt,&buf,bufpos,&grouplen,current_buf,&is_bufcros,&bufcros_cycle,DISTORTF_PRESCALE,last_total_samps,dz))!=CONTINUE)
+					return(exit_status);
+			}
+			if(is_bufcros && firstime) {
+				dz->lparray[DISTORTF_CYCLEN][n] = dz->buflen - dz->lparray[DISTORTF_STARTCYC][n] + *bufpos;
+				firstime = 0;
+			} else
+				dz->lparray[DISTORTF_CYCLEN][n] = *bufpos - dz->lparray[DISTORTF_STARTCYC][n];
+		}
+		break;
+	}
+	dz->lparray[DISTORTF_STARTCYC][dz->iparam[DISTORTF_SCALE]] = *bufpos;
+	if(is_bufcros) {
+		do_fractal_crosbuf(grouplen,bufcros_cycle,*current_buf,dz);
+		if((exit_status = write_samps(dz->sampbuf[!(*current_buf)],dz->buflen,dz))<0)
+			return(exit_status);
+		is_bufcros = 0;
+	} else
+		do_fractal(grouplen,*current_buf,dz);
+	return(CONTINUE);
+}
+
+/***************************** DO_FRACTAL *******************************/
+
+void do_fractal(int grouplen,int current_buf,dataptr dz)
+{
+	int n, k, i, index;
+	double ratio;
+	float *buf = dz->sampbuf[current_buf];
+	for(n=0;n<dz->iparam[DISTORTF_SCALE];n++) {
+		ratio = (double)grouplen/(double)dz->lparray[DISTORTF_CYCLEN][n];
+		k = 0;
+		i = dz->lparray[DISTORTF_STARTCYC][n];
+		while(i < dz->lparray[DISTORTF_STARTCYC][n+1]) {
+			index    = round(ratio * (double)k++);
+			buf[i++] += (float)(dz->param[DISTORTF_AMPFACT] * dz->sampbuf[FCYCBUF][index]);
+		}
+	}
+}
+
+/*************************** DO_FRACTAL_CROSBUF ***************************/
+
+void do_fractal_crosbuf(int grouplen,int bufcros_cycle,int current_buf,dataptr dz)
+{
+	float *buf = dz->sampbuf[!current_buf];
+	int n, k, i, index;
+	double ratio;
+	for(n=0;n<bufcros_cycle;n++) {
+		ratio = (double)grouplen/(double)dz->lparray[DISTORTF_CYCLEN][n];
+		k = 0;
+		i = dz->lparray[DISTORTF_STARTCYC][n];
+		while(i < dz->lparray[DISTORTF_STARTCYC][n+1]) {
+			index    = round(ratio * (double)k++);
+			buf[i++] += (float)(dz->param[DISTORTF_AMPFACT] * dz->sampbuf[FCYCBUF][index]);
+		}
+	}
+	ratio = (double)grouplen/(double)dz->lparray[DISTORTF_CYCLEN][n];
+	k = 0;
+	i = dz->lparray[DISTORTF_STARTCYC][n];
+	while(i < dz->buflen) {
+		index    = round(ratio * (double)k++);
+		buf[i++] += (float)(dz->param[DISTORTF_AMPFACT] * dz->sampbuf[FCYCBUF][index]);
+	}
+	buf = dz->sampbuf[current_buf];
+	i = 0;
+	while(i < dz->lparray[DISTORTF_STARTCYC][n+1]) {
+		index    = round(ratio * (double)k++);
+		buf[i++] += (float)(dz->param[DISTORTF_AMPFACT] * dz->sampbuf[FCYCBUF][index]);
+	}
+	for(n=bufcros_cycle+1;n<dz->iparam[DISTORTF_SCALE];n++) {
+		ratio = (double)grouplen/(double)dz->lparray[DISTORTF_CYCLEN][n];
+		k = 0;
+		i = dz->lparray[DISTORTF_STARTCYC][n];
+		while(i < dz->lparray[DISTORTF_STARTCYC][n+1]) {
+			index    = round(ratio * (double)k++);
+			buf[i++] += (float)(dz->param[DISTORTF_AMPFACT] * dz->sampbuf[FCYCBUF][index]);
+		}
+	}
+}
+
+/**************************** GET_SCALED_HALFCYCLE **************************/
+
+int get_scaled_halfcycle(int n,int *cnt,float **buf,int *bufpos,int *grouplen,int *current_buf,int *is_bufcros,int *bufcros_cycle,
+				  int prescale_param,int *last_total_samps,dataptr dz)
+{
+	int exit_status;
+	if(++(*cnt) >= dz->iparam[DISTORTF_SCALE]) {
+
+		dz->sampbuf[FCYCBUF][*grouplen] = (*buf)[*bufpos];
+		if(++(*grouplen) >dz->iparam[DISTORTF_CYCBUFLEN]) {
+			cop_out(*bufpos,*grouplen,*last_total_samps,dz);
+			return FINISHED;
+		}
+		*cnt = 0;
+	}
+	if(++(*bufpos) >= dz->ssampsread) {
+		*last_total_samps = dz->total_samps_read;
+		if((exit_status = change_buf_marking_crossing_cycle_no(n,buf,is_bufcros,bufcros_cycle,current_buf,dz))!=CONTINUE)
+			return(exit_status);
+		if(dz->vflag[IS_PRESCALED])
+			prescale(*current_buf,prescale_param,dz);
+		*bufpos = 0;
+	}
+	return(CONTINUE);
+}
+
+/****************************** CHANGE_BUF_MARKING_CROSSING_CYCLE_NO ****************************
+ *
+ * (1) 'bufcros_cycle' marks the cycle-no which crosses between buffers.
+ */
+
+int change_buf_marking_crossing_cycle_no(int n,float **buf,int *is_bufcros,int *bufcros_cycle,int *current_buf,dataptr dz)
+{
+	int exit_status;
+	if(dz->samps_left <= 0)
+		return(FINISHED);
+	if(*is_bufcros==TRUE) {
+		sprintf(errstr,"cycle_search exceeds buffer size.\n");
+		return(GOAL_FAILED);
+	}
+	*current_buf = !(*current_buf);
+	*buf = dz->sampbuf[*current_buf];
+	*bufcros_cycle = n;
+	*is_bufcros = 1;
+	if((exit_status = read_samps(*buf,dz))<0)
+		return(exit_status);		
+	return(CONTINUE);
+}

+ 210 - 0
dev/distort/distorth.c

@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+#define HCYCBUF	(2)
+
+static int 	get_halfcycle(float **buf,int *bufpos,int *cyclelen,int *current_buf,int *is_bufcros,
+			int prescale_param,int *last_total_samps,dataptr dz);
+static void do_harmonic(float *buf,int endsamp,int cyclestart,int cyclelen,dataptr dz);
+static void do_harmonic_crosbuf(int endsamp,int cyclestart,int cyclelen,int current_buf,dataptr dz);
+
+/**************************** DISTORTH ******************************
+ *
+ * Distort file by adding harmonics over each wavecycle.
+ */
+
+int distorth(int *bufpos,int phase,int *last_total_samps,int *current_buf,dataptr dz)
+{
+	int exit_status;
+	int cyclelen = 0;
+	float *buf  = dz->sampbuf[*current_buf];
+	int is_bufcros = 0;
+	int cyclestart = *bufpos;
+	switch(phase) {
+	case(1):
+		while(buf[*bufpos]>=0) {
+			if((exit_status = get_halfcycle(&buf,bufpos,&cyclelen,current_buf,&is_bufcros,
+				DISTORTH_PRESCALE,last_total_samps,dz))!=CONTINUE)
+				return(exit_status);
+		}
+		while(buf[*bufpos]<=0) {
+			if((exit_status = get_halfcycle(&buf,bufpos,&cyclelen,current_buf,&is_bufcros,
+				DISTORTH_PRESCALE,last_total_samps,dz))!=CONTINUE)
+				return(exit_status);
+		}
+		break;
+	case(-1):
+		while(buf[*bufpos]<=0) {
+			if((exit_status = get_halfcycle(&buf,bufpos,&cyclelen,current_buf,&is_bufcros,
+				DISTORTH_PRESCALE,last_total_samps,dz))!=CONTINUE)
+				return(exit_status);
+		}
+		while(buf[*bufpos]>=0) {
+			if((exit_status = get_halfcycle(&buf,bufpos,&cyclelen,current_buf,&is_bufcros,
+				DISTORTH_PRESCALE,last_total_samps,dz))!=CONTINUE)
+				return(exit_status);
+		}
+		break;
+	}
+	if(is_bufcros) {
+		do_harmonic_crosbuf(*bufpos,cyclestart,cyclelen,*current_buf,dz);
+		if((exit_status = write_samps(dz->sampbuf[!(*current_buf)],dz->buflen,dz))<0)
+			return(exit_status);
+		is_bufcros = 0;
+	} else
+		do_harmonic(buf,*bufpos,cyclestart,cyclelen,dz);
+	return(CONTINUE);
+}
+
+/**************************** GET_HALFCYCLE **************************/
+
+int get_halfcycle(float **buf,int *bufpos,int *cyclelen,int *current_buf,int *is_bufcros,
+				  int prescale_param,int *last_total_samps,dataptr dz)
+{
+	int exit_status;
+	dz->sampbuf[HCYCBUF][*cyclelen] = (*buf)[*bufpos];
+	if(++(*cyclelen) >dz->iparam[DISTORTH_CYCBUFLEN]) {
+		cop_out(*bufpos,*cyclelen,*last_total_samps,dz);
+		return FINISHED;
+	}
+	if(++(*bufpos) >= dz->ssampsread) {
+		*last_total_samps = dz->total_samps_read;
+		if((exit_status = change_buf(current_buf,is_bufcros,buf,dz))!=CONTINUE)
+			return(exit_status);
+		if(dz->vflag[IS_PRESCALED])
+			prescale(*current_buf,prescale_param,dz);
+		*bufpos = 0;
+	}
+	return(CONTINUE);
+}
+
+/*************************** DO_HARMONIC ***************************/
+
+void do_harmonic(float *buf,int endsamp,int cyclestart,int cyclelen,dataptr dz)
+{
+//TW UPDATE
+//	int n, foldover = 0;
+	int n;
+//TW REVISION (avoid warnings)
+	double val;
+	register int k, i;
+	for(n=0;n<dz->iparam[DISTORTH_HCNT];n++) {
+		k = cyclestart;
+		i = dz->iparray[DISTORTH_HNO][n];
+//TW UPDATE
+		if(i >= cyclelen/4)	/* Foldover */
+			continue;
+		while(k < endsamp) { 
+			/*RWD added cast: but always get the warning with +=... */
+//			buf[k++] += (float) /*round*/(dz->sampbuf[HCYCBUF][i] * dz->parray[DISTORTH_AMP][n]);
+//TW AVOID WARNING
+			val =  buf[k] + (dz->sampbuf[HCYCBUF][i] * dz->parray[DISTORTH_AMP][n]);
+			buf[k++] = (float)val;
+			i += dz->iparray[DISTORTH_HNO][n];
+//TW UPDATE
+			while(i >= cyclelen) 
+				i -= cyclelen;
+//TW UPDATE
+		}
+	}
+}
+
+/************************* DO_HARMONIC_CROSBUF *************************/
+
+void do_harmonic_crosbuf(int endsamp,int cyclestart,int cyclelen,int current_buf,dataptr dz)
+{
+	float *buf;
+//TW UPDATE
+//	int n, foldover = 0;
+	int n;
+//TW ADDITION (avoid warnings)
+	double val;
+	register int k, i;
+	for(n=0;n<dz->iparam[DISTORTH_HCNT];n++) {
+		k = cyclestart;
+		i = dz->iparray[DISTORTH_HNO][n];
+//TW UPDATE
+		if(i >= cyclelen/4)	/* Foldover */
+			continue;
+		buf = dz->sampbuf[!current_buf];
+		while(k < dz->buflen) {
+			/*RWD added cast */
+//			buf[k++] += (float) /*round*/(dz->sampbuf[HCYCBUF][i] * dz->parray[DISTORTH_AMP][n]);
+//TW REVISION (avoid warnings)
+			val = buf[k] + (dz->sampbuf[HCYCBUF][i] * dz->parray[DISTORTH_AMP][n]);
+			buf[k++] = (float)val;
+			i += dz->iparray[DISTORTH_HNO][n];
+//TW UPDATE
+//			while(i >= cyclelen) {
+			while(i >= cyclelen)
+				i -= cyclelen;
+//				if(dz->iparam[FOLDOVER_WARNING]==FALSE && foldover==1) {
+//					fprintf(stdout,"\nWARNING: FOLDOVER\n");
+//					fflush(stdout);
+//					dz->iparam[FOLDOVER_WARNING] = TRUE;				
+//				}
+//				foldover++;
+//			}
+//			foldover = 0;
+		}
+		buf = dz->sampbuf[current_buf];
+		k = 0;
+		while(k < endsamp) {
+			/*RWD added cast */
+//			buf[k++] += (float)/* round*/(dz->sampbuf[HCYCBUF][i] * dz->parray[DISTORTH_AMP][n]);
+//TW REVISION (avoid warnings)
+			val = buf[k] + (dz->sampbuf[HCYCBUF][i] * dz->parray[DISTORTH_AMP][n]);
+			buf[k++] = (float)val;
+			i += dz->iparray[DISTORTH_HNO][n];
+//TW UPDATE
+//			while(i >= cyclelen) {
+			while(i >= cyclelen)
+				i -= cyclelen;
+//				if(dz->iparam[FOLDOVER_WARNING]==FALSE && foldover==1) {
+//					fprintf(stdout,"WARNING : FOLDOVER\n");
+//					fflush(stdout);
+//					dz->iparam[FOLDOVER_WARNING] = TRUE;				
+//				}
+//				foldover++;
+//			}
+//			foldover = 0;
+		}
+	}
+}

+ 456 - 0
dev/distort/distortion.c

@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version*/
+#include <stdio.h>
+#include <stdlib.h>
+/*RWD*/
+#include <memory.h>
+
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <processno.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+static int  cyccnt(int *current_pos_in_buf,int *current_buf,int initial_phase,dataptr dz);
+
+/*************************** GET_INITIAL_PHASE **********************/
+
+int get_initial_phase(int *initial_phase,dataptr dz)
+{
+	float *b = dz->sampbuf[0];
+	int current_pos_in_buf = 0;
+	while(b[current_pos_in_buf]==0 && current_pos_in_buf < dz->ssampsread)
+		current_pos_in_buf++;
+	if(current_pos_in_buf >= dz->ssampsread) {
+		sprintf(errstr,"1st buffer is ALL ZEROES: Cannot proceed.\n");
+		return(GOAL_FAILED);
+	}
+	if(b[current_pos_in_buf] > 0)
+		*initial_phase = 1;
+	else
+		*initial_phase = -1;
+	return(FINISHED);
+}
+
+/*************************** PROCESS_WITH_SWAPPED_BUFS_ON_SINGLE_HALF_CYCLES ************************/
+
+int process_with_swapped_bufs_on_single_half_cycles(dataptr dz)  /* [distortion0] */	 
+{
+	int exit_status;
+	int current_buf = 0;
+	int lastzero = 0;
+	/*int*/float cyclemax = 0.0;
+	if((exit_status = read_samps(dz->sampbuf[current_buf],dz))<0)
+		return(exit_status);
+	current_buf = !current_buf;
+	while(dz->samps_left > 0) {
+		if((exit_status = read_samps(dz->sampbuf[current_buf],dz))<0)
+			return(exit_status);
+		current_buf = !current_buf;
+		switch(dz->process) {
+		case(DISTORT): 	exit_status = do_distort(current_buf,0,&lastzero,&cyclemax,dz);	break;
+		default:
+			sprintf(errstr,"Unknown case in process_with_swapped_bufs_on_single_half_cycles()\n");
+			return(PROGRAM_ERROR);
+		}
+		if(exit_status<0)
+			return(exit_status);
+		if((exit_status = write_samps(dz->sampbuf[current_buf],dz->buflen,dz))<0)
+			return(exit_status);
+	}
+	current_buf = !current_buf; 
+	switch(dz->process) {
+	case(DISTORT): 	exit_status = do_distort(current_buf,1,&lastzero,&cyclemax,dz); break;
+	default:
+		sprintf(errstr,"Unknown case in process_with_swapped_bufs_on_single_half_cycles()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(exit_status<0)
+		return(exit_status);
+	if(dz->ssampsread > 0)
+		return write_samps(dz->sampbuf[current_buf],dz->ssampsread,dz);
+	return FINISHED;
+}
+
+/*************************** PROCESS_WITH_SWAPPED_BUFS_ON_FULL_CYCLES ************************/
+
+int process_with_swapped_bufs_on_full_cycles(dataptr dz)  /* [distortion2] */
+{
+	int exit_status;
+	int current_pos_in_buf, cnt = 0;
+	int  buffer_overrun, initial_phase, current_buf = 0;
+	double thistime;
+	display_virtual_time(0,dz);
+	if((exit_status = read_samps(dz->sampbuf[current_buf],dz))<0)
+		return(exit_status);
+	if((exit_status = get_initial_phase(&initial_phase,dz))<0)
+		return(exit_status);
+	current_pos_in_buf = 0;
+	do {
+		thistime = (double)(dz->total_samps_read - dz->ssampsread + current_pos_in_buf)/(double)dz->infile->srate;
+		if((exit_status = read_values_from_all_existing_brktables(thistime,dz))<0)
+			return(exit_status);
+		buffer_overrun = FALSE;
+		switch(dz->process) {
+		case(DISTORT_ENV):	
+			exit_status = distort_env(&current_buf,initial_phase,&current_pos_in_buf,&buffer_overrun,&cnt,dz);
+			break;
+		case(DISTORT_REV):	
+			exit_status = distort_rev(&current_buf,initial_phase,&current_pos_in_buf,&buffer_overrun,&cnt,dz);
+			break;
+		default:
+			sprintf(errstr,"Unknown case in process_with_swapped_bufs_on_full_cycles()\n");
+			return(PROGRAM_ERROR);
+		}
+	} while(exit_status == CONTINUE);
+	if(exit_status<0)
+		return(exit_status);
+	if(cnt==0) {
+		sprintf(errstr,"source sound too short to attempt this process.\n");
+		return(GOAL_FAILED);
+	}
+//TW DELETED IN UPDATED CODE
+	if(current_pos_in_buf > 0)
+		return write_samps(dz->sampbuf[current_buf],current_pos_in_buf,dz);
+	return(FINISHED);
+}
+
+/***************************** PROCESS_ON_SINGLE_BUF_WITH_PHASE_DEPENDENCE *****************************/
+
+int process_on_single_buf_with_phase_dependence(dataptr dz)
+{
+	int exit_status;
+	int initial_phase;
+	int current_pos_in_buf = 0;
+	double  thistime;
+	display_virtual_time(0,dz);
+	if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
+		return(exit_status);
+	if((exit_status = get_initial_phase(&initial_phase,dz))<0)
+		return(exit_status);
+	do {
+		thistime = (double)(dz->total_samps_read - dz->ssampsread + current_pos_in_buf)/(double)dz->infile->srate;
+		if((exit_status = read_values_from_all_existing_brktables(thistime,dz))<0)
+			return(exit_status);
+		exit_status = distort_omt(&current_pos_in_buf,initial_phase,dz);
+	} while(exit_status==CONTINUE);
+		;
+	return(exit_status);
+}
+
+/**************** PROCESS_WITH_SWAPPED_BUFS_ON_FULL_CYCLES_WITH_NEWSIZE_OUTPUT_AND_SKIPCYCLES  *************************/
+
+int process_with_swapped_bufs_on_full_cycles_with_newsize_output_and_skipcycles(float *outbuf,int skip_param,dataptr dz)
+{
+	int exit_status;
+	int current_buf = 0, initial_phase, previous_cycle_crossed_bufs = FALSE;
+	int obufpos = 0, current_pos_in_buf = 0;
+	int cpinbf, iobufpos;
+	int cnt = 0;
+	double  thistime;
+	int lastcycle_len = 0, lastcycle_start;
+
+	display_virtual_time(0,dz);
+	if((exit_status = read_samps(dz->sampbuf[current_buf],dz))<0)
+		return(exit_status);
+	if((exit_status = get_initial_phase(&initial_phase,dz))<0)
+		return(exit_status);
+	if(dz->vflag[IS_DISTORT_SKIP] && (exit_status = skip_initial_cycles(&current_pos_in_buf,&current_buf,initial_phase,skip_param,dz))<0)
+		return(exit_status);
+	do {
+		thistime = (double)(dz->total_samps_read - dz->ssampsread + current_pos_in_buf)/(double)dz->infile->srate;
+		if((exit_status = read_values_from_all_existing_brktables(thistime,dz))<0)
+			return(exit_status);
+		switch(dz->process) {
+		case(DISTORT_AVG):
+			cpinbf = (int)current_pos_in_buf;
+			exit_status = distort_avg(&current_buf,initial_phase,&obufpos,&cpinbf,&cnt,dz);
+			current_pos_in_buf = (int)cpinbf;
+			break;
+		case(DISTORT_SHUF):	
+			exit_status = distort_shuf(&current_buf,initial_phase,&obufpos,&current_pos_in_buf,&cnt,dz);
+			break;
+		case(DISTORT_RPT):
+		case(DISTORT_RPT2):
+			exit_status = distort_rpt(&current_buf,initial_phase,&obufpos,&current_pos_in_buf,&cnt,
+				dz->iparam[DISTRPT_CYCLECNT],&lastcycle_len,&lastcycle_start,&previous_cycle_crossed_bufs,dz);
+			break;
+		case(DISTORT_RPTFL):
+			exit_status = distort_rpt_frqlim(&current_buf,initial_phase,&obufpos,&current_pos_in_buf,&cnt,
+				dz->iparam[DISTRPT_CYCLECNT],dz);
+			break;
+		case(DISTORT_INTP):
+			exit_status = distort_rpt(&current_buf,initial_phase,&obufpos,&current_pos_in_buf,&cnt,
+		   								   1,&lastcycle_len,&lastcycle_start,&previous_cycle_crossed_bufs,dz);
+			break;
+		case(DISTORT_DEL):
+			switch(dz->mode) {
+			case(DELETE_IN_STRICT_ORDER):
+				exit_status = distort_del(&current_buf,&current_pos_in_buf,initial_phase,&obufpos,&cnt,dz);
+				break;
+			case(KEEP_STRONGEST):
+			case(DELETE_WEAKEST):
+				exit_status = distort_del_with_loudness(&current_buf,initial_phase,&obufpos,&current_pos_in_buf,&cnt,dz);
+				break;
+			}
+			break;
+		case(DISTORT_RPL):
+			iobufpos = (int)obufpos;
+			exit_status = distort_rpl(&current_buf,initial_phase,&iobufpos,&current_pos_in_buf,&cnt,dz);
+			obufpos = (int)iobufpos;
+			break;
+		case(DISTORT_TEL):
+			iobufpos = (int)obufpos;
+			cpinbf = (int)current_pos_in_buf;
+			exit_status = distort_tel(&current_buf,initial_phase,&iobufpos,&cpinbf,&cnt,dz);
+			obufpos = (int)iobufpos;
+			current_pos_in_buf = (int)cpinbf;
+			break;
+		case(DISTORT_FLT):
+			cnt = 1;	
+			iobufpos = (int)obufpos;
+			exit_status = distort_flt(&current_buf,initial_phase,&iobufpos,&current_pos_in_buf,dz);
+			obufpos = (int)iobufpos;
+			break;
+		default:
+			sprintf(errstr,"Unknown case in process_with_swapped_bufs_on_full_cycles_with_newsize_output_and_skipcycles()\n");
+			return(PROGRAM_ERROR);
+		}
+	} while(exit_status == CONTINUE);
+	if(exit_status <0)
+		return(exit_status);
+	if(cnt==0) {
+		sprintf(errstr,"source sound too short to attempt this process.\n");
+		return(GOAL_FAILED);
+	}
+	if(obufpos > 0)
+		return write_samps(outbuf,obufpos,dz);
+	return(FINISHED);
+}
+
+/***************************** PROCESS_WITH_SWAPPED_BUF_TO_SWAPPED_OUTBUFS *****************************/
+
+int process_with_swapped_buf_to_swapped_outbufs(dataptr dz)
+{
+	int exit_status;
+	int current_buf = 0, output_phase = 1 /*, cyclemax = 0*/;
+	float cyclemax = 0.0;
+	int lastzero = 0, endsample;
+	int no_of_half_cycles = 0;
+	int startindex, startmarker, endindex;
+	display_virtual_time(0L,dz);
+	if((exit_status = read_samps(dz->sampbuf[current_buf],dz))<0)
+		return(exit_status);
+	if(dz->ssampsread <=0) {
+		sprintf(errstr,"No data found in input soundfile.\n");
+		return(DATA_ERROR);
+	}
+	current_buf = !current_buf;
+	while(dz->samps_left > 0) {
+		read_samps(dz->sampbuf[current_buf],dz);
+		current_buf = !current_buf;
+		switch(dz->process) {
+		case(DISTORT_MLT):
+		case(DISTORT_DIV): 
+			exit_status = mdistort(!LAST,&lastzero,&endsample,&output_phase,current_buf,&cyclemax,
+								&no_of_half_cycles,&startindex,&startmarker,&endindex,dz);
+			break;
+		default:
+			sprintf(errstr,"Unknown case in process_with_swapped_buf_to_swapped_outbufs()\n");
+			return(PROGRAM_ERROR);
+		}
+		if(exit_status<0)
+			return(exit_status);
+		if((exit_status = write_samps(dz->sampbuf[current_buf+2],dz->buflen,dz))<0)
+			return(exit_status);
+		memset((char *)dz->sampbuf[current_buf+2],0,dz->buflen * sizeof(float));
+	}
+	current_buf = !current_buf; 
+	switch(dz->process) {
+	case(DISTORT_MLT): 
+	case(DISTORT_DIV):
+		exit_status = mdistort(LAST,&lastzero,&endsample,&output_phase,current_buf,&cyclemax,
+							&no_of_half_cycles,&startindex,&startmarker,&endindex,dz); 
+		break;
+	default:
+		sprintf(errstr,"Unknown case in process_with_swapped_buf_to_swapped_outbufs()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(exit_status<0)
+		return(exit_status);
+	if(endsample > 0) 
+		return write_samps(dz->sampbuf[current_buf+2],endsample,dz);
+	return(FINISHED);
+}
+
+/******** PROCESS_WITH_SWAPPED_BUFS_ON_FULL_CYCLES_WITH_OPTIONAL_PRESCALE *******/
+
+int process_with_swapped_bufs_on_full_cycles_with_optional_prescale(dataptr dz)
+{
+	int exit_status;
+	int initial_phase;
+	int cnt = 0;
+//TW FIXED -> SAMPS
+	int bufpos = 0, last_total_samps_read = 0;
+	int prescale_param, current_buf = 0;
+	display_virtual_time(0,dz);
+	if((exit_status = read_samps(dz->sampbuf[current_buf],dz))<0)
+		return(exit_status);		
+	switch(dz->process) {
+	case(DISTORT_HRM):	prescale_param = DISTORTH_PRESCALE; break;
+	case(DISTORT_FRC):	prescale_param = DISTORTF_PRESCALE; break;
+	default:
+		sprintf(errstr,"Unknown case: process_with_swapped_bufs_on_full_cycles_with_optional_prescale()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(dz->vflag[IS_PRESCALED])
+		prescale(current_buf,prescale_param,dz);
+	if((exit_status = get_initial_phase(&initial_phase,dz))<0)
+		return(exit_status);
+	exit_status = CONTINUE;
+	switch(dz->process) {
+	case(DISTORT_HRM):
+		while(exit_status==CONTINUE) {
+//TW FIXED-> SAMPS
+			exit_status = distorth(&bufpos,initial_phase,&last_total_samps_read,&current_buf,dz);
+			cnt++;
+		}
+		break;
+	case(DISTORT_FRC):
+		while(exit_status==CONTINUE) {
+//TW FIXED-> SAMPS
+			exit_status = distortf(&bufpos,initial_phase,&last_total_samps_read,&current_buf,dz);
+			cnt++;
+		}
+		break;
+	}
+	if(exit_status<0)
+		return(exit_status);
+	if(cnt <= 1) {
+		sprintf(errstr,"source sound too short to attempt this process.\n");
+		return(GOAL_FAILED);
+	}
+	if(bufpos > 0)
+		return write_samps(dz->sampbuf[current_buf],bufpos,dz);
+	return(FINISHED);
+}
+
+/**************************** PRESCALE *****************************/
+
+/* prescaling added by rwd */
+
+void prescale(int current_buf,int prescale_param,dataptr dz)
+{
+	int i;
+	double temp;
+	for(i=0;i<dz->ssampsread;i++) {
+		temp = (double)dz->sampbuf[current_buf][i];
+		dz->sampbuf[current_buf][i] = (float)/* round*/(temp * dz->param[prescale_param]); /*RWD added cast */
+	}
+}
+
+/**************************** COP_OUT **************************/
+
+int cop_out(int i, int j, int last_total_samps_read, dataptr dz)
+{
+	j = last_total_samps_read + i - j + 1;
+	fprintf(stdout,"WARNING: Program assumes maximum wavelength is %lf secs.\n",MAXWAVELEN);
+	fprintf(stdout,"WARNING: Wavelength too long at infile time %lf secs.\n",(double)j/(double)dz->infile->srate);
+	return(GOAL_FAILED);
+}
+
+/***************************** PROCESS_FILE **************************/
+
+int process_cyclecnt(dataptr dz)
+{
+	int exit_status;
+	/*long i = 0;*/
+	int current_buf = 0;
+	int current_pos_in_buf = 0;
+	int initial_phase;
+	dz->itemcnt = 0;
+	if((exit_status = read_samps(dz->sampbuf[current_buf],dz))<0)
+		return(exit_status);
+	get_initial_phase(&initial_phase,dz);
+	while(cyccnt(&current_pos_in_buf,&current_buf,initial_phase,dz))
+		dz->itemcnt++;
+	sprintf(errstr,"%d cycles found.\n",dz->itemcnt);
+	return(FINISHED);
+}
+
+/************************** CYCCNT *************************/
+
+int cyccnt(int *current_pos_in_buf,int *current_buf,int initial_phase,dataptr dz)
+{
+	int exit_status;
+	register int i = *current_pos_in_buf;
+	float *b = dz->sampbuf[*current_buf];
+	int buffer_overrun = FALSE;
+	switch(initial_phase) {
+	case(1):
+		while(b[i]>=0) {
+			if(++i >= dz->ssampsread) {
+				if((exit_status = change_buf(current_buf,&buffer_overrun,&b,dz))!=CONTINUE)
+					return(FINISHED);
+				i = 0;
+			}
+		}
+		while(b[i]<=0) {
+			if(++i >= dz->ssampsread) {
+				if((exit_status = change_buf(current_buf,&buffer_overrun,&b,dz))!=CONTINUE)
+					return(FINISHED);
+				i = 0;
+			}
+		}
+		break;
+	case(-1):
+		while(b[i]<=0) {
+			if(++i >= dz->ssampsread) {
+				if((exit_status = change_buf(current_buf,&buffer_overrun,&b,dz))!=CONTINUE)
+					return(FINISHED);
+				i = 0;
+			}
+		}
+		while(b[i]>=0) {
+			if(++i >= dz->ssampsread) {
+				if((exit_status = change_buf(current_buf,&buffer_overrun,&b,dz))!=CONTINUE)
+					return(FINISHED);
+				i = 0;
+			}
+		}
+		break;
+	}
+	*current_pos_in_buf = i;
+	return(CONTINUE);
+}

+ 769 - 0
dev/distort/distortm.c

@@ -0,0 +1,769 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <processno.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+
+static int 		do_multiply(int endend,int phaseswitch,int lastzero,int *output_phase,int current_buf,
+				    int *endsample,dataptr dz);
+static int 		do_cros_multiply(int endend,int phaseswitch,int lastzero,int *output_phase,int current_buf,
+						 int *endsample,dataptr dz);
+static int		do_the_division(int i,int *output_phase,int *startindex,int *startmarker,int *endindex,int lastzero,
+						int lastmarker,int *no_of_half_cycles,int current_buf,int *endsample,dataptr dz);
+static int		do_divide(float *ob1,float *ob2,int input_phase,int endend,double ratio,int *output_phase,
+					int startindex,int endindex,int current_buf,int *endsample,dataptr dz);
+static int		do_idivide(float *ob1,float *ob2,int input_phase,int endend,double ratio,int *output_phase,
+			   int startindex,int endindex,int current_buf,int *endsample,dataptr dz);
+static int		too_big(int startindex,int endindex,dataptr dz);
+static int		get_iphase(int startmarker,int startindex,int current_buf,dataptr dz);
+static float	interpval2(int m,int current_buf,double ratio,int startindex,dataptr dz);
+static float	interpval(int m,int current_buf,double ratio,int startindex,dataptr dz);
+static float	getval2(int m,int current_buf,double ratio,int startindex,dataptr dz);
+static float	getval(int m,int current_buf,double ratio,int startindex,dataptr dz);
+static double 	set_ratio(int endend,int startindex,int endindex,dataptr dz);
+static int 		do_md(int crosbuf,int current_buf,int i,int lastzero,int lastmarker,int *output_phase,
+				int *no_of_half_cycles,int *endsample,int *startindex,int *startmarker,
+				int *endindex,dataptr dz);
+
+/************************* MDISTORT ***********************************
+ *
+ * Works on SINGLE HALF wavecycles.
+ *
+ * This looks for single half-wavecycles, and does not change there
+ * number (or their phase) in the output. It therefore resets the
+ * input & output phase on each entry.
+ */
+
+int mdistort(int is_last,int *lastzero,int *endsample,int *output_phase,int current_buf,
+float *cyclemax,int *no_of_half_cycles,int *startindex,int *startmarker,int *endindex,dataptr dz)
+{
+	int exit_status;
+	int crosbuf = FALSE;
+	register int i = *lastzero;
+	int samples, lastmarker, oldbufcnt;
+	int phase;
+	float *b = dz->sampbuf[current_buf];
+	if(is_last)
+		samples  = dz->ssampsread;
+	else
+		samples = dz->buflen;
+//TW CHANGED
+	while(smpflteq(b[i],0.0) && i<samples)
+		i++;	
+	lastmarker = i;
+	if(b[i]<0)
+		phase  = -1;
+	else
+		phase  = 1;
+	while(i < samples)  {
+		switch(phase) {
+		case(1):	    
+			if(b[i] > 0) {
+				if(b[i]>*cyclemax)
+					*cyclemax=b[i];
+				i++;
+			} else {
+				if((exit_status = do_md(crosbuf,current_buf,i,*lastzero,lastmarker,output_phase,
+								  		no_of_half_cycles,endsample,startindex,startmarker,endindex,dz))<0)
+					return(exit_status);
+			 	i = lastmarker = reset(i,samples,b,lastzero,cyclemax);
+				if(b[i]<0)
+					phase = -1;
+			}
+			break;
+		case(-1):
+			if(b[i] < 0.0) {
+				if(b[i]<*cyclemax)
+					*cyclemax=b[i];
+				i++;
+			} else {
+				if((exit_status = do_md(crosbuf,current_buf,i,*lastzero,lastmarker,output_phase,
+										no_of_half_cycles,endsample,startindex,startmarker,endindex,dz))<0)
+					return(exit_status);
+				i = lastmarker = reset(i,samples,b,lastzero,cyclemax);
+				if(b[i]>0.0)
+					phase = 1;
+			}
+			break;
+		}
+	}
+	if(!is_last) {
+		crosbuf = TRUE;
+		oldbufcnt = dz->buflen - *lastzero;
+		b = dz->sampbuf[!current_buf];
+		samples = dz->ssampsread;
+		i = 0;
+		exit_status = CONTINUE;	
+
+		while(exit_status == CONTINUE && i < samples)  {
+			switch(phase) {
+			case(1):	    
+				if(b[i] > 0.0) {
+					if(b[i] > *cyclemax)
+						*cyclemax=b[i];
+					i++;
+				} else {
+					if((exit_status = do_md(crosbuf,current_buf,i,*lastzero,lastmarker,output_phase,
+										no_of_half_cycles,endsample,startindex,startmarker,endindex,dz))<0)
+						return(exit_status);
+			 		i = lastmarker = reset(i,samples,b,lastzero,cyclemax);
+					if(b[i]<0)
+						phase = -1;
+				}
+				break;
+			case(-1):
+				if(b[i] < 0.0) {
+					if(b[i]<*cyclemax)
+						*cyclemax=b[i];
+					i++;
+				} else {
+					if((exit_status = do_md(crosbuf,current_buf,i,*lastzero,lastmarker,output_phase,
+										no_of_half_cycles,endsample,startindex,startmarker,endindex,dz))<0)
+						return(exit_status);
+					i = lastmarker = reset(i,samples,b,lastzero,cyclemax);
+					if(b[i]>0.0)
+						phase = 1;
+				}
+				break;
+			}
+		}
+#ifdef NOTDEF
+		/* removed TW 5:2002 */
+		if(i >= samples) {
+			sprintf(errstr,"wavecycle-group too large for buffer.\n");
+			return(GOAL_FAILED);
+		}
+#endif
+	}
+	return(FINISHED);
+}
+
+/*************************** DO_MULTIPLY ******************************
+ *
+ * (1)	Set up pointers to input and output buffers.
+ * (4)	Length of the complete half_cycle established.
+ * (5)  "mid_cyclelen" is length of first half-cycle in transformed sound.
+ * (6)  "remnant" is the number of samples left over when the cycling factor
+ *	is divided into the true src half_cyclelen.
+ * (7)  "mid_cycle" is buffer index of first half-cycle in transformed sound.
+ * (8)	With no phase-inversion, 1st OUTPUT half_cycle established by indexing
+ *	complete input half_cycle.
+ * (9)	With phase-inversion, ditto + phase-inversion.
+ * (10)	If there are remnant samples, interpolating sample pads are added
+ *	between the output half-cycles, until no remant samples remain.
+ * (1))	For all the remaining output halfcycles, establish start at end of
+ *	previous halfcycle, and end at mid_cycle_len beyond this.
+ * (12)	If it's on odd half-cycle, copy first half-cycle here, with
+ *	phase-inversion.
+ * (13)	But if it's an even half-cycle, copy ditto WITHOUT phase inversion.
+ * (14)	If factor is odd, startphase of transformed segements switch from
+ *	positive to negative and vice versa.
+ */
+
+int do_multiply(int endend,int phaseswitch,int lastzero,int *output_phase,int current_buf,int *endsample,dataptr dz)
+{
+	int  index;
+	register int n, m, k;
+	float *b1  = dz->sampbuf[current_buf];					/* 1 */
+	float *ob1 = dz->sampbuf[current_buf+2];
+	int  start, half_cyclelen, mid_cyclelen, remnant, mid_cycle;
+	half_cyclelen = endend -  lastzero;				/* 4 */
+	mid_cyclelen  = half_cyclelen/dz->iparam[DISTORTM_FACTOR];			/* 5 */
+	if(!mid_cyclelen) {
+		switch(phaseswitch) {
+		case(1):
+			for(n = lastzero; n < endend; n++)	/* i.e. just copy */
+				ob1[n] = b1[n];
+			break;
+		case(-1):
+			for(n = lastzero; n < endend; n++)
+				ob1[n] = -b1[n];
+			break;
+		}
+		return(FINISHED);
+	}
+	remnant	  = half_cyclelen - (mid_cyclelen * dz->iparam[DISTORTM_FACTOR]);	/* 6 */
+	mid_cycle     = lastzero + mid_cyclelen;			/* 7 */
+	switch(phaseswitch) {
+	case(1):
+		for(n = lastzero,m=0; n < mid_cycle; n++,m++) {
+			index = round((double)m * (double)dz->iparam[DISTORTM_FACTOR]);		/* 8 */
+			index += lastzero;
+			ob1[n] = b1[index];
+		}
+		break;
+	case(-1):
+		for(n = lastzero,m=0; n < mid_cycle; n++,m++) {
+			index = round((double)m * (double)dz->iparam[DISTORTM_FACTOR]);		/* 9 */
+			index += lastzero;
+			ob1[n] = -b1[index];
+		}
+		break;
+	}
+	if(remnant) {
+		ob1[mid_cycle] = ob1[mid_cycle-1]/2;				/* 10 */
+		mid_cycle++;
+		remnant--;
+	}
+	for(k=1; k<dz->iparam[DISTORTM_FACTOR]; k++) {
+		start      = mid_cycle;					/* 11 */
+		mid_cycle += mid_cyclelen;
+		if(ODD(k)) {						/* 12 */
+			for(n = start, m = lastzero; n < mid_cycle; n++, m++)
+				ob1[n] = -ob1[m];
+		} else {						/* 13 */
+			for(n = start, m = lastzero; n < mid_cycle; n++, m++)
+				ob1[n] = ob1[m];
+		}
+		if(remnant) {
+			ob1[mid_cycle] = ob1[n-1] /*/2 */ * 0.5f;
+			mid_cycle++;					/* 10 */
+			remnant--;
+		}
+	}
+	if(dz->vflag[DISTORTM_SMOOTH]) {		/* TW MAR:1995 Smoothing at end of cycle */
+		while(mid_cycle < endend) {
+			ob1[mid_cycle] = ob1[mid_cycle-1] /*/2 */ * 0.5f;
+			mid_cycle++;		
+		}
+	}
+	if(ODD(dz->iparam[DISTORTM_FACTOR]))						/* 14 */
+		*output_phase = -(*output_phase);
+	*endsample = endend;
+	return(FINISHED);
+}
+
+/*************************** DO_CROS_MULTIPLY ******************************/
+
+int do_cros_multiply
+(int endend,int phaseswitch,int lastzero,int *output_phase,int current_buf,int *endsample,dataptr dz)
+{
+	/*short*/int  index;			  /* RWD 4:2002 why a short ? */
+	register int m, n, k;
+	float *b1  = dz->sampbuf[current_buf];
+	float *bb, *q;
+	float *ob1 = dz->sampbuf[current_buf + 2];
+	float *b2  = dz->sampbuf[!current_buf];
+	float *ob2 = dz->sampbuf[(!current_buf) + 2];
+	int  start, half_cyclelen, mid_cyclelen, remnant;
+	int  mid_cycle, oldbufcnt;
+	int   is_2nd_buf = 0;
+	half_cyclelen = endend + dz->buflen -  lastzero;
+	mid_cyclelen  = half_cyclelen/dz->iparam[DISTORTM_FACTOR];
+	remnant	  	  = half_cyclelen - (mid_cyclelen * dz->iparam[DISTORTM_FACTOR]);
+	mid_cycle     = lastzero + mid_cyclelen;
+	if(!mid_cyclelen) {		/* i.e. IF WERE TRYING TO CREATE MORE CYCLES THAN THERE ARE SAMPLES */
+		switch(phaseswitch) {
+		case(1):
+			for(n = lastzero; n < dz->buflen; n++)  	/* i.e. just copy */
+				ob1[n] = b1[n];
+			for(n = 0; n < endend; n++)
+				ob2[n] = b2[n];
+			break;
+		case(-1):
+			for(n = lastzero; n < dz->buflen; n++)  	/* i.e. just copy */
+				ob1[n] = -b1[n];
+			for(n = 0; n < endend; n++)
+				ob2[n] = -b2[n];
+			break;
+		}
+		return(FINISHED);
+	}
+/* OTHERWISE: USE dz->sampbuf[4] and [5] AS TEMPORARY STORAGE LOCATIONS */
+	oldbufcnt = dz->buflen - lastzero;
+	bb 		  = dz->sampbuf[4]; 	/* copy start of complete halfcycle to dz->sampbuf[4] */
+	q  		  = b1 + lastzero;
+	memmove(bb,q,oldbufcnt * sizeof(float));
+	bb += oldbufcnt;	/* copy rest of complete halfcycle to end of that */
+	q  = b2;
+	memmove(bb,q,endend * sizeof(float));
+	for(n=0; n < mid_cyclelen; n++) {
+		index = round((double)n * (double)dz->iparam[DISTORTM_FACTOR]);
+		dz->sampbuf[5][n] = dz->sampbuf[4][index];/* convert halfcycle to compressed form */
+	}
+	start = lastzero;
+	if(mid_cycle > dz->buflen)
+		is_2nd_buf = 1;
+	if(!is_2nd_buf) {    	/* GOAL HALFCYCLE LIES IN FIRST BUFFER */
+		switch(phaseswitch) {
+		case(1):
+			for(n=start,m=0; n < mid_cycle; n++,m++)
+				ob1[n] = dz->sampbuf[5][m];
+			break;
+		case(-1):
+			for(n=start,m=0; n < mid_cycle; n++,m++)
+				ob1[n] = -dz->sampbuf[5][m];
+			break;
+		}
+		if(remnant) {
+			if(mid_cycle < dz->buflen) {
+				ob1[mid_cycle] = ob1[n-1]/2;
+				if(++mid_cycle >= dz->buflen) {
+					mid_cycle = 0;
+					is_2nd_buf = 1;
+				}
+			} else {
+				ob2[0] = ob1[dz->buflen-1]/2;
+				mid_cycle = 1;
+				is_2nd_buf = 1;
+			}
+			remnant--;
+		}
+	} else {		/* GOAL HALFCYCLE STRADDLES THE 2 BUFFERS */
+		switch(phaseswitch) {
+		case(1):
+			for(n=start,m=0; n < dz->buflen; n++,m++)
+				ob1[n] = dz->sampbuf[5][m];
+			mid_cycle -= dz->buflen;
+			for(n=0; n < mid_cycle; n++, m++)
+				ob2[n] = dz->sampbuf[5][m];
+			break;
+		case(-1):
+			for(n=start,m=0; n < dz->buflen; n++,m++)
+				ob1[n] = -dz->sampbuf[5][m];
+			mid_cycle -= dz->buflen;
+			for(n=0; n < mid_cycle; n++, m++)
+				ob2[n] = -dz->sampbuf[5][m];
+			break;
+		}
+	}
+	phaseswitch = -phaseswitch;
+	for(k=1; k<dz->iparam[DISTORTM_FACTOR]; k++) {	/* FOR ALL THE OTHER HALF-CYCLES */
+		if(!is_2nd_buf) {
+			start      = mid_cycle;
+			mid_cycle += mid_cyclelen;
+			if(mid_cycle < dz->buflen) {
+				if(phaseswitch==1) {	 /* GOAL HALFCYCLE LIES IN 1ST BUFFER */
+					for(n = start, m = 0; n < mid_cycle; n++, m++)
+						ob1[n] = dz->sampbuf[5][m];
+				} else {
+					for(n = start, m = 0; n < mid_cycle; n++, m++)
+						ob1[n] = -dz->sampbuf[5][m];
+				}
+				if(remnant) {
+					ob1[mid_cycle] = ob1[n-1] /*/2*/ * 0.5f;
+					remnant--;
+					if(++mid_cycle>=dz->buflen) {
+						mid_cycle = 0;
+						is_2nd_buf = 1;
+					}
+				}
+			} else {	/* GOAL HALFCYCLE STRADDLES 2 BUFFERS */
+				mid_cycle -= dz->buflen;
+				if(phaseswitch==1) {
+					for(n = start, m = 0; n < dz->buflen; n++, m++)
+						ob1[n] = dz->sampbuf[5][m];
+					for(n = 0; n < mid_cycle; n++, m++)
+						ob2[n] = dz->sampbuf[5][m];
+				} else {
+					for(n = start, m = 0; n < dz->buflen; n++, m++)
+						ob1[n] = -dz->sampbuf[5][m];
+					for(n = 0; n < mid_cycle; n++, m++)
+						ob2[n] = -dz->sampbuf[5][m];
+				}
+				if(remnant) {
+					if(n>0)
+						ob2[mid_cycle] = ob2[n-1] /*/2 */ * 0.5f;
+					else
+						ob2[mid_cycle] = ob1[dz->buflen-1] /* /2*/ * 0.5f;
+					remnant--;
+					mid_cycle++;
+				}
+				is_2nd_buf = 1;
+			}
+		} else {	/* GOAL HALFCYCLE IS ENTIRELY IN 2nd BUFFER */
+			start  = mid_cycle;
+			mid_cycle += mid_cyclelen;
+			if(phaseswitch==1) {
+				for(n = start, m = 0; n < mid_cycle; n++, m++)
+					ob2[n] = dz->sampbuf[5][m];
+			} else {
+				for(n = start, m = 0; n < mid_cycle; n++, m++)
+					ob2[n] = -dz->sampbuf[5][m];
+			}
+			if(remnant) {
+				ob2[mid_cycle] = ob2[n-1] /* /2 */ * 0.5f;
+				remnant--;
+				mid_cycle++;
+			}
+		}
+		phaseswitch = -phaseswitch;
+	}
+	if(dz->vflag[DISTORTM_SMOOTH]) {	/* TW MAR:1995 Smoothing at end of cycle */
+		if(mid_cycle!=endend) {	
+			if(mid_cycle > endend) {
+				while(mid_cycle < dz->buflen) {
+					ob1[mid_cycle] = ob1[mid_cycle-1]/* /2 */ * 0.5f;
+					mid_cycle++;		
+				}
+				mid_cycle = 0;
+				if(endend>0)
+					ob2[mid_cycle++] =  ob1[dz->buflen-1]/* /2 */ * 0.5f;
+			} else {
+				if(mid_cycle==0)
+					ob2[mid_cycle++] = ob1[dz->buflen-1]/* /2 */ * 0.5f;
+			}
+			while(mid_cycle < endend) {
+				ob2[mid_cycle] = ob2[mid_cycle-1]/* /2 */ * 0.5f;
+				mid_cycle++;
+			}
+		}
+	}
+	if(ODD(dz->iparam[DISTORTM_FACTOR]))		/* CHANGE OUTPUT PHASE FOR NEXT PASS, IF FACTOR IS ODD */
+		*output_phase = -(*output_phase);
+	*endsample = endend;
+	return(FINISHED);
+}
+
+/************************* SET_PHASESWITCH ****************************
+ *
+ * (1)	lastmarker is AFTER lastzero, So if it's bufptr val is LESS
+ *	it must be in the other buffer.
+ * (2)	If the factor is ODD, the start-phase of the waveform switches
+ *	every cycle. In this case, if input phase and output start-phase are
+ *	same, no phase-inversion necessary (phaseswitch = 1). Otherwise
+ *	phase of input signal must be inverted (phaseswitch = -1).
+ *	The logic of the code is equivalent to this (though it takes
+ *	a moment to deduce this!!
+ * (3)  If the factor is even, output start-phase is always positive.
+ *	Hence input phase must be inverted (phaseswitch = -1) only if it is
+ *	-ve.
+ */
+
+int set_phaseswitch(int output_phase,int lastzero,int lastmarker,int current_buf,dataptr dz)
+{
+	float *bbuf = dz->sampbuf[current_buf];
+	if(lastmarker < lastzero)				/* 1 */
+		bbuf = dz->sampbuf[!current_buf];
+	if(ODD(dz->iparam[DISTORTM_FACTOR])) {	/* 2 */
+		if(bbuf[lastmarker] > 0.0)
+			return(output_phase);
+		else    
+			return(-output_phase);
+	} else {								/* 3 */
+		if(bbuf[lastmarker] > 0.0)
+			return(1);
+	}	/* ELSE */
+	return(-1);
+}
+
+/************************* DO_THE_DIVISION ****************************/
+
+int do_the_division(int i,int *output_phase,int *startindex,int *startmarker,int *endindex,int lastzero,
+					int lastmarker,int *no_of_half_cycles,int current_buf,int *endsample,dataptr dz)
+{
+	int exit_status;
+	double ratio;	
+	float  *ob1,*ob2;
+	int    input_phase;
+	(*no_of_half_cycles)++;
+	if(*no_of_half_cycles == 1) {						 
+		*startindex  = lastzero;
+		*startmarker = lastmarker;
+		*endindex = i;
+	} else {
+		if(*no_of_half_cycles >= dz->iparam[DISTORTM_FACTOR]) {
+			if(too_big(*startindex,*endindex,dz)) {
+				sprintf(errstr,"Wavecycle length exceeds buffer length at %lf\n",
+				(double)(dz->total_samps_written + lastzero)/(double)dz->infile->srate);
+				return(GOAL_FAILED);
+			}
+			ratio = set_ratio(i,*startindex,*endindex,dz);
+			ob1 = dz->sampbuf[current_buf + 2];
+			ob2 = dz->sampbuf[(!current_buf) + 2];
+			input_phase = get_iphase(*startmarker,*startindex,current_buf,dz) * (*output_phase);
+			if(dz->vflag[DISTORTD_INTERP])
+				exit_status = do_idivide(ob1,ob2,input_phase,i,ratio,output_phase,*startindex,*endindex,current_buf,endsample,dz);
+			else
+				exit_status = do_divide(ob1,ob2,input_phase,i,ratio,output_phase,*startindex,*endindex,current_buf,endsample,dz);
+			if(exit_status < 0)
+				return(exit_status);
+			*no_of_half_cycles = 0;
+			return(FINISHED);
+		}
+	}
+	return(CONTINUE);
+}
+
+/************************** SET_RATIO ***************************/
+
+double set_ratio(int endend,int startindex,int endindex,dataptr dz)
+{
+	double ratio;
+	if(startindex < endindex) { 
+		if(endindex < endend)    /* SRC CYC & ALL GOAL CYCS IN SAME BUFFER  */
+			ratio =(double)(endindex - startindex)/(double)(endend - startindex);
+		else   		 	/* SRC CYC IN 1 BUF, GOAL CYC CROSSES BUFS */
+			ratio = (double)(endindex - startindex)/(double)(endend + dz->buflen - startindex);
+	} else {		 	 /* SRC CYC & ALL GOAL CYCS, CROSS BUFFERS  */
+		ratio = (double)(endindex + dz->buflen - startindex)/(double)(endend + dz->buflen - startindex);
+	}
+	return(ratio);
+}
+
+/*************************** DO_DIVIDE ******************************/
+
+int do_divide(float *ob1,float *ob2,int input_phase,int endend,double ratio,int *output_phase,
+			   int startindex,int endindex,int current_buf,int *endsample,dataptr dz)
+{
+	register int n, m;
+	switch(input_phase) {
+	case(1):			/* SRC CYCLE AND ENTIRE SET OF GOAL CYCLES IN SAME BUFFER */
+		if(startindex < endindex) {
+			if(endindex < endend) {
+				for(n=startindex,m=0; n <endend; n++,m++)
+					ob1[n] = getval(m,current_buf,ratio,startindex,dz);
+			} else {	/* SRC CYCLE IN ONE BUFFER, GOAL CYCLE CROSSES BUFFER BOUNDARY */
+				for(n=startindex,m=0; n <dz->buflen; n++,m++)
+					ob1[n] = getval(m,current_buf,ratio,startindex,dz);
+				for(n=0; n <endend; n++,m++)
+					ob2[n] = getval(m,current_buf,ratio,startindex,dz);
+			}
+		} else {		/* SRC CYCLE AND SET OF GOAL CYCLES, BOTH CROSS BUFFER BOUNDARY */
+			for(n=startindex,m=0; n <dz->buflen; n++,m++)
+				ob1[n] = getval(m,current_buf,ratio,startindex,dz);
+			for(n=0; n <endend; n++,m++) 
+				ob2[n] = getval2(m,current_buf,ratio,startindex,dz);
+		}
+		break;
+	case(-1):
+		if(startindex < endindex) {
+			if(endindex < endend) { 	/* SRC CYC & ALL GOAL CYCS IN 1 BUFF */
+				for(n=startindex,m=0; n <endend; n++,m++)
+					ob1[n] = -getval(m,current_buf,ratio,startindex,dz);
+			} else {		/* SRC CYC IN 1 BUF, GOAL SET CROSSES BUFFS */
+				for(n=startindex,m=0; n <dz->buflen; n++,m++)
+					ob1[n] = -getval(m,current_buf,ratio,startindex,dz);
+				for(n=0; n <endend; n++,m++)
+					ob2[n] = -getval(m,current_buf,ratio,startindex,dz);
+			}
+		} else {	   		/* SRC CYC & GOAL SET, CROSS BUFFS */
+			for(n=startindex,m=0; n <dz->buflen; n++,m++)
+				ob1[n] = -getval(m,current_buf,ratio,startindex,dz);
+			for(n=0; n <endend; n++,m++)
+				ob2[n] = -getval2(m,current_buf,ratio,startindex,dz);
+		}
+		break;
+	}
+	*output_phase = -(*output_phase);
+	*endsample = endend;
+	return(FINISHED);
+}
+
+/*************************** DO_IDIVIDE ******************************/
+
+int do_idivide(float *ob1,float *ob2,int input_phase,int endend,double ratio,int *output_phase,
+			   int startindex,int endindex,int current_buf,int *endsample,dataptr dz)
+{
+	register int n = 0, m;
+	switch(input_phase) {
+	case(1):
+		if(startindex < endindex) {
+			if(endindex < endend) { /* SRC CYC & ALL GOAL CYCS IN SAME BUFF */
+				for(n=startindex,m=0; n <endend; n++,m++)
+					ob1[n] = interpval(m,current_buf,ratio,startindex,dz);
+			} else {		    /* SRC CYC IN 1 BUF, GOAL CYC CROSSES BUF */
+				for(n=startindex,m=0; n <dz->buflen; n++,m++)
+					ob1[n] = interpval(m,current_buf,ratio,startindex,dz);
+				for(n=0; n <endend; n++,m++)
+					ob2[n] = interpval(m,current_buf,ratio,startindex,dz);
+			}
+		} else {		    /* SRC CYC & GOAL SET, CROSS BUFFERS  */
+			for(n=startindex,m=0; n <dz->buflen; n++,m++)
+				ob1[n] = interpval(m,current_buf,ratio,startindex,dz);
+			for(n=0; n <endend; n++,m++)
+				ob2[n] = interpval2(m,current_buf,ratio,startindex,dz);
+		}
+		break;
+	case(-1):
+		if(startindex < endindex) {
+			if(endindex < endend) {  /* SRC CYC & ALL GOAL CYCS IN SAME BUFF */
+				for(n=startindex,m=0; n <endend; n++,m++)
+					ob1[n] = -interpval(m,current_buf,ratio,startindex,dz);
+			} else {		   		 /* SRC CYC IN 1 BUF, GOAL SET CROSSES BUF */
+				for(n=startindex,m=0; n <dz->buflen; n++,m++)
+					ob1[n] = -interpval(m,current_buf,ratio,startindex,dz);
+				for(n=0; n <endend; n++,m++)
+					ob2[n] = -interpval(m,current_buf,ratio,startindex,dz);
+			}
+		} else {		    		/* SRC CYC & GOAL SET, CROSS BUFFS  */
+			for(n=startindex,m=0; n <dz->buflen; n++,m++)
+				ob1[n] = -interpval(m,current_buf,ratio,startindex,dz);
+			for(n=0; n <endend; n++,m++)
+				ob2[n] = -interpval2(m,current_buf,ratio,startindex,dz);
+		}
+		break;
+	}
+	*output_phase = -(*output_phase);
+	*endsample = n;
+	return(FINISHED);
+}
+
+/************************** GETVAL ******************************/
+
+float getval(int m,int current_buf,double ratio,int startindex,dataptr dz)
+{
+	float *bbuf = dz->sampbuf[current_buf];
+	int index = (int)round((double)m * ratio);
+	if((index += startindex)>=dz->buflen)
+		index = dz->buflen-1;
+	return(bbuf[index]);
+}
+
+/************************ GETVAL2 ****************************/
+
+float getval2(int m,int current_buf,double ratio,int startindex,dataptr dz)
+{
+	float *bbuf;
+	int index = (int)round((double)m * ratio);
+	index += startindex;
+	if(index >= dz->buflen) { 						/* If beyond end of thisbuf, */
+		if((index -= dz->buflen)>=dz->buflen)	/* put index within range    */
+			index = dz->buflen-1;			
+		bbuf = dz->sampbuf[!current_buf];   	/* BUT read from other buf.  */
+	} else
+		bbuf   = dz->sampbuf[current_buf];
+	return(bbuf[index]);
+}
+
+/***************************** INTERPVAL **********************************/
+
+float interpval(int m,int current_buf,double ratio,int startindex,dataptr dz)
+{
+	float *bbuf = dz->sampbuf[current_buf];
+	double findex = (double)m * ratio;
+	int   index  = (int)findex; /* truncate */
+	double frac   = findex - (double)index;
+	float diff,bb,ba;
+	index += startindex;
+	ba     = bbuf[index];
+	if(++index>=dz->buflen) {
+		bbuf = dz->sampbuf[!current_buf];
+		index = 0;
+	}
+	bb = bbuf[index];
+	diff = (float) /*round*/((double)(bb - ba) * frac);
+	return(ba + diff);
+}
+
+/****************************** INTERPVAL2 ***************************/
+
+float interpval2(int m,int current_buf,double ratio,int startindex,dataptr dz)
+{
+	float *bbuf;
+	float diff, ba, bb;
+	double findex = (double)m * ratio;
+	int   index  = (int)findex; /* truncate */
+	double frac   = findex - (double)index;
+	index += startindex;
+	if(index >= dz->buflen) { 						/* If beyond end thisbuf   */
+		if((index -= dz->buflen)>=dz->buflen)		/* put index within range  */
+			index = dz->buflen-1;			
+		bbuf   = dz->sampbuf[!current_buf];        /* BUT read from other buf. */
+		ba     = bbuf[index];
+		if(index < dz->buflen-1)
+			index++;
+	} else {
+		bbuf = dz->sampbuf[current_buf];
+		ba  = bbuf[index];
+		if(++index>=dz->buflen) {	/* IF at very end of buffer */
+			bbuf  = dz->sampbuf[!current_buf];
+			index = 0;				/* goto firstsamp in nextbuf */
+		}
+	}
+	bb = bbuf[index];
+	diff = (float)/*round*/((double)(bb - ba) * frac);
+	return(ba + diff);
+}
+
+/***************************** GET_IPHASE ************************/
+
+int get_iphase(int startmarker,int startindex,int current_buf,dataptr dz)
+{
+	float *bbuf;
+	if(startmarker < startindex)
+		bbuf = dz->sampbuf[!current_buf];
+	else
+		bbuf = dz->sampbuf[current_buf];
+	if(bbuf[startmarker] > 0)
+		return(1);
+	return(-1);
+}
+
+/*************************** TOO_BIG *******************************/
+
+int too_big(int startindex,int endindex,dataptr dz)
+{
+	int wavelen;
+	if((wavelen = endindex - startindex)<0)
+		wavelen += dz->buflen;
+	wavelen *= dz->iparam[DISTORTM_FACTOR];
+	if(wavelen >= dz->buflen)
+		return(1);
+	return(0);
+}
+
+/*************************** DO_MD *******************************/
+
+int do_md(int crosbuf,int current_buf,int i,int lastzero,int lastmarker,int *output_phase,
+	int *no_of_half_cycles,int *endsample,int *startindex,int *startmarker,int *endindex,dataptr dz)
+{
+	int exit_status;
+	double thistime;
+	int phaseswitch;
+	if(*no_of_half_cycles == 0) {
+		thistime = (double)(dz->total_samps_read - dz->ssampsread + lastmarker)/(double)dz->infile->srate;
+		if((exit_status = read_values_from_all_existing_brktables(thistime,dz))<0)
+			return(exit_status);
+	}
+	switch(dz->process) {
+	case(DISTORT_MLT):
+		phaseswitch = set_phaseswitch(*output_phase,lastzero,lastmarker,current_buf,dz);
+		if(crosbuf==TRUE)
+			return do_cros_multiply(i,phaseswitch,lastzero,output_phase,current_buf,endsample,dz);
+		else
+			return do_multiply(i,phaseswitch,lastzero,output_phase,current_buf,endsample,dz);
+	case(DISTORT_DIV):
+		return do_the_division(i,output_phase,startindex,startmarker,endindex,lastzero,lastmarker,
+						no_of_half_cycles,current_buf,endsample,dz);
+	}
+	sprintf(errstr,"Unknown case in do_md()\n");
+	return(PROGRAM_ERROR);
+}

+ 126 - 0
dev/distort/distorto.c

@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+#include <stdlib.h>
+#include <sfsys.h>
+#include <osbind.h>
+
+static int advance_func(int *current_pos_in_buf,dataptr dz);
+
+/**************************** DISTORT_OMT ******************************
+ *
+ * keep 'keep' cycles, omit 'omit' cycles.
+ */
+
+int distort_omt(int *current_pos_in_buf,int inital_phase,dataptr dz)
+{
+	int exit_status;
+	register int n;
+	int i = *current_pos_in_buf;
+	float *b = dz->sampbuf[0];
+	int keep = dz->iparam[DISTORTO_KEEP] - dz->iparam[DISTORTO_OMIT];
+	switch(inital_phase) {
+	case(1):
+		for(n=0;n<keep;n++) {
+			while(b[i]>=0.0) {
+				if((exit_status = advance_func(&i,dz))!=CONTINUE)
+					return(exit_status);
+			}
+			while(b[i]<=0.0) {
+				if((exit_status = advance_func(&i,dz))!=CONTINUE)
+					return(exit_status);
+			}
+		}
+		for(n=0;n<dz->iparam[DISTORTO_OMIT];n++) {
+			while(b[i]>=0.0) {
+				b[i] = 0;
+				if((exit_status = advance_func(&i,dz))!=CONTINUE)
+					return(exit_status);
+			}
+			while(b[i]<=0.0) {
+				b[i] = 0.0;
+				if((exit_status = advance_func(&i,dz))!=CONTINUE)
+					return(exit_status);
+			}
+		}
+		break;
+	case(-1):
+		for(n=0;n<keep;n++) {
+			while(b[i]<=0.0) {
+				if((exit_status = advance_func(&i,dz))!=CONTINUE)
+					return(exit_status);
+			}
+			while(b[i]>=0.0) {
+				if((exit_status = advance_func(&i,dz))!=CONTINUE)
+					return(exit_status);
+			}
+		}
+		for(n=0;n<dz->iparam[DISTORTO_OMIT];n++) {
+			while(b[i]<=00) {
+				b[i] = 0.0;
+				if((exit_status = advance_func(&i,dz))!=CONTINUE)
+					return(exit_status);
+			}
+			while(b[i]>=0.0) {
+				b[i] = 0.0;
+				if((exit_status = advance_func(&i,dz))!=CONTINUE)
+					return(exit_status);
+			}
+		}
+		break;
+	}
+	*current_pos_in_buf = i;
+	return(CONTINUE);
+}
+
+/******************************** ADVANCE_FUNC ***************************/
+
+int advance_func(int *current_pos_in_buf,dataptr dz)
+{
+	int exit_status;
+	if(++(*current_pos_in_buf) >= dz->ssampsread) {
+		if(dz->ssampsread > 0) {
+			if((exit_status = write_samps(dz->sampbuf[0],dz->ssampsread,dz))<0)
+				return(exit_status);
+		}
+		if(dz->samps_left <= 0)
+			return(FINISHED);
+		if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
+			return(exit_status);
+		*current_pos_in_buf = 0;
+	}
+	return(CONTINUE);
+}

+ 246 - 0
dev/distort/distortp.c

@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam vesion */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+#ifdef unix
+#define round(x) lround((x))
+#endif
+
+static int get_distort(int oldlen,int *pos_in_cycle_group,double *last_transpos,double *next_transpos,
+		double *transpos_step,int *thiscyclelen,int *init,dataptr dz);
+static int do_distrt(int oldlen,int *pos_in_cycle_group,double *last_transpos,double *next_transpos,
+		double *transpos_step,int *thiscyclelen,int *init,int *obufremain,int current_inbuf_pos, dataptr dz);
+static int move_to_outbut(int n,int *obufremain,dataptr dz);
+
+/************************* DISTORT_PITCH ***********************************
+ *
+ * Works on SINGLE HALF wavecycles.
+ *
+ * This looks for single half-wavecycles, and does not change there
+ * number (or their phase) in the output. It therefore resets the
+ * input & output phase on each entry.
+ */
+
+int distort_pitch(dataptr dz)
+{
+	int exit_status;
+	int pos_in_cycle_group = 0, thiscyclelen = 0, init = 1;
+	double last_transpos = 0.0, next_transpos = 0.0, transpos_step = 0.0;
+	int obufremain = dz->buflen;
+	int current_buf = 0;
+	int current_inbuf_pos = 0;
+	register int j = 1; /* for gardpnt */
+	int phase, cnt = 0;
+	float *inbuf      = dz->sampbuf[0];
+	float *cyclestore = dz->sampbuf[2];
+	cyclestore[0] = 0; /* gardpnt for wrap_around in interpolating values */
+	if((exit_status = read_samps(inbuf,dz))<0)
+		return(exit_status);
+	if((exit_status = get_initial_phase(&phase,dz))<0)
+		return(exit_status);
+	if((exit_status = skip_initial_cycles(&current_inbuf_pos,&current_buf,phase,DISTPCH_SKIPCNT,dz))<0)
+		return(exit_status);
+	do{
+		while(current_inbuf_pos < dz->ssampsread)  {	
+			switch(phase) {
+			case(1):
+				if(inbuf[current_inbuf_pos] >= 0) {
+					cyclestore[j] = inbuf[current_inbuf_pos];
+					if(++j >= dz->buflen) {
+						sprintf(errstr,"Cycle too large for buffer at %lf\n",
+						(double) dz->total_samps_read/(double)dz->infile->srate);
+						return(GOAL_FAILED);
+					}
+					current_inbuf_pos++;
+				} else {
+					if(inbuf[current_inbuf_pos]<0) {
+						phase=-1;
+						cnt++;
+					}
+				}
+				break;
+			case(-1):
+				if(inbuf[current_inbuf_pos] <= 0) {
+					cyclestore[j] = inbuf[current_inbuf_pos];
+					if(++j >= dz->buflen) {
+						sprintf(errstr,"Cycle too large for buffer at %lf\n",
+						(double)dz->total_samps_read/(double)dz->infile->srate);
+						return(GOAL_FAILED);
+					}
+					current_inbuf_pos++;
+				} else {
+					if(inbuf[current_inbuf_pos]>0) {
+						phase=1;
+						cnt++;
+					}
+				}
+				break;
+			}
+			if(cnt>=2) {	/* i.e. once we have a complete wavecycle */
+				if((exit_status = do_distrt
+				(j-1,&pos_in_cycle_group,&last_transpos,&next_transpos,&transpos_step,&thiscyclelen,&init,&obufremain,current_inbuf_pos,dz))<0)
+					return(exit_status);  /* j-1 = length of cycle */
+				cyclestore[0] = cyclestore[j-1];/*  wrap_around gardpnt for interpolation of values  */
+				j = 1;							/* leave space for grdpnt */
+				cnt = 0;
+			}
+		}
+		if((exit_status = read_samps(inbuf,dz))<0)
+			return(exit_status);
+		current_inbuf_pos = 0;
+	} while(dz->ssampsread>0);
+	if(dz->sbufptr[1]!=dz->sampbuf[1])
+		return write_samps(dz->sampbuf[1],dz->sbufptr[1] - dz->sampbuf[1],dz);
+	return(FINISHED);
+}
+
+/*********************** GET_DISTORT *************************/
+
+int get_distort
+(int oldlen,int *pos_in_cycle_group,double *last_transpos,double *next_transpos,
+double *transpos_step,int *thiscyclelen,int *init,dataptr dz)
+{
+	int newlen;
+	double randval;
+	if(*init) {
+		*thiscyclelen = round(drand48() * (double)dz->iparam[DISTPCH_CYCLECNT]) + 1;
+		*next_transpos = ((drand48() * 2.0) - 1.0) * dz->param[DISTPCH_OCTVAR];
+		*transpos_step = (*next_transpos - *last_transpos)/(double)(*thiscyclelen);
+		*pos_in_cycle_group = 0;
+		*init = 0;
+	} else {
+		if(++(*pos_in_cycle_group) < *thiscyclelen)
+			*last_transpos  += *transpos_step;
+		else {
+			*thiscyclelen  = round(drand48() * (double)dz->iparam[DISTPCH_CYCLECNT]) + 1;
+			*last_transpos = *next_transpos;
+			*next_transpos = ((drand48() * 2.0) - 1.0) * dz->param[DISTPCH_OCTVAR];
+			*transpos_step = (*next_transpos - *last_transpos)/(double)(*thiscyclelen);
+			*pos_in_cycle_group = 0;
+		}
+	}
+	randval = pow(2.0,*last_transpos);
+	newlen = round((double)oldlen * randval);
+	return(newlen);
+}
+		
+/*********************** DO_DISTRT *************************/
+
+int do_distrt(int oldlen,int *pos_in_cycle_group,double *last_transpos,double *next_transpos,
+double *transpos_step,int *thiscyclelen,int *init,int *obufremain,int current_inbuf_pos, dataptr dz)
+{
+	int exit_status;
+	float *cyclestore 		 = dz->sampbuf[2];
+	float *warpedcycle_store = dz->sampbuf[3];
+    int distortbuf_pos = 0, k, newlen;
+	double step, here, ratio;
+	float thisin, nextin;
+	double thistime;
+	if(*init) {
+		if(dz->brksize[DISTPCH_OCTVAR] > 0) {
+			if((exit_status = read_value_from_brktable(0.0,DISTPCH_OCTVAR,dz))<0)
+				return exit_status;
+		}
+		if(dz->brksize[DISTPCH_CYCLECNT] > 0) {
+			if((exit_status = read_value_from_brktable(0.0,DISTPCH_CYCLECNT,dz))<0)
+				return exit_status;
+		}
+	}
+	newlen = get_distort(oldlen,pos_in_cycle_group,last_transpos,next_transpos,transpos_step,thiscyclelen,init,dz);
+	thistime = (double)(dz->total_samps_read - dz->ssampsread + current_inbuf_pos)/(double)dz->infile->srate;
+	if(dz->brksize[DISTPCH_OCTVAR] > 0) {
+		if((exit_status = read_value_from_brktable(thistime,DISTPCH_OCTVAR,dz))<0)
+			return exit_status;
+	}
+	if(dz->brksize[DISTPCH_CYCLECNT] > 0) {
+		if((exit_status = read_value_from_brktable(thistime,DISTPCH_CYCLECNT,dz))<0)
+			return exit_status;
+	}
+	if(newlen <=0)
+		newlen = 1;
+	if(newlen == oldlen)  {
+		memmove((char *)warpedcycle_store,(char *)cyclestore,oldlen * sizeof(float));
+		distortbuf_pos = newlen;
+	} else {	
+		step = (double)oldlen/(double)newlen;
+		here = step;			    
+		while((k = (int)here)<oldlen) {
+			thisin = cyclestore[k];
+			nextin = cyclestore[k+1];
+			ratio = here - (double)k;
+			warpedcycle_store[distortbuf_pos++]  = (float)(/*round*/((double)(nextin - thisin)*ratio) + thisin);
+			if(distortbuf_pos >= dz->buflen) {
+				if((exit_status = move_to_outbut(dz->buflen,obufremain,dz))<0)
+					return(exit_status);
+				distortbuf_pos = 0;
+			}
+			here += step;
+		}
+	}
+	if(distortbuf_pos)
+		return move_to_outbut(distortbuf_pos,obufremain,dz);
+	return(FINISHED);
+}
+
+/*********************** MOVE_TO_OUTBUT *************************/
+
+int move_to_outbut(int n,int *obufremain,dataptr dz)
+{
+	int exit_status;
+	/* dz->sampbuf[1] = outbuf */
+	float *warpedcycle_ptr = dz->sampbuf[3];
+	while(n > *obufremain) {
+		if(*obufremain) {
+			memmove((char *)dz->sbufptr[1],(char *)warpedcycle_ptr,*obufremain * sizeof(float));
+			warpedcycle_ptr += *obufremain;
+			n      -= *obufremain;
+		}
+		if((exit_status = write_samps(dz->sampbuf[1],dz->buflen,dz))<0)
+			return(exit_status);
+		dz->sbufptr[1]  = dz->sampbuf[1];
+		*obufremain 	= dz->buflen;
+	}
+	if(n) {
+ 		memmove((char *)dz->sbufptr[1],(char *)warpedcycle_ptr,n * sizeof(float));
+		dz->sbufptr[1]  += n;
+		*obufremain 	-= n;
+	}
+	return(FINISHED);
+}

+ 121 - 0
dev/distort/distortr.c

@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+static void reverse_cycles(int startpos,int current_pos,int current_buf,dataptr dz);
+//TW UPDATE
+//static void reverse_cycles_crosbuf(int cyclestart,int current_pos,int current_buf,dataptr dz);
+static int  reverse_cycles_crosbuf(int cyclestart,int current_pos,int current_buf,dataptr dz);
+
+/************************** DISTORT_REV **************************/
+
+int distort_rev(int *current_buf,int initial_phase,int *current_pos,int *buffer_overrun,int *cnt,dataptr dz)
+{
+	int exit_status;
+	int cyclestart = *current_pos;
+	float *b = dz->sampbuf[*current_buf];
+	if((exit_status = get_full_cycle(b,buffer_overrun,current_buf,initial_phase,current_pos,DISTORTR_CYCLECNT,dz))!=CONTINUE)
+		return(exit_status);
+//TW UPDATE
+//	if(*buffer_overrun)
+//		reverse_cycles_crosbuf(cyclestart,*current_pos,*current_buf,dz);
+//	else
+	if(*buffer_overrun) {
+		if((exit_status = reverse_cycles_crosbuf(cyclestart,*current_pos,*current_buf,dz))<0)
+			return(exit_status);
+	} else
+		reverse_cycles(cyclestart,*current_pos,*current_buf,dz);	
+	(*cnt)++;
+	return(CONTINUE);
+}
+
+/**************************** REVERSE_CYCLES ***************************/
+
+void reverse_cycles(int startpos,int current_pos,int current_buf,dataptr dz)
+{
+	register int j, endpos = current_pos-1;
+	int midpoint = (current_pos - startpos)/2;	
+	float *buf = dz->sampbuf[current_buf];
+	float dummy;
+	for(j=0;j<midpoint;j++) {
+		dummy           = buf[startpos];
+		buf[startpos++] = buf[endpos];
+		buf[endpos--]   = dummy;
+	}
+}
+
+/******************** REVERSE_CYCLES_CROSBUF ****************/
+
+//TW UPDATE
+//void reverse_cycles_crosbuf(int cyclestart,int current_pos,int current_buf,dataptr dz)
+int reverse_cycles_crosbuf(int cyclestart,int current_pos,int current_buf,dataptr dz)
+{
+//TW UPDATE
+//	int exit_status;
+	float *this_buf      = dz->sampbuf[current_buf];
+	float *previous_buf  = dz->sampbuf[!current_buf];
+	int samps_in_thisbuf = current_pos;
+	int samps_in_previous_buf = dz->buflen - cyclestart;
+	int midpoint  = (samps_in_thisbuf + samps_in_previous_buf)/2;
+	int min_samps_in_one_of_bufs  = min(samps_in_previous_buf,samps_in_thisbuf);
+	register int j, startpos  = cyclestart, endpos  = current_pos - 1;
+	float dummy;
+	for(j=0;j<min_samps_in_one_of_bufs;j++) {
+		dummy                    = previous_buf[startpos];
+		previous_buf[startpos++] = this_buf[endpos];
+		this_buf[endpos--]       = dummy;
+	}
+	if(samps_in_previous_buf>samps_in_thisbuf) {
+		endpos = dz->buflen - 1;
+		for(j=min_samps_in_one_of_bufs;j<midpoint;j++) {
+			dummy                    = previous_buf[startpos];
+			previous_buf[startpos++] = previous_buf[endpos];
+			previous_buf[endpos--]   = dummy;
+		}
+	} else {
+		startpos = 0;
+		for(j=min_samps_in_one_of_bufs;j<midpoint;j++) {
+			dummy                = this_buf[startpos];
+			this_buf[startpos++] = this_buf[endpos];
+			this_buf[endpos--]   = dummy;
+		}
+	}
+
+	return write_samps(dz->sampbuf[!current_buf],dz->buflen,dz);
+}

+ 193 - 0
dev/distort/distorts.c

@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+static int do_shuffle(float *inbuf,int *obufpos,dataptr dz);
+static int do_shuffle_crosbuf(int current_buf,int *obufpos,int cycleno_in_group_at_bufcros,dataptr dz);
+
+/**************************** DISTORT_SHUF ******************************
+ *
+ * Distort file by shuffling GROUPS of cycles.
+ */
+
+int distort_shuf
+(int *current_buf,int initial_phase,int *obufpos,int *current_pos_in_buf,int *cnt,dataptr dz)
+{
+	int exit_status;
+	register int i = *current_pos_in_buf;
+	register int n;
+	int cycleno_in_group_at_bufcros = -1;
+	int cyclecnt = dz->iparam[DISTORTS_CYCLECNT] * dz->iparam[DISTORTS_DMNCNT];
+	float *inbuf  = dz->sampbuf[*current_buf];
+	for(n=0;n<cyclecnt;n++) {
+		dz->lparray[DISTORTS_STARTCYC][n] = i;
+		switch(initial_phase) {
+		case(1):
+			while(inbuf[i]>=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			while(inbuf[i]<=0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			break;
+		case(-1):
+			while(inbuf[i]<=0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			while(inbuf[i]>=0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			break;
+		}
+	}
+	dz->lparray[DISTORTS_STARTCYC][n] = i;
+	if(cycleno_in_group_at_bufcros >= 0)
+		exit_status = do_shuffle_crosbuf(*current_buf,obufpos,cycleno_in_group_at_bufcros,dz);
+	else
+		exit_status = do_shuffle(inbuf,obufpos,dz);
+	if(exit_status<0)
+		return(exit_status);
+	*current_pos_in_buf = i;
+	(*cnt)++;
+	return(CONTINUE);
+}
+
+/*************************** DO_SHUFFLE **************************/
+
+int do_shuffle(float *inbuf,int *obufpos,dataptr dz)
+{
+	/*RWD need this! */
+	int exit_status;
+
+	float *outbuf = dz->sampbuf[2];
+	register int outbufpos = *obufpos, k, m, n;
+	int  grpbase, thiscycle;
+	for(n=0;n<dz->iparam[DISTORTS_IMGCNT];n++) {
+		grpbase = dz->iparray[DISTORTS_MAP][n] * dz->iparam[DISTORTS_CYCLECNT];
+		for(m=0;m<dz->iparam[DISTORTS_CYCLECNT];m++) {
+			thiscycle = grpbase + m;
+			k = dz->lparray[DISTORTS_STARTCYC][thiscycle];
+			while(k < dz->lparray[DISTORTS_STARTCYC][thiscycle+1]) {
+				outbuf[outbufpos] = inbuf[k++];
+				if(++outbufpos >= dz->buflen) {
+					/* RWD 4:2002 added exit_status check */
+					exit_status = write_samps(outbuf,dz->buflen,dz);
+
+					if(exit_status < 0)
+						return exit_status;
+
+					outbufpos = 0;
+				}
+			}		
+		}
+	}
+	*obufpos = outbufpos;
+	return(FINISHED);
+}
+
+/********************** DO_SHUFFLE_CROSBUF *************************/
+
+int do_shuffle_crosbuf(int current_buf,int *obufpos,int cycleno_in_group_at_bufcros,dataptr dz)
+{
+	int exit_status;	/*RWD 4:2002 */
+	float *outbuf = dz->sampbuf[2];
+	register int k, m, n, outbufpos = *obufpos;
+	int  grpbase, thiscycle;
+	float *inbuf;
+	for(n=0;n<dz->iparam[DISTORTS_IMGCNT];n++) {
+		grpbase = dz->iparray[DISTORTS_MAP][n] * dz->iparam[DISTORTS_CYCLECNT];
+		for(m=0;m<dz->iparam[DISTORTS_CYCLECNT];m++) {
+			thiscycle = grpbase + m;
+			k = dz->lparray[DISTORTS_STARTCYC][thiscycle];
+			if(thiscycle == cycleno_in_group_at_bufcros) {
+				inbuf= dz->sampbuf[!current_buf];
+				while(k < dz->buflen) {
+					outbuf[outbufpos] = inbuf[k++];
+					if(++outbufpos >= dz->buflen) {
+						/* RWD 4:2002 added error check */
+						exit_status = write_samps(outbuf,dz->buflen,dz);
+						if(exit_status < 0)
+							return exit_status;
+						outbufpos = 0;
+					}
+				}
+				inbuf = dz->sampbuf[current_buf];
+				k = 0;
+			} else {
+				if(thiscycle < cycleno_in_group_at_bufcros)
+					inbuf = dz->sampbuf[!current_buf];
+				else
+					inbuf = dz->sampbuf[current_buf];
+			}
+			while(k < dz->lparray[DISTORTS_STARTCYC][thiscycle+1]) {
+				outbuf[outbufpos] = inbuf[k++];
+				if(++outbufpos >= dz->buflen) {
+					/*RWD as above */
+					exit_status = write_samps(outbuf,dz->buflen,dz);
+					if(exit_status < 0)
+						return exit_status;
+
+					outbufpos = 0;
+				}
+			}		
+		}
+	}
+	*obufpos = outbufpos;
+	return(FINISHED);
+}

+ 333 - 0
dev/distort/distresize.c

@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+#define	FIRST_FILE	(0)
+#define	SECOND_FILE	(1)
+
+static int get_initial_phases_for_resize(float *samplebuf0,int sampcnt0,float *samplebuf1,int sampcnt1,int *initial_phase);
+static int read_samps_cc(int k,int current_buf,int *bsamps_left,int *samps_read,int *in_samps,dataptr dz);
+static int get_cycles_and_resize(int *,int *,int *,int *,int *,int *,int *,int *,dataptr);
+static int switchbuf(float **b,int *current_buf,int *i,int *samps_left,int *samps_read,int *in_samps,dataptr dz);
+static int read_cycle_from_file0(int *,int *,int *,int *,int *,int *,int,dataptr);
+static int read_cycle_from_file1(int *,int *,int *,int *,int *,int *,int,dataptr);
+static int write_scaled_cycle_to_outbuf(int lastzero,int cyclelen0,int cyclelen1,int current_buf,int *obufpos,dataptr dz);
+
+/***************************** TWO_INFILES_RESIZE_PROCESS *****************************/
+
+int two_infiles_resize_process(dataptr dz)
+{
+	int exit_status;
+	int bsamps_left[2],samps_read[2],in_samps;
+	int current_buf = 0, initial_phase[2];
+	int bufpos_file0 = 0, bufpos_file1 = 0, obufpos = 0;
+	bsamps_left[0] = dz->insams[0];
+	bsamps_left[1] = dz->insams[1];
+	if((exit_status = read_samps_cc(FIRST_FILE,current_buf,bsamps_left,samps_read,&in_samps,dz))<0
+	|| (exit_status = read_samps_cc(SECOND_FILE,current_buf,bsamps_left,samps_read,&in_samps,dz))<0)
+		return(exit_status);
+	if((exit_status = get_initial_phases_for_resize(dz->sampbuf[3],in_samps,dz->sampbuf[0],samps_read[0],initial_phase))<0)
+		return(exit_status);
+	do {
+		exit_status = get_cycles_and_resize
+		(&bufpos_file0,&bufpos_file1,&obufpos,initial_phase,&current_buf,bsamps_left,samps_read,&in_samps,dz);
+	} while(exit_status==CONTINUE);
+	if(obufpos > 0)
+		return write_samps(dz->sampbuf[2],obufpos,dz);
+	return FINISHED;
+}
+
+/**************************** READ_SAMPS_CC ****************************/
+
+int read_samps_cc(int k,int current_buf,int *bsamps_left,int *samps_read,int *in_samps,dataptr dz)
+{
+	int sampsread;
+	switch(k) {
+	case(0):
+		if((sampsread = fgetfbufEx(dz->sampbuf[3], dz->buflen,dz->ifd[0],0)) < 0) {
+			sprintf(errstr, "Can't read from 1st input soundfile\n");
+			return(SYSTEM_ERROR);
+		}
+		bsamps_left[0] -= sampsread;
+		*in_samps = sampsread;
+		break;
+	case(1):
+		if((sampsread = fgetfbufEx(dz->sampbuf[current_buf], dz->buflen,dz->ifd[1],0)) < 0) {
+			sprintf(errstr, "Can't read from 2nd input soundfile\n");
+			return(SYSTEM_ERROR);
+		}
+		bsamps_left[1] -= sampsread;
+		samps_read[current_buf] = sampsread;
+		break;
+	default:
+		sprintf(errstr,"Unknown case in read_samps_cc()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/*************************** GET_INITIAL_PHASES_FOR_RESIZE **********************/
+
+int get_initial_phases_for_resize(float *samplebuf0,int sampcnt0,float *samplebuf1,int sampcnt1,int *initial_phase)
+{
+	int bufpos = 0;
+	while(samplebuf0[bufpos]==0.0 && bufpos < sampcnt0)   
+		bufpos++;
+	if(bufpos >= sampcnt0) {
+		sprintf(errstr,"No siginificant data in first buffer of file 1\n");
+		return(DATA_ERROR);
+	}
+	if(samplebuf0[bufpos] > 0.0)   
+		initial_phase[0] = 1; 
+	else 
+		initial_phase[0] = -1;
+	bufpos = 0;
+//TW
+//	while(samplebuf1[bufpos]==0 && bufpos < sampcnt1)   
+	while(smpflteq(samplebuf1[bufpos],0.0) && bufpos < sampcnt1)   
+		bufpos++;
+	if(bufpos >= sampcnt1) {
+		sprintf(errstr,"No siginificant data in first buffer of file 2\n");
+		return(DATA_ERROR);
+	}
+	if(samplebuf1[bufpos] > 0.0)   
+		initial_phase[1] = 1; 
+	else 
+		initial_phase[1] = -1;
+	return(FINISHED);
+}
+
+/********************************** GET_CYCLES_AND_RESIZE *******************************/
+
+int get_cycles_and_resize(int *bufpos_file0,int *bufpos_file1,int *obufpos,
+int *initial_phase,int *current_buf,int *bsamps_left,int *samps_read,int *in_samps,dataptr dz)
+{
+	int exit_status;
+	int  cyclelen[2] = {0,0};
+	int  lastzero = *bufpos_file1;
+
+	if((exit_status = read_cycle_from_file0
+	(bufpos_file0,&(cyclelen[0]),in_samps,bsamps_left,samps_read,current_buf,initial_phase[0],dz))!=CONTINUE)
+		return(exit_status);
+
+	if((exit_status = read_cycle_from_file1
+	(bufpos_file1,&(cyclelen[1]),in_samps,bsamps_left,samps_read,current_buf,initial_phase[1],dz))!=CONTINUE)
+		return(exit_status);
+
+	return write_scaled_cycle_to_outbuf(lastzero,cyclelen[0],cyclelen[1],*current_buf,obufpos,dz);
+}
+
+/**************************** SWITCHBUF *****************************
+ *
+ * Switch to other input buffer for 2nd infile.
+ */
+
+int switchbuf(float **b,int *current_buf,int *i,int *bsamps_left,int *samps_read,int *in_samps,dataptr dz)
+{
+	int exit_status;
+	if(bsamps_left[1]<=0)
+		return(FINISHED);
+	*current_buf = !(*current_buf);
+	*b = dz->sampbuf[*current_buf];
+	if((exit_status = read_samps_cc(SECOND_FILE,*current_buf,bsamps_left,samps_read,in_samps,dz))<0)
+		return(exit_status);
+	*i = 0;
+	return(CONTINUE);
+}
+
+/**************************** READ_CYCLE_FROM_FILE0 *****************************/
+
+int read_cycle_from_file0
+(int *bufpos_file0,int *cyclelen0,int *in_samps,int *bsamps_left,int *samps_read,
+int *current_buf,int initial_phase, dataptr dz)
+{
+	int exit_status;
+	int i 		= *bufpos_file0;
+	int cyclen = *cyclelen0;
+	float *b = dz->sampbuf[3];
+	switch(initial_phase) {
+	case(1):
+		while(b[i]>=0.0) {
+			cyclen++;
+			if(++i >= *in_samps) {
+				if(bsamps_left[0]<=0)
+					return(FINISHED);
+				if((exit_status = read_samps_cc(FIRST_FILE,*current_buf,bsamps_left,samps_read,in_samps,dz))<0)
+					return(exit_status);
+				i = 0;
+			}
+		}
+		while(b[i]<=0.0) {
+			cyclen++;
+			if(++i >= *in_samps) {
+				if(bsamps_left[0]<=0)
+					return(FINISHED);
+				if((exit_status = read_samps_cc(FIRST_FILE,*current_buf,bsamps_left,samps_read,in_samps,dz))<0)
+					return(exit_status);
+				i = 0;
+			}
+		}
+		break;
+	case(-1):
+		while(b[i]<=0.0) {
+			cyclen++;
+			if(++i >= *in_samps) {
+				if(bsamps_left[0]<=0)
+					return(FINISHED);
+				if((exit_status = read_samps_cc(FIRST_FILE,*current_buf,bsamps_left,samps_read,in_samps,dz))<0)
+					return(exit_status);
+				i = 0;
+			}
+		}
+		while(b[i]>=0.0) {
+			cyclen++;
+			if(++i >= *in_samps) {
+				if(bsamps_left[0]<=0)
+					return(FINISHED);
+				if((exit_status = read_samps_cc(FIRST_FILE,*current_buf,bsamps_left,samps_read,in_samps,dz))<0)
+					return(exit_status);
+				i = 0;
+			}
+		}
+		break;
+	}
+	*bufpos_file0 = i;
+	*cyclelen0 	  = cyclen;
+	return(CONTINUE);
+}
+
+/**************************** READ_CYCLE_FROM_FILE1 *****************************/
+
+int read_cycle_from_file1
+(int *bufpos_file1,int *cyclelen1,int *in_samps,int *bsamps_left,int *samps_read,
+int *current_buf,int initial_phase,dataptr dz)
+{
+	int exit_status;
+	int i = *bufpos_file1;
+	float *b = dz->sampbuf[*current_buf];
+	int cyclen = *cyclelen1;
+	switch(initial_phase) {
+	case(1):
+		while(b[i]>=0.0) {
+			cyclen++;
+			if(++i >= samps_read[*current_buf]) {
+				if((exit_status = switchbuf(&b,current_buf,&i,bsamps_left,samps_read,in_samps,dz))!=CONTINUE)
+					return(exit_status);
+			}
+		}
+		while(b[i]<=0.0) {
+			cyclen++;
+			if(++i >= samps_read[*current_buf]) {
+				if((exit_status = switchbuf(&b,current_buf,&i,bsamps_left,samps_read,in_samps,dz))!=CONTINUE)
+					return(exit_status);
+			}
+		}
+		break;
+	case(-1):
+		while(b[i]<=0.0) {
+			cyclen++;
+			if(++i >= samps_read[*current_buf]) {
+				if((exit_status = switchbuf(&b,current_buf,&i,bsamps_left,samps_read,in_samps,dz))!=CONTINUE)
+					return(exit_status);
+			}
+		}
+		while(b[i]>=0.0) {
+			cyclen++;
+			if(++i >= samps_read[*current_buf]) {
+				if((exit_status = switchbuf(&b,current_buf,&i,bsamps_left,samps_read,in_samps,dz))!=CONTINUE)
+					return(exit_status);
+			}
+		}
+		break;
+	}
+	*bufpos_file1 = i;
+	*cyclelen1 = cyclen;
+	return(CONTINUE);
+}
+
+/**************************** WRITE_SCALED_CYCLE_TO_OUTBUF *****************************/
+
+int write_scaled_cycle_to_outbuf(int lastzero,int cyclelen0,int cyclelen1,int current_buf,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	float *b;
+	int j = *obufpos;
+	int in_previous_buf = FALSE;
+	int sampcnt, index;
+	double scaler = (double)cyclelen1/(double)cyclelen0;
+	if(lastzero + cyclelen1 >= dz->buflen) {
+		b = dz->sampbuf[!current_buf];
+		in_previous_buf = TRUE;
+		for(sampcnt=0;sampcnt<cyclelen0;sampcnt++) {
+			index  = round((double)sampcnt * scaler);
+			index += lastzero;						
+			if(in_previous_buf) {					
+				if(index >= dz->buflen) {			
+					index -= dz->buflen;
+					b     = dz->sampbuf[current_buf];
+					in_previous_buf = FALSE;
+				}
+			} else									
+				index -= dz->buflen;
+			dz->sampbuf[2][j] = b[index];		
+			if(++j >= dz->buflen) {				
+				if((exit_status = write_samps(dz->sampbuf[2],dz->buflen,dz))<0) {
+					sprintf(errstr,"write_samps failed in write_scaled_cycle_to_outbuf()\n");
+					return(exit_status);
+				}
+				j = 0;
+			}
+		}
+	} else {
+		b = dz->sampbuf[current_buf];
+		for(sampcnt=0;sampcnt<cyclelen0;sampcnt++) {
+			index  = round((double)sampcnt * scaler);
+			dz->sampbuf[2][j] = b[index + lastzero];
+			if(++j >= dz->buflen) {				
+				if((exit_status = write_samps(dz->sampbuf[2],dz->buflen,dz))<0) {
+					sprintf(errstr,"write_samps failed in write_scaled_cycle_to_outbuf()\n");
+					return(exit_status);
+				}
+				j = 0;
+			}
+		}
+	}
+	*obufpos = j;
+	return(CONTINUE);
+}

+ 226 - 0
dev/distort/distrpl.c

@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+static int 	do_cycle_loudrep(int n,int current_buf,int current_pos_in_buf,int *obufpos,dataptr dz);
+static int 	do_cycle_loudrep_crosbuf
+			(int n,int cycleno_in_group_at_bufcross,int *current_buf,int current_pos_in_buf,int *obufpos,dataptr dz);
+static int get_ffcycle(int,dataptr);
+static int	write_cycle(int start, int end, int current_buf, int *obufpos,dataptr dz);
+
+/******************************* DISTORT_RPL *****************************/
+
+int distort_rpl(int *current_buf,int initial_phase,int *obufpos,int *current_pos_in_buf,int *cnt,dataptr dz)
+{
+	int exit_status;
+	int n = 0;
+	register int i = *current_pos_in_buf;
+	int	cycleno_in_group_at_bufcross = -1;
+	float *b  = dz->sampbuf[*current_buf];
+	switch(initial_phase) {
+	case(1):
+		for(n=0;n<dz->iparam[DISTRPL_CYCLECNT];n++) {
+			dz->lfarray[DISTRPL_CYCLEVAL][n] = 0;
+			dz->lparray[DISTRPL_STARTCYC][n] = i;
+			while(b[i]>=0.0) {		/* 8 */
+				dz->lfarray[DISTRPL_CYCLEVAL][n] += (float) fabs(b[i]);
+				if(++i >= dz->ssampsread) {	/* 10 */
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcross,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcross = n;
+					i = 0;
+				}
+			}
+			while(b[i]<=0.0) {		/* 18a */
+				dz->lfarray[DISTRPL_CYCLEVAL][n] += (float) fabs(b[i]);
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcross,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcross = n;
+					i = 0;
+				}
+			}
+		}
+		break;
+	case(-1):						/* 18b */
+		for(n=0;n<dz->iparam[DISTRPL_CYCLECNT];n++) {
+			dz->lfarray[DISTRPL_CYCLEVAL][n] = 0.0;
+			dz->lparray[DISTRPL_STARTCYC][n] = i;
+			while(b[i]<=0.0) {
+				dz->lfarray[DISTRPL_CYCLEVAL][n] += (float) fabs(b[i]);
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcross,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcross = n;
+					i = 0;
+				}
+			}
+			while(b[i]>=0.0) {
+				dz->lfarray[DISTRPL_CYCLEVAL][n] += (float) fabs(b[i]);
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcross,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcross = n;
+					i = 0;
+				}
+			}
+		}
+		break;
+	}
+	if(n) {
+		if(cycleno_in_group_at_bufcross >=0)
+			do_cycle_loudrep_crosbuf(n,cycleno_in_group_at_bufcross,current_buf,i,obufpos,dz);
+    	else
+			do_cycle_loudrep(n,*current_buf,i,obufpos,dz);
+	}
+	*current_pos_in_buf = i;
+	(*cnt)++;
+	return(CONTINUE);
+}
+
+/************************** DO_CYCLE_LOUDREP ************************/
+
+int do_cycle_loudrep(int n,int current_buf,int current_pos_in_buf,int *obufpos,dataptr dz)
+{
+	int exit_status;
+   int loudest, k;
+    dz->lparray[DISTRPL_STARTCYC][n] = current_pos_in_buf;
+    loudest = get_ffcycle(n,dz);
+    for(k=0;k<dz->iparam[DISTRPL_CYCLECNT];k++) {
+    	if((exit_status = 
+    	write_cycle(dz->lparray[DISTRPL_STARTCYC][loudest],dz->lparray[DISTRPL_STARTCYC][loudest+1],current_buf,obufpos,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/************************** DO_CYCLE_LOUDREP_CROSBUF ************************/
+
+int do_cycle_loudrep_crosbuf
+(int n,int cycleno_in_group_at_bufcross,int *current_buf,int current_pos_in_buf,int *obufpos,dataptr dz)
+{
+#define LOUDEST_CYCLE_AFTER_BUFCROSS	(0)
+#define LOUDEST_CYCLE_AT_BUFCROSS		(1)
+#define LOUDEST_CYCLE_BEFORE_BUFCROSS	(2)
+	int  exit_status;
+	int loudest, k;
+	int  is_cross;
+	dz->lparray[DISTRPL_STARTCYC][n] = current_pos_in_buf;
+	loudest = get_ffcycle(n,dz);
+	if(loudest > cycleno_in_group_at_bufcross)
+		is_cross = LOUDEST_CYCLE_AFTER_BUFCROSS;
+	else if(cycleno_in_group_at_bufcross == loudest)
+		is_cross = LOUDEST_CYCLE_AT_BUFCROSS;
+	else
+		is_cross = LOUDEST_CYCLE_BEFORE_BUFCROSS;
+
+	for(k=0;k<dz->iparam[DISTRPL_CYCLECNT];k++) {
+		switch(is_cross) {
+		case(LOUDEST_CYCLE_AFTER_BUFCROSS):
+			if((exit_status = 
+			write_cycle(dz->lparray[DISTRPL_STARTCYC][loudest],dz->lparray[DISTRPL_STARTCYC][loudest+1],*current_buf,obufpos,dz))<0)
+				return(exit_status);
+			break;
+		case(LOUDEST_CYCLE_AT_BUFCROSS):
+			(*current_buf) = !(*current_buf);	/* LOOK IN OTHER BUFFER */
+			if((exit_status = 
+			write_cycle(dz->lparray[DISTRPL_STARTCYC][loudest],dz->buflen,*current_buf,obufpos,dz))<0)
+				return(exit_status);
+			(*current_buf) = !(*current_buf);	/* THEN IN CURRENT BUFFER */
+			if((exit_status = 
+				write_cycle(0L,dz->lparray[DISTRPL_STARTCYC][loudest+1],*current_buf,obufpos,dz))<0)
+			return(exit_status);
+			break;	
+		case(LOUDEST_CYCLE_BEFORE_BUFCROSS):
+			(*current_buf) = !(*current_buf);	/* LOOK IN OTHER BUFFER */
+			if((exit_status = 
+			write_cycle(dz->lparray[DISTRPL_STARTCYC][loudest],dz->lparray[DISTRPL_STARTCYC][loudest+1],*current_buf,obufpos,dz))<0)
+				return(exit_status);
+			(*current_buf) = !(*current_buf);	/* RETURN TO CURRENT BUFFER */
+			break;	
+		default:
+			sprintf(errstr,"Unknown case in do_cycle_loudrep_crosbuf()\n");
+			return(PROGRAM_ERROR);
+		}
+	}
+	return(FINISHED);
+}
+
+/************************ GET_FFCYCLE *******************************
+ *
+ * Find loudest cycle.
+ */
+
+int get_ffcycle(int k,dataptr dz)
+{
+	int /*ffcycle = 0,*/ position = 0;
+	float ffcycle = 0;
+	int n;
+	for(n=0;n<k;n++) {
+		if(dz->lfarray[DISTRPL_CYCLEVAL][n] > ffcycle) {
+			ffcycle = dz->lfarray[DISTRPL_CYCLEVAL][n];
+			position = n;
+		}
+	}
+	return(position);
+}
+
+/***************************** WRITE_CYCLE **********************************/
+
+int write_cycle(int start, int end,int current_buf, int *obufpos,dataptr dz)
+{
+	int exit_status;
+	float *b = dz->sampbuf[current_buf];
+	int k;
+	int partoutbuf  = dz->buflen - *obufpos;				/* FIND HOW MUCH ROOM LEFT IN OUTBUF */
+	int insamps_to_write = end - start;   				/* FIND HOW MANY SAMPLES TO WRITE */
+	int outoverflow;		     						/* IF SAMPS-TO-WRITE WON'T FIT IN OUTBUF */
+	if((outoverflow = insamps_to_write - partoutbuf) > 0) {
+		while(*obufpos < dz->buflen)						/* WRITE UP TO END OF OUTBUF */
+			dz->sampbuf[2][(*obufpos)++] = b[start++];
+		if((exit_status = write_samps(dz->sampbuf[2],dz->buflen,dz))<0)
+			return(exit_status);
+		/* WRITE OUTBUF TO FILE */
+		*obufpos = 0;							 		/* RESET OUTBUF BUFFER INDEX TO START OF BUF */
+		insamps_to_write = outoverflow; 				/* RESET INSAMPS-TO-WRITE TO OVERFLOW */
+	}
+	for(k = 0;k < insamps_to_write; k++)
+		dz->sampbuf[2][(*obufpos)++] = b[start++]; 	/*WRITE (REMAINING) INSMPS TO OUTBUF */
+	return(FINISHED);
+}

+ 555 - 0
dev/distort/distrpt.c

@@ -0,0 +1,555 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <processno.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+
+static int 	do_repeat(int current_buf,int incycles_start,int incycles_end,int *obufpos,dataptr dz);
+static int 	do_repeat_bufcros(int current_buf,int incycles_start,int incycles_end,int *obufpos,dataptr dz);
+static int	do_interp(int current_buf,int incycle_start,int incycle_end,int *lastcycle_len,
+				int lastcycle_start,int *previous_cycle_crossed_bufs,int *obufpos,dataptr dz);
+static int	do_interp_bufcros(int current_buf,int incycle_end,int incycle_start,int *lastcycle_len,
+				int lastcycle_start,int *previous_cycle_crossed_bufs,int *obufpos,dataptr dz);
+static int	write_to_outbuf(int *obufpos,int collectbufpos,dataptr dz);
+static int	no_fault_change_buff(float **b,int *current_buf,dataptr dz);
+
+/********************** SKIP_INITIAL_CYCLES ******************************/
+
+int skip_initial_cycles(int *current_pos,int *current_buf,int phase,int skip_paramno,dataptr dz)
+{
+	int exit_status;
+	register int i = 0;
+	int n;
+	float *b = dz->sampbuf[*current_buf];
+	switch(phase) {
+	case(1):
+		for(n=0;n<dz->iparam[skip_paramno];n++) {
+			while(b[i]>=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = no_fault_change_buff(&b,current_buf,dz))<0)
+						return(exit_status);
+				}
+			}
+			while(b[i]<=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = no_fault_change_buff(&b,current_buf,dz))<0)
+						return(exit_status);
+				}
+			}
+		}
+		break;
+	case(-1):
+		for(n=0;n<dz->iparam[skip_paramno];n++) {
+			while(b[i]<=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = no_fault_change_buff(&b,current_buf,dz))<0)
+						return(exit_status);
+				}
+			}
+			while(b[i]>=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = no_fault_change_buff(&b,current_buf,dz))<0)
+						return(exit_status);
+				}
+			}
+		}
+		break;
+	}
+	*current_pos = i;
+	return(FINISHED);
+}
+
+/**************************** DISTORT_RPT ******************************
+ *
+ * Distort file by repeating GROUPS of cycles.
+ */
+
+int distort_rpt(int *current_buf,int initial_phase,int *obufpos,int *current_pos_in_buf,int *cnt,
+	int cyclecnt,int *lastcycle_len,int *lastcycle_start,int *previous_cycle_crossed_bufs,dataptr dz)
+{
+	int exit_status;
+	register int i = *current_pos_in_buf;
+	register int n;
+	int cycleno_in_group_at_bufcros = -1;
+	float *inbuf  = dz->sampbuf[*current_buf];
+	int incycles_end, incycles_start = i, jump_cyclecnt;
+	for(n=0;n<cyclecnt;n++) {
+		switch(initial_phase) {
+		case(1):
+			while(inbuf[i]>=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			while(inbuf[i]<=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			break;
+		case(-1):
+			while(inbuf[i]<=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			while(inbuf[i]>=0.0) {
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			break;
+		}
+	}
+	incycles_end = i;
+	switch(dz->process) {
+	case(DISTORT_INTP):
+		if(cycleno_in_group_at_bufcros >= 0)
+			exit_status = do_interp_bufcros(*current_buf,incycles_start,incycles_end,lastcycle_len,
+										*lastcycle_start,previous_cycle_crossed_bufs,obufpos,dz);
+		else
+			exit_status = do_interp(*current_buf,incycles_start,incycles_end,lastcycle_len,
+										*lastcycle_start,previous_cycle_crossed_bufs,obufpos,dz);
+		*lastcycle_start = *current_pos_in_buf;
+		break;
+	case(DISTORT_RPT):
+	case(DISTORT_RPT2):
+		if(cycleno_in_group_at_bufcros >= 0)
+			exit_status = do_repeat_bufcros(*current_buf,incycles_start,incycles_end,obufpos,dz);
+		else
+			exit_status = do_repeat(*current_buf,incycles_start,incycles_end,obufpos,dz);
+		break;
+	default:
+		sprintf(errstr,"Unknown case in distort_rpt()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(dz->process == DISTORT_RPT2) {
+		jump_cyclecnt = (dz->iparam[DISTRPT_MULTIPLY] - 1) * cyclecnt;
+		for(n=0;n<jump_cyclecnt;n++) {
+			switch(initial_phase) {
+			case(1):
+				while(inbuf[i]>=0) {
+					if(++i >= dz->ssampsread) {
+						if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+							return(exit_status);
+						cycleno_in_group_at_bufcros = n;
+						i = 0;
+					}
+				}
+				while(inbuf[i]<=0) {
+					if(++i >= dz->ssampsread) {
+						if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+							return(exit_status);
+						cycleno_in_group_at_bufcros = n;
+						i = 0;
+					}
+				}
+				break;
+			case(-1):
+				while(inbuf[i]<=0) {
+					if(++i >= dz->ssampsread) {
+						if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+							return(exit_status);
+						cycleno_in_group_at_bufcros = n;
+						i = 0;
+					}
+				}
+				while(inbuf[i]>=0) {
+					if(++i >= dz->ssampsread) {
+						if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+							return(exit_status);
+						cycleno_in_group_at_bufcros = n;
+						i = 0;
+					}
+				}
+				break;
+			}
+		}
+	}
+	if(exit_status<0)
+		return(exit_status);
+	*current_pos_in_buf = i;
+	(*cnt)++;
+	return(CONTINUE);
+}
+
+/*********************** DO_REPEAT *************************/
+
+int do_repeat(int current_buf,int incycles_start,int incycles_end,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	float *obuf, *ibuf = dz->sampbuf[current_buf] + incycles_start;
+	int outcnt = 0;
+	int incycle_len = incycles_end - incycles_start;
+	int incycle_samps = incycle_len;
+	int first_part_outbuf, second_part_outbuf;
+	int next_obufpos;
+	int finished = FALSE;
+	do {
+		while((next_obufpos = *obufpos + incycle_len) <= dz->buflen) { 
+			obuf = dz->sampbuf[2] + *obufpos;
+			memmove((char *)obuf,(char *)ibuf,incycle_samps * sizeof(float));
+			*obufpos = next_obufpos;
+			if(++outcnt >= dz->iparam[DISTRPT_MULTIPLY]) {
+				finished = TRUE;
+				break;
+			}
+		}
+		if(!finished) {
+			first_part_outbuf  = dz->buflen - *obufpos;
+			second_part_outbuf = incycle_len - first_part_outbuf;
+			obuf = dz->sampbuf[2] + *obufpos;
+			memmove((char *)obuf,(char *)ibuf,first_part_outbuf * sizeof(float));
+			obuf = dz->sampbuf[2];
+			if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
+				return(exit_status);
+			memmove((char *)obuf,(char *)(ibuf + first_part_outbuf),second_part_outbuf * sizeof(float));
+			*obufpos = second_part_outbuf;
+			if(++outcnt >= dz->iparam[DISTRPT_MULTIPLY])
+				finished = TRUE;
+		}
+	} while(!finished);
+	return(FINISHED);
+}
+
+/*********************** DO_REPEAT_BUFCROS *************************/
+
+int do_repeat_bufcros(int current_buf,int incycles_start,int incycles_end,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	float *obuf, *ibuf, *tempbuf;
+	int outcnt = 0;
+	int incycles_len = dz->buflen - incycles_start + incycles_end;
+	int incycle_samps = incycles_len;
+	int first_part_inbuf, second_part_inbuf;
+	int first_part_outbuf, second_part_outbuf;
+	int next_obufpos;
+	int finished = FALSE;
+	if(incycles_len >= dz->buflen) {
+		sprintf(errstr,"cycleslen exceeds bufferlen %lf secs\n",
+		(double)(dz->total_samps_read - dz->ssampsread + incycles_start)/(double)dz->infile->srate);
+		return(GOAL_FAILED);
+	}
+	first_part_inbuf  = dz->buflen - incycles_start;
+	second_part_inbuf = incycles_len - first_part_inbuf;
+	ibuf = dz->sampbuf[!current_buf] + incycles_start;
+	tempbuf = dz->sampbuf[3];
+	memmove((char *)tempbuf,(char *)ibuf,first_part_inbuf * sizeof(float));
+	ibuf = dz->sampbuf[current_buf]; 
+	tempbuf += first_part_inbuf;
+	memmove((char *)tempbuf,(char *)ibuf,second_part_inbuf * sizeof(float));
+	ibuf = dz->sampbuf[3];
+	do {
+		while((next_obufpos = *obufpos + incycles_len) <= dz->buflen) { 
+			obuf = dz->sampbuf[2] + *obufpos;
+			memmove((char *)obuf,(char *)ibuf,incycle_samps * sizeof(float));
+			*obufpos = next_obufpos;
+			if(++outcnt >= dz->iparam[DISTRPT_MULTIPLY]) {
+				finished = TRUE;
+				break;
+			}
+		}
+		if(!finished) {
+			first_part_outbuf  = dz->buflen - *obufpos;
+			second_part_outbuf = incycles_len - first_part_outbuf;
+			obuf = dz->sampbuf[2] + *obufpos;
+			memmove((char *)obuf,(char *)ibuf,first_part_outbuf * sizeof(float));
+			obuf = dz->sampbuf[2];
+			if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
+				return(exit_status);
+			memmove((char *)obuf,(char *)(ibuf + first_part_outbuf),second_part_outbuf * sizeof(float));
+			*obufpos = second_part_outbuf;
+			if(++outcnt >= dz->iparam[DISTRPT_MULTIPLY])
+				finished = TRUE;
+		}
+	} while(!finished);
+	return(FINISHED);
+}
+
+/*************************** DO_INTERP ****************************/
+
+int do_interp(int current_buf,int incycle_start,int incycle_end,int *lastcycle_len,
+			int lastcycle_start,int *previous_cycle_crossed_bufs,int *obufpos,dataptr dz)
+{
+	register int k;
+	int 	this_cyclelen, n;
+	double 	part[2], d, ratio;
+	int 	cycpoint[2];
+	int 	incycle_len = incycle_end - incycle_start;
+	int 	cycdiff = incycle_len - *lastcycle_len; /* difference in length of cycles */
+	float 	*tempbuf = dz->sampbuf[3];
+	float 	*inbuf   = dz->sampbuf[current_buf];
+	float 	*collectbuf = dz->sampbuf[4];
+	int 	collectbufpos = 0;
+	int 	maxcyclelen = max(incycle_len,*lastcycle_len);
+	if(maxcyclelen * dz->iparam[DISTINTP_MULTIPLY] > dz->buflen) {
+		sprintf(errstr,"Cycles too long for buffer\n");
+		return(GOAL_FAILED);
+	}
+	if(*lastcycle_len > 0) {		/* very first cycle (lastcycle_len=0)is merely copied: otherwise, interp */
+		for(n=1;n<dz->iparam[DISTINTP_MULTIPLY];n++) {
+			d  = round((double)cycdiff * (double)n/(double)dz->iparam[DISTINTP_MULTIPLY]);
+			d += (double)(*lastcycle_len);
+			this_cyclelen = (int)d; 
+			if(*previous_cycle_crossed_bufs) {
+				for(k=0;k<this_cyclelen;k++) {	   
+					ratio = (double)k/(double)this_cyclelen;
+					cycpoint[0]  = round(ratio * (double)(*lastcycle_len));
+					cycpoint[1]  = round(ratio * (double)incycle_len);
+					cycpoint[1] += incycle_start; 
+					part[0] = (double)tempbuf[cycpoint[0]] * (double)(dz->iparam[DISTINTP_MULTIPLY] - n);
+					part[1] = (double)inbuf[cycpoint[1]] * (double)n;
+					collectbuf[collectbufpos++] = (float)/*round*/((part[0] + part[1])/dz->iparam[DISTINTP_MULTIPLY]);
+				}
+				*previous_cycle_crossed_bufs = FALSE;
+			} else {
+				for(k=0;k<this_cyclelen;k++) {	   
+					ratio = (double)k/(double)this_cyclelen;
+					cycpoint[0]  = round(ratio * (double)(*lastcycle_len));
+					cycpoint[0] += lastcycle_start; 
+					cycpoint[1]  = round(ratio * (double)incycle_len);
+					cycpoint[1] += incycle_start; 
+					part[0] = (double)inbuf[cycpoint[0]] * (double)(dz->iparam[DISTINTP_MULTIPLY] - n);
+					part[1] = (double)inbuf[cycpoint[1]] * (double)n;
+					collectbuf[collectbufpos++] = (float)/*round*/((part[0] + part[1])/dz->iparam[DISTINTP_MULTIPLY]);
+				}
+			}
+		}
+	}
+	/******* COPY GOAL CYCLE ******/
+	memmove((char *)(&(collectbuf[collectbufpos])),(char *)(&(inbuf[incycle_start])),incycle_len * sizeof(float));
+	collectbufpos += incycle_len;
+	*lastcycle_len   = incycle_len;
+	return write_to_outbuf(obufpos,collectbufpos,dz);
+}
+
+/*************************** DO_INTERP_CROSBUF ****************************/
+
+int do_interp_bufcros(int current_buf,int incycle_start,int incycle_end,int *lastcycle_len,int lastcycle_start,
+					   int *previous_cycle_crossed_bufs,int *obufpos,dataptr dz)
+{
+	register int k;
+	int 	this_cyclelen, n;
+	double 	part[2], d, ratio;
+	int 	cycpoint[2];
+	int 	first_incycle_part  = dz->buflen - incycle_start;
+	int 	second_incycle_part = incycle_end;
+	int 	incycle_len = first_incycle_part + second_incycle_part;
+	int 	cycdiff = incycle_len - *lastcycle_len; /* difference in length of cycles */
+	float 	*inbuf;
+	float 	*tempbuf    = dz->sampbuf[3];
+	float 	*collectbuf = dz->sampbuf[4];
+	int 	collectbufpos = 0;
+	int 	maxcyclelen = max(incycle_len,*lastcycle_len);
+	if(maxcyclelen * dz->iparam[DISTINTP_MULTIPLY] > dz->buflen) {
+		sprintf(errstr,"Cycles too long for buffer\n");
+		return(GOAL_FAILED);
+	}
+	if(*previous_cycle_crossed_bufs) { 			/* IF THE CURRENT CYCLE CROSSES A BUFFER, AND THE LAST CYCLE CROSSES */
+		sprintf(errstr,"Buffer space overrun\n"); /* A BUFFER, 2 BUFFER ENDS ARE CROSSED AND WE CAN'T DO THE READING */
+		return(GOAL_FAILED);
+	}
+	*previous_cycle_crossed_bufs = TRUE;
+
+	if(*lastcycle_len > 0) {		/* very first cycle (lastcycle_len=0)is merely copied: otherwise, interp */
+
+		/* PUT BUFFER_CROSSING CYCLE INTO A TEMPORARY STORE */
+		inbuf = dz->sampbuf[!current_buf] + incycle_start;
+		tempbuf = dz->sampbuf[3];
+		memmove((char *)tempbuf,(char *)inbuf,first_incycle_part * sizeof(float));
+		inbuf = dz->sampbuf[current_buf];
+		tempbuf += first_incycle_part;
+		memmove((char *)tempbuf,(char *)inbuf,second_incycle_part * sizeof(float));
+		tempbuf = dz->sampbuf[3];
+
+		for(n=1;n<dz->iparam[DISTINTP_MULTIPLY];n++) {
+			d  = round((double)cycdiff * (double)n/(double)dz->iparam[DISTINTP_MULTIPLY]);
+			d += (double)(*lastcycle_len);
+			this_cyclelen = (int)d; 
+			for(k=0;k<this_cyclelen;k++) {	   
+				ratio = (double)k/(double)this_cyclelen;
+				cycpoint[0]  = round(ratio * (double)(*lastcycle_len));
+				cycpoint[0] += lastcycle_start; 
+				inbuf = dz->sampbuf[!current_buf];	/* PREVIOUS CYC MUST BE COMPLETELY IN PREVIOUS BUF */  
+				part[0] = (double)inbuf[cycpoint[0]] * (double)(dz->iparam[DISTINTP_MULTIPLY]-n);
+				cycpoint[1]  = round(ratio * (double)this_cyclelen);
+				part[1] = (double)tempbuf[cycpoint[1]] * (double)(dz->iparam[DISTINTP_MULTIPLY]-n);
+				collectbuf[collectbufpos++] = (float)/*round*/((part[0] + part[1])/dz->iparam[DISTINTP_MULTIPLY]);
+			}
+		}
+	}
+	/******* COPY GOAL CYCLE ******/
+	memmove((char *)(&(collectbuf[collectbufpos])),(char *)tempbuf,incycle_len * sizeof(float));
+	collectbufpos += incycle_len;
+	*lastcycle_len   = incycle_len;
+	return write_to_outbuf(obufpos,collectbufpos,dz);
+}
+
+
+/****************************** NO_FAULT_CHANGE_BUFF *****************************/
+
+int no_fault_change_buff(float **b,int *current_buf,dataptr dz)
+{
+	if(dz->samps_left <= 0) {
+		sprintf(errstr,"Not enough cycles to perform this process.\n");
+		return(GOAL_FAILED);
+	}
+	*current_buf = !(*current_buf);
+	*b = dz->sampbuf[*current_buf];
+	return read_samps(*b,dz);
+}
+
+/****************************** WRITE_TO_OUTBUF *****************************/
+
+int write_to_outbuf(int *obufpos,int collectbufpos,dataptr dz)
+{
+	int exit_status;	
+	int obuf_free = dz->buflen - *obufpos;
+	int collectbufcnt = collectbufpos;
+	float *collectbuf = dz->sampbuf[4];
+	dz->sbufptr[2] = dz->sampbuf[2] + *obufpos;
+	if(collectbufcnt <= obuf_free) {
+		memmove((char *)dz->sbufptr[2],(char *)collectbuf,collectbufcnt * sizeof(float));
+		*obufpos += collectbufcnt;
+	} else {
+		memmove((char *)dz->sbufptr[2],(char *)collectbuf,obuf_free * sizeof(float));
+		if((exit_status = write_samps(dz->sampbuf[2],dz->buflen,dz))<0)
+			return(exit_status);
+		dz->sbufptr[2] = dz->sampbuf[2];
+		collectbuf    += obuf_free;
+		collectbufcnt -= obuf_free;
+		memmove((char *)dz->sbufptr[2],(char *)collectbuf, collectbufcnt * sizeof(float));
+		*obufpos = collectbufcnt;
+	}
+	return(FINISHED);
+}
+
+/**************************** DISTORT_RPT_FRQLIM ******************************
+ *
+ * Distort file by repeating GROUPS of cycles, but don't count too-short cycles.
+ */
+
+int distort_rpt_frqlim(int *current_buf,int initial_phase,int *obufpos,int *current_pos_in_buf,int *cnt,
+	int cyclecnt,dataptr dz)
+{
+	int exit_status;
+	register int i = *current_pos_in_buf;
+	register int n;
+	int mincyclen = (int)round(dz->infile->srate/dz->param[DISTRPT_CYCLIM]), thiscyclen;
+	int cycleno_in_group_at_bufcros = -1;
+	float *inbuf  = dz->sampbuf[*current_buf];
+	int incycles_end, incycles_start = i;
+	for(n=0;n<cyclecnt;n++) {
+		switch(initial_phase) {
+		case(1):
+			thiscyclen = 0;
+			for(;;) {
+				while(inbuf[i]>=0) {
+					if(++i >= dz->ssampsread) {
+						if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+							return(exit_status);
+						cycleno_in_group_at_bufcros = n;
+						i = 0;
+					}
+					thiscyclen++;
+				}
+				while(inbuf[i]<=0) {
+					if(++i >= dz->ssampsread) {
+						if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+							return(exit_status);
+						cycleno_in_group_at_bufcros = n;
+						i = 0;
+					}
+					thiscyclen++;
+				}
+				if(thiscyclen >= mincyclen)
+					break;
+			}
+			break;
+		case(-1):
+			thiscyclen = 0;
+			for(;;) {
+				while(inbuf[i]<=0) {
+					if(++i >= dz->ssampsread) {
+						if((exit_status = change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+							return(exit_status);
+						cycleno_in_group_at_bufcros = n;
+						i = 0;
+					}
+					thiscyclen++;
+				}
+				while(inbuf[i]>=0) {
+					if(++i >= dz->ssampsread) {
+						if((exit_status =  change_buff(&inbuf,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+							return(exit_status);
+						cycleno_in_group_at_bufcros = n;
+						i = 0;
+					}
+					thiscyclen++;
+				}
+				if(thiscyclen >= mincyclen)
+					break;
+			}
+			break;
+		}
+	}
+	incycles_end = i;
+	if(cycleno_in_group_at_bufcros >= 0)
+		exit_status = do_repeat_bufcros(*current_buf,incycles_start,incycles_end,obufpos,dz);
+	else
+		exit_status = do_repeat(*current_buf,incycles_start,incycles_end,obufpos,dz);
+	if(exit_status<0)
+		return(exit_status);
+	*current_pos_in_buf = i;
+	(*cnt)++;
+	return(CONTINUE);
+}

+ 247 - 0
dev/distort/disttel.c

@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <distort.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <osbind.h>
+
+static int 	do_cycle_tele(int n,int current_buf,int *obufpos,dataptr dz);
+static int 	do_cycle_tele_crosbuf(int n,int cycleno_in_group_at_bufcros,int current_buf,int *obufpos,dataptr dz);
+static int get_longcycle(int,dataptr);
+static int get_meancycle(int,dataptr);
+static float 	indexed_value(float *b,int k,double ratio,dataptr dz);
+static float 	indexed_value_at_crosbuf(float *b,int k,double ratio,int current_buf,dataptr dz);
+
+/******************************* DISTORT_TEL ******************************/
+						 
+int distort_tel(int *current_buf,int initial_phase,int *obufpos,int *current_pos_in_buf,int *cnt,dataptr dz)
+{
+	int exit_status;
+	register int i = *current_pos_in_buf;
+	int n = 0;
+	int cycleno_in_group_at_bufcros = -1;
+	float *b  = dz->sampbuf[*current_buf];
+	switch(initial_phase) {				/* 4 */
+	case(1):
+		for(n=0;n<dz->iparam[DISTTEL_CYCLECNT];n++) {		/* 5 */
+			dz->lparray[DISTTEL_CYCLEVAL][n] = 0;			/* 6 */
+			dz->lparray[DISTTEL_STARTCYC][n] = i;		/* 7 */
+			while(b[i]>=0.0) {		/* 8 */	
+				/* RWD NB this is counting samples */
+				dz->lparray[DISTTEL_CYCLEVAL][n]++;
+				if(++i >= dz->ssampsread) {	/* 10 */
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			while(b[i]<=0.0) {		/* 18a */
+				dz->lparray[DISTTEL_CYCLEVAL][n]++;
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+		}
+		break;
+	case(-1):						/* 18b */
+		for(n=0;n<dz->iparam[DISTTEL_CYCLECNT];n++) {
+			dz->lparray[DISTTEL_CYCLEVAL][n] = 0;
+			dz->lparray[DISTTEL_STARTCYC][n] = i;
+			while(b[i]<=0.0) {
+				dz->lparray[DISTTEL_CYCLEVAL][n]++;
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+			while(b[i]>=0.0) {
+				dz->lparray[DISTTEL_CYCLEVAL][n]++;
+				if(++i >= dz->ssampsread) {
+					if((exit_status = change_buff(&b,&cycleno_in_group_at_bufcros,current_buf,dz))!=CONTINUE)
+						return(exit_status);
+					cycleno_in_group_at_bufcros = n;
+					i = 0;
+				}
+			}
+		}
+		break;
+	}
+	if(n) {
+		if(cycleno_in_group_at_bufcros >= 0) {
+			exit_status = do_cycle_tele_crosbuf(n,cycleno_in_group_at_bufcros,*current_buf,obufpos,dz);
+		} else {
+			exit_status = do_cycle_tele(n,*current_buf,obufpos,dz);
+		}
+		if(exit_status<0)
+			return(exit_status);
+	}
+	*current_pos_in_buf = i;
+	(*cnt)++;
+	return(CONTINUE);
+}
+
+/*************************** DO_CYCLE_TELE *************************/
+
+int do_cycle_tele(int n,int current_buf,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	float *b = dz->sampbuf[current_buf];
+	double ratio;
+	int k, j, reflength/*, cyclesum*/;
+	float cyclesum;
+	/*int*/float average_value;
+	if(dz->vflag[IS_DISTTEL_AVG])
+		reflength = get_meancycle(n,dz);
+	else
+		reflength = get_longcycle(n,dz);
+	for(j = 0;j < reflength; j++) {
+		ratio = (double)j/(double)reflength;
+		cyclesum = 0.0;
+		k = 0;
+		while(k<n)
+			cyclesum += indexed_value(b,k++,ratio,dz);
+		average_value = (float) /*round*/ ((double)cyclesum/(double)n);
+		if((exit_status = output_val(average_value,obufpos,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/*************************** DO_CYCLE_TELE_CROSBUF *************************/
+
+int do_cycle_tele_crosbuf(int n,int cycleno_in_group_at_bufcros,int current_buf,int *obufpos,dataptr dz)
+{							 
+	int exit_status;
+	float *b;
+	double ratio;
+	int k, j, reflength /*, cyclesum*/;
+	float cyclesum;
+	/*int*/float average_value;
+	if(dz->vflag[IS_DISTTEL_AVG])
+		reflength = get_meancycle(n,dz);
+	else
+		reflength = get_longcycle(n,dz);
+	for(j = 0;j < reflength; j++) {
+		ratio = (double)j/(double)reflength;
+		cyclesum = 0.0;
+		k = 0;
+		b = dz->sampbuf[!current_buf];
+		while(k < cycleno_in_group_at_bufcros)
+			cyclesum += indexed_value(b,k++,ratio,dz);
+		cyclesum += indexed_value_at_crosbuf(b,k++,ratio,current_buf,dz);
+		b = dz->sampbuf[current_buf];
+		while(k<n)
+			cyclesum += indexed_value(b,k++,ratio,dz);
+		average_value = (float) /*round*/((double)cyclesum/(double)n);
+		if((exit_status = output_val(average_value,obufpos,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+
+/***************************** INDEXED_VALUE ***********************/
+
+float indexed_value(float *b,int k,double ratio,dataptr dz)
+{
+	int index = round((double)(dz->lparray[DISTTEL_CYCLEVAL][k])*ratio);
+	index += dz->lparray[DISTTEL_STARTCYC][k];
+	return b[index];
+}
+
+/*********************** INDEXED_VALUE_AT_CROSBUF ***********************/
+
+float indexed_value_at_crosbuf(float *b,int k,double ratio,int current_buf,dataptr dz)
+{
+	int index = round((double)(dz->lparray[DISTTEL_CYCLEVAL][k])*ratio);
+	index += dz->lparray[DISTTEL_STARTCYC][k];
+	if(index >= dz->buflen) {
+		index -= dz->buflen;
+		b = dz->sampbuf[current_buf];
+	}
+	return b[index];
+}
+
+/************************ GET_LONGCYCLE *******************************
+ *
+ * Find longest cycle.
+ */
+
+int get_longcycle(int k,dataptr dz)
+{
+	int longest = 0;
+	int n;
+	for(n=0;n<k;n++) {
+		if(dz->lparray[DISTTEL_CYCLEVAL][n] > longest)
+			longest = dz->lparray[DISTTEL_CYCLEVAL][n];
+	}
+	return(longest);
+}
+
+/************************ GET_MEANCYCLE *******************************
+ *
+ * Find average cycle length.
+ */
+
+int get_meancycle(int k,dataptr dz)
+{
+	int sum = 0, mean;
+	int n;
+	for(n=0;n<k;n++)
+		sum += dz->lparray[DISTTEL_CYCLEVAL][n];
+	mean = round((double)sum/(double)k);
+	return(mean);
+}
+
+/************************* OUTPUT_VAL **********************/
+
+int output_val(float value,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	dz->sampbuf[2][(*obufpos)++] = value;
+	if(*obufpos>=dz->buflen) {
+		if((exit_status = write_samps(dz->sampbuf[2],dz->buflen,dz))<0)
+			return(exit_status);
+		*obufpos = 0;
+	}
+	return(FINISHED);
+}

+ 236 - 0
dev/distort/main.c

@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+/* floatsam version */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <distort.h>
+#include <filetype.h>
+#include <processno.h>
+#include <modeno.h>
+#include <formants.h>
+#include <cdpmain.h>
+#include <special.h>
+#include <logic.h>
+#include <globcon.h>
+#include <cdpmain.h>
+
+#include <sfsys.h>
+#include <ctype.h>
+#include <string.h>
+
+char errstr[2400];
+
+/* extern */ int	sloom = 0;
+/* extern */ int sloombatch = 0;	/*TW may 2001 */
+/* extern */ int anal_infiles = 0;
+/* extern */ int is_converted_to_stereo = -1;
+const char* cdp_version = "7.1.0";
+
+/**************************************** MAIN *********************************************/
+
+int main(int argc,char *argv[])
+{
+	int exit_status;
+	dataptr dz = NULL;
+//	char *special_data_string = NULL;
+	char **cmdline;
+	int  cmdlinecnt;
+	aplptr ap;
+	int *valid = NULL;
+	int is_launched = FALSE;
+	int  validcnt = 0;
+
+	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);
+		}
+					  /* GET PRE_DATA, ALLOCATE THE APPLICATION, CHECK FOR EXTRA INFILES */
+		cmdline    = argv;
+		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++;
+	}
+	
+/*********************************************************************************************************************
+		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);
+}
+

+ 767 - 0
dev/distort/pulse.c

@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <cdpmain.h>
+#include <tkglobals.h>
+#include <pnames.h>
+#include <distort.h>
+#include <processno.h>
+#include <modeno.h>
+#include <globcon.h>
+#include <logic.h>
+#include <filetype.h>
+#include <mixxcon.h>
+#include <distort1.h>
+#include <flags.h>
+#include <speccon.h>
+#include <arrays.h>
+#include <special.h>
+#include <formants.h>
+#include <sfsys.h>
+#include <osbind.h>
+#include <string.h>
+#include <arrays.h>
+#include <math.h>
+#include <ctype.h>
+
+/*
+
+PRESCALE PULSE-ENVELOPE FILE BETWEEN 0 and 1 in time and copy into parray[PULSENV]
+PRESCALE PULSE-TRANSPOS FILE BETWEEN 0 and 1 in time and copy into parray[PULSTRN]
+
+NB randomisation pulse-transposition only works if it's a brktable
+
+HAS TO BE MONO SNDFILE;
+
+*/
+
+static int	write_pulse_to_output(int *pbufpos,int *obufpos,dataptr dz);
+static void	randomise_pulse_transposition(dataptr dz);
+static int	randomise_pulse_envelope(int obufpos,dataptr dz);
+static double	gen_sndtabindex(int obufpos,double *sndtabindex,double *pulsenvindex,double *envstep,
+					int insertsmps,double tablen,int randomise_transpos,dataptr dz);
+static int	extract_waveform(int *waveset_start,dataptr dz);
+static int	get_wavesetstart(int ibufpos,dataptr dz);
+/* in ap_distort */
+static int	prescale_pulse_transpos(dataptr dz);
+static int	read_impulse_amp_val(double thistime,double *amp,dataptr dz);
+
+/************************************* PREPROCESS_PULSE *************************************/
+
+int preprocess_pulse(dataptr dz)
+{
+	double k;
+	int exit_status;
+	if(dz->iparam[PULSE_ENVSIZE] > 0) {
+		if((dz->parray[PULSENV] = (double *)malloc((dz->iparam[PULSE_ENVSIZE] * 2) * sizeof(double)))==NULL) {
+			sprintf(errstr,"Out of memory for storing backup of original pulse envelope.\n");
+			return(MEMORY_ERROR);
+		}
+		memcpy((char *)dz->parray[PULSENV],(char *)dz->parray[ORIG_PULSENV],(dz->iparam[PULSE_ENVSIZE] * 2) * sizeof(double));
+								/* copy original envelope into parray */
+		if((dz->iparray[0] = (int *)malloc(dz->iparam[PULSE_ENVSIZE] * sizeof(int)))==NULL) {
+			sprintf(errstr,"Out of memory for storing markers for envelope warping.\n");
+			return(MEMORY_ERROR);
+		}
+	}
+	if(dz->brksize[PULSE_TRANSPOS] > 0) {
+		if((exit_status = prescale_pulse_transpos(dz))<0)
+			return(exit_status);
+	} else {
+		k = dz->param[PULSE_TRANSPOS] / 12.0;
+		dz->param[PULSE_TRANSPOS] = pow(2.0,k);	/* convert semitones to frq-ratio */
+	}
+	return(FINISHED);
+}
+
+/*********************************** PRESCALE_PULSE_TRANSPOS *************************************/
+
+int prescale_pulse_transpos(dataptr dz)
+{
+	int brklen = dz->brksize[PULSE_TRANSPOS] * 2;
+	int maxtimindx = brklen  - 2;
+	int n,m;
+	double maxtime = dz->brk[PULSE_TRANSPOS][maxtimindx], scaler;
+	scaler = 1.0/maxtime;
+	for(n=0,m=1;n<brklen;n+=2,m+=2)
+		dz->brk[PULSE_TRANSPOS][n] *= scaler;			/* scale to 0 to 1 time range */
+	dz->brk[PULSE_TRANSPOS][maxtimindx] = 1.0;
+	if((dz->parray[PULSTRN] = (double *)malloc(brklen * sizeof(double)))==NULL) {
+		sprintf(errstr,"Out of memory for storing backup of original pulse transposition envelope\n");
+		return(MEMORY_ERROR);
+	}
+	memcpy((char *)dz->parray[PULSTRN],(char *)dz->brk[PULSE_TRANSPOS],brklen * sizeof(double));
+	return(FINISHED);
+}
+
+/************************************* DO_PULSETRAIN *************************************/
+
+int do_pulsetrain(dataptr dz)
+{
+	int exit_status;
+	float *ibuf = dz->sampbuf[0];	/* stores input  */
+	float *obuf = dz->sampbuf[1];	/* stores output */
+	float *sbuf = dz->sampbuf[2];	/* stores waveset cycoes, for SYN option  */
+	float *pbuf = dz->sampbuf[3];	/* stores pulse, before writing to output */
+	int srate = dz->infile->srate;
+	float *spliceptr, *obufend = obuf + dz->buflen;
+	int startsamp = round(dz->param[PULSE_STARTTIME] * srate);
+	int insertdur = round(dz->param[PULSE_DUR] * srate);
+	int last_total_ssampsread, total_ssampsread = 0, ssampsread = 0, insertsmps = 0;
+	int  smpsecsize = F_SECSIZE, secsleft, edit_todo = (int)round(ENDBIT_SPLICE);
+	int ibufpos = 0, ibufleft, obufpos = 0, pbufpos = 0, obufleft;
+	double amp, frq, sndtabindex, pulsenvindex;
+	int waveset_len = 0;
+	double envstep;
+	int randomise_transpos = 0, firsttime = 1;
+	int smps_pretime, waveset_start;
+	double interp, valdiff, k;
+	float val, upval;
+	int here, n, m;
+
+	if(dz->mode == PULSE_SYNI)
+		startsamp = dz->iparam[PULSE_STARTTIME];
+	else
+		startsamp = round(dz->param[PULSE_STARTTIME] * srate);
+
+	/* PROCESS FILE PRIOR TO PULSE-TRAIN'S START, IF NESS */ 
+
+	if(dz->mode == PULSE_IMP) {
+		k = dz->duration;
+		if(!dz->vflag[PULSE_KEEPSTART]) {
+			k -= dz->param[PULSE_STARTTIME];
+			if(!dz->vflag[PULSE_KEEPEND])
+				k = min(dz->param[PULSE_DUR],k);
+		} else if(!dz->vflag[PULSE_KEEPEND]) {
+			k = dz->param[PULSE_STARTTIME] + dz->param[PULSE_DUR];
+			k = min(dz->duration,k);
+		}
+	} else {
+		k = dz->param[PULSE_DUR];
+		if(dz->vflag[PULSE_KEEPEND]) {
+			k += dz->duration;
+			if(!dz->vflag[PULSE_KEEPSTART])
+				k -= dz->param[PULSE_STARTTIME];
+		} else if(dz->vflag[PULSE_KEEPSTART])
+			k += dz->param[PULSE_STARTTIME];
+	}
+	dz->tempsize = (int)round(k * (dz->infile->srate));
+
+	while(total_ssampsread + dz->buflen < startsamp) {
+		if(( exit_status = read_samps(ibuf,dz)) < 0) {
+			sprintf(errstr, "Can't read samps from input soundfile\n");
+			return(SYSTEM_ERROR);
+		}
+		ssampsread = dz->ssampsread;
+		last_total_ssampsread = total_ssampsread;
+		total_ssampsread += ssampsread;
+		if(dz->vflag[PULSE_KEEPSTART]) {
+			if(ssampsread > 0) {
+				if((exit_status = write_samps(ibuf,ssampsread,dz))<0)
+					return(exit_status);
+			}
+		}
+	}
+	if((secsleft = (startsamp - total_ssampsread)/smpsecsize)> 0) {
+		if(( ssampsread = fgetfbufEx(ibuf,secsleft * F_SECSIZE, dz->ifd[0],0)) < 0) {
+			sprintf(errstr, "Can't read samps from input soundfile\n");
+			return(SYSTEM_ERROR);
+		}
+		last_total_ssampsread = total_ssampsread;
+		total_ssampsread += ssampsread;
+		if(dz->vflag[PULSE_KEEPSTART]) {
+			if(ssampsread > 0) {
+				if((exit_status = write_samps(ibuf,ssampsread,dz))<0)
+					return(exit_status);
+			}
+		}
+	}
+	smps_pretime = startsamp - total_ssampsread;	/* no of samples before param-specified time */
+
+	if(( ssampsread = fgetfbufEx(ibuf, dz->buflen + F_SECSIZE, dz->ifd[0],0)) < 0) {
+		sprintf(errstr, "Can't read samples from input soundfile\n");	/* To get wraparound points */
+		return(SYSTEM_ERROR);
+	}
+	last_total_ssampsread = total_ssampsread;
+	if(ssampsread > dz->buflen) {	
+		sndseekEx(dz->ifd[0],last_total_ssampsread + dz->buflen,0);
+		total_ssampsread = last_total_ssampsread + dz->buflen;
+	} else {	/* We'RE AT END oF FILE... */	
+		total_ssampsread = last_total_ssampsread + ssampsread;
+		ibuf[ssampsread] = 0.0;	/* CREATE zero-val wraparound points */
+		
+	}
+
+	/* FIND START OF WAVESETS */ 
+
+	if((waveset_start = get_wavesetstart(smps_pretime,dz)) < 0) {
+		sprintf(errstr,"Can't find the required waveset start within a single buffer.\n");
+		return(GOAL_FAILED);
+	}
+	if((waveset_start > 0) && dz->vflag[PULSE_KEEPSTART]) {
+		memcpy((char *)obuf,(char *)ibuf,waveset_start * sizeof(float));
+		obufpos = waveset_start;	/* copy any inbuf remnant prior to pulsing, to outbuf */
+	}
+	ibufpos = waveset_start;
+
+	if(dz->mode!=PULSE_IMP)	{
+		if((waveset_len = extract_waveform(&waveset_start,dz))<0) {	/* NB copy rounding sample[s] at end */
+			sprintf(errstr,"Can't find the required wavesets within a single buffer.\n");
+			return(GOAL_FAILED);
+		}
+		sndtabindex = 0.0;							/* position in storage buffer */
+	} else
+		sndtabindex = (double)waveset_start;		/* position in input buffer */
+
+	/* INITIALISE SHAPE AND LENGTH OF FIRST IMPULSE */ 
+
+	if(dz->iparam[PULSE_ENVSIZE] > 0)
+		randomise_pulse_envelope(obufpos,dz);	/* randomise shape of pulse, and copy reshaped pulse to read-env-table */
+										/* +insert edit shoulders at start and end */
+	if(!flteq(dz->param[PULSE_PITCHRAND],0.0)) {
+		randomise_transpos = 1;
+		if(dz->brksize[PULSE_TRANSPOS] <= 0) {
+			fprintf(stdout,"WARNING: Randomisation of transposition only applies to a transposition TABLE\n");
+			fflush(stdout);
+			randomise_transpos = 0;
+		} else
+			randomise_pulse_transposition(dz);
+	} else if (dz->brksize[PULSE_TRANSPOS] > 0) {		/* if NOT randomised, convert to frqratio NOW */
+		for(n=0,m=1;n<dz->brksize[PULSE_TRANSPOS];n++,m+=2) {
+			k = dz->parray[PULSTRN][m]/SEMITONES_PER_OCTAVE;
+			dz->brk[PULSE_TRANSPOS][m] = pow(2.0,k);
+		}
+	}
+	pulsenvindex = 0.0;
+	if(dz->iparam[PULSE_ENVSIZE] <= 0)
+		amp = 1.0;
+	else
+		amp = dz->parray[PULSENV][0];
+	if(dz->brksize[PULSE_FRQ] > 0) {
+		if((exit_status = read_value_from_brktable(0.0,PULSE_FRQ,dz))<0)
+			return exit_status;
+	}
+	frq = dz->param[PULSE_FRQ];
+	if(dz->param[PULSE_FRQRAND] > 0.0) {
+		k = ((drand48() * 2.0) - 1.0) * dz->param[PULSE_FRQRAND];
+		k /= SEMITONES_PER_OCTAVE;
+		k = pow(2.0,k);
+		frq *= k;
+	}
+	envstep = frq/srate;
+
+	/* DO IMPULSE TRAIN */ 
+
+	while(insertsmps < insertdur) {
+		if(!firsttime && flteq(pulsenvindex,0.0)) {	/* if at start of new pulse */
+			if((exit_status = write_pulse_to_output(&pbufpos,&obufpos,dz))<0)
+				return(exit_status);
+		}
+		firsttime = 0;
+		if(dz->mode!=PULSE_IMP)	{
+			interp = fmod(sndtabindex,1.0);
+			here = (int)floor(sndtabindex);
+			val    = sbuf[here++];
+			upval  = sbuf[here];
+			valdiff = (upval - val) * interp;
+			pbuf[pbufpos++] = (float)((val + valdiff) * amp);
+			if(pbufpos >= dz->buflen) {
+				sprintf(errstr,"Pulse length exceeds length of internal buffer : cannot proceed.\n");
+				return(GOAL_FAILED);
+			}
+		} else {
+			interp = fmod(sndtabindex,1.0);
+			ibufpos = (int)floor(sndtabindex);
+			while(ibufpos  >= ssampsread) {
+				/* read extra sector, for wraparound vals for interpolation */
+				if(( ssampsread = fgetfbufEx(ibuf, dz->buflen + F_SECSIZE, dz->ifd[0],0)) < 0) {
+					sprintf(errstr, "Can't read samps from input soundfile\n");	/* read failed */
+					return(SYSTEM_ERROR);
+				}
+				if(ssampsread <= 0) {	/* read zero bytes = EOF */
+					if(obufpos > 0) {
+						if((exit_status = write_samps(obuf,obufpos,dz))<0)
+							return(exit_status);
+					}
+					return(FINISHED);
+				}
+				if(ssampsread <= dz->buflen) {	/* generate zero-val wraparound points if buffer+wrap not full */
+					ibuf[ssampsread] = 0.0;
+					total_ssampsread += ssampsread;
+				} else {
+					last_total_ssampsread = total_ssampsread;
+					ssampsread = dz->buflen;	/* effective read is a buffer-full */
+					total_ssampsread += ssampsread;
+					sndseekEx(dz->ifd[0],last_total_ssampsread + dz->buflen,0);
+				}
+				ibufpos -= dz->buflen; /* as current read succeeded, last input buffer was full: so this val is >= 0 */
+				sndtabindex -= (double)dz->buflen;
+			}
+			val    = ibuf[ibufpos++];
+			upval  = ibuf[ibufpos];
+			valdiff = (upval - val) * interp;
+			pbuf[pbufpos++] = (float)((val + valdiff) * amp);
+			if(pbufpos >= dz->buflen) {
+				sprintf(errstr,"Pulse length exceeds length of internal buffer : cannot proceed\n");
+				return(GOAL_FAILED);
+			}
+		}
+		amp = gen_sndtabindex(obufpos,&sndtabindex,&pulsenvindex,&envstep,insertsmps,(double)waveset_len,randomise_transpos,dz);
+		insertsmps++;
+	}
+	if(pbufpos > 0) {
+		if((exit_status = write_pulse_to_output(&pbufpos,&obufpos,dz))<0)
+			return(exit_status);
+	}
+
+	/* DO REST OF INPUT FILE AFTER PULSETRAIN, IF NESS */ 
+
+	if(dz->vflag[PULSE_KEEPEND]) {
+		for(;;) {
+			ibufleft = ssampsread - ibufpos;
+			obufleft = dz->buflen - obufpos;
+			spliceptr = obuf+obufpos;
+			if(ibufleft >= obufleft) {
+				memcpy((char *)(obuf+obufpos),(char *)(ibuf+ibufpos),obufleft * sizeof(float));
+				while(edit_todo > 0) {
+					k = *spliceptr * ((ENDBIT_SPLICE - (double)edit_todo)/ENDBIT_SPLICE);
+					*spliceptr++ = (float)k;
+					edit_todo--;
+					if(spliceptr >= obufend)
+						break;
+				}						
+				ibufpos += obufleft;
+				if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
+					return(exit_status);
+				obufpos = 0;
+			} else {
+				memcpy((char *)(obuf+obufpos),(char *)(ibuf+ibufpos),ibufleft * sizeof(float));
+				while(edit_todo > 0) {
+					k = *spliceptr * ((ENDBIT_SPLICE - (double)edit_todo)/ENDBIT_SPLICE);
+					*spliceptr++ = (float)k;
+					edit_todo--;
+					if(spliceptr >= obufend)
+						break;
+				}						
+				obufpos += ibufleft;
+				if(( exit_status = read_samps(ibuf, dz)) < 0) {
+					sprintf(errstr, "Can't read samps from input soundfile\n");
+					return(SYSTEM_ERROR);
+				}
+				ssampsread = dz->ssampsread;
+				if(ssampsread <= 0)
+					break;
+				ibufpos = 0;
+			}
+		}
+	}
+	if(obufpos > 0) {
+		if((exit_status = write_samps(obuf,obufpos,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+	
+/************************************* GET_WAVESETSTART *************************************/
+
+int get_wavesetstart(int ibufpos,dataptr dz)
+{
+	float *ibuf = dz->sampbuf[0];
+	
+	if(ibuf[ibufpos] > 0.0) {
+		while(ibuf[ibufpos] > 0.0) {
+			if(++ibufpos >= dz->buflen)
+				return(-1);
+		}
+	} else if(ibuf[ibufpos] < 0.0) { 
+		while(ibuf[ibufpos] < 0.0) {
+			if(++ibufpos >= dz->buflen)
+				return(-1);
+		}
+	} else {
+		while(smpflteq(ibuf[ibufpos],0.0)) {
+			if(++ibufpos >= dz->buflen)
+				return(-1);
+		}
+	}
+	return(ibufpos);
+}
+
+/************************************* EXTRACT_WAVEFORM *************************************/
+
+// NOV 2002 MAXSAMP -> F_MAXSAMP as well as short -> float
+int extract_waveform(int *waveset_start,dataptr dz)
+{
+	int ibufpos = *waveset_start, waveform_len = 0;
+	float *ibuf = dz->sampbuf[0];
+	float *sbuf = dz->sampbuf[2];
+	double frqlimit = dz->infile->srate/PULSE_FRQLIM;
+	double amplimit = dbtogain((double)PULSE_DBLIM) * F_MAXSAMP;
+	int capture_samps = 0, capture_wavesets = 0;
+	int last_waveform_len = 0;
+	double maxval, last_maxval = 0.0, wcntr = 0;
+
+	if(dz->mode == PULSE_SYN)
+		capture_samps = (int)round(dz->param[PULSE_WAVETIME] * dz->infile->srate);
+	else
+		capture_wavesets = dz->iparam[PULSE_WAVETIME];
+	while(smpflteq(ibuf[ibufpos],0.0)) {
+		if(++ibufpos >= dz->buflen)
+			return(-1);
+	}
+	*waveset_start = ibufpos;
+	maxval = fabs(ibuf[ibufpos]);
+
+	switch(dz->mode) {
+	case(PULSE_SYN):
+		for(;;) {
+			if(ibuf[ibufpos] > 0.0) {
+				while(ibuf[ibufpos] > 0.0) {
+					if(++ibufpos >= dz->buflen)
+						return(-1);
+					maxval = max(maxval,fabs(ibuf[ibufpos]));
+				}
+				while(ibuf[ibufpos] <= 0.0) {
+					if(++ibufpos >= dz->buflen)
+						return(-1);
+					maxval = max(maxval,fabs(ibuf[ibufpos]));
+				}
+			} else if(ibuf[ibufpos] < 0.0) { 
+				while(ibuf[ibufpos] < 0.0) {
+					if(++ibufpos >= dz->buflen)
+						return(-1);
+					maxval = max(maxval,fabs(ibuf[ibufpos]));
+				}
+				while(ibuf[ibufpos] >= 0.0) {
+					if(++ibufpos >= dz->buflen)
+						return(-1);
+					maxval = max(maxval,fabs(ibuf[ibufpos]));
+				}
+			}
+			if((waveform_len = ibufpos - *waveset_start) >= capture_samps)
+				break;
+			else {
+				last_waveform_len = waveform_len;
+				last_maxval = maxval;
+			}
+		}
+		if(capture_samps - last_waveform_len < waveform_len - capture_samps) {
+			waveform_len = last_waveform_len;
+			maxval = last_maxval;
+		}
+		break;
+	case(PULSE_SYNI):
+		while(wcntr < capture_wavesets) {
+			if(ibuf[ibufpos] > 0.0) {
+				while(ibuf[ibufpos] > 0.0) {
+					if(++ibufpos >= dz->buflen)
+						return(-1);
+					maxval = max(maxval,fabs(ibuf[ibufpos]));
+				}
+				while(ibuf[ibufpos] <= 0.0) {
+					if(++ibufpos >= dz->buflen)
+						return(-1);
+					maxval = max(maxval,fabs(ibuf[ibufpos]));
+				}
+			} else if(ibuf[ibufpos] < 0.0) {
+				while(ibuf[ibufpos] < 0.0) {
+					if(++ibufpos >= dz->buflen)
+						return(-1);
+					maxval = max(maxval,fabs(ibuf[ibufpos]));
+				}
+				while(ibuf[ibufpos] >= 0.0) {
+					if(++ibufpos >= dz->buflen)
+						return(-1);
+					maxval = max(maxval,fabs(ibuf[ibufpos]));
+				}
+			}
+			wcntr++;
+		}
+		waveform_len = ibufpos - *waveset_start;
+		break;
+	}
+	if(waveform_len <= 0) {
+		sprintf(errstr,"Failed to establish a viable sound to loop\n");
+		return(GOAL_FAILED);
+	} else if((double)waveform_len <= frqlimit) {
+		frqlimit = (double)dz->infile->srate/(double)waveform_len;
+		fprintf(stdout,"WARNING: Waveset length is only %d samples, corresponding to frq >= %.1lf hz\n",waveform_len,frqlimit);
+		fflush(stdout);
+	}
+	if((double)maxval <= amplimit) {
+		fprintf(stdout,"WARNING: Waveset amplitude is <= %lf dB\n",(double)PULSE_DBLIM);
+		fflush(stdout);
+	}
+	memcpy((char *)sbuf,(char *)(ibuf + *waveset_start),waveform_len * sizeof(float));
+	return(waveform_len);
+}
+
+/************************************* GEN_TABINDEX *************************************/
+
+double gen_sndtabindex(int obufpos,double *sndtabindex,double *pulsenvindex,double *envstep,
+					int insertsmps,double tablen,int randomise_transpos,dataptr dz)
+{
+	int exit_status;
+	double thistime, amp, frq, k;
+	*pulsenvindex += *envstep;
+	if(*pulsenvindex >= 1.0) {
+		if(dz->iparam[PULSE_ENVSIZE] <= 0) {			/* no impulse: must continue to end of sndtable (zero-cross) to avoid glitch */
+			*sndtabindex += dz->param[PULSE_TRANSPOS];	/* transpos sticks at previous value as table end has been reached */
+			if(*sndtabindex >= tablen) {
+				*pulsenvindex = 0.0;				/* reset to start of envelope */
+				*sndtabindex = 0.0;
+				thistime = (double)insertsmps/(double)dz->infile->srate;
+				if(dz->brksize[PULSE_FRQ] > 0) {
+					if((exit_status = read_value_from_brktable(thistime,PULSE_FRQ,dz))<0)
+						return exit_status;
+				}
+				frq = dz->param[PULSE_FRQ];
+				if(dz->param[PULSE_FRQRAND] > 0.0) {
+					k = ((drand48() * 2.0) - 1.0) * dz->param[PULSE_FRQRAND];
+					k /= SEMITONES_PER_OCTAVE;
+					k = pow(2.0,k);
+					frq *= k;
+				}
+				*envstep = frq/dz->infile->srate;
+				if(randomise_transpos && (dz->param[PULSE_PITCHRAND] > 0.0))
+					randomise_pulse_transposition(dz);
+			}
+			return(1.0);							/* no impulse: amplitude is always 1.0 */
+		}
+	/* GET NEW VALUE OF PULSE FRQ, AND HENCE OF STEP IN ENVEL TABLE */
+		thistime = (double)insertsmps/(double)dz->infile->srate;
+		if(dz->brksize[PULSE_FRQ] > 0) {
+			if((exit_status = read_value_from_brktable(thistime,PULSE_FRQ,dz))<0)
+				return exit_status;
+		}
+		frq = dz->param[PULSE_FRQ];
+		if(dz->param[PULSE_FRQRAND] > 0.0) {
+			k = ((drand48() * 2.0) - 1.0) * dz->param[PULSE_FRQRAND];
+			k /= SEMITONES_PER_OCTAVE;
+			k = pow(2.0,k);
+			frq *= k;
+		}
+		*envstep = frq/dz->infile->srate;
+		if(dz->iparam[PULSE_ENVSIZE] > 0)
+			randomise_pulse_envelope(obufpos,dz);	/* randomise shape of pulse, and copy reshaped pulse to read-env-table */
+										/* insert edit shoulders at start and end */
+										/* orig envelope has been copied to parray[PULSENV], variant copied back to brk[] */
+		
+		if(randomise_transpos && (dz->param[PULSE_PITCHRAND] > 0.0))
+			randomise_pulse_transposition(dz);
+		
+		*pulsenvindex = 0.0;				/* reset to start of envelope */
+		if((exit_status = read_impulse_amp_val(*pulsenvindex,&amp,dz))<0)
+			return exit_status;
+		if(dz->mode!=PULSE_IMP)
+			*sndtabindex = 0.0;
+		else
+			*sndtabindex = floor(*sndtabindex + 1.0);	/* sync table pointer with actual samples in input stream */
+	} else {
+		if(dz->iparam[PULSE_ENVSIZE] <= 0) {			/* no impulse */
+			if(dz->brksize[PULSE_TRANSPOS]) {
+				if((exit_status = read_value_from_brktable(*pulsenvindex,PULSE_TRANSPOS,dz))<0)
+					return exit_status;
+			}
+			*sndtabindex += dz->param[PULSE_TRANSPOS];
+			*sndtabindex = fmod(*sndtabindex,tablen);	/* cycle around soundtable */
+			return(1.0);								/* no impulse: amplitude is always 1.0 */
+		}
+		if((exit_status = read_impulse_amp_val(*pulsenvindex,&amp,dz))<0)
+			return exit_status;
+		if(dz->brksize[PULSE_TRANSPOS]) {
+			if((exit_status = read_value_from_brktable(*pulsenvindex,PULSE_TRANSPOS,dz))<0)
+				return exit_status;
+		}
+		*sndtabindex += dz->param[PULSE_TRANSPOS];
+		if(dz->mode!=PULSE_IMP)
+			*sndtabindex = fmod(*sndtabindex,tablen);
+	}
+	return amp;
+}
+
+/************************************* RANDOMISE_PULSE_ENVELOPE *************************************/
+
+int randomise_pulse_envelope(int obufpos,dataptr dz)
+{
+	int n, m, kk, maxpos, maxmark;
+	int *mark = dz->iparray[0];
+	double ratio, above, below, randmove, k, maxi, timearound;
+	double convertor = (dz->param[PULSE_FRQ] * ENDBIT_SPLICE)/(double)dz->infile->srate;
+	double abovestep, belowstep, minbelowtime, minabovetime;
+	int not_above, not_below;
+
+	dz->parray[PULSENV][0] = dz->parray[ORIG_PULSENV][0];
+	for(n=3;n<dz->iparam[PULSE_ENVSIZE]*2;n+=2) {
+		if(dz->parray[ORIG_PULSENV][n] < dz->parray[ORIG_PULSENV][n-2]) {
+			ratio = dz->parray[PULSENV][n-2]/dz->parray[ORIG_PULSENV][n-2];	/* ratio of previous val's new height to it's old height */
+			above = (dz->parray[ORIG_PULSENV][n-2] - dz->parray[ORIG_PULSENV][n]) * ratio; /* vert distance twixt preceding point & this, scaled */
+			below = (dz->parray[ORIG_PULSENV][n]) * ratio;							/* vert distance twixt 0 & this, scaled */
+			k = ((drand48() * 2.0) - 1.0) * dz->param[PULSE_SHAPERAND];
+			if(k >= 0.0)
+				randmove = above * k;
+			else
+				randmove = below * k;
+			dz->parray[PULSENV][n] = below + randmove;
+		} else if(dz->parray[ORIG_PULSENV][n] > dz->parray[ORIG_PULSENV][n-2]) {
+			ratio = (1.0 - dz->parray[PULSENV][n-2])/(1.0 - dz->parray[ORIG_PULSENV][n-2]); /* simil ratio of dist from top [1.0] */
+			above = (1.0 - dz->parray[ORIG_PULSENV][n]) * ratio; /* vert distance twixt top [1.0] & this point, scaled */
+			below = (dz->parray[ORIG_PULSENV][n] - dz->parray[ORIG_PULSENV][n-2]) * ratio; /* vert distance preceeding pnt & this, scaled */
+			k = ((drand48() * 2.0) - 1.0) * dz->param[PULSE_SHAPERAND];
+			if(k >= 0.0)
+				randmove = above * k;
+			else
+				randmove = below * k;
+			dz->parray[PULSENV][n] = dz->parray[PULSENV][n-2] + below + randmove;
+		} else {
+			dz->parray[PULSENV][n] = dz->parray[PULSENV][n-2];
+		}
+	}
+	/* randomise pulse-env timings */
+	for(m=1;m < dz->iparam[PULSE_ENVSIZE]-1; m++)
+		mark[m] = 0;
+	kk = dz->iparam[PULSE_ENVSIZE] - 2;
+	while(kk>0) {
+		maxi = 0.0;
+		maxpos = 0;
+		maxmark = 0;
+		not_above = 0;
+		not_below = 0;
+		for(m=1,n=2;n < (dz->iparam[PULSE_ENVSIZE]-1) * 2; n+=2,m++) {
+			if(mark[m]==0) {
+				timearound = dz->parray[PULSENV][n+2] - dz->parray[PULSENV][n-2];
+				if(timearound > maxi) {
+					maxi = timearound;
+					maxpos = n;
+					maxmark = m;
+				}
+			}
+		}
+		abovestep = dz->parray[PULSENV][maxpos+3] - dz->parray[PULSENV][maxpos+1]; 
+		belowstep = dz->parray[PULSENV][maxpos+1] - dz->parray[PULSENV][maxpos-1];
+		minbelowtime = fabs(convertor * belowstep);
+		minabovetime = fabs(convertor * abovestep);
+		if((above = dz->parray[PULSENV][maxpos+2] - dz->parray[PULSENV][maxpos]) < minabovetime)
+			not_above = 1;
+		if((below = dz->parray[PULSENV][maxpos] - dz->parray[PULSENV][maxpos-2]) < minbelowtime)
+			not_below = 1;
+		if(not_above) {
+			if(not_below) {
+				sprintf(errstr,"WARNING: possible glitch, due to sudden envelope change, after %lf secs\n",
+				(dz->total_samps_written + obufpos)/(double)dz->infile->srate);
+				fflush(stdout);
+				k = 0.0;
+			} else
+				k = drand48() * -1.0 * dz->param[PULSE_TIMERAND];
+		} else if(not_below)
+			k = drand48() * dz->param[PULSE_TIMERAND];
+		else
+			k = ((drand48() * 2.0) - 1.0) * dz->param[PULSE_TIMERAND];
+/* KLUDGE --> */
+		k *= 0.5;
+/* <-- KLUDGE */
+		if(k >= 0.0) 
+			randmove = above * k;
+		else
+			randmove = below * k;
+		dz->parray[PULSENV][maxpos] += randmove;
+		mark[maxmark] = 1;
+		kk--;
+	}
+	return(FINISHED);
+}
+
+/************************************* RANDOMISE_PULSE_TRANSPOSITION *************************************/
+
+void randomise_pulse_transposition(dataptr dz)
+{
+	int n, m;
+	double k;
+	for(n=0,m=1;n<dz->brksize[PULSE_TRANSPOS];n++,m+=2) {
+		if(flteq(dz->brk[PULSE_TRANSPOS][m],0.0))
+			dz->brk[PULSE_TRANSPOS][m] = 1.0;
+		else {
+			k = ((drand48() * 2.0) - 1.0) * dz->param[PULSE_PITCHRAND];
+			k *= dz->parray[PULSTRN][m]/SEMITONES_PER_OCTAVE;
+			dz->brk[PULSE_TRANSPOS][m] = pow(2.0,k);
+		}
+	}
+}
+
+/************************************* WRITE_PULSE_TO_OUTPUT *************************************/
+
+int write_pulse_to_output(int *pbufpos,int *obufpos,dataptr dz)
+{
+	int exit_status;
+	float *obuf = dz->sampbuf[1];
+	float *pbuf = dz->sampbuf[3];
+	int n, m;
+	if(dz->iparam[PULSE_ENVSIZE] > 0) {
+		for(n=0;n<round(ENDBIT_SPLICE);n++)		/* WRITE PULSE-BUFFER TO OUTPUT, with relevant splices if there's an impulse envelope */
+			pbuf[n] = (float)(pbuf[n] * (double)n/ENDBIT_SPLICE);
+		for(m = *pbufpos-1,n=0;n<round(ENDBIT_SPLICE);n++,m--)
+			pbuf[m] = (float)(pbuf[m] * (double)n/ENDBIT_SPLICE);
+	}
+	for(n=0;n<*pbufpos;n++) {
+		obuf[(*obufpos)++] = pbuf[n];
+		if(*obufpos >= dz->buflen) {
+			if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
+				return(exit_status);
+			*obufpos = 0;
+		}
+	}
+	*pbufpos = 0;
+	return(FINISHED);
+}
+
+/**************************** READ_IMPULSE_AMP_VAL *****************************/
+
+int read_impulse_amp_val(double thistime,double *amp,dataptr dz)
+{
+    double *p, lotime, loval, hitime, hival, timediff, step, ratio;
+	p = dz->parray[PULSENV];
+	if(flteq(thistime,0.0)) {
+		*amp = dz->parray[PULSENV][1];
+		return(FINISHED);
+	}
+	while(*p < thistime)
+		p += 2;
+	p -= 2;
+	lotime = *p++;
+	loval  = *p++;
+	hitime = *p++;
+	hival  = *p++;
+	timediff = thistime - lotime;
+	step = hival - loval;
+	ratio = timediff/(hitime-lotime);
+	*amp = loval + (step * ratio);
+    return(FINISHED);
+}
+
+