Explorar o código

initial commit

richarddobson %!s(int64=3) %!d(string=hai) anos
pai
achega
82f319fcb2
Modificáronse 5 ficheiros con 2468 adicións e 0 borrados
  1. 20 0
      dev/formants/CMakeLists.txt
  2. 846 0
      dev/formants/ap_formants.c
  3. 707 0
      dev/formants/formants.c
  4. 655 0
      dev/formants/formav.c
  5. 240 0
      dev/formants/main.c

+ 20 - 0
dev/formants/CMakeLists.txt

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

+ 846 - 0
dev/formants/ap_formants.c

@@ -0,0 +1,846 @@
+/*
+ * 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 <fmnts.h>
+#include <processno.h>
+#include <modeno.h>
+#include <globcon.h>
+#include <logic.h>
+#include <filetype.h>
+#include <mixxcon.h>
+#include <speccon.h>
+#include <flags.h>
+#include <arrays.h>
+#include <formants.h>
+#include <sfsys.h>
+#include <osbind.h>
+#include <string.h>
+#include <math.h>
+#include <srates.h>
+
+/********************************************************************************************/
+/********************************** FORMERLY IN pconsistency.c ******************************/
+/********************************************************************************************/
+
+static int 	check_compatibility_of_params_for_form(dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN procspec.c **********************************/
+/********************************************************************************************/
+
+static int  zero_formant(dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+#define MSECOND  (1.059463)
+#define SECOND   (1.122462)
+#define MTHIRD   (1.1892)
+#define THIRD    (1.259921)
+#define FOURTH   (1.33484)
+#define TRITONE  (1.414214)
+#define FIFTH    (1.4983)
+#define MSIXTH   (1.5874)
+#define SIXTH    (1.6818)
+#define MSEVENTH (1.781797)
+#define SEVENTH  (1.88775)
+static int  formants_preprocess(dataptr dz);
+static int  setup_internal_arrays_and_params_for_fmntsee(dataptr dz);
+//TW REMOVED: redundant
+//static int  get_max_formantval(dataptr dz);
+static int  setup_internal_params_and_arrays_for_formsee(dataptr dz);
+static int  get_formant_sample_points(int *fcnt,dataptr dz);
+
+/***************************************************************************************/
+/****************************** FORMERLY IN aplinit.c **********************************/
+/***************************************************************************************/
+
+/***************************** ESTABLISH_BUFPTRS_AND_EXTRA_BUFFERS **************************/
+
+int establish_bufptrs_and_extra_buffers(dataptr dz)
+{
+	int exit_status;
+	int is_spec = FALSE;
+	dz->extra_bufcnt = -1;	/* ENSURE EVERY CASE HAS A PAIR OF ENTRIES !! */
+	dz->bptrcnt = 0;
+	dz->bufcnt  = 0;
+	switch(dz->process) {
+	case(FORMANTS):   		dz->extra_bufcnt =  0; dz->bptrcnt = 4; 	is_spec = TRUE;		break;
+	case(FORM):       		dz->extra_bufcnt =  0; dz->bptrcnt = 4; 	is_spec = TRUE;		break;
+	case(VOCODE):     		dz->extra_bufcnt =  0; dz->bptrcnt = 4; 	is_spec = TRUE;		break;
+	case(FMNTSEE):    		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(FORMSEE):    		dz->extra_bufcnt =  1; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	default:
+		sprintf(errstr,"Unknown program type [%d] in establish_bufptrs_and_extra_buffers()\n",dz->process);
+		return(PROGRAM_ERROR);
+	}
+
+	if(dz->extra_bufcnt < 0) {
+		sprintf(errstr,"bufcnts have not been set: establish_bufptrs_and_extra_buffers()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(is_spec)
+		return establish_spec_bufptrs_and_extra_buffers(dz);
+	else if((dz->process==HOUSE_SPEC && dz->mode==HOUSE_CONVERT) || dz->process==INFO_DIFF) {
+		if((exit_status = establish_spec_bufptrs_and_extra_buffers(dz))<0)
+			return(exit_status);
+	}
+	return establish_groucho_bufptrs_and_extra_buffers(dz);
+}
+
+/***************************** SETUP_INTERNAL_ARRAYS_AND_ARRAY_POINTERS **************************/
+
+int setup_internal_arrays_and_array_pointers(dataptr dz)
+{
+	int n;		 
+	dz->ptr_cnt    = -1;		//base constructor...process
+	dz->array_cnt  = -1;
+	dz->iarray_cnt = -1;
+	dz->larray_cnt = -1;
+	switch(dz->process) {
+	case(FORMANTS):	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(FORM):	  	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(VOCODE): 	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(FMNTSEE):	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(FORMSEE):	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	}
+
+/*** WARNING ***
+ANY APPLICATION DEALING WITH A NUMLIST INPUT: MUST establish AT LEAST 1 double array: i.e. dz->array_cnt = at least 1
+**** WARNING ***/
+
+
+	if(dz->array_cnt < 0 || dz->iarray_cnt < 0 || dz->larray_cnt < 0 || dz->ptr_cnt < 0 || dz->fptr_cnt < 0) {
+		sprintf(errstr,"array_cnt not set in setup_internal_arrays_and_array_pointers()\n");	   
+		return(PROGRAM_ERROR);
+	}
+
+	if(dz->array_cnt > 0) {  
+		if((dz->parray  = (double **)malloc(dz->array_cnt * sizeof(double *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal double arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->array_cnt;n++)
+			dz->parray[n] = NULL;
+	}
+	if(dz->iarray_cnt > 0) {
+		if((dz->iparray = (int     **)malloc(dz->iarray_cnt * sizeof(int *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal int arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->iarray_cnt;n++)
+			dz->iparray[n] = NULL;
+	}
+	if(dz->larray_cnt > 0) {	  
+		if((dz->lparray = (int    **)malloc(dz->larray_cnt * sizeof(int *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal long arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->larray_cnt;n++)
+			dz->lparray[n] = NULL;
+	}
+	if(dz->ptr_cnt > 0)   {  	  
+		if((dz->ptr    	= (double  **)malloc(dz->ptr_cnt  * sizeof(double *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal pointer arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->ptr_cnt;n++)
+			dz->ptr[n] = NULL;
+	}
+	if(dz->fptr_cnt > 0)   {  	  
+		if((dz->fptr = (float  **)malloc(dz->fptr_cnt * sizeof(float *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal float-pointer arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->fptr_cnt;n++)
+			dz->fptr[n] = NULL;
+	}
+	return(FINISHED);
+}
+
+/****************************** ASSIGN_PROCESS_LOGIC *********************************/
+
+int assign_process_logic(dataptr dz)
+{						 
+	switch(dz->process) {
+	case(FORMANTS):		setup_process_logic(ANALFILE_ONLY,		  	ANAL_TO_FORMANTS,	FORMANTS_OUT,	dz);	break;
+	case(FORM):		  	setup_process_logic(ANAL_AND_FORMANTS,	  	BIG_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(VOCODE):	  	setup_process_logic(TWO_ANALFILES,		  	MIN_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(FMNTSEE):	  	setup_process_logic(FORMANTFILE_ONLY,	  	PSEUDOSNDFILE,		SNDFILE_OUT,	dz);	break;
+	case(FORMSEE):	  	setup_process_logic(ANALFILE_ONLY,	  		PSEUDOSNDFILE,		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;
+	mode = 0;
+	switch(process) {
+	case(FORMANTS):	  	exit_status = set_internalparam_data("i",ap);					break;
+	case(FORM):		  	return(FINISHED);
+	case(VOCODE):	  	return(FINISHED);									
+	case(FMNTSEE):	  	exit_status = set_internalparam_data("d",ap);					break;
+	case(FORMSEE):	  	exit_status = set_internalparam_data("di",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)	   
+{
+	aplptr ap = dz->application;
+
+	switch(ap->special_data) {
+	default:
+		sprintf(errstr,"Unknown special_data type: read_special_data()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+
+/****************************** PARAM_PREPROCESS *********************************/
+
+int param_preprocess(dataptr dz)	
+{
+	switch(dz->process) {
+	case(FORMANTS):		return formants_preprocess(dz);
+	case(VOCODE):		return initialise_specenv2(dz);
+	case(FMNTSEE):		return setup_internal_arrays_and_params_for_fmntsee(dz);
+	case(FORMSEE):		return setup_internal_params_and_arrays_for_formsee(dz);
+	case(FORM):			
+		break;
+	default:
+		sprintf(errstr,"PROGRAMMING PROBLEM: Unknown process in param_preprocess()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/************************** FORMANTS_PREPROCESS ******************************/
+
+int formants_preprocess(dataptr dz)
+{
+	int exit_status;
+	if((exit_status = write_formant_descriptor(&dz->flbufptr[1],dz->flbufptr[2],dz))<0)
+		return(exit_status);
+	dz->iparam[FMNT_SAMPS_TO_WRITE] = dz->descriptor_samps;
+	return(FINISHED);
+}
+
+/******************** PRINT_FORMANT_PARAMS_TO_SCREEN **********************/
+
+void print_formant_params_to_screen(dataptr dz)
+{
+/* CORRECTIONS: June 1999 */
+	int n;
+	float *bf = dz->bigfbuf;
+	char temp[200];
+	
+	fprintf(stdout,"INFO: Number of formant bands %d\n",dz->infile->specenvcnt);
+	fprintf(stdout,"INFO: Formant envelope frequency band centres (hz)\n");
+	sprintf(errstr,"INFO: ");
+	for(n=0;n<dz->infile->specenvcnt;n++) {
+		sprintf(temp," frq[%d] = %.1f",n,exp(*bf++));
+		strcat(errstr,temp);
+		if((n % 3)==2) {
+			fprintf(stdout,"%s\n",errstr);
+			sprintf(errstr,"INFO: ");
+		} else {
+			strcat(errstr,"\t");
+		}
+	}
+	if((n % 3) > 0)
+		fprintf(stdout,"%s\n",errstr);
+	fprintf(stdout,"INFO: Formant band tops (HZ)\n");
+	sprintf(errstr,"INFO: ");
+	for(n=0;n<dz->infile->specenvcnt;n++) {
+		sprintf(temp," top[%d] = %.1f",n,*bf++);
+		strcat(errstr,temp);
+		if((n % 3)==2) {
+			fprintf(stdout,"%s\n",errstr);
+			sprintf(errstr,"INFO: ");
+		} else {
+			strcat(errstr,"\t");
+		}
+	}
+	if((n % 3) > 0)
+		fprintf(stdout,"%s\n",errstr);
+	fflush(stdout);
+}
+
+/************ SETUP_INTERNAL_ARRAYS_AND_PARAMS_FOR_FMNTSEE *************/
+
+int setup_internal_arrays_and_params_for_fmntsee(dataptr dz)
+{
+    dz->wlength = dz->insams[0]/dz->wanted;	/* sample frames to process */
+	if((dz->sndbuf  = (float *)malloc((size_t)(((dz->infile->specenvcnt + SPACER)*sizeof(float)) * FMNT_BUFMULT)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for pseudosound buffer.\n");
+		return(MEMORY_ERROR);
+	}
+	return(FINISHED);
+}
+
+/***************************** GET_MAX_FORMANTVAL *************************/
+
+//TW UPDATE: get_max_formantval REMOVED , REDUNDANT
+
+/************ SETUP_INTERNAL_PARAMS_AND_ARRAYS_FOR_FORMSEE *************/
+
+int setup_internal_params_and_arrays_for_formsee(dataptr dz)
+{
+	int exit_status;
+    dz->wlength = dz->insams[0]/dz->wanted;	/* sample frames to process */
+	if((exit_status = get_formant_sample_points(&(dz->iparam[FSEE_FCNT]),dz))<0)
+		return(exit_status);
+	dz->param[FSEE_FMAX]  = 0.0;
+	if((dz->sndbuf = (float *)malloc(dz->clength * FMNT_BUFMULT * sizeof(float)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for formant pseudo-sound array.\n");
+		return(MEMORY_ERROR);
+	}
+	return(FINISHED);
+}
+
+/*********************** GET_FORMANT_SAMPLE_POINTS **********************/
+
+int get_formant_sample_points(int *fcnt,dataptr dz)
+{
+	double thisfrq = dz->chwidth, frqhere, triple_band = 0.0;
+	int n = 0;
+	switch(dz->vflag[FSEE_DISPLAY]) {
+	case(PICHWISE_FORMANTS):
+		while(thisfrq < dz->nyquist) {
+			n++;
+			if((frqhere=thisfrq*MSECOND)< dz->nyquist) n++;	    else    break;
+			if((frqhere=thisfrq*SECOND) < dz->nyquist) n++;	    else    break;
+			if((frqhere=thisfrq*MTHIRD) < dz->nyquist) n++;	    else    break;
+			if((frqhere=thisfrq*THIRD)  < dz->nyquist) n++;	    else    break;
+			if((frqhere=thisfrq*FOURTH) < dz->nyquist) n++;	    else    break;
+			if((frqhere=thisfrq*TRITONE)< dz->nyquist) n++;	    else    break;
+			if((frqhere=thisfrq*FIFTH)  < dz->nyquist) n++;	    else    break;
+			if((frqhere=thisfrq*MSIXTH) < dz->nyquist) n++;	    else    break;
+			if((frqhere=thisfrq*SIXTH)  < dz->nyquist) n++;	    else    break;
+			if((frqhere=thisfrq*MSEVENTH)<dz->nyquist) n++;	    else    break;
+			if((frqhere=thisfrq*SEVENTH)< dz->nyquist) n++;	    else    break;
+			thisfrq *= 2.0;
+		}
+		*fcnt = n;
+		break;
+	case(FREQWISE_FORMANTS):
+		triple_band = dz->chwidth * 3.0;
+		while(thisfrq < dz->nyquist) {
+			n++;
+			thisfrq += triple_band;
+		}
+		*fcnt = n;
+		break;
+	}
+	if((dz->windowbuf[0] = (float *)realloc((char *)dz->windowbuf[0],(*fcnt) * sizeof(float)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for formant sample points buffer.\n");
+		return(MEMORY_ERROR);
+	}
+	n = 0;
+	thisfrq = dz->chwidth;
+	switch(dz->vflag[FSEE_DISPLAY]) {
+	case(PICHWISE_FORMANTS):
+		for(;;) {
+			dz->windowbuf[0][n++]=(float)thisfrq;	       	   if(n >= *fcnt) break;
+			dz->windowbuf[0][n++]=(float)(thisfrq * MSECOND);  if(n >= *fcnt) break;
+			dz->windowbuf[0][n++]=(float)(thisfrq * SECOND);   if(n >= *fcnt) break;
+			dz->windowbuf[0][n++]=(float)(thisfrq * MTHIRD);   if(n >= *fcnt) break;
+			dz->windowbuf[0][n++]=(float)(thisfrq * THIRD);    if(n >= *fcnt) break;
+			dz->windowbuf[0][n++]=(float)(thisfrq * FOURTH);   if(n >= *fcnt) break;
+			dz->windowbuf[0][n++]=(float)(thisfrq * TRITONE);  if(n >= *fcnt) break;
+			dz->windowbuf[0][n++]=(float)(thisfrq * FIFTH);    if(n >= *fcnt) break;
+			dz->windowbuf[0][n++]=(float)(thisfrq * MSIXTH);   if(n >= *fcnt) break;
+			dz->windowbuf[0][n++]=(float)(thisfrq * SIXTH);    if(n >= *fcnt) break;
+			dz->windowbuf[0][n++]=(float)(thisfrq * MSEVENTH); if(n >= *fcnt) break;
+			dz->windowbuf[0][n++]=(float)(thisfrq * SEVENTH);  if(n >= *fcnt) break;
+			thisfrq *= 2.0;
+		}
+		break;
+	case(FREQWISE_FORMANTS):
+		while(thisfrq < dz->nyquist) {
+			dz->windowbuf[0][n++] = (float)thisfrq;
+			thisfrq += triple_band;
+		}
+		break;
+	}
+	if(*fcnt > dz->clength || *fcnt==0) {
+		sprintf(errstr,"Invalid formant_cnt: get_formant_sample_points()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN procspec.c **********************************/
+/********************************************************************************************/
+
+/**************************** SPEC_PROCESS_FILE ****************************/
+
+int spec_process_file(dataptr dz)
+{	
+	dz->total_windows = 0;
+
+	display_virtual_time(0L,dz);
+
+	switch(dz->process) {
+	case(FORMANTS):	return specformants(dz);
+	case(FORM):		return specform(dz);
+	case(VOCODE):	return outer_twofileinput_loop(dz);
+	case(FMNTSEE):	return specfmntsee(dz);	
+	case(FORMSEE):	return outer_formsee_loop(dz);
+	default:
+		sprintf(errstr,"Unknown process in procspec()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/**************************** INNER_LOOP ****************************/
+
+int inner_loop
+(int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
+{
+	int exit_status;
+	int local_zero_set = FALSE;
+	int wc;
+
+   	for(wc=0; wc<windows_in_buf; wc++) {
+		if(dz->total_windows==0) {
+			if((exit_status = skip_or_special_operation_on_window_zero(dz))<0)
+				return(exit_status);
+			if(exit_status==TRUE) {
+				dz->flbufptr[0] += dz->wanted;
+				dz->total_windows++;
+				dz->time = (float)(dz->time + dz->frametime);
+				continue;
+			}
+		}
+		if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0)
+			return(exit_status);
+
+		switch(dz->process) {
+		case(FORMSEE):	exit_status = specformsee(dz);						break;
+		default:
+			sprintf(errstr,"unknown process in inner_loop()\n");
+			return(PROGRAM_ERROR);
+		}
+		if(exit_status<0)
+			return(exit_status);
+		dz->flbufptr[0] += dz->wanted;
+		dz->total_windows++;
+		dz->time = (float)(dz->time + dz->frametime);
+	}
+//TW UPDATE
+//	if(!dz->zeroset && local_zero_set==TRUE) {
+	if(!dz->zeroset && (local_zero_set==TRUE)) {
+		fprintf(stdout,"WARNING: Zero-amp spectral window(s) encountered: orig window(s) substituted.\n"); 
+		fflush(stdout);
+		dz->zeroset = TRUE;
+	}
+	return(FINISHED);
+}
+
+/***************** SKIP_OR_SPECIAL_OPERATION_ON_WINDOW_ZERO ************/
+
+int skip_or_special_operation_on_window_zero(dataptr dz)
+{
+	int exit_status = FINISHED;
+	switch(dz->process) {
+	case(FORMANTS): case(FORMSEE): case(FMNTSEE):	case(VOCODE): 
+		switch(dz->process) {
+		case(FORMSEE):
+		case(FMNTSEE):
+			memset((char *)dz->flbufptr[0],0,(size_t)dz->wanted * sizeof(float));
+			break;
+		case(FORMANTS):
+			if((exit_status = zero_formant(dz))<0)
+				return(exit_status);
+			if((dz->iparam[FMNT_SAMPS_TO_WRITE] += dz->infile->specenvcnt) >= dz->buflen2) {
+				if((exit_status = write_exact_samps(dz->flbufptr[2],dz->buflen2,dz))<0)
+					return(exit_status);
+				dz->iparam[FMNT_SAMPS_TO_WRITE] = 0;
+				dz->flbufptr[1] = dz->flbufptr[2];
+			} else
+				dz->flbufptr[1] += dz->infile->specenvcnt;
+			break;
+		}
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+/**************************** OUTER_TWOFILEINPUT_LOOP ***************************/
+
+int outer_twofileinput_loop(dataptr dz)
+{
+	int exit_status;
+	int windows_to_process, windows_in_buf, samps_read, samps_to_write, wc, got;
+	int file_to_keep = 0, finished = 0, stop_at_end_of_shortest_file = 0;
+	int stop_at_end_of_process = 0;
+	dz->time = 0.0f;
+	switch(dz->process) {
+	case(VOCODE):
+		windows_to_process = min(dz->insams[0],dz->insams[1])/dz->wanted;
+		stop_at_end_of_shortest_file = 1;
+		break;
+	default:
+		sprintf(errstr,"unknown case in outer_twofileinput_loop()\n");
+		return(PROGRAM_ERROR);
+	}
+   	while(!finished) {
+
+		if((exit_status = read_both_files(&windows_in_buf,&got,dz))<0)
+			return(exit_status);
+		samps_to_write = got;
+ 		for(wc=0; wc<windows_in_buf; wc++) {
+			if(dz->total_windows==0) {
+				if((exit_status = skip_or_special_operation_on_window_zero(dz))<0)
+				 	return(exit_status);
+				if(exit_status==TRUE) {
+					if((exit_status = advance_one_2fileinput_window(dz))<0)
+						return(exit_status);
+					continue;
+				}
+			}
+			if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0)
+				return(exit_status);
+			switch(dz->process) {
+			case(VOCODE): 
+				if((exit_status = specvocode(dz))<0)
+					return(exit_status);
+				break;
+			default:
+				sprintf(errstr,"unknown process in outer_twofileinput_loop()\n");
+				return(PROGRAM_ERROR);
+			}
+			if((exit_status = advance_one_2fileinput_window(dz))<0)
+				return(exit_status);
+			if(dz->total_windows >= windows_to_process) {
+				if((exit_status = keep_excess_samps_from_correct_file(&samps_to_write,file_to_keep,got,wc,dz))<0)
+					return(exit_status);
+				finished = 1;
+				break;
+			}
+		}
+		if(samps_to_write > 0) {
+			if((exit_status = write_samps(dz->bigfbuf,samps_to_write,dz))<0)
+				return(exit_status);
+		}
+	}
+	if(!stop_at_end_of_process && !stop_at_end_of_shortest_file) {
+		if((exit_status = read_either_file(&samps_read,file_to_keep,dz))<0)
+			return(exit_status);
+		while(samps_read > 0) {
+			if((exit_status = write_samps(dz->bigfbuf,samps_read,dz))<0)
+				return(exit_status);
+			if((exit_status = read_either_file(&samps_read,file_to_keep,dz))<0)
+				return(exit_status);
+		}
+	}
+	return(FINISHED);
+}
+
+/****************************** ZERO_FORMANT ***************************/
+
+int zero_formant(dataptr dz)
+{
+	int n;
+	for(n=0;n<dz->infile->specenvcnt;n++)
+		dz->flbufptr[1][n] = 0.0f;
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN pconsistency.c ******************************/
+/********************************************************************************************/
+
+/****************************** CHECK_PARAM_VALIDITY_AND_CONSISTENCY *********************************/
+
+int check_param_validity_and_consistency(dataptr dz)
+{
+	int exit_status, chans, stype;
+	int srate;
+	char filename[200];
+	handle_pitch_zeros(dz);
+	switch(dz->process) {
+	case(FORMANTS):
+		chans = dz->infile->channels;
+//TW 2003: specenvcnt is number of pieces of data in a single formant
+//TW 2004: it would be more logical for channels to be equal to specenvcnt
+//TW However, this breaks some other things ...notably 
+//TW the gobo, which will only accept Formant,Pitch (and Envelope) files, for recombination
+//TW if they share the same number of channels (i.e. 1)
+//TW Rewriting the gobo program is one's worst nightmare!!!
+		dz->infile->channels = 1;
+		if((exit_status = create_sized_outfile(dz->wordstor[0],dz))<0)
+			return(exit_status);
+		dz->infile->channels = chans;
+		break;
+	case(FORM):		   
+		return check_compatibility_of_params_for_form(dz);
+	case(FMNTSEE):
+		chans = dz->infile->channels;
+		srate = dz->infile->srate;
+		stype = dz->infile->stype;
+		dz->infile->channels = 1;
+		dz->infile->srate    = dz->infile->origrate;
+		dz->infile->stype	 = SAMP_SHORT;
+		if((exit_status = create_sized_outfile(dz->wordstor[0],dz))<0)
+			return(exit_status);
+		dz->infile->channels = chans;
+		dz->infile->srate    = srate;
+		dz->infile->stype = stype;
+		break;
+	case(FORMSEE):
+		chans = dz->infile->channels;
+		srate = dz->infile->srate;
+		stype = dz->infile->stype;
+		dz->infile->channels = 1;
+		dz->infile->srate    = dz->infile->origrate;
+		dz->infile->stype	 = SAMP_SHORT;
+//TW  process uses tempfile before normalising output
+		strcpy(filename,dz->outfilename);
+		get_other_filename(filename,'1');
+		if((exit_status = create_sized_outfile(filename,dz))<0)
+			return(exit_status);
+		dz->infile->channels = chans;
+		dz->infile->srate    = srate;
+		dz->infile->stype = stype;
+		break;
+	}
+	return(FINISHED);
+}
+
+/************ CHECK_COMPATIBILITY_OF_PARAMS_FOR_FORM *************/
+
+int check_compatibility_of_params_for_form(dataptr dz)
+{
+	if(dz->param[FORM_FTOP] <= dz->param[FORM_FBOT]) {
+		sprintf(errstr,"Frequency limits incompatible\n");
+		return(USER_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN buffers.c ***********************************/
+/********************************************************************************************/
+
+/**************************** ALLOCATE_LARGE_BUFFERS ******************************/
+
+int allocate_large_buffers(dataptr dz)
+{
+	switch(dz->process) {
+	case(FMNTSEE):	case(FORMSEE):	
+		return allocate_single_buffer(dz);
+
+	case(VOCODE):	
+		return allocate_double_buffer(dz);
+
+	case(FORMANTS):	case(FORM):		
+		return allocate_analdata_plus_formantdata_buffer(dz);
+	default:
+		sprintf(errstr,"Unknown program no. in allocate_large_buffers()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN cmdline.c ***********************************/
+/********************************************************************************************/
+
+int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
+{
+	if     (!strcmp(prog_identifier_from_cmdline,"get"))  			dz->process = FORMANTS;
+	else if(!strcmp(prog_identifier_from_cmdline,"put"))  	   		dz->process = FORM;
+	else if(!strcmp(prog_identifier_from_cmdline,"vocode"))    		dz->process = VOCODE;
+	else if(!strcmp(prog_identifier_from_cmdline,"see"))	   		dz->process = FMNTSEE;
+	else if(!strcmp(prog_identifier_from_cmdline,"getsee"))   		dz->process = FORMSEE;
+	else {
+		sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
+		return(USAGE_ONLY);
+	}
+//TW UPDATE
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN usage.c *************************************/
+/********************************************************************************************/
+
+/******************************** USAGE1 ********************************/
+
+int usage1(void)
+{
+	sprintf(errstr,
+	"\nEXTRACTION AND USE OF FORMANTS FROM SPECTRAL FILES\n\n"
+	"USAGE: formants NAME (mode) infile (infile2) outfile parameters: \n"
+	"\n"
+	"where NAME can be any one of\n"
+	"\n"
+	"get     put     vocode     see      getsee\n\n"
+	"Type 'formants get' for more info on formants get..ETC.\n");
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE2 ********************************/
+
+int usage2(char *str)
+{
+	if(!strcmp(str,"get")) {
+		fprintf(stdout,
+		"formants get infile outfile -fN|-pN\n\n"
+		"EXTRACT EVOLVING FORMANT ENVELOPE FROM AN ANALYSIS FILE.\n\n"
+		"OUTFILE is a formant file, which can be used in other formant applications.\n\n"
+		"-f     extract formant envelope linear frqwise,\n"
+		"       using 1 point for every N equally-spaced frequency-channels.\n"
+		"-p     extract formant envelope linear pitchwise,\n"
+		"       using N equally-spaced pitch-bands per octave.\n");
+	} else if(!strcmp(str,"put")) {
+		fprintf(stdout,
+		"formants put 1 infile fmntfile outfile [-i] [-llof] [-hhif] [-ggain]\n"
+		"formants put 2 infile fmntfile outfile      [-llof] [-hhif] [-ggain]\n\n"
+		"IMPOSE SPECTRAL ENVELOPE IN A FORMANTFILE ON SPECTRUM IN A PVOC ANALYSIS FILE.\n\n"
+		"MODES.\n"
+		"(1) New formant envelope REPLACES sound's own formant envelope.\n"
+		"(2) New formant envelope IMPOSED ON TOP OF sound's own formant envelope.\n\n"
+		"INFILE and OUTFILE are PVOC analysis files. FMNTFILE is a formant data file.\n"
+		"-l      LOF  = low frq,  below which spectrum is set to zero.\n"
+		"-h      HIF  = high frq, above which spectrum is set to zero.\n"
+		"-g      GAIN = adjustment to spectrum loudness (normally < 1.0).\n"
+		"-i      quicksearch for formants (less accurate).\n");
+	} else if(!strcmp(str,"vocode")) {
+		fprintf(stdout,
+		"formants vocode infile infile2 outfile -fN|-pN [-llof] [-hhif] [-ggain]\n\n"
+		"IMPOSE SPECTRAL ENVELOPE OF 2nd SOUND, ON 1st SOUND.\n\n"
+		"-f     extract formant envelope linear frqwise,\n"
+		"       using 1 point for every N equally-spaced frequency-channels.\n"
+		"-p     extract formant envelope linear pitchwise,\n"
+		"       using N equally-spaced pitch-bands per octave.\n"
+		"-l     LOF = low frq,  below which data is filtered out.\n"
+		"-h     HIF = high frq, above which data is filtered out.\n"
+		"-g     GAIN adjustment to signal (normally < 1.0).\n");
+	} else if(!strcmp(str,"see")) {
+		fprintf(stdout,
+		"formants see infile outsndfile [-v]\n\n"
+		"CONVERT FORMANT DATA IN A BINARY FORMANTDATA FILE TO 'SNDFILE' FOR VIEWING.\n\n"
+		"-v     display data about formant-band parameters.\n\n"
+		"The resulting logarithmically scaled display indicates formant shapes,\n"
+		"but NOT the absolute amplitude values.\n");
+	} else if(!strcmp(str,"getsee")) {
+		fprintf(stdout,
+		"formants getsee infile outsndfile -fN|-pN [-s]\n\n"
+		"EXTRACT FORMANTS FROM ANALFILE AND WRITE AS 'SNDFILE' FOR VIEWING.\n\n"
+		"-f     extract formant envelope linear frqwise,\n"
+		"       using 1 point for every N equally-spaced frequency-channels.\n"
+		"-p     extract formant envelope linear pitchwise,\n"
+		"       using N equally-spaced pitch-bands per octave.\n"
+		"-s     semitone bands for display (Default: equal hz bands).\n\n"
+		"The resulting logarithmically scaled display indicates formant shapes,\n"
+		"but NOT the absolute amplitude values.\n"
+		"\n"
+//TW temporary cmdline restriction
+		"(Do not use filenames which end in '1').\n");
+	} else
+		fprintf(stdout,"Unknown option '%s'\n",str);
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE3 ********************************/
+
+int usage3(char *str1,char *str2)
+{
+	sprintf(errstr,"Insufficient parameters on command line.\n");
+	return(USAGE_ONLY);
+}
+

+ 707 - 0
dev/formants/formants.c

@@ -0,0 +1,707 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <pnames.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <flags.h>
+#include <fmnts.h>
+#include <cdpmain.h>
+#include <formants.h>
+#include <speccon.h>
+#include <sfsys.h>
+#include <string.h>
+#include <fmnts.h>
+
+static int  inner_form_loop(int windows_in_buf,dataptr dz);
+static int  do_specform(dataptr dz);
+static int  form_filter(dataptr dz);
+static int  form_gain(dataptr dz);
+static int  vocode_channel(int vc,dataptr dz);
+static int	eliminate_out_of_range_data(dataptr dz);
+static int	vocogain(dataptr dz);
+static int  reset_file_to_start_and_pointers_to_after_descriptor_blocks(int *windows_in_buf,dataptr dz);
+static int  renormalise_formsee(dataptr dz);
+//static int  setformval(int *thissamp,float inval,double normaliser,double adjuster);
+static int  setformval(float *thissamp,float inval,double normaliser,double adjuster);
+static int  do_specformants(dataptr dz);
+static int  extract_formant_and_place_in_output_buffer(int formantlen,dataptr dz);
+
+static int  get_max_formantval(dataptr dz);
+static int  initialise_the_formant_data(int *windows_in_buf,dataptr dz);
+
+/****************************** SPECFORMANTS ***************************/
+
+int specformants(dataptr dz)
+{
+	int exit_status;
+	int wc, windows_in_buf;
+	int OK  = 1;
+	if(sloom)
+		dz->total_samps_read = 0L;
+	dz->time = 0.0f;
+	while(OK) {
+		if((exit_status = read_samps(dz->bigfbuf,dz)) < 0)
+			return exit_status;
+		if(dz->ssampsread <= 0)
+			break;
+		dz->flbufptr[0] = dz->bigfbuf;
+		windows_in_buf = dz->ssampsread/dz->wanted;    
+		for(wc=0; wc<windows_in_buf; wc++) {
+			if(dz->total_windows==0) {
+				if((exit_status = skip_or_special_operation_on_window_zero(dz))<0)
+				 	return(exit_status);
+				if(exit_status==TRUE) {
+					dz->flbufptr[0] += dz->wanted;
+					dz->total_windows++;
+					dz->time = (float)(dz->time + dz->frametime);
+					continue;
+				}
+			}
+			if((exit_status = do_specformants(dz))<0)
+				return(exit_status);
+			dz->flbufptr[0]  += dz->wanted;			/* move along bigfbuf */
+			dz->total_windows++;
+			dz->time = (float)(dz->time + dz->frametime);
+		}
+	}
+	if(dz->iparam[FMNT_SAMPS_TO_WRITE] > 0) {
+		if((exit_status = write_samps(dz->flbufptr[2],dz->iparam[FMNT_SAMPS_TO_WRITE],dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/**************************** DO_SPECFORMANTS ***************************
+ *
+ * Extract formants from an analfile.
+ */
+
+int do_specformants(dataptr dz)
+{
+	int exit_status;
+	rectify_window(dz->flbufptr[0],dz);
+	if((exit_status = extract_specenv(0,0,dz))<0)
+		return(exit_status);
+	memmove((char *)dz->flbufptr[1],(char *)dz->specenvamp,(dz->infile->specenvcnt * sizeof(float)));
+	if((dz->iparam[FMNT_SAMPS_TO_WRITE] += dz->infile->specenvcnt) >= dz->buflen2) {
+		if((exit_status = write_exact_samps(dz->flbufptr[2],dz->buflen2,dz))<0)
+			return(exit_status);
+		dz->iparam[FMNT_SAMPS_TO_WRITE] = 0L;
+		dz->flbufptr[1] = dz->flbufptr[2];
+	} else
+		dz->flbufptr[1] += dz->infile->specenvcnt;	/* move along dz->flbufptr[2] */
+	return(FINISHED);
+}
+
+/****************************** SPECFORM ***************************/
+
+int specform(dataptr dz)
+{
+	int exit_status, current_status;
+	int windows_in_buf;
+ 
+	if(sloom)
+		dz->total_samps_read = 0L;
+
+	dz->time = 0.0f;
+	if((exit_status = setup_formant_params(dz->ifd[1],dz))<0)
+		return(exit_status);
+
+//	if((exit_status = read_samps(dz->bigfbuf,dz)) < 0)	ALREADY READ IN setup_formant_params()
+//		return(exit_status);
+	while(dz->ssampsread > 0) {
+    	dz->flbufptr[0] = dz->bigfbuf;
+    	windows_in_buf = dz->ssampsread/dz->wanted;
+	   	if((exit_status = inner_form_loop(windows_in_buf,dz))<0) {
+			dz->specenvamp2 = (float *)0;
+			return(exit_status);
+		}
+		current_status = exit_status;
+		if(dz->flbufptr[0] - dz->bigfbuf > 0) {
+			if((exit_status = write_samps(dz->bigfbuf,(dz->flbufptr[0] - dz->bigfbuf),dz))<0) {
+				dz->specenvamp2 = NULL;
+				return(exit_status);
+			}
+		}
+		if(current_status!=CONTINUE)
+			break;
+		if((exit_status = read_samps(dz->bigfbuf,dz)) < 0)
+			return(exit_status);
+	}
+ 	dz->specenvamp2 = NULL;
+	return(FINISHED);
+}
+
+/****************************** INNER_FORM_LOOP ***************************/
+
+int inner_form_loop(int windows_in_buf,dataptr dz)
+{
+	int exit_status;
+	int wc;
+	double pre_amptotal, post_amptotal;
+ 	for(wc=0; wc<windows_in_buf; wc++) {
+		if(dz->total_windows==0) {
+			if((exit_status = move_along_formant_buffer(dz))!=CONTINUE)
+				return(exit_status);
+			dz->flbufptr[0] += dz->wanted;
+			dz->total_windows++;
+			dz->time = (float)(dz->time + dz->frametime);
+			continue;			/* SKIP FIRST (ZERO-AMP) WINDOW */
+		}
+		if(dz->mode==FORM_REPLACE) {
+			rectify_window(dz->flbufptr[0],dz);
+			if((exit_status = extract_specenv(0,0,dz))<0)
+				return(exit_status);
+		}
+		dz->specenvamp2  = dz->flbufptr[1];
+		pre_amptotal = post_amptotal = 0.0;
+		if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
+			return(exit_status);
+		if((exit_status = do_specform(dz))<0)
+			return(exit_status);
+		if((exit_status = form_filter(dz))<0)
+				return(exit_status);
+		if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
+			return(exit_status);
+		if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
+			return(exit_status);
+		if(!flteq(dz->param[FORM_GAIN],1.0)) {
+			if((exit_status = form_gain(dz))<0)
+				return(exit_status);
+  				/* NB This check must be BEFORE move_along_formant_buffer() */
+		}
+		dz->flbufptr[0] += dz->wanted;
+  		if(++dz->total_windows >= dz->wlength)
+			return(FINISHED);
+		if((exit_status = move_along_formant_buffer(dz))!=CONTINUE)
+			return(exit_status);
+		dz->time = (float)(dz->time + dz->frametime);
+	}
+	return(CONTINUE);
+}
+
+/**************************** DO_SPECFORM ***************************
+ *
+ * Impose formants onto an analfile.
+ */
+
+int do_specform(dataptr dz)
+{
+	int exit_status;
+	int vc;
+	double thisspecamp0, thisspecamp1, thisvalue;
+	rectify_window(dz->flbufptr[0],dz);
+	switch(dz->mode) {
+	case(FORM_REPLACE):
+		for(vc = 0; vc < dz->wanted ; vc += 2) {
+			if((exit_status = getspecenvamp(&thisspecamp0,(double)dz->flbufptr[0][FREQ],0,dz))<0)
+				return(exit_status);
+			if((exit_status = getspecenvamp(&thisspecamp1,(double)dz->flbufptr[0][FREQ],1,dz))<0)
+				return(exit_status);
+			if(thisspecamp0 < VERY_TINY_VAL)
+				dz->flbufptr[0][AMPP] = 0.0f;
+			else {
+				if((thisvalue = dz->flbufptr[0][AMPP] * thisspecamp1/thisspecamp0)< VERY_TINY_VAL)
+					dz->flbufptr[0][AMPP] = 0.0f;
+				else
+					dz->flbufptr[0][AMPP] = (float)thisvalue;
+			}
+		}
+		break;
+	case(FORM_IMPOSE):
+		for(vc = 0; vc < dz->wanted ; vc += 2) {
+			if((exit_status = getspecenvamp(&thisspecamp1,(double)dz->flbufptr[0][FREQ],1,dz))<0)
+				return(exit_status);
+			if((thisvalue = dz->flbufptr[0][AMPP] * thisspecamp1)< VERY_TINY_VAL)
+				dz->flbufptr[0][AMPP] = 0.0f;
+			else
+				dz->flbufptr[0][AMPP] = (float)thisvalue;
+		}
+		break;
+	default:
+		sprintf(errstr,"Unknown case in do_specform()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/****************************** FORM_FILTER ***************************/
+
+int form_filter(dataptr dz)
+{
+	int vc;
+	for(vc = 0; vc < dz->wanted ; vc += 2) {
+		if(dz->flbufptr[0][FREQ] < dz->param[FORM_FBOT]
+			|| dz->flbufptr[0][FREQ] > dz->param[FORM_FTOP])
+			dz->flbufptr[0][AMPP] = 0.0f;
+	}
+	return(FINISHED);
+}
+
+/****************************** FORM_GAIN ***************************/
+
+int form_gain(dataptr dz)
+{
+	int vc;
+	for(vc=0;vc<dz->wanted;vc+=2)
+		dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FORM_GAIN]);
+	return(FINISHED);
+}
+
+/************************** SPECVOCODE ***********************/
+
+int specvocode(dataptr dz)
+{
+	int exit_status;
+	int vc;
+	double pre_amptotal, post_amptotal;
+	rectify_window(dz->flbufptr[0],dz);
+	if((exit_status = extract_specenv(0,0,dz))<0)
+		return(exit_status);
+	rectify_window(dz->flbufptr[1],dz);
+	if((exit_status = extract_specenv(1,1,dz))<0)
+		return(exit_status);
+	if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
+		return(exit_status);
+	for(vc = 0; vc < dz->wanted; vc += 2) {
+		if((exit_status = vocode_channel(vc,dz))<0)
+			return(exit_status);
+	}
+	if((exit_status = eliminate_out_of_range_data(dz))<0)
+		return(exit_status);
+	if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
+		return(exit_status);
+	if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
+		return(exit_status);
+	return vocogain(dz);
+}
+
+/************************** VOCODE_CHANNEL ***********************/
+
+int vocode_channel(int vc,dataptr dz)
+{
+	int exit_status;
+	double thisvalue;
+	double thisspecamp1, thisspecamp2;
+	if((exit_status = getspecenvamp(&thisspecamp1,(double)dz->flbufptr[0][FREQ],0,dz))<0)
+		return(exit_status);
+	if((exit_status = getspecenvamp(&thisspecamp2,(double)dz->flbufptr[1][FREQ],1,dz))<0)
+		return(exit_status);
+	if(thisspecamp1 <= 0.0)
+		dz->flbufptr[0][AMPP] = 0.0f;
+	else {
+		if((thisvalue = dz->flbufptr[0][AMPP] * thisspecamp2/thisspecamp1)  < VERY_TINY_VAL)
+			dz->flbufptr[0][AMPP] = 0.0f;
+		else
+			dz->flbufptr[0][AMPP] = (float)thisvalue;
+	}
+	return(FINISHED);
+}
+
+/************************** ELIMINATE_OUT_OF_RANGE_DATA ***********************/
+
+int	eliminate_out_of_range_data(dataptr dz)
+{
+	int vc;
+	for(vc = 0;vc < dz->wanted; vc+=2) {
+		if(dz->flbufptr[0][FREQ] < dz->param[VOCO_LOF] || dz->flbufptr[0][FREQ] > dz->param[VOCO_HIF])
+			dz->flbufptr[0][AMPP] = 0.0f;
+	}
+	return(FINISHED);
+}
+
+/************************** VOCOGAIN ***********************/
+
+int	vocogain(dataptr dz)
+{
+	int vc;
+	if(!flteq(dz->param[VOCO_GAIN],1.0))	{
+		for(vc=0;vc<dz->wanted;vc+=2)
+			dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[VOCO_GAIN]);
+	}
+	return(FINISHED);
+}
+
+/**************************** SPECFMNTSEE ***************************/
+
+int specfmntsee(dataptr dz)
+{
+	int exit_status;
+	double thisval;
+	int   windows_in_buf, wc;
+	int    cc;
+	double normaliser;
+//	double adjuster   = (double)MAXSAMP/log(10000.0);
+	double adjuster   = F_MAXSAMP/log(10000.0);
+	int outcnt = 0, outbufcnt = 0;
+	if(sloom)
+		dz->total_samps_read = 0L;
+	if((exit_status = initialise_the_formant_data(&windows_in_buf,dz))<0)
+		return(exit_status);
+	normaliser = 9999.0/dz->param[FMNTSEE_MAX];
+	dz->time = 0.0f;
+	do {
+		for(wc=0; wc<windows_in_buf; wc++) {
+			if(dz->total_windows==0) {
+				if((exit_status = skip_or_special_operation_on_window_zero(dz))<0)
+					return(exit_status);
+				if(exit_status==TRUE) {
+					dz->flbufptr[0] += dz->wanted;
+					dz->total_windows++;
+					dz->time = (float)(dz->time + dz->frametime);
+					continue;
+				}
+			}
+			for(cc = 0; cc < dz->wanted; cc++) {
+				thisval  = log((dz->flbufptr[0][cc] * normaliser) + 1.0);
+				thisval *= adjuster;
+
+//				dz->sndbuf[outcnt] = (short)round(thisval);
+				dz->sndbuf[outcnt] = (float)thisval;
+
+				if(++outcnt >= (dz->infile->specenvcnt + SPACER) * FMNT_BUFMULT) {
+					sprintf(errstr,"buffer accounting error in specfmntsee()\n");
+					return(PROGRAM_ERROR);
+				}
+			}
+			for(cc = 0; cc < SPACER; cc++)
+//				dz->sndbuf[outcnt++] = (short)0; 
+				dz->sndbuf[outcnt++] = 0.0f; 
+			if(++outbufcnt >= FMNT_BUFMULT) {
+				if(outcnt != (dz->infile->specenvcnt + SPACER) * FMNT_BUFMULT) {
+					sprintf(errstr,"bufcount error in specfmntsee()\n");
+					return(PROGRAM_ERROR);
+				}
+				if(outcnt > 0) {
+					if((exit_status = write_samps(dz->sndbuf,outcnt,dz))<0)
+						return(exit_status);
+				}
+				outcnt    = 0;
+				outbufcnt = 0;
+			}
+			dz->flbufptr[0]  += dz->wanted;		/* move along bigfbuf */
+			dz->time = (float)(dz->time + dz->frametime);
+		}
+		if((exit_status = read_samps(dz->bigfbuf,dz)) < 0) {
+			sprintf(errstr,"Sound read error.\n");
+			return(SYSTEM_ERROR);
+		}
+		dz->flbufptr[0] = dz->bigfbuf;
+		windows_in_buf = dz->ssampsread/dz->wanted;    
+	} while(windows_in_buf > 0);
+	if(outcnt) {
+		if((exit_status = write_samps(dz->sndbuf,outcnt,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/*********************** RESET_FILE_TO_START_AND_POINTERS_TO_AFTER_DESCRIPTOR_BLOCKS **********************/
+
+int reset_file_to_start_and_pointers_to_after_descriptor_blocks(int *windows_in_buf,dataptr dz)
+{
+	int exit_status;
+	if(sndseekEx(dz->ifd[0],0L,0)<0) { /* RESET FILE POINTER TO START OF DATA */
+		sprintf(errstr,"seek failed in reset_file_to_start_and_pointers_to_after_descriptor_blocks()\n");
+		return(SYSTEM_ERROR);
+	}
+	if((exit_status = read_samps(dz->bigfbuf,dz)) < 0) {
+		sprintf(errstr,"Read problem after rewind in reset_file_to_start_and_pointers_to_after_descriptor_blocks()\n");
+		return(SYSTEM_ERROR);
+	}
+	*windows_in_buf = dz->ssampsread/dz->wanted;    
+	if((*windows_in_buf -= DESCRIPTOR_DATA_BLOKS) < 0) {
+		sprintf(errstr,"Buffers too SMALL in reset_file_to_start_and_pointers_to_after_descriptor_blocks()\n");
+		return(PROGRAM_ERROR);
+	}
+	dz->flbufptr[0] = dz->bigfbuf + (DESCRIPTOR_DATA_BLOKS * dz->wanted);
+	return(FINISHED);
+}
+
+/**************************** OUTER_FORMSEE_LOOP ****************************/
+
+int outer_formsee_loop(dataptr dz)
+{
+	int exit_status;
+	int windows_in_buf, peakscore = 0, pitchcnt = 0;
+	int in_start_portion = TRUE, least = 0, descnt = 0;
+
+	if(sloom)
+		dz->total_samps_read = 0L;
+   if((exit_status = read_samps(dz->bigfbuf,dz)) < 0)
+	   return(exit_status);
+
+   while(dz->ssampsread > 0) {
+    	dz->flbufptr[0] = dz->bigfbuf;
+    	windows_in_buf = dz->ssampsread/dz->wanted;
+		if((exit_status = inner_loop(&peakscore,&descnt,&in_start_portion,&least,&pitchcnt,windows_in_buf,dz))<0)
+			return(exit_status);
+		if((exit_status = write_samps(dz->bigfbuf,dz->ssampsread,dz))<0)
+			return(exit_status);
+	   if((exit_status = read_samps(dz->bigfbuf,dz)) < 0)
+		   return(exit_status);
+	}
+	if(dz->ssampsread < 0) {
+		sprintf(errstr,"Sound read error.\n");
+		return(SYSTEM_ERROR);
+	}  
+    return renormalise_formsee(dz);
+}
+
+
+/******************************* RENORMALISE_FORMSEE ****************************
+ *
+ * Multiply by 9999/formantmax ->  range 0 TO 9999.
+ * Add 1                        ->  range 1 TO 10000.
+ * Take log :			->  range 0 TO log(10000).(log display)
+ * Times MAXSAMPP/log(10000) :	->  range 0 TO MAXSAMPP	(log log display)
+ */
+
+int renormalise_formsee(dataptr dz)
+{
+	int exit_status;
+	int	 cc, vc;
+	int wc, outcnt, outbufcnt, total_samps_read;
+	int ssampsread, total_samps_todo = dz->total_samps_written;
+	int windows_in_buf;
+	int windows_remaining = dz->wlength;
+	float thissamp;
+	double normaliser;
+	double adjuster   = F_MAXSAMP/log(10000.0);
+	int chans, stype;
+	int srate;
+	if(dz->param[FSEE_FMAX] < VERY_TINY_VAL) {
+		sprintf(errstr,"No siginificant data found in srcfile\n");
+		return(DATA_ERROR);
+	}
+//TW NEW MECHANISM writes renormalised vals from original file created (tempfile) into true outfile
+// true outfile gets the name the user originally input
+	if(sndcloseEx(dz->ifd[0]) < 0) {
+		sprintf(errstr, "WARNING: Can't close input soundfile\n");
+		return(SYSTEM_ERROR);
+	}
+	if(sndcloseEx(dz->ofd) < 0) {
+		sprintf(errstr, "WARNING: Can't close output soundfile\n");
+		return(SYSTEM_ERROR);
+	}
+	if((dz->ifd[0] = sndopenEx(dz->outfilename,0,CDP_OPEN_RDWR)) < 0) {   /* RWD Nov 2003 was RDONLY */
+		sprintf(errstr,"Failure to reopen file %s for renormalisation.\n",dz->outfilename);
+		return(SYSTEM_ERROR);
+	}
+    /* RWD Jumy 2010 no lopmger need this - now built into sndopenEx in sfsys */
+	//sndseekEx(dz->ifd[0],0,0);
+	chans = dz->infile->channels;
+	srate = dz->infile->srate;
+	stype = dz->infile->stype;
+	dz->infile->channels = 1;
+	dz->infile->srate    = dz->infile->origrate;
+	dz->infile->stype	 = SAMP_SHORT;
+	if((exit_status = create_sized_outfile(dz->wordstor[0],dz))<0) {
+		sprintf(errstr,"Failure to create file %s for renormalisation.\n",dz->wordstor[0]);
+		return(exit_status);
+	}
+	dz->infile->channels = chans;
+	dz->infile->srate    = srate;
+	dz->infile->stype = stype;
+	if((exit_status = reset_peak_finder(dz))<0)
+		return(exit_status);
+
+	normaliser = 9999.0/dz->param[FSEE_FMAX];
+	total_samps_todo = dz->total_samps_written;
+	outbufcnt				 = 0L;
+	outcnt                   = 0L;
+	total_samps_read         = 0L;
+	dz->total_samps_written  = 0L;
+	dz->total_windows		 = 0L;
+	dz->total_samps_read     = 0L;
+	while(total_samps_todo > 0) {
+		if((exit_status = read_samps(dz->bigfbuf,dz)) < 0) {
+			sprintf(errstr,"Sound read error.\n");
+			close_and_delete_tempfile(dz->outfilename,dz);
+			return(SYSTEM_ERROR);
+		}  
+		dz->flbufptr[0] = dz->bigfbuf;
+		total_samps_read += dz->ssampsread;
+		ssampsread  = dz->ssampsread;
+		if(total_samps_todo - ssampsread<0) {
+			ssampsread = total_samps_todo;
+			total_samps_todo = 0;
+		} else
+			total_samps_todo -= ssampsread;
+		windows_in_buf = ssampsread/dz->wanted;
+		if(windows_remaining - windows_in_buf < 0) {
+			windows_in_buf = windows_remaining;
+			windows_remaining = 0;
+		} else
+			windows_remaining -= windows_in_buf;
+		for(wc=0;wc<windows_in_buf;wc++) {
+			if(dz->total_windows==0) {
+				for(cc=0;cc<dz->clength;cc++)
+					dz->sndbuf[outcnt++] = 0.0f;
+			} else {
+				for(cc=0,vc=0;cc<dz->iparam[FSEE_FCNT];cc++,vc += 2)  {		/* 1 */
+					if((exit_status = setformval(&thissamp,dz->flbufptr[0][AMPP],normaliser,adjuster))<0)
+						return(exit_status);
+					dz->sndbuf[outcnt++] = thissamp;
+				}
+				for(;cc<dz->clength;cc++)
+					dz->sndbuf[outcnt++] = 0.0f;
+			}
+			if(++outbufcnt >= FMNT_BUFMULT) {
+				if(outcnt!=dz->clength * FMNT_BUFMULT) {
+					sprintf(errstr,"Buffercnt error in renormalise_formsee()\n");
+					close_and_delete_tempfile(dz->outfilename,dz);
+					return(PROGRAM_ERROR);
+				}
+				if(outcnt > 0) {
+					if((exit_status = write_samps(dz->sndbuf,outcnt,dz))<0)  {
+						close_and_delete_tempfile(dz->outfilename,dz);
+						return(exit_status);
+					}
+				}
+				outcnt    = 0;
+				outbufcnt = 0;
+			}
+			dz->flbufptr[0] += dz->wanted;
+			dz->total_windows++;
+		}
+		if(windows_remaining <=0)
+			break;
+	}
+	if(outcnt) {
+		if((exit_status = write_samps(dz->sndbuf,outcnt,dz))<0) {
+			close_and_delete_tempfile(dz->outfilename,dz);
+			return(exit_status);
+		}
+	}
+	close_and_delete_tempfile(dz->outfilename,dz);
+	return(FINISHED);
+}
+
+/****************************** SETFORMVAL ***************************/
+
+//int setformval(int *thissamp,float inval,double normaliser,double adjuster)
+int setformval(float *thissamp,float inval,double normaliser,double adjuster)
+{
+	double thisval = log((inval * normaliser) + 1.0);
+//	thisval  *= adjuster;
+//	*thissamp  = round(thisval);
+	*thissamp  = (float)(thisval * adjuster);
+	return(FINISHED);
+}
+
+/**************************** SPECFORMSEE ***************************/
+
+int specformsee(dataptr dz)
+{
+	int exit_status;
+	rectify_window(dz->flbufptr[0],dz);
+	if((exit_status = extract_specenv(0,0,dz))<0)
+		return(exit_status);
+	return extract_formant_and_place_in_output_buffer(dz->iparam[FSEE_FCNT],dz);
+}
+	
+/*********************** EXTRACT_FORMANT_AND_PLACE_IN_OUTPUT_BUFFER **********************/
+
+int extract_formant_and_place_in_output_buffer(int formantlen,dataptr dz)
+{
+	int exit_status;
+	int cc, vc;
+	double thisamp;
+	for(cc=0,vc=0;cc<formantlen;cc++,vc+=2) {
+		if((exit_status = getspecenvamp(&thisamp,dz->windowbuf[0][cc],0,dz))<0)
+			return(exit_status);
+		dz->flbufptr[0][AMPP] = (float)thisamp;
+		if(dz->flbufptr[0][AMPP] > dz->param[FSEE_FMAX])
+			dz->param[FSEE_FMAX] = dz->flbufptr[0][AMPP];
+	}
+	for(;cc<dz->clength;cc++,vc+=2)
+		dz->flbufptr[0][AMPP] = 0.0f;
+	return(FINISHED);
+}
+
+/***************************** GET_MAX_FORMANTVAL *************************/
+
+int get_max_formantval(dataptr dz)
+{
+	int exit_status;
+	int   total_floats_in_file = (dz->wlength + DESCRIPTOR_DATA_BLOKS) * dz->infile->specenvcnt;
+	int   floats_read = min(total_floats_in_file,dz->big_fsize);
+	float *sbufend = dz->bigfbuf + floats_read;
+	float *sbuf    = dz->flbufptr[0]; 
+			/* which has already skipped the float descriptor blocks */
+	dz->param[FMNTSEE_MAX] = 0.0;
+	do {
+		while(sbuf < sbufend) {
+			if(*sbuf > dz->param[FMNTSEE_MAX])
+				dz->param[FMNTSEE_MAX] = *sbuf;
+			sbuf++;
+		}
+		if((exit_status = read_samps(dz->bigfbuf,dz)) < 0) {
+			sprintf(errstr,"Sound read error.\n");
+			return(SYSTEM_ERROR);
+		}  
+		sbuf      = dz->bigfbuf;
+		sbufend   = dz->bigfbuf + dz->ssampsread;
+	} while(dz->ssampsread > 0);
+	return(FINISHED);
+}
+
+/***************************** INITIALISE_THE_FORMANT_DATA *************************/
+
+int initialise_the_formant_data(int *windows_in_buf,dataptr dz)
+{
+	int exit_status;
+	int fsamps_to_read = dz->descriptor_samps/DESCRIPTOR_DATA_BLOKS;
+	if((exit_status = read_samps(dz->bigfbuf,dz)) < 0)
+		return(exit_status);
+	if(dz->ssampsread < dz->descriptor_samps) {
+		sprintf(errstr,"No significant data in formantfile.\n");
+		return(DATA_ERROR);
+	}
+	dz->flbufptr[0] = dz->bigfbuf;
+	memmove((char *)dz->specenvpch,(char *)dz->flbufptr[0],(size_t)(fsamps_to_read * sizeof(float)));
+	dz->flbufptr[0] += dz->infile->specenvcnt;
+	memmove((char *)dz->specenvtop,(char *)dz->flbufptr[0],(size_t)(fsamps_to_read * sizeof(float)));
+	dz->flbufptr[0] += dz->infile->specenvcnt;
+	dz->flbufptr[0] = dz->bigfbuf + (DESCRIPTOR_DATA_BLOKS * dz->wanted);
+	*windows_in_buf = dz->ssampsread/dz->wanted;    
+	if((*windows_in_buf -= DESCRIPTOR_DATA_BLOKS) <= 0) {
+		sprintf(errstr,"Buffers too SMALL for formant data.\n");
+		return(PROGRAM_ERROR);
+	}
+	if(dz->vflag[FMNT_VIEW])
+		print_formant_params_to_screen(dz);
+	if((exit_status = get_max_formantval(dz))<0)
+		return(exit_status);
+	return reset_file_to_start_and_pointers_to_after_descriptor_blocks(windows_in_buf,dz);
+}

+ 655 - 0
dev/formants/formav.c

@@ -0,0 +1,655 @@
+/*
+ * 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
+ *
+ */
+
+
+
+// (2) Do need an entry in  standalone ....
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <filetype.h>
+#include <cdpmain.h>
+#include <logic.h>
+#include <sfsys.h>
+
+char errstr[2400];
+
+static int local_print_messages_and_close_sndfiles(int exit_status,int is_launched,int ofd,int *ifd,int infilecnt);
+static int local_read_samps(float *bbuf,int wanted,int *total_samps_read, int *ssampsread,int n,int *ifd, int totalsize);
+static int reset_file_to_start_and_pointers_to_after_descriptor_blocks
+			(int *ifd,int *windows_in_buf,int n,int wanted,int specenvcnt,float *bigfbuf,float **flbufptr,
+			int *total_samps_read,int totalsize);
+static int check_the_formant_data(int *windows_in_buf,float *specenvpch,float *specenvtop,float *bigfbuf,float **flbufptr,char **argv,
+								infileptr ifp,int specenvcnt,int wanted,int *total_samps_read,int totalsize,int n,int *ifd);
+static int initialise_the_formant_data(int *windows_in_buf,float *specenvpch,float *specenvtop,float *bigfbuf,float **flbufptr,
+								infileptr ifp,int specenvcnt,int wanted,int *total_samps_read,int totalsize,int n,int *ifd);
+static void display_sloom_time(int samps_sent,int totalsize);
+static int local_readhead(infileptr inputfile,int ifd,char *filename,int getmax,int needmaxinfo);
+static void local_splice_multiline_string(char *str,char *prefix);
+static int flteq(double f1,double f2);
+static int formant_headwrite(int ofd,infileptr ifp);
+
+#define FAILED	(-1)
+#define SUCCEEDED	(0)
+#define PBAR_LENGTH	(256)
+
+#define CONTINUE      (1)
+#define FINISHED      (0)
+#define	GOAL_FAILED	  (-1)	/* program succeeds, but users goal not achieved: e.g. find pitch */
+#define USER_ERROR    (-2)	/* program fails because wrong data, no data etc given by user */
+#define	DATA_ERROR	  (-3)	/* Data is unsuitable, incorrect or missing */
+#define	MEMORY_ERROR  (-4)	/* program fails because ran out of, or mismanaged, memory */
+#define	SYSTEM_ERROR  (-5)  /* failure to write to or truncate outfile: usually means H/D is full */
+#define PROGRAM_ERROR (-6)	/* program fails because the programming is naff */
+#define	USAGE_ONLY	  (-7)	/* program interrogated for usage_message only */	
+#define	TK_USAGE	  (-8)	/* program interrogated by TK for usage_message only */	
+#define	BAD_INFILECNT (-9)	/* Bad infilecnt sent from TK at program testing stage */
+
+#ifndef FALSE
+#define FALSE   (0)
+#endif
+
+#ifndef TRUE
+#define TRUE	(1)
+#endif
+
+#define DESCRIPTOR_DATA_BLOKS 	(2)
+#define	ENDOFSTR			 ('\0')
+#define FLTERR 		 	(0.000002)
+
+/**************************************** MAIN *********************************************/
+
+// cmdline formav formfil1 formfil2 [formfil3 ....] outformfil dur
+
+int main(int argc,char *argv[])
+{
+	int exit_status, n, m, k, infilecnt;
+	int is_launched = FALSE;
+	int *ifd = NULL, ofd = -1;
+	int specenvcnt;
+	int wanted, windows_in_buf,outfltcnt,outwindowcnt;
+	infileptr ifp,ifp2;
+	float *bigfbuf, *bigbufend, *flbufptr, *oflbufptr, *specenvpch, *specenvtop;
+	int total_windows = 0, ssampsread, min_inwindowsize, totalsize, size, total_samps_read;
+	double dur;
+	
+	if(sflinit("cdp")){
+		sfperror("cdp: initialisation\n");
+		return(FAILED);
+	}
+	if(argc < 5) {
+		fprintf(stdout,"ERROR: Insufficient arguments on commandline.\n");
+		fflush(stdout);
+		return(FAILED);
+	}
+	if(sscanf(argv[argc-1],"%lf",&dur)!=1) {
+		fprintf(stdout,"ERROR: Cannot read output duration from command line.\n");
+		fflush(stdout);
+		return(FAILED);
+	}
+	if (dur < 0.2) {
+		fprintf(stdout,"ERROR: Output duration (%lf) too short (min 0.2 secs).\n",dur);
+		fflush(stdout);
+		return(FAILED);
+	}
+	if((ifp = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
+		fprintf(stdout,"ERROR: INSUFFICIENT MEMORY to store data on infiles (1)\n");
+		fflush(stdout);
+		return(FAILED);
+	}
+	if((ifp2 = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
+		fprintf(stdout,"ERROR: INSUFFICIENT MEMORY to store data on infiles (2)\n");
+		fflush(stdout);
+		return(FAILED);
+	}
+	if((ifd = (int *)malloc((argc-3) * sizeof(int))) == NULL) {
+		fprintf(stdout,"ERROR: Insufficient memory.\n");
+		fflush(stdout);
+		return(FAILED);
+	}
+	for(n=1;n<argc-2;n++) {
+		m = n-1;
+		if((ifd[m] = sndopenEx(argv[n],0,CDP_OPEN_RDONLY)) < 0) {
+			sprintf(errstr,"FAILED TO OPEN FILE %s\n",argv[n]);
+			exit_status =	DATA_ERROR;
+			local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,m);
+			return(FAILED);
+		}
+	}
+	infilecnt = m+1;
+
+	for(n=0;n<infilecnt;n++) {	
+		if((exit_status = local_readhead(ifp,ifd[n],argv[n+1],0,0))<0) {
+			exit_status =	SYSTEM_ERROR;
+			local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+			return(FAILED);
+		}
+		if(n==0) {
+			if(ifp->filetype != FORMANTFILE) {
+				sprintf(errstr,"First input file is not a formant file.\n");
+				exit_status = DATA_ERROR;
+				local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+				return(FAILED);
+			}
+			ifp2->filetype		= ifp->filetype;
+			ifp2->srate 	   	= ifp->srate;	   		
+			ifp2->stype 	    = ifp->stype;
+			ifp2->origstype  	= ifp->origstype;
+			ifp2->origrate   	= ifp->origrate;
+			ifp2->channels   	= ifp->channels;
+			ifp2->origchans  	= ifp->origchans;
+			ifp2->specenvcnt 	= ifp->specenvcnt;
+			ifp2->Mlen 	   		= ifp->Mlen;
+			ifp2->Dfac 	   		= ifp->Dfac;
+			ifp2->arate 	   	= ifp->arate;
+			ifp2->descriptor_samps = ifp->descriptor_samps;
+		} else {
+			if(ifp2->filetype	!= ifp->filetype
+			|| ifp2->srate 		!= ifp->srate
+			|| ifp2->stype 		!= ifp->stype
+			|| ifp2->origstype  != ifp->origstype
+			|| ifp2->origrate   != ifp->origrate
+			|| ifp2->channels   != ifp->channels
+			|| ifp2->origchans  != ifp->origchans
+			|| ifp2->specenvcnt != ifp->specenvcnt
+			|| ifp2->Mlen 	   	!= ifp->Mlen
+			|| ifp2->Dfac 	   	!= ifp->Dfac
+			|| ifp2->arate 		!= ifp->arate
+			|| ifp2->descriptor_samps != ifp->descriptor_samps) {
+				sprintf(errstr,"Input files have incompatible properties.\n");
+				exit_status = DATA_ERROR;
+				local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+				return(FAILED);
+			}
+		}
+	}
+	wanted = ifp->specenvcnt * 8;
+	specenvcnt = ifp->specenvcnt;
+	min_inwindowsize = 10000000;
+	totalsize = 0;
+	for(n=0;n<infilecnt;n++) {
+		size = sndsizeEx(ifd[n]);
+		if(n==0)
+			min_inwindowsize = size;
+		else if(size < min_inwindowsize)
+			min_inwindowsize = size;
+		totalsize += size;
+	}
+	if(min_inwindowsize - (specenvcnt * 2) <= 0) {
+		sprintf(errstr,"No significant data in at least one of input files\n");
+		local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+		return(FAILED);
+	}
+	outfltcnt = ((int)round(dur / ifp->frametime) * specenvcnt) + 2;
+	if((ofd = sndcreat_formatted(argv[argc-1],outfltcnt,SAMP_FLOAT,
+			ifp->channels,ifp->srate,CDP_CREATE_NORMAL)) < 0) {
+		sprintf(errstr,"Cannot open output file %s\n", argv[argc-1]);
+		exit_status = SYSTEM_ERROR;
+		local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+		return(FAILED);
+	}
+	outwindowcnt = (outfltcnt/specenvcnt) - 2;
+	is_launched = 1;
+	if((specenvpch = (float *)malloc(specenvcnt * sizeof(float))) == NULL) {
+		sprintf(errstr,"Insufficient memory to store formant descriptor data 1.\n");
+		exit_status = MEMORY_ERROR;
+		local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+		return(FAILED);
+	}
+	if((specenvtop = (float *)malloc(specenvcnt * sizeof(float))) == NULL) {
+		sprintf(errstr,"Insufficient memory to store formant descriptor data 2.\n");
+		exit_status = MEMORY_ERROR;
+		local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+		return(FAILED);
+	}
+	if((oflbufptr = (float *)malloc(specenvcnt * sizeof(float))) == NULL) {
+		sprintf(errstr,"Insufficient memory to store output formant data.\n");
+		exit_status = MEMORY_ERROR;
+		local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+		return(FAILED);
+	}
+	memset((char *)oflbufptr,0,specenvcnt * sizeof(float));
+	if((bigfbuf = (float *)malloc(wanted * sizeof(float))) == NULL) {
+		sprintf(errstr,"Insufficient memory to store input formant data.\n");
+		exit_status = MEMORY_ERROR;
+		local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+		return(FAILED);
+	}
+	bigbufend = bigfbuf + wanted;
+	memset((char *)bigfbuf,0,wanted * sizeof(float));
+	total_samps_read = 0;
+	for(n=0;n<infilecnt;n++) {
+		if(n==0) {
+			if((exit_status = initialise_the_formant_data(&windows_in_buf,specenvpch,specenvtop,bigfbuf,
+			&flbufptr,ifp,specenvcnt,wanted,&total_samps_read,totalsize,n,ifd))<0) {
+				local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+				return(FAILED);
+			}
+		} else {
+			if((exit_status = check_the_formant_data(&windows_in_buf,specenvpch,specenvtop,bigfbuf,
+				&flbufptr,argv,ifp,specenvcnt,wanted,&total_samps_read,totalsize,n,ifd))<0) {
+				local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+				return(FAILED);
+			}
+		}
+		m = 0;
+		while(m < windows_in_buf) {
+			for(k = 0;k<specenvcnt;k++)
+				oflbufptr[k] += flbufptr[k];
+			flbufptr += specenvcnt;
+			total_windows++;
+			m++;
+		}
+		for (;;) {
+			if((exit_status = local_read_samps(bigfbuf,wanted,&total_samps_read,&ssampsread,n,ifd,totalsize)) < 0)
+				return(exit_status);
+			if(ssampsread <= 0)
+				break;
+			windows_in_buf = ssampsread/specenvcnt;
+			flbufptr = bigfbuf;
+			m = 0;
+			while(m < windows_in_buf) {
+				for(k = 0;k<specenvcnt;k++)
+					oflbufptr[k] += flbufptr[k];
+				flbufptr += specenvcnt;
+				total_windows++;
+				m++;
+			}
+		}
+		if(sndcloseEx(ifd[n]) < 0) {
+			fprintf(stdout,"WARNING: Failed to close file %s\n",argv[n+1]);
+			fflush(stdout);
+		}
+		ifd[n] = -1;
+	}
+	ifd = NULL;
+	for(k = 0;k<specenvcnt;k++)
+		oflbufptr[k] = (float) (oflbufptr[k]/(double)total_windows);
+	if(fputfbufEx(specenvpch,specenvcnt,ofd)<=0) {
+		sprintf(errstr,"Can't write to output soundfile: %s\n",sferrstr());
+		return(SYSTEM_ERROR);
+	}
+	if(fputfbufEx(specenvtop,specenvcnt,ofd)<=0) {
+		sprintf(errstr,"Can't write to output soundfile: %s\n",sferrstr());
+		return(SYSTEM_ERROR);
+	}
+	for(n=0;n<outwindowcnt;n++) {
+		if(fputfbufEx(oflbufptr,specenvcnt,ofd)<=0) {
+			sprintf(errstr,"Can't write to output soundfile: %s\n",sferrstr());
+			return(SYSTEM_ERROR);
+		}
+	}
+	if(sndcloseEx(ofd) < 0) {
+		sprintf(errstr,"ERROR: Failed to close output file %s\n",argv[argc-1]);
+		exit_status = SYSTEM_ERROR;
+		local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+		return(FAILED);
+	}
+	if((exit_status = formant_headwrite(ofd,ifp))<0) {
+		local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+		return(FAILED);
+	}
+	local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt);
+	return(SUCCEEDED);
+}
+
+/***************************** INITIALISE_THE_FORMANT_DATA *************************/
+
+int initialise_the_formant_data(int *windows_in_buf,float *specenvpch,float *specenvtop,float *bigfbuf,float **flbufptr,
+								infileptr ifp,int specenvcnt,int wanted,int *total_samps_read,int totalsize,int n,int *ifd)
+{
+	int exit_status;
+	int ssampsread;
+	int fsamps_to_read = ifp->descriptor_samps/DESCRIPTOR_DATA_BLOKS;
+	if((exit_status = local_read_samps(bigfbuf,wanted,total_samps_read,&ssampsread,n,ifd,totalsize)) < 0)
+		return(exit_status);
+	if(ssampsread < ifp->descriptor_samps) {
+		sprintf(errstr,"No significant data in formantfile.\n");
+		return(DATA_ERROR);
+	}
+	*flbufptr = bigfbuf;
+	memcpy((char *)specenvpch,(char *)(*flbufptr),(size_t)(fsamps_to_read * sizeof(float)));
+	*flbufptr += specenvcnt;
+	memcpy((char *)specenvtop,(char *)(*flbufptr),(size_t)(fsamps_to_read * sizeof(float)));
+	*flbufptr = bigfbuf + (DESCRIPTOR_DATA_BLOKS * specenvcnt);
+	*windows_in_buf = ssampsread/specenvcnt;    
+	if((*windows_in_buf -= DESCRIPTOR_DATA_BLOKS) <= 0) {
+		sprintf(errstr,"Buffers too SMALL for formant data.\n");
+		return(PROGRAM_ERROR);
+	}
+	return reset_file_to_start_and_pointers_to_after_descriptor_blocks
+	(ifd,windows_in_buf,n,wanted,specenvcnt,bigfbuf,flbufptr,total_samps_read,totalsize);
+}
+
+/***************************** CHECK_THE_FORMANT_DATA *************************/
+
+int check_the_formant_data(int *windows_in_buf,float *specenvpch,float *specenvtop,float *bigfbuf,float **flbufptr,char **argv,
+								infileptr ifp,int specenvcnt,int wanted,int *total_samps_read,int totalsize,int n,int *ifd)
+{
+	int exit_status, k;
+	int ssampsread;
+	int fsamps_to_read = ifp->descriptor_samps/DESCRIPTOR_DATA_BLOKS;
+	if((exit_status = local_read_samps(bigfbuf,wanted,total_samps_read,&ssampsread,n,ifd,totalsize)) < 0)
+		return(exit_status);
+	if(ssampsread < ifp->descriptor_samps) {
+		sprintf(errstr,"No significant data in formantfile.\n");
+		return(DATA_ERROR);
+	}
+	*flbufptr = bigfbuf;
+	for(k=0;k<specenvcnt;k++) {
+		if(!flteq(specenvpch[k],(*flbufptr)[k])) {
+			sprintf(errstr,"Formant file %s has a different format to the others\n",argv[n+1]);
+			return(DATA_ERROR);
+		}
+	}
+	*flbufptr += specenvcnt;
+	for(k=0;k<specenvcnt;k++) {
+		if(!flteq(specenvtop[k],(*flbufptr)[k])) {
+			sprintf(errstr,"Formant file %s has a different format to the others\n",argv[n+1]);
+			return(DATA_ERROR);
+		}
+	}
+	*flbufptr = bigfbuf + (DESCRIPTOR_DATA_BLOKS * specenvcnt);
+	*windows_in_buf = ssampsread/specenvcnt;    
+	if((*windows_in_buf -= DESCRIPTOR_DATA_BLOKS) <= 0) {
+		sprintf(errstr,"Buffers too SMALL for formant data.\n");
+		return(PROGRAM_ERROR);
+	}
+	return reset_file_to_start_and_pointers_to_after_descriptor_blocks
+	(ifd,windows_in_buf,n,wanted,specenvcnt,bigfbuf,flbufptr,total_samps_read,totalsize);
+}
+
+/*********************** RESET_FILE_TO_START_AND_POINTERS_TO_AFTER_DESCRIPTOR_BLOCKS **********************/
+
+int reset_file_to_start_and_pointers_to_after_descriptor_blocks
+(int *ifd,int *windows_in_buf,int n,int wanted,int specenvcnt,float *bigfbuf,float **flbufptr,int *total_samps_read,int totalsize)
+{
+	int exit_status;
+	int ssampsread;
+	if(sndseekEx(ifd[n],0L,0)<0) { /* RESET FILE POINTER TO START OF DATA */
+		sprintf(errstr,"seek failed in reset_file_to_start_and_pointers_to_after_descriptor_blocks()\n");
+		return(SYSTEM_ERROR);
+	}
+	if((exit_status = local_read_samps(bigfbuf,wanted,total_samps_read,&ssampsread,n,ifd,totalsize)) < 0) {
+		sprintf(errstr,"Read problem after rewind in reset_file_to_start_and_pointers_to_after_descriptor_blocks()\n");
+		return(SYSTEM_ERROR);
+	}
+	*total_samps_read -= ssampsread;	/* allow for the backtracking invloved in reading descriptor blocks */
+	*windows_in_buf = ssampsread/specenvcnt;    
+	if((*windows_in_buf -= DESCRIPTOR_DATA_BLOKS) < 0) {
+		sprintf(errstr,"Buffers too SMALL in reset_file_to_start_and_pointers_to_after_descriptor_blocks()\n");
+		return(PROGRAM_ERROR);
+	}
+	(*flbufptr) = bigfbuf + (DESCRIPTOR_DATA_BLOKS * specenvcnt);
+	return(FINISHED);
+}
+
+/*********************** LOCAL_READ_SAMPS **********************/
+
+int local_read_samps(float *bbuf,int wanted,int *total_samps_read, int *ssampsread,int n,int *ifd,int totalsize)
+{
+	if((*ssampsread = fgetfbufEx(bbuf, wanted,ifd[n],0)) < 0) {
+		sprintf(errstr,"Can't read samples from input soundfile.\n");
+		return(SYSTEM_ERROR);
+	}
+	*total_samps_read += *ssampsread;
+	display_sloom_time(*total_samps_read,totalsize);
+
+	return(FINISHED);
+}
+
+
+/*********************** DISPLAY_SLOOM_TIME **********************/
+
+void display_sloom_time(int samps_sent,int totalsize) {
+	double float_time   = min(1.0,(double)samps_sent/(double)totalsize);
+	int display_time = round(float_time * PBAR_LENGTH);
+	fprintf(stdout,"TIME: %d\n",display_time);
+	fflush(stdout);
+}
+
+/****************************** LOCAL_PRINT_MESSAGES_AND_CLOSE_SNDFILES ******************************/
+
+int	local_print_messages_and_close_sndfiles(int exit_status,int is_launched,int ofd,int *ifd,int infilecnt)
+{
+	int n;							/* OUTPUT ERROR MESSAGES */
+	switch(exit_status) {
+	case(FINISHED):			break;
+	case(PROGRAM_ERROR):	
+		fprintf(stdout,"ERROR: INTERNAL ERROR: (Bug?)\n");
+		local_splice_multiline_string(errstr,"ERROR:");
+		break;
+	case(SYSTEM_ERROR):		
+		fprintf(stdout,"ERROR: SYSTEM ERROR\n");
+		local_splice_multiline_string(errstr,"ERROR:");
+		break;
+	case(MEMORY_ERROR):		
+		fprintf(stdout,"ERROR: MEMORY ERROR\n");
+		local_splice_multiline_string(errstr,"ERROR:");
+		break;
+	case(USER_ERROR):		
+		fprintf(stdout,"ERROR: DATA OR RANGE ERROR\n");
+		local_splice_multiline_string(errstr,"ERROR:");
+		break;
+	case(DATA_ERROR):		
+		fprintf(stdout,"ERROR: INVALID DATA\n");
+		local_splice_multiline_string(errstr,"ERROR:");
+		break;
+	case(GOAL_FAILED):		
+		fprintf(stdout,"ERROR: CANNOT ACHIEVE TASK:\n");
+		local_splice_multiline_string(errstr,"ERROR:");
+		break;
+	case(USAGE_ONLY):
+		fprintf(stdout,"ERROR: PROGRAM ERROR: usage messages should not be called.\n");
+		fflush(stdout);
+		break;
+	case(TK_USAGE):			
+		exit_status = FINISHED;
+		break;
+	default:
+		fprintf(stdout,"ERROR: INTERNAL ERROR: (Bug?)\n");
+		fprintf(stdout,"ERROR: Unknown case in print_messages_and_close_sndfiles)\n");
+		exit_status = PROGRAM_ERROR;
+		break;
+	}
+	if(ofd >= 0 && (exit_status!=FINISHED || !is_launched) && sndunlink(ofd) < 0)
+		fprintf(stdout, "ERROR: Can't set output soundfile for deletion.\n");
+//	if((ofd >= 0) && dz->needpeaks){
+//		if(sndputpeaks(dz->ofd,dz->outchans,dz->outpeaks)) {
+//			fprintf(stdout,"WARNING: failed to write PEAK data\n");
+//			fflush(stdout);
+//		}
+//	}
+	if(ofd >= 0  && sndcloseEx(ofd) < 0) {
+		fprintf(stdout, "WARNING: Can't close output sf-soundfile : %s\n",sferrstr());
+		fflush(stdout);
+	}
+	if(ifd != NULL && infilecnt >= 0) {
+		for(n=0;n<infilecnt;n++) {
+		  /* ALL OTHER CASES */
+			if(ifd[n] >= 0 && sndcloseEx(ifd[n]) < 0)
+				fprintf(stdout, "WARNING: Can't close input sf-soundfile %d.\n",n+1);
+		}
+	}
+	sffinish();
+	fprintf(stdout,"END:");
+	fflush(stdout);
+	if(exit_status != FINISHED) {
+		return(FAILED);
+	}
+	return(SUCCEEDED);
+}
+
+int local_readhead(infileptr inputfile,int ifd,char *filename,int getmax,int needmaxinfo)
+{
+	SFPROPS props = {0};
+	int isenv = 0;
+	int os;
+	
+	if(!snd_headread(ifd,&props)) {
+		fprintf(stdout,"INFO: Failure to read properties, in %s\n",filename);
+		fflush(stdout);
+		return(DATA_ERROR);
+	}
+	inputfile->srate = props.srate;
+	inputfile->channels = props.chans;
+
+	switch(props.samptype) {
+	case(SHORT16):	inputfile->stype = SAMP_SHORT;	break;
+	case(FLOAT32):	inputfile->stype = SAMP_FLOAT;	break;
+	case(SHORT8):	inputfile->stype = SAMP_BYTE;	break;
+	default:	/* remaining symbols have same int value */	break;
+	}
+//TW TEMPORARY SUBSTITUTION
+	inputfile->filetype = SNDFILE;
+	if(sndgetprop(ifd,"is an envelope",(char *) &isenv,sizeof(int)) >= 0)
+		inputfile->filetype = ENVFILE;
+	else if(sndgetprop(ifd,"is a formant file",(char *) &isenv,sizeof(int)) >= 0)
+		inputfile->filetype = FORMANTFILE;
+	else if(sndgetprop(ifd,"is a pitch file",(char *) &isenv,sizeof(int)) >= 0)
+		inputfile->filetype = PITCHFILE;
+	else if(sndgetprop(ifd,"is a transpos file",(char *) &isenv,sizeof(int)) >= 0)
+		inputfile->filetype = TRANSPOSFILE;
+	else if(sndgetprop(ifd,"original sampsize",(char *) &os,sizeof(int)) > 0)
+		inputfile->filetype = ANALFILE;
+
+	inputfile->specenvcnt = props.specenvcnt;
+	if(inputfile->channels != 1) {
+		sprintf(errstr,"Channel count not equal to 1 in %s: readhead()\n"
+		"Implies failure to write correct header in another program.\n",
+		filename);
+		return(PROGRAM_ERROR);
+	}
+	if(sndgetprop(ifd,"orig channels",(char *)&(inputfile->origchans),sizeof(int)) < 0) {
+		fprintf(stdout,"Cannot read original channels count: %s\n",filename);
+		fflush(stdout);
+		return(DATA_ERROR);
+	}
+	if(sndgetprop(ifd,"original sampsize",(char *)&(inputfile->origstype),sizeof(int)) < 0) {
+		fprintf(stdout,"Cannot read original sample type: %s\n",filename);
+		fflush(stdout);
+		return(DATA_ERROR);
+	}
+	if(sndgetprop(ifd,"original sample rate",(char *)&(inputfile->origrate),sizeof(int)) < 0) {
+		fprintf(stdout,"Cannot read original sample rate: %s\n",filename);
+		fflush(stdout);
+		return(DATA_ERROR);
+	}
+	if(sndgetprop(ifd,"arate",(char *)&(inputfile->arate),sizeof(float)) < 0) {
+		fprintf(stdout,"Cannot read analysis rate: %s\n",filename);
+		fflush(stdout);
+		return(DATA_ERROR);
+	}
+	if(sndgetprop(ifd,"analwinlen",(char *)&(inputfile->Mlen),sizeof(int)) < 0) {
+		fprintf(stdout,"Cannot read analysis window length: %s\n",filename);
+		fflush(stdout);
+		return(DATA_ERROR);
+	}
+	if(sndgetprop(ifd,"decfactor",(char *)&(inputfile->Dfac),sizeof(int)) < 0) {
+		fprintf(stdout,"Cannot read original decimation factor: %s\n",filename);
+		fflush(stdout);
+		return(DATA_ERROR);
+	}
+	return(FINISHED);
+}
+
+/****************************** LOCAL_SPLICE_MULTILINE_STRING ******************************/
+
+void local_splice_multiline_string(char *str,char *prefix)
+{
+	char *p, *q, c;
+	p = str;
+	q = str;
+	while(*q != ENDOFSTR) {
+		while(*p != '\n' && *p != ENDOFSTR)
+			p++;
+		c = *p;
+		*p = ENDOFSTR;
+		fprintf(stdout,"%s %s\n",prefix,q);
+		*p = c;
+		if(*p == '\n')
+			 p++;
+		while(*p == '\n') {
+			fprintf(stdout,"%s \n",prefix);
+			p++;
+		}
+		q = p;
+		p++;
+	}
+}
+
+/**************************** FLTEQ *******************************/
+
+int flteq(double f1,double f2)
+{
+	double upperbnd, lowerbnd;
+	upperbnd = f2 + FLTERR;		
+	lowerbnd = f2 - FLTERR;		
+	if((f1>upperbnd) || (f1<lowerbnd))
+		return(FALSE);
+	return(TRUE);
+}
+
+/***************************** FORMANT_HEADWRITE *******************************/
+
+int formant_headwrite(int ofd,infileptr ifp)
+{	
+	int  property_marker = 1;
+
+    if(sndputprop(ofd,"specenvcnt", (char *)&(ifp->specenvcnt), sizeof(int)) < 0){
+		sprintf(errstr,"Failure to write specenvcnt: headwrite()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(sndputprop(ofd,"orig channels", (char *)&(ifp->origchans), sizeof(int)) < 0){
+		sprintf(errstr,"Failure to write original channel data: headwrite()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(sndputprop(ofd,"original sampsize", (char *)&(ifp->origstype), sizeof(int)) < 0){
+		sprintf(errstr,"Failure to write original sample size. headwrite()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(sndputprop(ofd,"original sample rate", (char *)&(ifp->origrate), sizeof(int)) < 0){
+		sprintf(errstr,"Failure to write original sample rate. headwrite()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(sndputprop(ofd,"arate",(char *)&(ifp->arate),sizeof(float)) < 0){
+		sprintf(errstr,"Failed to write analysis sample rate. headwrite()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(sndputprop(ofd,"analwinlen",(char *)&(ifp->Mlen),sizeof(int)) < 0){
+		sprintf(errstr,"Failure to write analysis window length. headwrite()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(sndputprop(ofd,"decfactor",(char *)&(ifp->Dfac),sizeof(int)) < 0){
+		sprintf(errstr,"Failure to write decimation factor. headwrite()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(sndputprop(ofd,"is a formant file", (char *)&property_marker, sizeof(int)) < 0){
+		sprintf(errstr,"Failure to write formant property: headwrite()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+

+ 240 - 0
dev/formants/main.c

@@ -0,0 +1,240 @@
+/*
+ * 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
+ *
+ */
+
+
+
+/* Sept 05: via formantsg.c: fixed formants put
+   added version number support.
+  */
+#include <stdio.h>
+#include <stdlib.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <fmnts.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;
+//TW UPDATE
+/*extern*/ int	sloombatch = 0;
+/*extern*/ int anal_infiles = 1;
+/*extern*/ int is_converted_to_stereo = -1;
+
+/**************************************** MAIN *********************************************/
+
+const char* cdp_version = "7.1.0";
+
+
+int main(int argc,char *argv[])
+{
+	int exit_status;
+//	FILE *fp   = NULL;
+	dataptr dz = NULL;
+//	char *special_data_string = NULL;
+	char **cmdline;
+	int  cmdlinecnt;
+	aplptr ap;
+	int *valid = NULL;
+	int is_launched = FALSE;
+	int  validcnt;
+						/* CHECK FOR SOUNDLOOM */
+//TW UPDATE
+	if((argc==2) && strcmp(argv[1],"--version")==0) {
+		fprintf(stdout,"%s\n",cdp_version);
+		fflush(stdout);
+		return 0;
+	}
+	if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
+		sloom = 0;
+		sloombatch = 1;
+	}
+
+	if(!sloom) {
+		if((exit_status = allocate_and_initialise_validity_flags(&valid,&validcnt))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+	}
+	if(sflinit("cdp")){
+		sfperror("cdp: initialisation\n");
+		return(FAILED);
+	}
+
+						  /* SET UP THE PRINCIPLE DATASTRUCTURE */
+	if((exit_status = establish_datastructure(&dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+	if(!sloom) {
+							  /* INITIAL CHECK OF CMDLINE DATA */
+		if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+		cmdline    = argv;	/* GET PRE_DATA, ALLOCATE THE APPLICATION, CHECK FOR EXTRA INFILES */
+		cmdlinecnt = argc;
+		if((exit_status = get_process_and_mode_from_cmdline(&cmdlinecnt,&cmdline,dz))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}		
+		if((exit_status = setup_particular_application(dz))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+		if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) {
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+			return(FAILED);
+		}
+	} else {
+		if((exit_status = parse_tk_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {  	/* includes setup_particular_application()      */
+			exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);/* and cmdlinelength check = sees extra-infiles */
+			return(exit_status);		 
+		}
+	}
+	ap = dz->application;
+
+/*********************************************************************************************************************
+	   cmdline[0]				 		  2 vals					   		  ACTIVE		 
+TK 		(infile) (more-infiles) (outfile) (flag val) (formantsqksrch) (special) params  options   variant-params  flags
+CMDLINE	(infile) (more-infiles) (outfile) (formants) (formantsqksrch) (special) params  POSSIBLY  POSSIBLY	  	POSSIBLY
+								 		  1 val
+*********************************************************************************************************************/
+
+	if((exit_status = parse_infile_and_hone_type(cmdline[0],valid,dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+	if((exit_status = setup_param_ranges_and_defaults(dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+
+					/* OPEN FIRST INFILE AND STORE DATA, AND INFORMATION, APPROPRIATELY */
+
+	if(dz->input_data_type!=NO_FILE_AT_ALL) {
+		if((exit_status = open_first_infile(cmdline[0],dz))<0) {	
+			print_messages_and_close_sndfiles(exit_status,is_launched,dz);	
+			return(FAILED);
+		}
+//TW UPDATE
+		cmdlinecnt--;
+		cmdline++;
+	}
+	
+/*********************************************************************************************************************
+		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 = spec_process_file(dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	if((exit_status = complete_output(dz))<0) {
+		print_messages_and_close_sndfiles(exit_status,is_launched,dz);
+		return(FAILED);
+	}
+	exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz);
+	free(dz);
+	return(SUCCEEDED);
+}
+