Browse Source

initial commit

richarddobson 3 years ago
parent
commit
99669b2552
4 changed files with 1726 additions and 0 deletions
  1. 20 0
      dev/specinfo/CMakeLists.txt
  2. 781 0
      dev/specinfo/ap_specinfo.c
  3. 234 0
      dev/specinfo/main.c
  4. 691 0
      dev/specinfo/specinfo.c

+ 20 - 0
dev/specinfo/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(specinfo main.c ap_specinfo.c specinfo.c)
+
+target_link_libraries(specinfo cdp2k sfsys ${EXTRA_LIBRARIES})
+
+my_install(specinfo)
+

+ 781 - 0
dev/specinfo/ap_specinfo.c

@@ -0,0 +1,781 @@
+/*
+ * 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 <specinfo.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_validity_of_octvu_params(dataptr dz);
+static int 	check_consistency_of_report_params(dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+#define MARGIN_OF_ERROR (16) /* 8 channels * 2 for both amp AND frq */
+
+static int  setup_internal_arrays_and_params_for_level(dataptr dz);
+static int  calculate_octvu_energy_band_parameters(dataptr dz);
+static int  specpeak_preprocess(dataptr dz);
+static int  create_hearing_response_adjustment_curve(dataptr dz);
+static int  get_frq_bands(int *cnt,dataptr dz);
+static int	 setup_internal_params_and_arrays_for_specreport(dataptr dz);
+static int  setup_internal_print_params(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(WINDOWCNT):  		dz->extra_bufcnt =  0; dz->bptrcnt = 0; 	is_spec = TRUE;		break;
+	case(CHANNEL):    		dz->extra_bufcnt =  0; dz->bptrcnt = 0; 	is_spec = TRUE;		break;
+	case(FREQUENCY):  		dz->extra_bufcnt =  0; dz->bptrcnt = 0; 	is_spec = TRUE;		break;
+	case(LEVEL):      		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(OCTVU):      		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(PEAK):	      		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(REPORT):     		dz->extra_bufcnt =  0; dz->bptrcnt = 4; 	is_spec = TRUE;		break;
+	case(PRINT):      		dz->extra_bufcnt =  0; 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(WINDOWCNT):dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(CHANNEL):	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(FREQUENCY):dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(LEVEL):  	dz->array_cnt =1;  dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(OCTVU):  	dz->array_cnt =1;  dz->iarray_cnt =2;  dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(PEAK):   	dz->array_cnt =2;  dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(REPORT): 	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(PRINT):	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(WINDOWCNT):	setup_process_logic(ANALFILE_ONLY,		  	SCREEN_MESSAGE,		NO_OUTPUTFILE,	dz);	break;
+	case(CHANNEL):		setup_process_logic(ANALFILE_ONLY,		  	SCREEN_MESSAGE,		NO_OUTPUTFILE,	dz);	break;
+	case(FREQUENCY):	setup_process_logic(ANALFILE_ONLY,		  	SCREEN_MESSAGE,		NO_OUTPUTFILE,	dz);	break;
+	case(LEVEL):		setup_process_logic(ANALFILE_ONLY,		  	PSEUDOSNDFILE,		SNDFILE_OUT,	dz);	break;
+	case(OCTVU):		setup_process_logic(ANALFILE_ONLY,		  	TO_TEXTFILE,		TEXTFILE_OUT,	dz);	break;
+	case(PEAK):			setup_process_logic(ANALFILE_ONLY,		  	TO_TEXTFILE,		TEXTFILE_OUT,	dz);	break;
+	case(REPORT):		setup_process_logic(ANALFILE_ONLY,		  	TO_TEXTFILE,		TEXTFILE_OUT,	dz);	break;
+	case(PRINT):		setup_process_logic(ANALFILE_ONLY,		  	TO_TEXTFILE,		TEXTFILE_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(WINDOWCNT):  	return(FINISHED);
+	case(CHANNEL):	  	return(FINISHED);
+	case(FREQUENCY):  	return(FINISHED);
+	case(LEVEL):	  	return(FINISHED);
+	case(OCTVU):	  	exit_status = set_internalparam_data("di",ap);					break;
+	case(PEAK):		  	exit_status = set_internalparam_data("dii",ap);					break;
+	case(REPORT):	  	exit_status = set_internalparam_data("ii",ap);					break;
+	case(PRINT):	  	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)	   
+{
+	aplptr ap = dz->application;
+	switch(ap->special_data) {
+	default:
+		sprintf(errstr,"Unknown special_data type: read_special_data()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+/****************************** PARAM_PREPROCESS *********************************/
+
+int param_preprocess(dataptr dz)	
+{
+	switch(dz->process) {
+	case(LEVEL):		return setup_internal_arrays_and_params_for_level(dz);
+	case(OCTVU):		return calculate_octvu_energy_band_parameters(dz);
+	case(PEAK):			return specpeak_preprocess(dz);
+	case(REPORT):		return setup_internal_params_and_arrays_for_specreport(dz);
+	case(PRINT):		return setup_internal_print_params(dz);
+
+	case(WINDOWCNT):	case(CHANNEL):		case(FREQUENCY):	
+		return(FINISHED);
+	default:
+		sprintf(errstr,"PROGRAMMING PROBLEM: Unknown process in param_preprocess()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/************ SETUP_INTERNAL_ARRAYS_AND_PARAMS_FOR_LEVEL *************/
+
+int setup_internal_arrays_and_params_for_level(dataptr dz)
+{
+	dz->wlength   = dz->insams[0]/dz->wanted;
+    if((dz->parray[0] = (double *)malloc(dz->wlength * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for level info array.\n");
+		return(MEMORY_ERROR);
+	}
+    if((dz->sndbuf    = (float  *)malloc(dz->wlength * sizeof(float))) ==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for level sound buffer.\n");
+		return(MEMORY_ERROR);
+	}
+	return(FINISHED);
+}
+
+/******************** CALCULATE_OCTVU_ENERGY_BAND_PARAMETERS ******************/
+
+int calculate_octvu_energy_band_parameters(dataptr dz)
+{
+	int n, last_chan_bandtop;
+	double *bandtop;
+	double last_bandtop, bandmid;
+
+	if(dz->vflag[IS_OCTVU_FUND]) {
+		last_bandtop = dz->param[OCTVU_FUND] * ROOT_2;
+		dz->itemcnt = 1;
+		while(last_bandtop < dz->nyquist) {
+			  last_bandtop *= 2;
+			  dz->itemcnt++;
+		}
+	} else
+		dz->itemcnt  = DEFAULT_OCTBANDS;
+
+	if((dz->parray[OCTVU_ENERGY]  = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL
+	|| (bandtop   				  = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL
+	|| (dz->iparray[OCTVU_CHBTOP] = (int    *)malloc(dz->itemcnt * sizeof(int   )))==NULL
+	|| (dz->iparray[OCTVU_CHBBOT] = (int    *)malloc(dz->itemcnt * sizeof(int   )))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for level for octave band arrays.\n");
+		return(MEMORY_ERROR);
+	}
+	if(dz->vflag[IS_OCTVU_FUND]) {
+		last_bandtop = dz->param[OCTVU_FUND] * ROOT_2;
+		for(n = 0; n < dz->itemcnt;n++) {
+			bandtop[n] = last_bandtop;
+			last_bandtop *= 2.0;
+		}
+		n--;
+		bandtop[n] = min(bandtop[n],dz->nyquist);
+	} else {
+		last_bandtop = dz->nyquist;
+		for(n = dz->itemcnt-1;n >= 0 ; n--) {
+			bandtop[n] = last_bandtop;
+			last_bandtop /= 2.0;
+		}
+	}
+	last_chan_bandtop = 0;
+	dz->param[OCTVU_BBBTOP] = bandtop[0];
+	last_chan_bandtop = 0;
+	for(n = 0;n < dz->itemcnt;n++) {
+		dz->iparray[OCTVU_CHBBOT][n]  = max(0,last_chan_bandtop - (2 * MARGIN_OF_ERROR));
+		dz->iparray[OCTVU_CHBTOP][n]  = (int)((bandtop[n] + dz->halfchwidth)/dz->chwidth);/* TRUNCATE */
+		dz->iparray[OCTVU_CHBTOP][n]++;
+		dz->iparray[OCTVU_CHBTOP][n] *= 2; /* allow for amp AND frq */
+		dz->iparray[OCTVU_CHBTOP][n]  = min(dz->wanted, dz->iparray[OCTVU_CHBTOP][n] + MARGIN_OF_ERROR);
+		last_chan_bandtop = dz->iparray[OCTVU_CHBTOP][n];
+	}
+	bandmid = bandtop[0]/ROOT_2;
+	fprintf(dz->fp,"\t\t\t\tBAND FREQUENCIES\n");
+	for(n = 0;n < dz->itemcnt;n++) {
+		fprintf(dz->fp,"%.2lf",bandmid);
+		bandmid *= 2.0;
+		if(n<dz->itemcnt-1)
+			fprintf(dz->fp,"\t");
+		else
+			fprintf(dz->fp,"\n\n");
+	}
+	return(FINISHED);
+}
+
+/************************** SPECPEAK_PREPROCESS ******************************/
+
+int specpeak_preprocess(dataptr dz)
+{
+	int exit_status;
+	int k;
+	dz->param[PEAK_FWINDOW] *= OCTAVES_PER_SEMITONE;
+	if(dz->vflag[PEAK_HEAR] && (exit_status = create_hearing_response_adjustment_curve(dz))<0)
+		return(exit_status);
+	if((dz->iparam[PEAK_TGROUP] = round(dz->param[PEAK_TWINDOW]/dz->frametime))<=0)
+		dz->iparam[PEAK_TGROUP] = 1;
+	 if((exit_status = get_frq_bands(&(dz->iparam[PEAK_BANDCNT]),dz))<0)
+	 	return(exit_status);
+	for(k=0;k<dz->iparam[PEAK_BANDCNT];k++)
+		dz->parray[PEAK_MAXI][k] = 0.0;
+	if(exit_status<0)
+		return(exit_status);
+	dz->param[PEAK_ENDTIME] = 0.0;
+	return(FINISHED);
+}
+
+/***************** CREATE_HEARING_RESPONSE_ADJUSTMENT_CURVE ********************/
+
+int create_hearing_response_adjustment_curve(dataptr dz)
+{   float *sf, *sp, *sa;
+    dz->infile->specenvcnt = 17;
+    if((dz->specenvfrq = (float *)malloc(dz->infile->specenvcnt * sizeof(float)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for spectral envelope frq array.\n");
+		return(MEMORY_ERROR);
+	}
+    if((dz->specenvpch = (float *)malloc(dz->infile->specenvcnt * sizeof(float)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for spectral envelope pitch array.\n");
+		return(MEMORY_ERROR);
+	}
+    if((dz->specenvamp = (float *)malloc(dz->infile->specenvcnt * sizeof(float)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for spectral envelope amplitude array.\n");
+		return(MEMORY_ERROR);
+	}
+    sf = dz->specenvfrq;
+    sp = dz->specenvpch;
+    sa = dz->specenvamp;
+    sf[0]  =    1.0f;   sa[0]  = 0.0f;       sp[0]  = 0.0f;       
+    sf[1]  =   20.0f;   sa[1]  = 0.01f;      sp[1]  = (float)log(sf[1]);   
+    sf[2]  =   50.0f;   sa[2]  = 0.141254f;  sp[2]  = (float)log(sf[2]);   
+    sf[3]  =  100.0f;   sa[3]  = 0.446684f;  sp[3]  = (float)log(sf[3]);   
+    sf[4]  =  200.0f;   sa[4]  = 1.0f;       sp[4]  = (float)log(sf[4]);   
+    sf[5]  =  400.0f;   sa[5]  = 1.995262f;  sp[5]  = (float)log(sf[5]);   
+    sf[6]  =  500.0f;   sa[6]  = 1.995262f;  sp[6]  = (float)log(sf[6]);   
+    sf[7]  = 1000.0f;   sa[7]  = 0.794328f;  sp[7]  = (float)log(sf[7]);   
+    sf[8]  = 1600.0f;   sa[8]  = 0.630957f;  sp[8]  = (float)log(sf[8]);   
+    sf[9]  = 2000.0f;   sa[9]  = 1.258925f;  sp[9]  = (float)log(sf[9]);   
+    sf[10] = 3500.0f;   sa[10] = 2.371374f;  sp[10] = (float)log(sf[10]);  
+    sf[11] = 5000.0f;   sa[11] = 1.995262f;  sp[11] = (float)log(sf[11]);  
+    sf[12] = 6000.0f;   sa[12] = 1.0f;       sp[12] = (float)log(sf[12]);  
+    sf[13] = 8000.0f;   sa[13] = 0.501187f;  sp[13] = (float)log(sf[13]);  
+    sf[14] = 10000.0f;  sa[14] = 0.031622f;  sp[14] = (float)log(sf[14]);  
+    sf[15] = 14000.0f;  sa[15] = 0.0f;       sp[15] = (float)log(sf[15]);  
+    sf[16] = 30000.0f;  sa[16] = 0.0f;       sp[16] = (float)log(sf[16]);  
+	return(FINISHED);
+}
+
+/******************************* GET_FRQ_BANDS ***********************/
+
+int get_frq_bands(int *cnt,dataptr dz)
+{
+	double bandratio = pow(2.0,dz->param[PEAK_FWINDOW]);
+	double frqtop = dz->param[PEAK_CUTOFF] * bandratio; 
+	int k = 0;
+	while(frqtop < dz->nyquist) {
+		k++;
+		frqtop *= bandratio;
+	}
+	k++;
+	if((dz->parray[PEAK_BAND] = (double *)malloc(k * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for peak bands array.\n");
+		return(MEMORY_ERROR);
+	}
+	if((dz->parray[PEAK_MAXI] = (double *)malloc(k * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for peak maximi array.\n");
+		return(MEMORY_ERROR);
+	}
+	frqtop = dz->param[PEAK_CUTOFF] * bandratio; 
+	k = 0;
+	while(frqtop < dz->nyquist) {
+		dz->parray[PEAK_BAND][k++] = (float)frqtop;
+		frqtop *= bandratio;
+	}
+	dz->parray[PEAK_BAND][k++] = (float)dz->nyquist;
+	*cnt = k;
+	return(FINISHED);
+}
+
+/************ SETUP_INTERNAL_PARAMS_AND_ARRAYS_FOR_SPECREPORT *************/
+
+int	setup_internal_params_and_arrays_for_specreport(dataptr dz)
+{
+	int exit_status;
+	dz->itemcnt = dz->iparam[REPORT_PKCNT];		/* specenv chans where peaks are */
+	if((dz->peakno     = (int *)malloc((dz->itemcnt+1) * sizeof(int)))==NULL)	 {
+		sprintf(errstr,"INSUFFICIENT MEMORY for peak reporting count array.\n");
+		return(MEMORY_ERROR);
+	}											/* specenv chans where peaks are */
+	if((dz->lastpeakno = (int *)malloc((dz->itemcnt+1) * sizeof(int)))==NULL)	 {
+		sprintf(errstr,"INSUFFICIENT MEMORY for peak reporting last peak array.\n");
+		return(MEMORY_ERROR);
+	}
+	dz->peakno[dz->itemcnt] = 0;
+	if((exit_status = setup_stability_arrays_and_constants(REPORT_STABL,REPORT_SL1,dz))<0)
+		return(exit_status);
+	dz->iparam[REPORT_LAST_PKCNT_HERE] = 0;
+	return(FINISHED);
+}
+
+/************ SETUP_INTERNAL_PRINT_PARAMS *************/
+
+int setup_internal_print_params(dataptr dz)
+{
+   	dz->iparam[PRNT_STARTW] = round(dz->param[PRNT_STIME] / dz->frametime);
+   	dz->iparam[PRNT_ENDW]   = dz->iparam[PRNT_STARTW] + dz->iparam[PRNT_WCNT];
+	if(dz->iparam[PRNT_ENDW] > dz->wlength)
+		dz->iparam[PRNT_ENDW] = dz->wlength;
+	return(FINISHED);
+}
+
+
+/********************************************************************************************/
+/********************************** FORMERLY IN procspec.c **********************************/
+/********************************************************************************************/
+
+/**************************** SPEC_PROCESS_FILE ****************************/
+
+int spec_process_file(dataptr dz)
+{	
+	dz->total_windows = 0;
+
+	switch(dz->process) {
+	case(WINDOWCNT):return specwcnt(dz);
+	case(CHANNEL):	return specchan(dz);
+	case(FREQUENCY):return specfrq(dz);
+	case(LEVEL):	return speclevel(dz);							
+	case(OCTVU):	return specoctvu(dz);
+	case(PEAK):		return outer_textout_only_loop(dz);							
+	case(REPORT): 	return outer_textout_only_loop(dz);
+	case(PRINT):	return outer_textout_only_loop(dz);							
+	default:
+		sprintf(errstr,"Unknown process in procspec()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/***************** 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(REPORT):
+		rectify_window(dz->flbufptr[0],dz);
+		if((exit_status = extract_specenv(0,0,dz))<0)
+			return(exit_status);
+ /* put 1st specenv in end of stability store && copy 1st buf to end of bufstore */
+		memmove((char *)dz->stable->spec[dz->iparam[REPORT_SL1]],
+			(char *)dz->specenvamp,dz->infile->specenvcnt * sizeof(int));
+		memmove((char *)dz->stable->sbuf[dz->iparam[REPORT_SL1]],
+			(char *)dz->flbufptr[0],(size_t)dz->wanted * sizeof(float));		 
+		dz->stable->total_pkcnt[dz->iparam[REPORT_SL1]] = 0; /* 1st window has 0 amp, hence 0 peaks */
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+/***************************** 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);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN pconsistency.c ******************************/
+/********************************************************************************************/
+
+/****************************** CHECK_PARAM_VALIDITY_AND_CONSISTENCY *********************************/
+
+int check_param_validity_and_consistency(dataptr dz)
+{
+	int exit_status, chans, stype;
+	int srate;
+	handle_pitch_zeros(dz);
+	switch(dz->process) {
+	case(OCTVU):	   return check_validity_of_octvu_params(dz);
+	case(REPORT):	   return check_consistency_of_report_params(dz);
+	case(LEVEL):		
+		chans = dz->infile->channels;
+		srate = dz->infile->origrate;
+		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->origrate = srate;
+		dz->infile->stype	 = stype;
+		break;
+	}
+	return(FINISHED);
+}
+
+/********************** CHECK_VALIDITY_OF_OCTVU_PARAMS **********************/
+
+int check_validity_of_octvu_params(dataptr dz)
+{
+	if((dz->iparam[OCTVU_TBLOK] = round((dz->param[OCTVU_TSTEP] * MS_TO_SECS)
+		/dz->frametime))>dz->wlength) {
+		sprintf(errstr,"Time_step too long for input file.\n");
+		return(DATA_ERROR);
+	}
+	if(dz->iparam[OCTVU_TBLOK]<=0) {
+		sprintf(errstr,
+			"Time_step too short for input file (are you using secs instead of mS?).\n");
+		return(DATA_ERROR);
+	}
+	return(FINISHED);
+}
+
+/************ CHECK_CONSISTENCY_OF_REPORT_PARAMS *************/
+
+int check_consistency_of_report_params(dataptr dz)
+{
+	if(dz->brksize[REPORT_LOFRQ]==0 && dz->brksize[REPORT_HIFRQ]==0) {
+		if(flteq(dz->param[REPORT_LOFRQ],dz->param[REPORT_HIFRQ])) {
+			sprintf(errstr,"Frequency limits define a zero-width frq band.\n");
+			return(USER_ERROR);
+		}
+		if(dz->param[REPORT_LOFRQ] > dz->param[REPORT_HIFRQ])
+			swap(&dz->param[REPORT_LOFRQ],&dz->param[REPORT_HIFRQ]);
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN buffers.c ***********************************/
+/********************************************************************************************/
+
+/**************************** ALLOCATE_LARGE_BUFFERS ******************************/
+
+int allocate_large_buffers(dataptr dz)
+{
+	switch(dz->process) {
+	case(LEVEL): 	case(OCTVU):	case(PEAK):
+	case(PRINT):	
+		return allocate_single_buffer(dz);
+
+	case(REPORT):	
+		return allocate_double_buffer(dz);
+
+	case(WINDOWCNT): case(CHANNEL):	 case(FREQUENCY):
+		return(FINISHED);
+	default:
+		sprintf(errstr,"Unknown program no. in allocate_large_buffers()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN cmdline.c ***********************************/
+/********************************************************************************************/
+
+int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
+{
+	if     (!strcmp(prog_identifier_from_cmdline,"windowcnt")) 		dz->process = WINDOWCNT;
+	else if(!strcmp(prog_identifier_from_cmdline,"channel"))   		dz->process = CHANNEL;
+	else if(!strcmp(prog_identifier_from_cmdline,"frequency")) 		dz->process = FREQUENCY;
+	else if(!strcmp(prog_identifier_from_cmdline,"level"))     		dz->process = LEVEL;
+	else if(!strcmp(prog_identifier_from_cmdline,"octvu"))     		dz->process = OCTVU;
+	else if(!strcmp(prog_identifier_from_cmdline,"peak"))  	   		dz->process = PEAK;
+	else if(!strcmp(prog_identifier_from_cmdline,"report"))    		dz->process = REPORT;
+	else if(!strcmp(prog_identifier_from_cmdline,"print"))     		dz->process = PRINT;
+	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,
+	"\nINFORMATION ON A SPECTRAL FILE\n\n"
+	"USAGE: specinfo NAME (mode) infile outfile parameters: \n"
+	"\n"
+	"where NAME can be any one of\n"
+	"\n"
+	"windowcnt  channel  frequency  level   octvu   peak   report   print\n\n"
+	"Type 'specinfo windowcnt' for more info on specinfo windowcnt..ETC.\n");
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE2 ********************************/
+
+int usage2(char *str)
+{
+	if(!strcmp(str,"windowcnt")) {
+		sprintf(errstr,
+		"specinfo windowcnt infile\n\n"
+		"RETURNS NUMBER OF ANALYSIS WINDOWS IN INFILE.\n");
+	} else if(!strcmp(str,"channel")) {
+		sprintf(errstr,
+		"specinfo channel infile frq\n\n"
+		"RETURNS PVOC CHANNEL NUMBER CORRESPONDING TO FREQUENCY GIVEN.\n");
+	} else if(!strcmp(str,"frequency")) {
+		sprintf(errstr,
+		"specinfo frequency infile analysis_channel_number\n\n"
+		"RETURNS CENTRE FRQ OF PVOC CHANNEL SPECIFIED.\n");
+	} else if(!strcmp(str,"level")) {
+		sprintf(errstr,
+		"specinfo level infile outsndfile\n\n"
+		"CONVERT (VARYING) LEVEL OF ANALFILE TO PSEUDO-SNDFILE (1 WINDOW -> 1 SAMPLE)\n\n"
+		"View with a sndfile display program.\n\n"
+		"DO NOT ATTEMPT TO PLAY FILE!!.\n");
+	} else if(!strcmp(str,"octvu")) {
+		sprintf(errstr,
+		"specinfo octvu infile outtextfile time_step [-ffundamental]\n\n"
+		"DISPLAY TIMEVARYING AMPLITUDE OF SPECTRUM, WITHIN OCTAVE BANDS.\n\n"
+		"timestep is in MILLIsecs.\n"
+		"Band-energy is totalled over each timestep duration.\n"
+		"-f Octaves are centered on octave transpositions of fundamental.\n\n"
+		"The reported values are RELATIVE levels only\n"
+		"and the lowest band includes all energy down to '0Hz'.\n");
+	} else if(!strcmp(str,"peak")) {
+		sprintf(errstr,
+		"specinfo peak infile outtextfile [-ccutoff_frq] [-ttimewindow] [-ffrqwindow] [-h]\n\n"
+		"LOCATE TIME-VARYING ENERGY CENTRE OF SPECTRUM.\n\n"
+		"CUTOFF_FRQ  above which spectral search begins\n"
+		"TIMEWINDOW  for energy averaging: in SECONDS\n"
+		"FRQWINDOW   for energy averaging: in SEMITONES\n"
+		"-h          adjust result for sensitivity of ear.\n\n"
+		"OUTFILE is a text file of lines of data in form...\n\n"
+		"	WINDOW starttime endtime : PEB lofrq TO hifrq'\n\n"
+		"(where 'PEB' means PEAK ENERGY BAND)\n");
+	} else if(!strcmp(str,"report")) {
+		fprintf(stdout,
+		"specinfo report mode infile outfile -fN|-pN [-i] pks [-bbt] [-ttp] [-sval]\n\n"
+		"REPORT ON LOCATION OF FREQUENCY PEAKS IN EVOLVING SPECTRUM,\n\n"
+		"OUTFILE is a textfile\n\n"
+		"MODES\n"
+		"(1) Report on spectral peaks.\n"
+		"(2) Report spectral peaks in loudness order.\n"
+		"(3) Report spectral peaks as frq only (no time data).\n"
+		"(4) Report spectral peaks in loudness order, as frq only (no time data).\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"
+		"-i   quicksearch for formants (less accurate).\n"
+		"PKS  (max) number of peaks to find : Range 1 - %d\n"
+		"-b   BT is bottom frequency to start peak search.\n"
+		"-t   TP is top frequency to stop peak search.\n"
+		"-s   VAL is number of windows over which peaks averaged.\n"
+		"     Range 2 - %d : default %d : WARNING: high values slow program!!\n\n"
+		"bottom frequency & top frequency may vary over time.\n",MAXPKCNT,MAXSTABIL,DEFAULT_STABILITY);
+	} else if(!strcmp(str,"print")) {
+		sprintf(errstr,
+		"specinfo print infile outtextfile time [-wwindowcnt]\n\n"
+		"PRINT DATA IN ANALYSIS FILE AS TEXT TO FILE.\n\n"
+		"TIME      in file at which printout begins.\n"
+		"WINDOWCNT number of windows to print.\n"
+		"OUTFILE   textfile to accept data.\n\n"
+   		"WARNING:  using more than a few windows will generate a huge textfile.\n");
+	} else
+		sprintf(errstr,"Unknown option '%s'\n",str);
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE3 ********************************/
+
+int usage3(char *str1,char *str2)
+{
+	if(!strcmp(str1,"windowcnt"))	
+		return(CONTINUE);
+	else
+		sprintf(errstr,"Insufficient parameters on command line.\n");
+	return(USAGE_ONLY);
+}
+
+

+ 234 - 0
dev/specinfo/main.c

@@ -0,0 +1,234 @@
+/*
+ * 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 <specinfo.h>
+#include <filetype.h>
+#include <processno.h>
+#include <modeno.h>
+#include <formants.h>
+#include <cdpmain.h>
+#include <special.h>
+#include <logic.h>
+#include <globcon.h>
+#include <cdpmain.h>
+#include <sfsys.h>
+#include <ctype.h>
+#include <string.h>
+
+char errstr[2400];
+
+/*extern*/ int	sloom = 0;
+/*extern*/ int sloombatch = 0;
+/*extern*/ int anal_infiles = 1;
+/*extern*/ int is_converted_to_stereo = -1;
+const char* cdp_version = "7.1.0";
+
+/**************************************** MAIN *********************************************/
+
+int main(int argc,char *argv[])
+{
+	int exit_status;
+	dataptr dz = NULL;
+	char **cmdline;
+	int  cmdlinecnt;
+	aplptr ap;
+	int *valid = NULL;
+	int is_launched = FALSE;
+	int  validcnt;
+
+	if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
+		fprintf(stdout,"%s\n",cdp_version);
+		fflush(stdout);
+		return 0;
+	}
+						/* CHECK FOR SOUNDLOOM */
+	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->process!=HOUSE_BUNDLE  && 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);
+}
+

+ 691 - 0
dev/specinfo/specinfo.c

@@ -0,0 +1,691 @@
+/*
+ * 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 <processno.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <flags.h>
+#include <specinfo.h>
+#include <cdpmain.h>
+#include <formants.h>
+#include <speccon.h>
+#include <sfsys.h>
+#include <osbind.h>
+#include <string.h>
+#include <specinfo.h>
+
+static int  inner_level_loop(int windows_in_buf,dataptr dz);
+static int  do_speclevel(dataptr dz);
+static int  normalise_as_transfering_to_sndbuf_and_write_to_file(dataptr dz);
+static int  read_another_buffer(int *totalwindows_in_buf,dataptr dz);
+static int  zero_energy_bands(dataptr dz);
+static int  print_energy_bands(dataptr dz);
+static int  inner_textout_only_loop(int *peakscore,int *descnt,int windows_in_buf,dataptr dz);
+static int  output_peak_data(dataptr dz);
+static int  specpeak(dataptr dz);
+static int  specprint(dataptr dz);
+static int  specreport(int *peakscore,int *descnt,dataptr dz);
+static int  find_maximum(int *maxloc,dataptr dz);
+static int  print_window(int windowcnt,dataptr dz);
+static int  report_stable_peaks(int *peakscore,int *descnt,dataptr dz);
+static int  sort_peaks(int *peakscore,int *descnt,dataptr dz) ;
+static int  sort_report_peaks_by_amplitude(int pkcnt_here,dataptr dz);
+static int  sort_report_peaks_by_frq(int pkcnt_here,dataptr dz);
+static int	show_new_peaks(int pkcnt_here,dataptr dz);
+static int  print_peaks(int pkcnt_here,dataptr dz);
+
+/****************************** SPECWCNT ***************************/
+
+int specwcnt(dataptr dz)
+{
+	sprintf(errstr,"File contains %d windows\n",dz->wlength);
+	return(FINISHED);
+}
+
+/************************* SPECCHAN ***************************/
+
+int specchan(dataptr dz)
+{
+	int thischan = (int)((dz->param[CHAN_FRQ]+(dz->halfchwidth))/dz->chwidth);	/* TRUNCATE */
+	sprintf(errstr,"%.2lf Hz is in channel %d\n",dz->param[CHAN_FRQ],thischan);
+	return(FINISHED);
+}
+
+/************************* SPECFRQ ***************************/
+
+int specfrq(dataptr dz)
+{
+ 	double frq = (double)dz->iparam[FRQ_CHAN] * dz->chwidth;
+	sprintf(errstr,"%.2lf Hz is centre frq of channel %d\n",frq,dz->iparam[FRQ_CHAN]);
+	return(FINISHED);
+}
+
+/**************************** SPECLEVEL ****************************/
+
+int speclevel(dataptr dz)
+{
+	int exit_status;
+	int samps_read, windows_in_buf;
+
+	if(sloom)
+		dz->total_samps_read = 0L;
+
+	while((samps_read = fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0)) > 0) {
+
+		if(sloom)
+			dz->total_samps_read += samps_read;
+
+    	dz->flbufptr[0] = dz->bigfbuf;
+    	windows_in_buf = samps_read/dz->wanted;
+    	if((exit_status = inner_level_loop(windows_in_buf,dz))<0)
+			return(exit_status);
+		if(dz->finished)
+		   break;
+	}  
+	if(samps_read<0) {
+		sprintf(errstr,"Sound read error.\n");
+		return(SYSTEM_ERROR);
+	}
+	if((exit_status = normalise_as_transfering_to_sndbuf_and_write_to_file(dz))<0)
+		return(exit_status);
+	return(FINISHED);
+}
+
+/**************************** INNER_LEVEL_LOOP ****************************/
+
+int inner_level_loop(int windows_in_buf,dataptr dz)
+{
+	int exit_status;
+	int wc;
+   	for(wc=0; wc<windows_in_buf; wc++) {
+		if((exit_status = do_speclevel(dz))<0)
+			return(exit_status);
+		dz->flbufptr[0] += dz->wanted;
+		dz->total_windows++;
+	}
+	return(FINISHED);
+}
+
+/**************************** DO_SPECLEVEL ****************************/
+
+int do_speclevel(dataptr dz)
+{
+
+#define VERY_BIG  (10000000.0)
+
+	int vc;
+	dz->parray[0][dz->itemcnt] = 0.0;
+	for(vc = 0; vc < dz->wanted; vc += 2) 
+		dz->parray[0][dz->itemcnt] += dz->flbufptr[0][vc];
+	if(dz->parray[0][dz->itemcnt] > VERY_BIG) {
+		sprintf(errstr,"Apparent(?) huge signal level in analysis window %d. do_speclevel()\n",dz->itemcnt + 1);
+		return(PROGRAM_ERROR);
+	}
+	if(++dz->itemcnt > dz->wlength) {
+		sprintf(errstr,"Storage arithmetic problem in do_speclevel().\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/********** NORMALISE_AS_TRANSFERING_TO_SNDBUF_AND_WRITE_TO_FILE *********/
+
+int normalise_as_transfering_to_sndbuf_and_write_to_file(dataptr dz)
+{
+
+	double maxwindow = 0.0, normaliser;
+	int n;
+	for(n=0;n<dz->wlength;n++) {
+		if(dz->parray[0][n] > maxwindow)
+		maxwindow = dz->parray[0][n];
+	}
+	if(flteq(maxwindow,0.0)) {
+		sprintf(errstr,"No signal level in analysis file.\n");
+		return(DATA_ERROR);
+	}
+	normaliser = F_MAXSAMP/maxwindow;
+	for(n=0;n<dz->wlength;n++)
+		dz->sndbuf[n] = (float)(dz->parray[0][n] * normaliser);
+	return write_samps(dz->sndbuf,dz->wlength,dz);
+}
+
+/**************************** SPECOCTVU ****************************/
+
+int specoctvu(dataptr dz)
+{
+	int exit_status;
+	int totalwindows_in_buf, windownumber_in_buf;
+	int x, q, n;
+	double topfrq;
+	if((exit_status = read_another_buffer(&totalwindows_in_buf,dz))!=CONTINUE) {
+		if(exit_status==FINISHED)
+			fprintf(stdout,"WARNING: No data in input file.\n");
+		return(exit_status);
+	}
+	windownumber_in_buf = 0;
+	while(dz->total_windows < dz->wlength && totalwindows_in_buf > 0) {
+		if((exit_status = zero_energy_bands(dz))<0)
+			return(exit_status);
+		for(x = 0; x<dz->iparam[OCTVU_TBLOK];x++) {
+			if(windownumber_in_buf >= totalwindows_in_buf) {
+				if((exit_status = read_another_buffer(&totalwindows_in_buf,dz))!=CONTINUE)
+					break;
+				windownumber_in_buf = 0;
+			}
+			q = n = 0;
+			topfrq = dz->param[OCTVU_BBBTOP];
+			for(q=0;q<dz->itemcnt;q++) {
+				for(n = dz->iparray[OCTVU_CHBBOT][q]; n < dz->iparray[OCTVU_CHBTOP][q]; n += 2) {
+					if(fabs(dz->flbufptr[0][n+1]) < topfrq)
+						dz->parray[OCTVU_ENERGY][q] += dz->flbufptr[0][n];
+				}
+				topfrq *= 2.0;
+			}
+			dz->flbufptr[0] += dz->wanted;
+			windownumber_in_buf++;
+			if(++dz->total_windows >= dz->wlength) {
+				break;
+			}
+		}
+		if(exit_status<0)
+			return(exit_status);
+		if(x>0 && (exit_status = print_energy_bands(dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/**************************** READ_ANOTHER_BUFFER ****************************/
+
+int read_another_buffer(int *totalwindows_in_buf,dataptr dz)
+{
+	int samps_read;
+	if((samps_read = fgetfbufEx(dz->bigfbuf, dz->big_fsize,dz->ifd[0],0)) <= 0) {
+		if(samps_read<0) {
+			sprintf(errstr,"Sound read error.\n");
+			return(SYSTEM_ERROR);
+		}
+		return(FINISHED);
+	}
+	dz->flbufptr[0] 		 = dz->bigfbuf;
+	*totalwindows_in_buf = samps_read/dz->wanted;
+	return(CONTINUE);
+}
+
+/**************************** ZERO_ENERGY_BANDS ****************************/
+
+int zero_energy_bands(dataptr dz)
+{
+	int n;
+	for(n=0;n<dz->itemcnt;n++)
+		dz->parray[OCTVU_ENERGY][n] = 0.0;
+	return(FINISHED);
+}
+
+/******************** PRINT_ENERGY_BANDS ***********************/
+
+int print_energy_bands(dataptr dz)
+{
+
+#define SCALEFACT (5000.0)
+
+	int n;
+	char temp[64];
+	double output;
+	errstr[0] = ENDOFSTR;
+	for(n=0;n<dz->itemcnt;n++) {
+		output = SCALEFACT * dz->parray[OCTVU_ENERGY][n];
+		if(output>0)	{							
+			output = log(output);
+			if(sloom) {
+				sprintf(temp,"%.3lf",output);
+				strcat(errstr,temp);
+			}
+			fprintf(dz->fp,"%.3lf",output);
+		} else {
+			if(sloom) {
+				sprintf(temp,"-----"/*,output*/);
+				strcat(errstr,temp);
+			}
+			fprintf(dz->fp,"-----");
+		}
+		if(n < dz->itemcnt-1) {
+			if(sloom)
+				strcat(errstr,"\t");
+			fprintf(dz->fp,"\t");
+		} else {
+			if(sloom) {
+				fprintf(stdout,"INFO: %s\n",errstr);
+				fflush(stdout);
+				errstr[0] = ENDOFSTR;
+			}
+			fprintf(dz->fp,"\n");
+		}
+	}
+	return(FINISHED);
+}
+
+/**************************** OUTER_TEXTOUT_ONLY_LOOP ****************************/
+
+int outer_textout_only_loop(dataptr dz)
+{
+	int exit_status;
+	int samps_read, windows_in_buf;
+	int peakscore = 0;
+	int descnt = 0;
+	dz->time = 0.0f;
+	while((samps_read = fgetfbufEx(dz->bigfbuf, dz->big_fsize,dz->ifd[0],0)) > 0) {
+    	dz->flbufptr[0] = dz->bigfbuf;
+    	windows_in_buf = samps_read/dz->wanted;
+    	if((exit_status = inner_textout_only_loop(&peakscore,&descnt,windows_in_buf,dz))<0)
+			return(exit_status);
+		if(dz->finished)
+		   break;
+	}
+	if(samps_read<0) {
+		sprintf(errstr,"Sound read error.\n");
+		return(SYSTEM_ERROR);
+	}
+	if(dz->process == PEAK && dz->itemcnt) {
+ 		if((exit_status = output_peak_data(dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/**************************** INNER_TEXTOUT_ONLY_LOOP ****************************/
+
+int inner_textout_only_loop(int *peakscore,int *descnt,int windows_in_buf,dataptr dz)
+{
+	int exit_status;
+	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++;
+				continue;
+			}
+		}
+		if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0)
+			return(exit_status);
+		switch(dz->process) {
+		case(PEAK):		exit_status = specpeak(dz);	  break;
+		case(PRINT):	exit_status = specprint(dz);  break;
+		case(REPORT):	exit_status = specreport(peakscore,descnt,dz); break;
+		default:
+			sprintf(errstr,"unknown process in inner_textout_only_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);
+	}
+	return(FINISHED);
+}
+
+/******************************** OUTPUT_PEAK_DATA *************************/
+
+int output_peak_data(dataptr dz)
+{
+	int exit_status;
+	int here;
+	int k;
+	double frqtop, frqbot, starttime;
+	starttime = dz->param[PEAK_ENDTIME];
+	dz->param[PEAK_ENDTIME]  += (dz->iparam[PEAK_TGROUP] * dz->frametime);
+	if((exit_status = find_maximum(&here,dz))<0)
+		return(exit_status);
+	if(here==0)
+		frqbot = dz->param[PEAK_CUTOFF];
+	else
+		frqbot = dz->parray[PEAK_BAND][here-1];
+	frqtop = dz->parray[PEAK_BAND][here];
+
+	if(sloom) {
+		fprintf(stdout,"INFO: WINDOW\t%.4lf\t%.4lf\t:PEB \t%.4lf\tTO\t%.4lf\n",starttime, dz->param[PEAK_ENDTIME], frqbot, frqtop);
+		fflush(stdout);
+	}
+	fprintf(dz->fp,"WINDOW\t%.4lf\t%.4lf\t:PEB \t%.4lf\tTO\t%.4lf\n",starttime, dz->param[PEAK_ENDTIME], frqbot, frqtop);
+	for(k=0;k<dz->iparam[PEAK_BANDCNT];k++)
+		dz->parray[PEAK_MAXI][k] = 0.0;
+	return(FINISHED);
+}
+
+/****************************** SPECPEAK ****************************/
+
+int specpeak(dataptr dz)
+{
+	int exit_status;
+	double thisamp, sensitivity_of_ear;
+	int cc, vc, n;
+	for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
+		if(dz->flbufptr[0][FREQ]<dz->param[PEAK_CUTOFF] || dz->flbufptr[0][FREQ]>dz->nyquist)
+			continue;
+		n = 0;
+		while(dz->flbufptr[0][FREQ] > dz->parray[PEAK_BAND][n])
+			n++;
+		thisamp = dz->flbufptr[0][AMPP];
+		if(dz->vflag[PEAK_HEAR]) {
+			if((exit_status = getspecenvamp(&sensitivity_of_ear,dz->flbufptr[0][FREQ],0,dz))<0)
+				return(exit_status);
+			thisamp *= sensitivity_of_ear;
+		}
+		dz->parray[PEAK_MAXI][n] += thisamp;
+	}
+	if(++dz->itemcnt >= dz->iparam[PEAK_TGROUP]) {
+		if((exit_status = output_peak_data(dz))<0)
+			return(exit_status);
+		dz->itemcnt = 0;
+	}
+	return(FINISHED);
+}
+
+/****************************** SPECPRINT ****************************/
+
+int specprint(dataptr dz)
+{
+	int exit_status;
+	if(dz->total_windows >= dz->iparam[PRNT_ENDW]) {
+		dz->finished = 1;
+		return(FINISHED);
+	}
+	if(dz->total_windows >= dz->iparam[PRNT_STARTW]) {
+		if((exit_status = print_window(dz->total_windows,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/**************************** SPECREPORT ***************************/
+
+int specreport(int *peakscore,int *descnt,dataptr dz)
+{
+	int exit_status;
+	double lofrq, hifrq;
+	lofrq = dz->param[REPORT_LOFRQ];
+	hifrq = dz->param[REPORT_HIFRQ];
+	if(dz->brksize[REPORT_LOFRQ] || dz->brksize[REPORT_HIFRQ]) {
+		if(flteq(lofrq,hifrq)) {
+			sprintf(errstr,"Frequency limits define a zero-width band at time %.2lf.\n",dz->time);
+			return(USER_ERROR);
+		}
+		if(lofrq > hifrq)
+			swap(&lofrq,&hifrq);
+	}
+	rectify_window(dz->flbufptr[0],dz);
+	if((exit_status = extract_specenv(0,0,dz))<0)
+		return(exit_status);
+	if((exit_status = report_stable_peaks(peakscore,descnt,dz))<0)
+		return(exit_status);
+	return(FINISHED);
+}
+
+/**************************** FIND_MAXIMUM **************************/
+
+int find_maximum(int *maxloc,dataptr dz)
+{
+	double thismax = -1.0;
+	int k;
+	*maxloc = -1;
+	for(k=0;k<dz->iparam[PEAK_BANDCNT];k++) {
+		if(dz->parray[PEAK_MAXI][k] > thismax) {
+			thismax = dz->parray[PEAK_MAXI][k];
+			*maxloc = k;
+		}
+	}
+/* what if maxloc is NOT SET */
+	if(*maxloc < 0) {
+		sprintf(errstr,"Failed to find any peak in data\n");
+		return(GOAL_FAILED);
+	}
+	return(FINISHED);
+}
+
+/******************************** PRINT_WINDOW *************************/
+
+int print_window(int windowcnt,dataptr dz)
+{
+	int cc, vc;
+	fprintf(dz->fp,"************* WINDOW %d *****************\n",windowcnt);
+	for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
+		fprintf(dz->fp,"amp[%d] = %.12f\t",cc,dz->flbufptr[0][AMPP]);
+		if(dz->flbufptr[0][FREQ] < .01f)
+			fprintf(dz->fp,"frq[%d] = %lf\n",cc,dz->flbufptr[0][FREQ]);
+		else
+			fprintf(dz->fp,"frq[%d] = %.2lf\n",cc,dz->flbufptr[0][FREQ]);
+    }
+	return(FINISHED);
+}
+
+/****************************** REPORT_STABLE_PEAKS ***************************/
+
+int report_stable_peaks(int *peakscore,int *descnt,dataptr dz)
+{
+	int exit_status;
+	int thispkcnt;
+	/* shuffle back stored specenvs */
+	memmove((char *)dz->stable->spec[0],
+	(char *)dz->stable->spec[1],dz->iparam[REPORT_SL1] * (dz->infile->specenvcnt * sizeof(int)));
+	/* put latest specenv array here */
+	memmove((char *)dz->stable->spec[dz->iparam[REPORT_SL1]],
+	(char *)dz->specenvamp,(dz->infile->specenvcnt * sizeof(int)));
+	/* shuffle back stored fpks */
+	memmove((char *)dz->stable->fpk[0],
+	(char *)dz->stable->fpk[1],dz->iparam[REPORT_SL1] * (dz->infile->specenvcnt * sizeof(int)));
+	/* shuffle back stored fpk_totals */
+	memmove((char *)dz->stable->total_pkcnt,
+	(char *)(dz->stable->total_pkcnt+1),dz->iparam[REPORT_SL1] * sizeof(int));
+	/* put into last fpk[z] store */
+	if((exit_status = extract_formant_peaks2(REPORT_SL1,&thispkcnt,dz->param[REPORT_LOFRQ],dz->param[REPORT_HIFRQ],dz))<0)
+		return(exit_status);
+	dz->stable->total_pkcnt[dz->iparam[REPORT_SL1]] = thispkcnt;
+	if(dz->total_windows >= dz->iparam[REPORT_SL1]) {
+		if((exit_status = sort_peaks(peakscore,descnt,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+
+/****************************** SORT_PEAKS ****************6**************/ 
+
+int sort_peaks(int *peakscore,int *descnt,dataptr dz) 
+{
+	int exit_status;
+	int this_pkcnt;
+	int n = 0, pkcnt_here;
+	if(dz->total_windows<=dz->iparam[REPORT_SL1])
+		memset((char *)dz->stable->design_score,0,dz->infile->specenvcnt * sizeof(int));
+	if((exit_status = score_peaks(peakscore,REPORT_SL1,REPORT_STABL,dz))<0)
+		return(exit_status);
+	if(*peakscore==0)
+		return(FINISHED);
+		 		 	/* Find how many times each peak occurs across the stabilise buffers */
+ 	if((exit_status = collect_scores(&this_pkcnt,descnt,dz))<0)
+		return(exit_status);
+		/* Sort these on the basis of the most commonly occuring */
+ 	if((exit_status = sort_design(this_pkcnt,dz))<0)
+		return(exit_status);
+	if(this_pkcnt<=dz->itemcnt || (dz->stable->des[dz->itemcnt-1]->score > dz->stable->des[dz->itemcnt]->score)) {
+		pkcnt_here = min(this_pkcnt,dz->itemcnt);
+		for(n=0;n<pkcnt_here;n++)	/* If most common pkcnt (or less) peaks more common than ALL others */
+			dz->peakno[n] = dz->stable->des[n]->chan;/* these are the peaks to keep */
+	} else {						/* Else choose amongst equivalent peaks, in terms of amplitude */
+		if((exit_status = sort_equivalent_scores(this_pkcnt,dz))<0)
+			return(exit_status);
+		pkcnt_here = dz->itemcnt;
+	}
+	switch(dz->mode) {
+	case(AMP_ORDERED_TIMED): 
+	case(AMP_ORDERED_UNTIMED):
+		if((exit_status = sort_report_peaks_by_amplitude(pkcnt_here,dz))<0)
+			return(exit_status);
+		break;
+	case(FRQ_ORDERED_TIMED): 
+	case(FRQ_ORDERED_UNTIMED):	
+		if((exit_status = sort_report_peaks_by_frq(pkcnt_here,dz))<0)
+			return(exit_status);
+		break;
+	default:
+		sprintf(errstr,"unknown case in sort_peaks()\n");
+		return(PROGRAM_ERROR);
+	}
+	if((exit_status = show_new_peaks(pkcnt_here,dz))<0)
+		return(exit_status);
+	if(dz->total_windows>dz->iparam[REPORT_SL1]) {	/* Logically this should be '>=sl1' : but */
+		if((exit_status = unscore_peaks(peakscore,dz))<0) /* don't have to subtract window 0, as NO PEAKS there */
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/****************************** SORT_REPORT_PEAKS_BY_AMPLITUDE ******************************/ 
+
+int sort_report_peaks_by_amplitude(int pkcnt_here,dataptr dz)
+{
+	int n, m, thischan;
+	double thisamp;
+	for(n=0;n<pkcnt_here;n++) {	 		/* For every channel in the set of possible channels */
+		dz->stable->des[n]->amp = 0.0; 				/* and store in des-array assocd with channel */
+		thischan = dz->stable->des[n]->chan;
+		for(m=0;m<dz->iparam[REPORT_STABL];m++)  		/* sum amplitudes in that chan across all specenv buffers */
+			dz->stable->des[n]->amp += dz->stable->spec[m][thischan]; 	/* and store in des-array assocd with channel */
+	}
+	for(n=1;n<pkcnt_here;n++) {
+		thisamp  = dz->stable->des[n]->amp;
+		m = n-1;
+		while(m >= 0 && dz->stable->des[m]->amp > thisamp) {
+			dz->stable->des[m+1]->amp  = dz->stable->des[m]->amp;
+			dz->stable->des[m+1]->chan = dz->stable->des[m]->chan;
+			m--;
+		}
+		dz->stable->des[m+1]->amp  = dz->stable->des[n]->amp;
+		dz->stable->des[m+1]->chan = dz->stable->des[n]->chan;
+	}
+	return(FINISHED);
+}
+ 
+/****************************** SORT_REPORT_PEAKS_BY_FRQ ***************************/
+
+int sort_report_peaks_by_frq(int pkcnt_here,dataptr dz)
+{	
+	int n, m, k;
+	for(n=0;n<pkcnt_here-1;n++) {
+		for(m=n+1;m<pkcnt_here;m++) {
+			if(dz->specenvfrq[dz->peakno[n]] > dz->specenvfrq[dz->peakno[m]]) {
+				k             = dz->peakno[m];
+				dz->peakno[m] = dz->peakno[n];
+				dz->peakno[n] = k;
+			}
+		}
+	}
+	return(FINISHED);
+}
+
+/****************************** SHOW_NEW_PEAKS ***************************/
+
+int	show_new_peaks(int pkcnt_here,dataptr dz)
+{
+	int exit_status;
+	int n, m, newpeak = 0;					 /*RWD added init */
+	if(pkcnt_here!=dz->iparam[REPORT_LAST_PKCNT_HERE]) {
+		if((exit_status = print_peaks(pkcnt_here,dz))<0)
+			return(exit_status);
+	} else {
+		for(n=0;n<pkcnt_here;n++) {
+			newpeak = 1; 
+			for(m=0;m<dz->iparam[REPORT_LAST_PKCNT_HERE];m++) {
+				if(dz->peakno[n] == dz->lastpeakno[m]) {
+				   	newpeak = 0;
+					break;
+				}
+			}
+			if(newpeak)
+				break;
+		}
+		if(newpeak) {
+			if((exit_status = print_peaks(pkcnt_here,dz))<0)
+				return(exit_status);
+		}
+	}
+	dz->iparam[REPORT_LAST_PKCNT_HERE] = pkcnt_here;
+	for(n = 0;n < pkcnt_here; n++)
+		dz->lastpeakno[n] = dz->peakno[n];
+	return(FINISHED);
+}
+
+/****************************** PRINT_PEAKS ***************************/
+
+int print_peaks(int pkcnt_here,dataptr dz)
+{
+	int n;
+	char temp[200];
+	switch(dz->mode) {
+	case(FRQ_ORDERED_TIMED): 
+	case(AMP_ORDERED_TIMED):
+		if(sloom)
+			sprintf(errstr,"%.3lf secs : ",dz->time - (dz->stable->offset * dz->frametime));
+		fprintf(dz->fp,"%.3lf secs : ",dz->time - (dz->stable->offset * dz->frametime));
+	case(FRQ_ORDERED_UNTIMED): 
+	case(AMP_ORDERED_UNTIMED):
+		for(n=0;n<pkcnt_here;n++) {
+			if(sloom) {
+				sprintf(temp,"\t%.2f",dz->specenvfrq[dz->peakno[n]]);
+				strcat(errstr,temp);
+			}
+			fprintf(dz->fp,"\t%.2f",dz->specenvfrq[dz->peakno[n]]);
+			if(n && n%8==0) {
+				if(sloom) {
+					fprintf(stdout,"INFO: %s\n",errstr);
+					fflush(stdout);
+					sprintf(errstr,"\t\t");
+				}
+				fprintf(dz->fp,"\n\t\t");
+			}
+		}
+		break;
+	default:
+		sprintf(errstr,"Unknown case in print_peaks()\n");
+		return(PROGRAM_ERROR);
+	}
+	if(sloom) {
+		fprintf(stdout,"INFO: %s\n",errstr);
+		fflush(stdout);
+	}
+	fprintf(dz->fp,"\n");
+	return(FINISHED);
+}