Browse Source

initial commit

richarddobson 3 years ago
parent
commit
e78a688e15

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

+ 413 - 0
dev/pagrab/pagrab.c

@@ -0,0 +1,413 @@
+/*
+ * 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
+ *
+ */
+
+
+
+
+/**************************************************************************
+ *
+ * Convert snd data to text format suitable for Pview in Sound Loom
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <osbind.h>
+#include <math.h>
+#include <float.h>
+#include <float.h>
+#include <sfsys.h>
+#include <cdplib.h>
+
+#define VIEW_WIDTH          900     /* width of sloom display */
+#define VIEW_HEIGHT         300     /* heigth of sloom display */
+#define HALF_VIEW_HEIGHT    150     /* half heigth of sloom display */
+#define COLOR_SPECTRUM       45     /* number of individual colours supported */
+
+#define EFFECTIVE_VIEW_WIDTH (VIEW_WIDTH - (VIEW_HEIGHT * 2))
+
+#define F_SECSIZE   (256)
+
+/*  Functions   */
+
+static  int     tidy_up(int,unsigned int);
+static  int     open_in(char*), open_out(char *);
+static  int     get_big_buf(void);
+static  int     write_output(int obufcnt);
+static  int     write_window(int totchans,float *rbuf,int bufcnt);
+static  int     make_outfile(int del,char *filename);
+
+float *bigbuf, *sampbuf, *osambuf;
+
+float arate, frametime;
+int buflen, obuflen;        /* buffer length in samps           */
+int  ifd, ofd;              /* input soundfile descriptor       */
+int channels;               /* number of channels of input      */
+int startwin, endwin, startchan, endchan, outfilesize, obufcnt;
+char outfilename[200];
+
+int srate, origstype, origrate, stype;
+int Mlen, Dfac, del;
+
+SFPROPS sfprops = {0};
+const char* cdp_version = "7.1.0";
+
+int main(int argc,char *argv[])
+{
+    unsigned int start = hz1000();
+    double starttime, endtime;
+
+    /* initialise SFSYS */
+    if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
+        fprintf(stdout,"%s\n",cdp_version);
+        fflush(stdout);
+        return 0;
+    }
+    if( sflinit("paview") < 0 ) {
+        fprintf(stdout,"ERROR: Cannot initialise soundfile system.\n");
+        fflush(stdout);
+        return tidy_up(3,start);
+    }
+    if(argc!=8)  {
+        fprintf(stdout,"ERROR: Wrong number of arguments.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    if(sscanf(argv[2],"%lf",&starttime)!=1) {
+        fprintf(stdout,"ERROR: cannot read start time.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    if(sscanf(argv[3],"%lf",&endtime)!=1) {
+        fprintf(stdout,"ERROR: cannot read end time.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    if(sscanf(argv[4],"%s",outfilename)!=1) {
+        fprintf(stdout,"ERROR: cannot outfilename.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    if(sscanf(argv[5],"%d",&startchan)!=1) {
+        fprintf(stdout,"ERROR: cannot read sonogram flag.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    if(sscanf(argv[6],"%d",&endchan)!=1) {
+        fprintf(stdout,"ERROR: cannot read sonogram flag.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    if(sscanf(argv[7],"%d",&del)!=1) {
+        fprintf(stdout,"ERROR: cannot read deletion flag.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    /* open input file */
+    if(open_in(argv[1]) < 0)
+        return tidy_up(2,start);
+
+    startwin = (int)floor(starttime/frametime);
+    endwin   = (int)ceil(endtime/frametime);
+
+    if(open_out(argv[4]) < 0)
+        return tidy_up(2,start);
+
+    /* get biggest buffer */
+    if(get_big_buf() == 0)
+        return tidy_up(1,start);
+        
+    if(make_outfile(del,outfilename)<0)
+        return tidy_up(1,start);
+
+    /* tidy up */
+    return tidy_up(0,start);
+}
+
+/**************************** OPEN_IN ****************************
+ *
+ * opens input soundfile and gets header 
+ */
+
+int open_in(char *name) /* opens input soundfile and gets header */
+{
+    if( (ifd = sndopenEx(name,0,CDP_OPEN_RDONLY)) < 0 ) {
+        fprintf(stdout,"ERROR: Cannot open file: %s\n\t",name);
+        fflush(stdout);
+        return(-1);
+    }
+    if(snd_headread(ifd,&sfprops)<=0) {
+        fprintf(stdout,"ERROR: Cannot read file properties: %s\n\t",name);
+        fflush(stdout);
+        return(-1);
+    }
+
+    channels = sfprops.chans;
+    arate = sfprops.arate;
+    origrate = sfprops.origrate;
+    Mlen = sfprops.winlen;
+    Dfac = sfprops.decfac;
+
+    frametime  = (float)(1.0/ sfprops.arate);
+    if(sfprops.type != wt_analysis){
+        fprintf(stdout,"ERROR: %s is not an analysis file\n",name);
+        fflush(stdout);
+        return(-1);
+    }
+    return 0;
+}
+
+/**************************** OPEN_OUT ****************************
+ *
+ * opens input soundfile and gets header 
+ */
+
+int open_out(char *name)    /* opens input soundfile and gets header */
+{
+    outfilesize = (endwin - startwin) * channels;
+    if((ofd = sndcreat_ex(name,outfilesize,&sfprops,0,CDP_CREATE_NORMAL)) < 0) {
+        fprintf(stdout,"ERROR: Cannot open output file %s\n",name);
+        fflush(stdout);
+        return(-1);
+    }
+    return 0;
+}
+
+/**************************** GET_BIG_BUF ****************************
+ *
+ * allocates memory for the biggest possible buffer 
+ */
+
+int get_big_buf()
+{
+    size_t i;
+
+    if((bigbuf=(float*)Malloc(((channels * 4) + F_SECSIZE) * sizeof(float))) == NULL) {
+        fprintf(stdout,"ERROR: Failed to allocate float buffer.\n");
+        fflush(stdout);
+        return 0;
+    }
+    i = ((size_t)bigbuf+sizeof(float)-1)/sizeof(float)*sizeof(float);   /* align bigbuf to word boundary */
+    bigbuf = (float*)i;
+    memset((char *)bigbuf,0,(channels * 4) * sizeof(float));
+    sampbuf = bigbuf + channels;
+    /* allow for wrap-around */
+    buflen = channels;
+    obuflen = (int)ceil((double)channels / (double)F_SECSIZE);
+    obuflen *= F_SECSIZE;
+    osambuf = sampbuf + channels;
+    /* allow for wrap-around */
+    return 1;
+}
+
+/**************************** MAKE TEXTFILE *****************************/
+
+int make_outfile(int del,char *filename)
+{
+    int samplen, total_windowsgot_got, samps_remain;
+    int got, sampsgot, windowsgot, bufcnt;
+    int channelstoshow, done_display, changrpcnt;
+    float *rbuf;
+    double channelmax;
+    int n, displayed_channel_cnt, channel_cnt, totchans;
+    
+    if((samplen  = sndsizeEx(ifd))<0) {     /* FIND SIZE OF FILE */
+        fprintf(stdout, "ERROR: Can't read size of input file %s.\n",filename);
+        fflush(stdout);
+        return -1;
+    }
+    total_windowsgot_got = 0;
+    samps_remain = 0;
+    rbuf = sampbuf;
+    totchans = channels/2;
+    if((channelstoshow = endchan - startchan) == 0) {
+        if(endchan != totchans)
+            endchan++;
+        else if(startchan !=0)
+            startchan--;
+        channelstoshow++;
+    }
+
+    memset((char *)osambuf,0, obuflen * sizeof(float));
+    done_display = 0;
+
+    obufcnt = 0;                                    /* count in buffer of output values */
+    while((got = fgetfbufEx(sampbuf,buflen,ifd,1)) > 0 ) {
+        sampsgot = samps_remain;                    /* Take into account any wrapped around values */
+        sampsgot += got;
+        windowsgot = sampsgot/channels;
+        samps_remain = sampsgot - (windowsgot * channels);
+        bufcnt = 0;                                 /* cnt in buffer we're reading from (which includes wrap-around) */
+        for(n=0;n<windowsgot;n++) {                 /* for every window */
+            total_windowsgot_got++;                 /* count the windows */
+            if(total_windowsgot_got <= startwin) {  /* if not at 1st window to display, continue */
+                if(del)
+                    if(write_window(totchans,rbuf,bufcnt)<0)
+                        return -1;
+                bufcnt += channels;
+                continue;
+            }
+            else if(total_windowsgot_got > endwin) {            /* if beyond last window to display, quit */
+                if(del) {
+                    if(write_window(totchans,rbuf,bufcnt)<0)
+                        return -1;
+                    bufcnt += channels;
+                    continue;
+                } else {
+                    done_display = 1;
+                    break;
+                }
+            }
+            changrpcnt = 0;                         /* count of set-of-channels to group together for display */
+            channelmax = 0.0;
+            for(channel_cnt=0;channel_cnt < startchan;channel_cnt++) {
+                if(del) {
+                    osambuf[obufcnt++] = rbuf[bufcnt++];
+                    osambuf[obufcnt++] = rbuf[bufcnt++];
+                    if(obufcnt >= obuflen) {
+                        if(write_output(obufcnt) < 0)
+                            return -1;
+                    }
+                } else {
+                    osambuf[obufcnt++] = 0.0;
+                    bufcnt++;
+                    osambuf[obufcnt++] = rbuf[bufcnt++];
+                    if(obufcnt >= obuflen) {
+                        if(write_output(obufcnt) < 0)
+                            return -1;
+                    }
+                }
+            }
+            for(displayed_channel_cnt = 0; displayed_channel_cnt < channelstoshow; displayed_channel_cnt++) {
+                if(del) {
+                    osambuf[obufcnt++] = 0.0;
+                    bufcnt++;
+                    osambuf[obufcnt++] = rbuf[bufcnt++];
+                    if(obufcnt >= obuflen) {
+                        if(write_output(obufcnt) < 0)
+                            return -1;
+                    }
+                } else {
+                    osambuf[obufcnt++] = rbuf[bufcnt++];
+                    osambuf[obufcnt++] = rbuf[bufcnt++];
+                    if(obufcnt >= obuflen) {
+                        if(write_output(obufcnt) < 0)
+                            return -1;
+                    }
+                }
+            }
+            channel_cnt += displayed_channel_cnt;
+            while(channel_cnt < totchans) {
+                if(del) {
+                    osambuf[obufcnt++] = rbuf[bufcnt++];
+                    osambuf[obufcnt++] = rbuf[bufcnt++];
+                    if(obufcnt >= obuflen) {
+                        if(write_output(obufcnt) < 0)
+                            return -1;
+                    }
+                } else {
+                    osambuf[obufcnt++] = 0.0;
+                    bufcnt++;
+                    osambuf[obufcnt++] = rbuf[bufcnt++];
+                    if(obufcnt >= obuflen) {
+                        if(write_output(obufcnt) < 0)
+                            return -1;
+                    }
+                }
+                channel_cnt++;
+            }
+        }
+        if(done_display)                            /* if reached end of windows to display, quit */
+            break;
+
+        if(samps_remain) {                          /* if there are extra samples beyond end of windows */
+            rbuf = sampbuf - samps_remain;          /* wrap them around */
+            memcpy((char *)rbuf,(char *)(rbuf + (windowsgot * channels)),samps_remain * sizeof(float));
+        } else
+            rbuf = sampbuf;
+    }
+    if(obufcnt >= 0) {
+        if(write_output(obufcnt) < 0)
+            return -1;
+    }
+    sndcloseEx(ofd);
+    return(0);
+}
+
+/**************************** TIDY_UP ****************************
+ *
+ * Exit, freeing buffers and closing files where necessary.
+ */
+
+int tidy_up(int where,unsigned int start)
+{
+    switch(where) {
+    case 0:
+        Mfree(bigbuf);
+    case 1:
+        sndcloseEx(ifd);
+    case 2:
+//      sffinish();
+    default:
+        break;
+    }
+    while(!(hz1000() - start))
+        ;
+    return(1);
+}
+    
+/**************************** WRITE_OUTPUT ****************************/
+
+int write_output(int samps_written)
+{
+    if(fputfbufEx(osambuf,samps_written,ofd) < 0) {
+        fprintf(stdout, "ERROR: Failed to complete data write to analysis output file.\n");
+        if(sndunlink(ofd) < 0)
+            fprintf(stdout, "ERROR: Can't set output analysis for deletion.\n");
+        if(sndcloseEx(ofd) < 0)
+            fprintf(stdout, "WARNING: Can't close output analysis.\n");
+        fflush(stdout);
+        return -1;
+    }
+    memset((char *)osambuf,0, obuflen * sizeof(float));
+    obufcnt = 0;
+    return 0;
+}
+
+/**************************** WRITE_WINDOW ****************************/
+
+int write_window(int totchans,float *rbuf,int bufcnt)
+{
+    int channel_cnt;
+    for(channel_cnt=0;channel_cnt < totchans;channel_cnt++) {
+        osambuf[obufcnt++] = rbuf[bufcnt++];
+        osambuf[obufcnt++] = rbuf[bufcnt++];
+        if(obufcnt >= obuflen) {
+            if(write_output(obufcnt) < 0)
+                return -1;
+        }
+    }
+    return 0;
+}
+

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

+ 406 - 0
dev/paview/paview.c

@@ -0,0 +1,406 @@
+/*
+ * 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
+ *
+ */
+
+
+
+
+/**************************************************************************
+ *
+ * Convert snd data to text format suitable for Pview in Sound Loom
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <osbind.h>
+#include <math.h>
+#include <float.h>
+#include <float.h>
+#include <sfsys.h>
+#include <cdplib.h>
+
+#define VIEW_WIDTH          900     /* width of sloom display */
+#define VIEW_HEIGHT         300     /* heigth of sloom display */
+#define HALF_VIEW_HEIGHT    150     /* half heigth of sloom display */
+#define COLOR_SPECTRUM       45     /* number of individual colours supported */
+
+#define EFFECTIVE_VIEW_WIDTH (VIEW_WIDTH - (VIEW_HEIGHT * 2))
+
+#define F_SECSIZE   (256)
+
+/*  Functions   */
+
+static  int     tidy_up(int,unsigned int);
+static  int     open_in(char*);
+static  int     get_big_buf(void);
+static  int     make_textfile(int sonogram,char *filename);
+static  int     write_output(int outlen,double *outbuf,double convertor,int sonogram,FILE *fp);
+
+
+float *bigbuf, *sampbuf;
+
+int Mlen;
+float arate, frametime;
+int buflen;             /* buffer length in samps           */
+int  ifd;                   /* input soundfile descriptor       */
+int  channels, expanded;    /* number of channels of input      */
+int startwin, endwin, startchan, endchan;
+const char* cdp_version = "7.1.0";
+
+int main(int argc,char *argv[])
+{
+    unsigned int start = hz1000();
+    char filename[200];
+    double starttime, endtime;
+    int sonogram;
+
+    if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
+        fprintf(stdout,"%s\n",cdp_version);
+        fflush(stdout);
+        return 0;
+    }
+    /* initialise SFSYS */
+    if( sflinit("paview") < 0 ) {
+        fprintf(stdout,"ERROR: Cannot initialise soundfile system.\n");
+        fflush(stdout);
+        return tidy_up(3,start);
+    }
+    if(argc!=7)  {
+        fprintf(stdout,"ERROR: Wrong number of arguments.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    if(sscanf(argv[2],"%lf",&starttime)!=1) {
+        fprintf(stdout,"ERROR: cannot read start time.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    if(sscanf(argv[3],"%lf",&endtime)!=1) {
+        fprintf(stdout,"ERROR: cannot read end time.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    if(sscanf(argv[4],"%d",&sonogram)!=1) {
+        fprintf(stdout,"ERROR: cannot read sonogram flag.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    if(sscanf(argv[5],"%d",&startchan)!=1) {
+        fprintf(stdout,"ERROR: cannot read sonogram flag.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    if(sscanf(argv[6],"%d",&endchan)!=1) {
+        fprintf(stdout,"ERROR: cannot read sonogram flag.\n");
+        fflush(stdout);
+        return tidy_up(2,start);
+    }
+    /* open input file */
+    if(open_in(argv[1]) < 0)
+        return tidy_up(2,start);
+
+    startwin = (int)floor(starttime/frametime);
+    endwin   = (int)ceil(endtime/frametime);
+
+    strcpy(filename,argv[1]);
+
+    /* get biggest buffer */
+    if(get_big_buf() == 0)
+        return tidy_up(1,start);
+        
+    /* max soundfiles */
+    if(make_textfile(sonogram,filename)<0)
+        return tidy_up(1,start);
+
+    /* tidy up */
+    return tidy_up(0,start);
+}
+
+/**************************** OPEN_IN ****************************
+ *
+ * opens input soundfile and gets header 
+ */
+
+int open_in(char *name) /* opens input soundfile and gets header */
+{
+    if((ifd = sndopenEx(name,0,CDP_OPEN_RDONLY)) < 0)   {
+        fprintf(stdout,"ERROR: Cannot open file: %s\n\t",name);
+        fflush(stdout);
+        return(-1);
+    }
+
+    /*  get channels        */
+
+    if(sndgetprop(ifd, "channels", (char*)&channels, sizeof(int)) < 0) {
+        fprintf(stdout,"ERROR: Cannot get channel count of %s\n",name);
+        fflush(stdout);
+        return(-1);
+    }
+    /*  get frametime       */
+
+    if(sndgetprop(ifd,"arate",(char *)&arate,sizeof(float)) < 0){
+        fprintf(stdout,"ERROR: Failure to read analysis sample rate, in %s\n",name);
+        fflush(stdout);
+        return(-1);
+    }
+    frametime  = (float)(1.0/arate);
+    return 0;
+}
+
+/**************************** GET_BIG_BUF ****************************
+ *
+ * allocates memory for the biggest possible buffer 
+ */
+
+int get_big_buf()
+{
+    size_t i;
+
+    if((bigbuf=(float*)Malloc(((channels * 2) + F_SECSIZE) * sizeof(float))) == NULL) {
+        fprintf(stdout,"ERROR: Failed to allocate float buffer.\n");
+        fflush(stdout);
+        return 0;
+    }
+    i = ((size_t)bigbuf+sizeof(float)-1)/sizeof(float)*sizeof(float);   /* align bigbuf to word boundary */
+    bigbuf = (float*)i;
+    memset((char *)bigbuf,0,(channels * 2) * sizeof(float));
+    sampbuf = bigbuf + channels;
+    buflen = channels;
+    /* allow for wrap-around */
+    return 1;
+}
+
+/**************************** MAKE TEXTFILE *****************************/
+
+int make_textfile(int sonogram,char *filename)
+{
+    FILE *fp;
+    int samplen, zoomfact, total_windowsgot_got, samps_remain;
+    int got, sampsgot, windowsgot, bufcnt, wingrpcnt;
+    int channelstoshow, chanscale, ch_outlen, w_outlen, done_display, obufcnt, changrpcnt;
+    float *rbuf;
+    double *outbuf;
+    double channelmax;
+    int n, displayed_channel_cnt, channel_cnt, totchans;
+    double convertor, zscale;
+    
+    expanded = 0;
+    if(sonogram) {
+        w_outlen = VIEW_WIDTH;
+        ch_outlen = VIEW_HEIGHT;
+        convertor = COLOR_SPECTRUM / 3.0; /* converts range 0 --> 3 TO range of colours */
+    } else  {
+        w_outlen = EFFECTIVE_VIEW_WIDTH;
+        ch_outlen = HALF_VIEW_HEIGHT;
+        convertor = HALF_VIEW_HEIGHT / 6.0; /* converts range 0 --> 3 TO range 0 -> quarter-view-heigth */
+    }
+
+
+    if((outbuf = (double *)malloc(ch_outlen * sizeof(double))) == NULL) {
+        fprintf(stdout, "ERROR: Insufficient memory to store output values.\n");
+        fflush(stdout);
+        return -1;
+    }
+    if((samplen  = sndsizeEx(ifd))<0) {     /* FIND SIZE OF FILE */
+        fprintf(stdout, "ERROR: Can't read size of input file %s.\n",filename);
+        fflush(stdout);
+        return -1;
+    }
+    if((fp = fopen("cdptest00.txt","w"))==NULL) {
+        fprintf(stdout, "ERROR: Failed to open the Sound Loom display file 'cdptest00.txt'\n");
+        fflush(stdout);
+        return -1;
+    }
+    zoomfact = max(1L,(int)ceil((double)(endwin - startwin)/w_outlen));
+    total_windowsgot_got = 0;
+    samps_remain = 0;
+    rbuf = sampbuf;
+    totchans = channels/2;
+    if((channelstoshow = endchan - startchan) == 0) {
+        if(endchan != totchans)
+            endchan++;
+        else if(startchan !=0)
+            startchan--;
+        channelstoshow++;
+    }
+
+    zscale = (double)channelstoshow / (double)ch_outlen;
+    if(zscale < .5)
+        expanded = (int)round((double)ch_outlen / (double)channelstoshow);
+
+    chanscale = (int)ceil((double)channelstoshow / (double)ch_outlen);  /* ratio of channels to available pixels */
+
+    memset((char *)outbuf,0, ch_outlen * sizeof(double));
+    done_display = 0;
+
+    wingrpcnt = 0;                                  /* cnt of set-of-windows to be zoomed together */
+    while((got = fgetfbufEx(sampbuf,buflen,ifd,1)) > 0 ) {
+        sampsgot = samps_remain;                    /* Take into account any wrapped around values */
+        sampsgot += got;
+        windowsgot = sampsgot/channels;
+        samps_remain = sampsgot - (windowsgot * channels);
+        bufcnt = 0;                                 /* cnt in buffer we're reading from (which includes wrap-around) */
+        for(n=0;n<windowsgot;n++) {                 /* for every window */
+            total_windowsgot_got++;                 /* count the windows */
+            if(total_windowsgot_got <= startwin) {  /* if not at 1st window to display, continue */
+                bufcnt  += channels;
+                continue;
+            }
+            else if(total_windowsgot_got > endwin) {            /* if beyond last window to display, quit */
+                done_display = 1;
+                break;
+            }
+            obufcnt = 0;                            /* count in buffer of output values */
+            changrpcnt = 0;                         /* count of set-of-channels to group together for display */
+            channelmax = 0.0;
+            for(channel_cnt=0;channel_cnt < startchan;channel_cnt++)
+                bufcnt += 2;
+            for(displayed_channel_cnt = 0; displayed_channel_cnt < channelstoshow; displayed_channel_cnt++) {
+                if(rbuf[bufcnt] > channelmax)       /* for each channel to display */   
+                    channelmax = rbuf[bufcnt];      /* find maximum value amongst group of channels */
+                if(++changrpcnt >= chanscale) {     /* once whole group has been surveyed */
+                    if(channelmax > outbuf[obufcnt])/* transfer maxvalue to output, if it's larger than val alreasdy there */
+                        outbuf[obufcnt] = channelmax;   /* (we are also possibly averaging over windows, by zoomfact) */
+                    obufcnt++;                      /* move to next outbuffer location */
+                    channelmax = 0.0;               /* reset channelmax to min */
+                    changrpcnt = 0;                 /* start counting next group */
+                }
+                bufcnt += 2;                        /* move up to next amplitude value */
+            }
+            if(changrpcnt > 0) {                    /* last channels may not be a full group: if not, output their val here */
+                if(channelmax > outbuf[obufcnt])
+                    outbuf[obufcnt] = channelmax;
+                obufcnt++;
+                channelmax = 0.0;
+                changrpcnt = 0;
+            }
+            channel_cnt += displayed_channel_cnt;
+            while(channel_cnt < totchans) {
+                bufcnt += 2;
+                channel_cnt++;
+            }
+            wingrpcnt++;
+            if(wingrpcnt >= zoomfact) {         /* if we have looked at enough windows (in the zoom) */
+                if(write_output(ch_outlen,outbuf,convertor,sonogram,fp) < 0) {
+                    fclose(fp);
+                    fprintf(stdout, "ERROR: Failed to complete data write to Sound Loom display file 'cdptest00.txt'\n");
+                    fflush(stdout);
+                    return -1;
+                }
+                memset((char *)outbuf,0, ch_outlen * sizeof(double));
+                wingrpcnt = 0;                      /* reset the obuf, and the window counter */
+            }
+        }
+        if(done_display)                            /* if reached end of windows to display, quit */
+            break;
+
+        if(samps_remain) {                          /* if there are extra samples beyond end of windows */
+            rbuf = sampbuf - samps_remain;          /* wrap them around */
+            memcpy((char *)rbuf,(char *)(rbuf + (windowsgot * channels)),samps_remain * sizeof(float));
+        } else
+            rbuf = sampbuf;
+    }
+    if(wingrpcnt > 0) {                             /* last windows looed at did not form a complete zoom set */
+        if(write_output(ch_outlen,outbuf,convertor,sonogram,fp) < 0) {
+            fclose(fp);
+            fprintf(stdout, "ERROR: Failed to complete data write to Sound Loom display file 'cdptest00.txt'\n");
+            fflush(stdout);
+            return -1;
+        }
+    }
+    fclose(fp);
+    return(0);
+}
+
+/**************************** TIDY_UP ****************************
+ *
+ * Exit, freeing buffers and closing files where necessary.
+ */
+
+int tidy_up(int where,unsigned int start)
+{
+    switch(where) {
+    case 0:
+        Mfree(bigbuf);
+    case 1:
+        sndcloseEx(ifd);
+    case 2:
+//      sffinish();
+    default:
+        break;
+    }
+    while(!(hz1000() - start))
+        ;
+    return(1);
+}
+    
+/**************************** WRITE_OUTPUT ****************************/
+
+int write_output(int outlen,double *outbuf,double convertor,int sonogram,FILE *fp)
+{
+    int z, x, zob=0;
+    int channelstoshow; 
+    char temp[2000];
+    char temp2[64];
+    temp[0] = '\0';
+    if(expanded) {
+        channelstoshow = endchan - startchan;
+        for(z = 0;z < channelstoshow; z++) {        /* output trhe results */
+            outbuf[z] *= 999.0;
+            outbuf[z] += 1.0;                   /* Range    0-1       -->> 1 to 1000  */
+            outbuf[z] = log10(outbuf[z]);       /* Range    1 to 1000 -->> 1 to 3  */
+            outbuf[z] *= convertor;
+            if(sonogram) {
+                zob  = (int)round(outbuf[z]);
+            }
+            for(x = 0; x < expanded; x++) {
+                if(sonogram) {
+                    sprintf(temp2,"%d",zob);
+                } else {
+                    sprintf(temp2,"%lf",outbuf[z]);
+                }
+                strcat(temp2," ");
+                strcat(temp,temp2);
+            }
+        }
+    } else {
+        for(z = 0;z < outlen; z++) {        /* output trhe results */
+            outbuf[z] *= 999.0;
+            outbuf[z] += 1.0;                   /* Range    0-1       -->> 1 to 1000  */
+            outbuf[z] = log10(outbuf[z]);       /* Range    1 to 1000 -->> 1 to 3  */
+            outbuf[z] *= convertor;             /* For Sonogram: Range    1 to 3      -->> 0 to 0 to max colour  */
+                                                /* FOr Spectrum: Range    1 to 3      -->> 0 to half of HALF_VIEW_HEIGHT  */
+            if(sonogram) {
+                sprintf(temp2,"%d",(int)round(outbuf[z]));
+            } else {
+                sprintf(temp2,"%lf",outbuf[z]);
+            }
+            strcat(temp2," ");
+            strcat(temp,temp2);
+        }
+    }
+    if(fprintf(fp,"%s\n",temp) < 1)
+        return -1;
+    return 1;
+}

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

+ 1143 - 0
dev/pitch/ap_pitch.c

@@ -0,0 +1,1143 @@
+/*
+ * 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 <pitch.h>
+#include <processno.h>
+#include <modeno.h>
+#include <globcon.h>
+#include <logic.h>
+#include <filetype.h>
+#include <mixxcon.h>
+#include <flags.h>
+#include <speccon.h>
+#include <arrays.h>
+#include <special.h>
+#include <formants.h>
+#include <sfsys.h>
+#include <osbind.h>
+#include <string.h>
+#include <math.h>
+#include <srates.h>
+
+#ifndef HUGE
+#define HUGE 3.40282347e+38F
+#endif
+
+/********************************************************************************************/
+/********************************** FORMERLY IN pconsistency.c ******************************/
+/********************************************************************************************/
+
+static int 	check_viability_and_compatibility_of_shiftp_params(dataptr dz);
+static int  sub_check_shiftp(dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+#define SCALEFUDGE  (3.0)
+static int  tune_preprocess(dataptr dz);
+static int  convert_params_for_tune(dataptr dz);
+static int  pick_preprocess(dataptr dz);
+static int  adjust_parameters_for_specpick(dataptr dz);
+static int  mark_chosen_channels_in_bitflags(dataptr dz);
+static int  chan_containing_partial(int *botpchan,double *lastchtop,int *chan,double partial,dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN specialin.c *********************************/
+/********************************************************************************************/
+
+static int  generate_template_frqs(char *str,int datatype,dataptr dz);
+static int  get_input_frqs(char *str,int datatype,double **fundamentals, double **harmonics,int *infrqcnt,dataptr dz);
+static int  generate_template(double *fundamentals, double *harmonics, int infrqcnt, dataptr dz);
+static int  getnextfrq(double *minfrq,double *fundamentals,double *harmonics,int infrqcnt);
+static int  chordget(char *str,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(ALT):        		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(OCT):        		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(SHIFTP):     		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(TUNE):       		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(PICK):       		dz->extra_bufcnt =  0; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(MULTRANS):   		dz->extra_bufcnt =  1; dz->bptrcnt = 1; 	is_spec = TRUE;		break;
+	case(CHORD):      		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(ALT):    	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(OCT):    	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(SHIFTP): 	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(TUNE):   	dz->array_cnt = 0; dz->iarray_cnt =1;  dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(PICK):   	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt =1;  dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(MULTRANS): dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(CHORD):  	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(ALT):			setup_process_logic(ANAL_WITH_PITCHDATA,  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(OCT):			setup_process_logic(ANAL_WITH_PITCHDATA,  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(SHIFTP):		setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(TUNE):			setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(PICK):			setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(MULTRANS):		setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	case(CHORD):		setup_process_logic(ANALFILE_ONLY,		  	EQUAL_ANALFILE,		ANALFILE_OUT,	dz);	break;
+	default:
+		sprintf(errstr,"Unknown process: assign_process_logic()\n");
+		return(PROGRAM_ERROR);
+		break;
+	}
+	if(dz->has_otherfile) {
+		switch(dz->input_data_type) {
+		case(ALL_FILES):
+		case(TWO_SNDFILES):
+		case(SNDFILE_AND_ENVFILE):
+		case(SNDFILE_AND_BRKFILE):
+		case(SNDFILE_AND_UNRANGED_BRKFILE):
+		case(SNDFILE_AND_DB_BRKFILE):
+			break;
+		case(MANY_SNDFILES):
+			if(dz->process==INFO_TIMELIST)
+				break;
+			/* fall thro */
+		default:
+			sprintf(errstr,"Most processes accepting files with different properties\n"
+						   "can only take 2 sound infiles.\n");
+			return(PROGRAM_ERROR);
+		}
+	}
+	return(FINISHED);
+}
+
+/***************************** SET_LEGAL_INFILE_STRUCTURE **************************
+ *
+ * Allows 2nd infile to have different props to first infile.
+ */
+
+void set_legal_infile_structure(dataptr dz)
+{
+	switch(dz->process) {
+	default:
+		dz->has_otherfile = FALSE;
+		break;
+	}
+}
+
+/***************************************************************************************/
+/****************************** FORMERLY IN internal.c *********************************/
+/***************************************************************************************/
+
+/****************************** SET_LEGAL_INTERNALPARAM_STRUCTURE *********************************/
+
+int set_legal_internalparam_structure(int process,int mode,aplptr ap)
+{
+	int exit_status = FINISHED;
+
+	switch(process) {
+	case(ALT):		  	return(FINISHED);
+	case(OCT):		  	return(FINISHED);
+	case(SHIFTP):	  	exit_status = set_internalparam_data("idddddd",ap);				break;
+	case(TUNE):		  	return(FINISHED);
+	case(PICK):		  	exit_status = set_internalparam_data("ii",ap);					break;
+	case(MULTRANS):	  	return(FINISHED);
+	case(CHORD):	  	return(FINISHED);
+	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) {
+	case(FRQ_OR_FRQSET):
+	case(PITCH_OR_PITCHSET):	return generate_template_frqs(str,(int)ap->special_data,dz);
+
+	case(SEMIT_TRANSPOS_SET): 	return chordget(str,dz);
+	default:
+		sprintf(errstr,"Unknown special_data type: read_special_data()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/**************************** GENERATE_TEMPLATE_FRQS ****************************/
+
+int generate_template_frqs(char *str,int datatype,dataptr dz) /* 'datatype' has to be  PITCH_OR_PITCHSET or FRQ_OR_FRQSET */
+{
+ 	double *fundamentals, *harmonics;
+	int infrqcnt;
+	int exit_status;
+	if((exit_status = get_input_frqs(str,datatype,&fundamentals,&harmonics,&infrqcnt,dz))<0)
+		return(exit_status);
+	if((exit_status = generate_template(fundamentals,harmonics,infrqcnt,dz))<0)
+		return(exit_status);
+	free(fundamentals);
+	free(harmonics);
+	return(FINISHED);
+}
+
+/**************************** GET_INPUT_FRQS ****************************/
+
+int get_input_frqs(char *str,int datatype,double **fundamentals, double **harmonics,int *infrqcnt,dataptr dz)
+{		
+	double dummy = 0.0, mididummy = 0.0;
+	FILE *fp;
+	int n, is_numeric = 0;
+	int arraysize = BIGARRAY;
+	char temp[200], *p;
+
+	*infrqcnt = 0;
+
+	if(!sloom) {
+//TW NEW CONVENTION ON numeric filenames
+		if(!value_is_numeric(str) && file_has_invalid_startchar(str)) {
+    		sprintf(errstr,"Filename has invalid start-character [%s]\n",str);
+			return(USER_ERROR);
+		}
+		if(value_is_numeric(str)) {
+			if(sscanf(str,"%lf",&dummy)!=1) {
+				sprintf(errstr,"Invalid frq or pitch data: get_input_frqs()\n");
+				return(DATA_ERROR);
+			}
+			is_numeric = 1;
+		}
+	} else {
+		if(str[0]==NUMERICVAL_MARKER) {
+			str++;
+			if(strlen(str)<=0 || sscanf(str,"%lf",&dummy)!=1) {
+				sprintf(errstr,"Invalid frq or pitch data: get_input_frqs()\n");
+				return(DATA_ERROR);
+			}
+			is_numeric = 1;
+		}
+	}
+	if(is_numeric) {
+		if(datatype == PITCH_OR_PITCHSET) {
+			mididummy = dummy;
+			dummy = miditohz(dummy);
+		}
+		if(dummy <= 0.0 || dummy >= dz->nyquist) {
+			if(datatype == PITCH_OR_PITCHSET) {
+				sprintf(errstr,"Input midi value %lf in file %s is outside frq range (>0 - %.0lf[nyquist])\n",
+				mididummy,str,dz->nyquist);
+			} else {
+				sprintf(errstr,"Input frq value %lf in file %s is outside frq range (>0 - %.0lf[nyquist])\n",
+				dummy,str,dz->nyquist);
+			}
+			return(USER_ERROR);
+		}
+		if((*fundamentals = (double *)malloc(sizeof(double)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY to store fundamentals.\n");
+			return(MEMORY_ERROR);
+		}
+		(*fundamentals)[(*infrqcnt)++] = (float)dummy;
+	} else {
+		if((fp = fopen(str,"r"))==NULL) {
+			sprintf(errstr,"Cannot open file %s to read template.\n",str);
+			return(DATA_ERROR);
+		}
+		if((*fundamentals = (double *)malloc(arraysize * sizeof(double)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY to store fundamentals.\n");
+			return(MEMORY_ERROR);
+		}
+		while(fgets(temp,200,fp)!=NULL) {
+			p = temp;
+			while(get_float_from_within_string(&p,&dummy)) {
+				switch(datatype) {
+				case(PITCH_OR_PITCHSET):
+					mididummy = dummy;
+					dummy = miditohz(dummy);
+					/* fall thro */
+				case(FRQ_OR_FRQSET):
+					if(dummy <= 0.0 || dummy >= dz->nyquist) {
+						if(datatype == PITCH_OR_PITCHSET) {
+							sprintf(errstr,"Input midi value %lf in file %s is outside frq range (>0 - %.0lf[nyquist])\n",
+							mididummy,str,dz->nyquist);
+						} else {
+							sprintf(errstr,"Input frq value %lf in file %s is outside frq range (>0 - %.0lf[nyquist])\n",
+							dummy,str,dz->nyquist);
+						}
+						return(USER_ERROR);
+					}
+					break;
+				}
+				(*fundamentals)[*infrqcnt] = (float)dummy;
+				if(++(*infrqcnt)>=arraysize) {
+					arraysize += BIGARRAY;
+					if((*fundamentals = (double *)realloc((char *)(*fundamentals),arraysize*sizeof(double)))==NULL) {
+						sprintf(errstr,"INSUFFICIENT MEMORY to reallocate fundamentals store.\n");
+						return(MEMORY_ERROR);
+					}
+				}
+			}
+		}
+		if(*infrqcnt==0) {
+			sprintf(errstr,"No data found in frq template file %s\n",str);
+			return(DATA_ERROR);
+		}
+		if((*fundamentals = (double *)realloc((char *)(*fundamentals),(*infrqcnt) * sizeof(double)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY to reallocate fundamentals store.\n");
+			return(MEMORY_ERROR);
+		}
+		if(fclose(fp)<0) {
+			fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",str);
+			fflush(stdout);
+		}
+	}
+	if((*harmonics = (double *)malloc((*infrqcnt) * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to store harmonics.\n");
+		return(MEMORY_ERROR);
+	}
+	for(n=0;n<(*infrqcnt);n++)
+		(*harmonics)[n] = (*fundamentals)[n];
+	return(FINISHED);
+}
+    
+/**************************** GENERATE_TEMPLATE *************************/
+
+int generate_template(double *fundamentals, double *harmonics, int infrqcnt, dataptr dz)
+{
+	int exit_status;
+	int n;
+	double lastchtop, thischtop, thisfrq;
+	for(n=0;n<infrqcnt;n++) {
+		if(fundamentals[n]>=dz->nyquist) {
+			sprintf(errstr,"Input frq %d = %lf >= nyquist[%.0lf].\n",n+1,fundamentals[n],dz->nyquist);
+			return(DATA_ERROR);
+		}
+	}
+	lastchtop = 0.0;
+	thischtop = dz->chwidth/2.0;
+	if((exit_status = getnextfrq(&thisfrq,fundamentals,harmonics,infrqcnt))<0)
+		return(exit_status);
+	if((exit_status = float_array(&(dz->frq_template),dz->clength))<0)
+		return(exit_status);
+	for(n=0;n<dz->clength;n++) {
+		while(thisfrq < lastchtop) {
+			if((exit_status = getnextfrq(&thisfrq,fundamentals,harmonics,infrqcnt))<0)
+				return(exit_status);
+		}
+		if(thisfrq > thischtop)
+			dz->frq_template[n] = (float)(-1.0);
+		else
+			dz->frq_template[n] = (float)thisfrq;
+		lastchtop = thischtop;
+		if((thischtop += dz->chwidth) > dz->nyquist)
+			thischtop = dz->nyquist;
+	}
+	return(FINISHED);
+}
+
+/***************************** GETNEXTFRQ *****************************/
+
+int getnextfrq(double *minfrq,double *fundamentals,double *harmonics,int infrqcnt)
+{
+	int minptr = 0, n;
+	*minfrq = HUGE;
+	for(n=0;n<infrqcnt;n++) {
+		if(harmonics[n] < *minfrq) {		/* FIND CURRENT MIN FRQ IN ARRAY harmonics[] */
+			*minfrq = harmonics[n];
+			minptr   = n;
+		}
+	}
+	harmonics[minptr] += fundamentals[minptr];	/* INCREMENT MIN VALUE TO NEXT APPROPRIATE HARMONIC */
+	return(FINISHED);
+}
+
+/*************************** CHORDGET ******************************/
+
+int chordget(char *str,dataptr dz)
+{
+	FILE *fp;
+	double val;
+	int arraysize = BIGARRAY;
+	char temp[200], *q;
+	if((dz->transpos = (float *)malloc(arraysize * sizeof(float)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for transposition array.\n");
+		return(MEMORY_ERROR);
+	}
+	if(!sloom) {
+//TW NEW CONVENTION on numeric filenames
+		if(!value_is_numeric(str) && file_has_invalid_startchar(str)) {
+    		sprintf(errstr,"Cannot read parameter value [%s]\n",str);
+			return(USER_ERROR);
+		}
+//TW REVISED Dec 2002
+		if(value_is_numeric(str)) {
+			sprintf(errstr,"This process takes chord-data in a FILE only.\n");
+			return(DATA_ERROR);
+		}
+		if((fp = fopen(str,"r"))==NULL) {
+			sprintf(errstr,"Can't open text file %s to read.\n",str);
+			return(DATA_ERROR);
+		}
+	} else {
+		if(str[0] == NUMERICVAL_MARKER) {
+//TW THis Check should be redundant: trapped by Sound Loom
+			sprintf(errstr,"This process takes chord-data in a FILE only.\n");
+			return(DATA_ERROR);
+		} else if((fp = fopen(str,"r"))==NULL) {
+			sprintf(errstr,"Can't open text file %s to read.\n",str);
+			return(DATA_ERROR);
+		}
+	}
+	while(fgets(temp,200,fp)==temp) {
+		q = temp;
+		while(get_float_from_within_string(&q,&val)) {
+			val *= OCTAVES_PER_SEMITONE;	/* CONVERT SEMITONES TO OCTAVES */
+			val = pow(2.0,val);				/* CONVERT OCTAVES TO FRQ RATIO */
+			if(val <= MIN_TRANSPOS || val > MAX_TRANSPOS) {
+				sprintf(errstr,"transposition out of range (frq ratio %lf to %lf)\n",
+				LOG2(MIN_TRANSPOS) * SEMITONES_PER_OCTAVE,LOG2(MAX_TRANSPOS) * SEMITONES_PER_OCTAVE);
+				return(DATA_ERROR);
+			}
+			dz->transpos[dz->itemcnt] = (float)val;
+			if(++dz->itemcnt >= arraysize) {
+				arraysize += BIGARRAY;
+				if((dz->transpos = (float *)realloc((char *)dz->transpos,arraysize * sizeof(float)))==NULL) {
+					sprintf(errstr,"INSUFFICIENT MEMORY to reallocate transposition array.\n");
+					return(MEMORY_ERROR);
+				}
+			}
+		}
+	}	    
+	if(dz->itemcnt == 0) {
+		sprintf(errstr,"No data in file %s\n",str);
+		return(DATA_ERROR);
+	}
+	if((dz->transpos = (float *)realloc((char *)dz->transpos,dz->itemcnt * sizeof(float)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY to reallocate transposition array.\n");
+		return(MEMORY_ERROR);
+	}
+	if(fclose(fp)<0) {
+		fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",str);
+		fflush(stdout);
+	}
+	return(FINISHED);
+}
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+/****************************** PARAM_PREPROCESS *********************************/
+
+int param_preprocess(dataptr dz)	
+{
+	int check;
+
+	switch(dz->process) {
+	case(OCT):			return initialise_specenv(&check,dz);
+	case(SHIFTP):		return adjust_params_and_setup_internal_params_for_shiftp(dz);
+	case(TUNE):			return tune_preprocess(dz);
+	case(PICK):			return pick_preprocess(dz);
+
+  	case(ALT):	case(MULTRANS): case(CHORD): 		
+  		return(FINISHED);
+	default:
+		sprintf(errstr,"PROGRAMMING PROBLEM: Unknown process in param_preprocess()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/************ ADJUST_PARAMS_AND_SETUP_INTERNAL_PARAMS_FOR_SHIFTP *************/
+
+int adjust_params_and_setup_internal_params_for_shiftp(dataptr dz)
+{
+	int exit_status;
+	double frq;
+	frq = dz->param[SHIFTP_FFRQ]  + dz->chwidth/2.0;
+	dz->iparam[SHIFTP_FDCNO] = (int)floor(frq/dz->chwidth);
+	dz->param[SHIFTP_S1L1] = dz->param[SHIFTP_SHF1] - 1.0;
+ 	dz->param[SHIFTP_1LS1] = 1.0 - dz->param[SHIFTP_SHF1];
+	if(dz->mode == P_SHFT_UP_AND_DN) {
+		dz->param[SHIFTP_S2L1] = dz->param[SHIFTP_SHF2] - 1.0;
+		dz->param[SHIFTP_1LS2] = 1.0 - dz->param[SHIFTP_SHF2];
+	}
+	else {	   
+		dz->param[SHIFTP_S2L1] = 0.0;
+		dz->param[SHIFTP_1LS2] = 0.0;
+	}
+	dz->param[SHIFTP_NS1] = dz->param[SHIFTP_SHF1];
+	if(dz->mode == P_SHFT_UP_AND_DN)
+		dz->param[SHIFTP_NS2] = dz->param[SHIFTP_SHF2];
+	else						 
+		dz->param[SHIFTP_NS2] =  0.0;
+	if(dz->vflag[SHP_IS_DEPTH] && dz->brksize[SHIFTP_DEPTH]==0) {
+		if((exit_status = reset_shiftps_according_to_depth_value(dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/************************ RESET_SHIFTPS_ACCORDING_TO_DEPTH_VALUE ****************************/
+
+int reset_shiftps_according_to_depth_value(dataptr dz)
+{
+	switch(dz->mode) {
+	case(6):
+  		if(dz->param[SHIFTP_SHF2] > 1.0)
+  			dz->param[SHIFTP_NS2] = (dz->param[SHIFTP_S2L1] * dz->param[SHIFTP_DEPTH]) + 1.0;
+		else
+			dz->param[SHIFTP_NS2] = 1.0 - (dz->param[SHIFTP_1LS2] * dz->param[SHIFTP_DEPTH]);
+	default:
+		if(dz->param[SHIFTP_SHF1] > 1.0)
+			dz->param[SHIFTP_NS1]  = (dz->param[SHIFTP_S1L1] * dz->param[SHIFTP_DEPTH]) + 1.0;
+		else
+			dz->param[SHIFTP_NS1]  = 1.0 - (dz->param[SHIFTP_1LS1] * dz->param[SHIFTP_DEPTH]);
+	}
+	return(FINISHED);
+}
+
+/************************** TUNE_PREPROCESS ******************************/
+
+int tune_preprocess(dataptr dz)
+{
+	int exit_status;
+	if((exit_status = convert_params_for_tune(dz))<0)
+		return(exit_status);
+	if((dz->iparray[TUNE_LOUD] = (int *)malloc(dz->wanted * sizeof(int)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for loudness array.\n");
+		return(MEMORY_ERROR);
+	}
+	return setup_ring(dz);
+}
+
+/************ CONVERT_PARAMS_FOR_TUNE *************/
+
+int convert_params_for_tune(dataptr dz)
+{
+	double *p;
+	int n;
+	if(dz->brksize[TUNE_CLAR]==0)
+		dz->param[TUNE_CLAR] = 1.0 - dz->param[TUNE_CLAR];
+	else {
+		p = dz->brk[TUNE_CLAR] + 1;
+		for(n = 0;n<dz->brksize[TUNE_CLAR];n++) {
+			*p = 1.0 - *p;
+			p += 2;
+		}
+	}
+	return(FINISHED);
+}
+
+/************************** PICK_PREPROCESS ******************************/
+
+int pick_preprocess(dataptr dz)
+{
+	int exit_status;
+	if((exit_status = adjust_parameters_for_specpick(dz))<0)
+		return(exit_status);
+	if((exit_status = setup_internal_bitflags(PICK_BFLG,PICK_LONGPOW2,PICK_DIVMASK,dz))<0)
+		return(exit_status);
+	return mark_chosen_channels_in_bitflags(dz);
+}
+
+/************ ADJUST_PARAMETERS_FOR_SPECPICK *************/
+
+int adjust_parameters_for_specpick(dataptr dz)
+{
+	/* Make perceived clarity grow linearly with entered val: PICK */
+
+	double *p;
+	int n;
+	if(dz->brksize[PICK_CLAR] == 0) {
+		dz->param[PICK_CLAR] = 1.0 - dz->param[PICK_CLAR];
+		dz->param[PICK_CLAR] = pow(dz->param[PICK_CLAR],SCALEFUDGE);
+	} else {
+		p = dz->brk[PICK_CLAR] + 1;
+		for(n=0; n < dz->brksize[PICK_CLAR]; n++) {
+			*p = 1.0 - *p;
+			*p = pow(*p,SCALEFUDGE);
+			p += 2;
+		}
+	}
+	return(FINISHED);
+}
+
+/***************************** MARK_CHOSEN_CHANNELS_IN_BITFLAGS *************/
+
+int mark_chosen_channels_in_bitflags(dataptr dz)
+{
+	int exit_status;
+	int n=1, chan;
+	int mask;
+	int botpchan = 0;
+	double lastchtop = dz->chwidth/2.0;
+	double partial = dz->param[PICK_FUND];
+	do {
+		if((exit_status = chan_containing_partial(&botpchan,&lastchtop,&chan,partial,dz))<0) {
+			sprintf(errstr,"Problem with partial->channel calculation: mark_chosen_channels_in_bitflags()\n");
+			return(PROGRAM_ERROR);
+		}
+		mask = 1;		  /* set bitflag */
+		dz->lparray[PICK_BFLG][(chan>>dz->iparam[PICK_LONGPOW2])] 
+			|= (mask <<= (chan & dz->iparam[PICK_DIVMASK]));
+		switch(dz->mode) {
+		case(PIK_HARMS):  		   n++;   partial  =  dz->param[PICK_FUND] * (double)n;	    					break;
+		case(PIK_OCTS):    	 	   		  partial  =  partial * 2.0;	    									break;
+		case(PIK_ODD_HARMS):  	   n+=2;  partial  =  dz->param[PICK_FUND] * (double)n;	    					break;
+		case(PIK_LINEAR):	       		  partial +=  dz->param[PICK_LIN];    									break;
+		case(PIK_DISPLACED_HARMS): n++;   partial  = (dz->param[PICK_FUND] 
+										* (double)n) + dz->param[PICK_LIN];  
+			break;
+		default:
+			sprintf(errstr,"Programing Problem: Unknown mode in mark_chosen_channels_in_bitflags()\n");
+			return(PROGRAM_ERROR);
+		}
+	} while(partial < dz->nyquist);
+	return(FINISHED);
+}
+
+/************************** CHAN_CONTAINING_PARTIAL *************************/
+
+int chan_containing_partial(int *botpchan,double *lastchtop,int *chan,double partial,dataptr dz)
+{
+	int n;
+	double chtop;
+	chtop = *lastchtop;
+	for(n=*botpchan; n<=dz->clength ;n++) {
+		if(partial < chtop) {
+			*botpchan = n;
+			*lastchtop = chtop;
+			*chan = n;
+			return(FINISHED);
+		}
+		chtop += dz->chwidth;
+	}
+	return(GOAL_FAILED);
+}
+
+/********************************************************************************************/
+/********************************** 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(ALT):		return outer_loop(dz);
+	case(OCT):		return outer_loop(dz);
+	case(SHIFTP):	return outer_loop(dz);
+	case(TUNE):		return outer_loop(dz);
+	case(PICK):		return outer_loop(dz);
+	case(MULTRANS):	return outer_loop(dz);
+	case(CHORD):	return outer_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(ALT):		exit_status = specalt(pitchcnt,dz);	  				break;		
+		case(OCT):		exit_status = specoct(dz);	  						break;
+		case(CHORD):	exit_status = specchord(dz);  						break;
+		case(MULTRANS):	exit_status = specchord2(dz); 						break;
+		case(PICK):		exit_status = specpick(dz);	  						break;
+		case(SHIFTP):	exit_status = specshiftp(dz); 						break;
+		case(TUNE):		exit_status = spectune(dz);	  						break;
+		default:
+			sprintf(errstr,"unknown process in inner_loop()\n");
+			return(PROGRAM_ERROR);
+		}
+		if(exit_status<0)
+			return(exit_status);
+		dz->flbufptr[0] += dz->wanted;
+		dz->total_windows++;
+		dz->time = (float)(dz->time + dz->frametime);
+	}
+	if(!dz->zeroset && local_zero_set==TRUE) {
+		fprintf(stdout,"WARNING: Zero-amp spectral window(s) encountered: orig window(s) substituted.\n"); 
+		fflush(stdout);
+		dz->zeroset = TRUE;
+	}
+	return(FINISHED);
+}
+
+/***************** SKIP_OR_SPECIAL_OPERATION_ON_WINDOW_ZERO ************/
+
+int skip_or_special_operation_on_window_zero(dataptr dz)
+{
+	int vc;
+	switch(dz->process) {
+	case(CHORD):   case(OCT):   case(MULTRANS):
+		switch(dz->process) {
+		case(CHORD):
+		case(MULTRANS):
+			for(vc = 0; vc < dz->wanted; vc += 2)
+				dz->windowbuf[0][FREQ] = dz->flbufptr[0][FREQ];
+			break;
+		}
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN pconsistency.c ******************************/
+/********************************************************************************************/
+
+/****************************** CHECK_PARAM_VALIDITY_AND_CONSISTENCY *********************************/
+
+int check_param_validity_and_consistency(dataptr dz)
+{
+	handle_pitch_zeros(dz);
+	switch(dz->process) {
+	case(SHIFTP):	   return check_viability_and_compatibility_of_shiftp_params(dz);
+	}
+	return(FINISHED);
+}
+
+/***************** CHECK_VIABILITY_AND_COMPATIBILITY_OF_SHIFTP_PARAMS ******************/
+
+int check_viability_and_compatibility_of_shiftp_params(dataptr dz)
+{
+	int exit_status;
+	double thistime = 0.0;
+	if(dz->vflag[SHP_IS_DEPTH]) {
+		if((exit_status = check_depth_vals(SHIFTP_DEPTH,dz))<0)
+			return(exit_status);
+	}
+	if(dz->brksize[SHIFTP_FFRQ] || dz->brksize[SHIFTP_SHF1] || dz->brksize[SHIFTP_SHF2]) {
+		while(thistime < dz->duration + dz->frametime) {
+			if((exit_status = read_values_from_all_existing_brktables(thistime,dz))<0)
+				return(exit_status);
+			if((exit_status = sub_check_shiftp(dz))<0)
+				return(exit_status);
+			thistime += dz->frametime;
+		}
+		return(FINISHED);
+	}
+	return sub_check_shiftp(dz);
+}
+
+/*********************** SUB_CHECK_SHIFTP ***********************/
+
+int sub_check_shiftp(dataptr dz)
+{
+	double frq = dz->param[SHIFTP_FFRQ] + dz->chwidth/2.0;
+	int fdcno = (int)floor(frq/dz->chwidth);
+	switch(dz->mode) {
+	case(P_SHFT_UP_AND_DN):
+		dz->param[SHIFTP_SHF1] *= OCTAVES_PER_SEMITONE;
+		dz->param[SHIFTP_SHF1] = pow(2.0,dz->param[SHIFTP_SHF1]);
+		dz->param[SHIFTP_SHF2] *= OCTAVES_PER_SEMITONE;
+		dz->param[SHIFTP_SHF2] = pow(2.0,dz->param[SHIFTP_SHF2]);
+
+		if(dz->param[SHIFTP_SHF1] > 1.0
+		&& round((double)(dz->clength-1)/dz->param[SHIFTP_SHF1]) < fdcno) {
+			sprintf(errstr,"Shift above frq split is too great to work.\n");
+			return(DATA_ERROR);
+		}
+		if(dz->param[SHIFTP_SHF1] <= 1.0
+		&& round((double)(dz->clength-1)*dz->param[SHIFTP_SHF1]) <= fdcno) {
+			sprintf(errstr,"Shift above frq split is too great to work.\n");
+			return(DATA_ERROR);
+		}
+		if(dz->param[SHIFTP_SHF2] > dz->param[SHIFTP_FFRQ]/SPEC_MINFRQ) {
+			sprintf(errstr,"Shift below frq split is too great to work.\n");
+			return(DATA_ERROR);
+		}
+		if(dz->param[SHIFTP_SHF2] <= 1.0
+		&& (1.0/dz->param[SHIFTP_SHF2]) >= dz->param[SHIFTP_FFRQ]/SPEC_MINFRQ) {
+			sprintf(errstr,"Shift below frq split is too great to work.\n");
+			return(DATA_ERROR);
+		}
+		break;
+	case(P_SHFT_DN):
+		dz->param[SHIFTP_SHF1] *= OCTAVES_PER_SEMITONE;
+		dz->param[SHIFTP_SHF1] = pow(2.0,dz->param[SHIFTP_SHF1]);
+		if(dz->param[SHIFTP_SHF1] > 1.0
+		&& round((double)(dz->clength-1)/dz->param[SHIFTP_SHF1]) < fdcno) {
+			sprintf(errstr,"Shift incompatible with frqsplit.\n");
+			return(DATA_ERROR);
+		}
+		if(dz->param[SHIFTP_SHF1] <= 1.0
+		&& round((double)(dz->clength-1)*dz->param[SHIFTP_SHF1]) < fdcno) {
+			sprintf(errstr,"Shift incompatible with frqsplit.\n");
+			return(DATA_ERROR);
+		}
+		break;
+	case(P_SHFT_UP):
+		dz->param[SHIFTP_SHF1] *= OCTAVES_PER_SEMITONE;
+		dz->param[SHIFTP_SHF1] = pow(2.0,dz->param[SHIFTP_SHF1]);
+		if(dz->param[SHIFTP_SHF1] > 1.0
+		&& round((double)(dz->clength-1)/dz->param[SHIFTP_SHF1]) < fdcno) {
+			sprintf(errstr,"Shift incompatible with frqsplit.\n");
+			return(DATA_ERROR);
+		}
+		if(dz->param[SHIFTP_SHF1] <= 1.0
+		&& round((double)(dz->clength-1)*dz->param[SHIFTP_SHF1]) <= fdcno) {
+			sprintf(errstr,"Shift incompatible with frqsplit.\n");
+			return(DATA_ERROR);
+		}
+		break;
+	}
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN buffers.c ***********************************/
+/********************************************************************************************/
+
+/**************************** ALLOCATE_LARGE_BUFFERS ******************************/
+
+int allocate_large_buffers(dataptr dz)
+{
+	switch(dz->process) {
+	case(ALT):		case(OCT):		case(SHIFTP):	
+	case(TUNE):		case(PICK):		case(MULTRANS):	
+	case(CHORD):
+		return allocate_single_buffer(dz);
+	}
+	sprintf(errstr,"Unknown program no. in allocate_large_buffers()\n");
+	return(PROGRAM_ERROR);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN cmdline.c ***********************************/
+/********************************************************************************************/
+
+int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
+{
+	if     (!strcmp(prog_identifier_from_cmdline,"altharms"))	   	dz->process = ALT;
+	else if(!strcmp(prog_identifier_from_cmdline,"octmove"))	   	dz->process = OCT;
+	else if(!strcmp(prog_identifier_from_cmdline,"transp"))    	    dz->process = SHIFTP;
+	else if(!strcmp(prog_identifier_from_cmdline,"tune"))	   		dz->process = TUNE;
+	else if(!strcmp(prog_identifier_from_cmdline,"pick"))	   		dz->process = PICK;
+	else if(!strcmp(prog_identifier_from_cmdline,"chord"))    		dz->process = MULTRANS;
+	else if(!strcmp(prog_identifier_from_cmdline,"chordf"))	   		dz->process = CHORD;
+	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,
+	"\nPITCH OPERATIONS ON A SPECTRAL FILE\n\n"
+	"USAGE: pitch NAME (mode) infile outfile parameters: \n"
+	"\n"
+	"where NAME can be any one of\n"
+	"\n"
+	"altharms    octmove    transp    tune    pick    chordf    chord\n\n"
+	"Type 'pitch altharms' for more info on pitch altharms..ETC.\n");
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE2 ********************************/
+
+int usage2(char *str)
+{
+	if(!strcmp(str,"altharms")) {
+		fprintf(stdout,
+		"pitch altharms mode infile pitchfile outfile [-x]\n"
+		"\n"
+		"DELETE ALTERNATE HARMONICS\n"
+		"\n"
+		"MODES :-\n"
+		"1   delete odd harmonics.\n"
+		"    Usually produces octave up transposition with no formant change.\n"
+		"2   delete even harmonics.\n"
+		"-x  alternative spectral reconstruction.\n\n"
+		"PITCHFILE must be derived from infile\n");
+	} else if(!strcmp(str,"octmove")) {
+		fprintf(stdout,
+		"pitch octmove 1-2 infile pitchfile outfile [-i] transposition\n"
+		"pitch octmove 3   infile pitchfile outfile [-i] transposition bassboost\n"
+		"\n"
+		"OCTAVE TRANSPOSE WITHOUT FORMANT SHIFT\n"
+		"\n"
+		"MODES :-\n"
+		"1   transpose up.\n"
+		"2   transpose down.\n"
+		"3   transpose down, with bass-reinforcement.\n"
+		"\n"
+		"PITCHFILE must be derived from infile.\n"
+		"transposition an integer transposition-ratio: 2 is 8va, 3 is 12th etc.\n"
+		"              as in harmonic series.\n"
+		"bassboost     bass reinforcement: values >=0.0\n"
+		"-i            quicksearch for formants (less accurate).\n"
+		"\n"
+		"bassboost may vary over time.\n");
+	} else if(!strcmp(str,"transp")) {	  /* SHIFTP */
+		fprintf(stdout,
+		"pitch transp 1-3 infile outfile frq_split                     [-ddepth]\n"
+		"pitch transp 4-5 infile outfile frq_split transpos            [-ddepth]\n"
+		"pitch transp 6   infile outfile frq_split transpos1 transpos2 [-ddepth]\n"
+		"\n"
+		"SHIFT PITCH OF (PART OF) SPECTRUM\n"
+		"\n"
+		"MODES :-\n"
+		"1   Octave transpose up, above freq_split.\n"
+		"2   Octave transpose down, below freq_split.\n"
+		"3   Octave transpose up and down.\n"
+		"4   Pitch  transpose up, above freq_split.\n"
+		"5   Pitch  transpose down, below freq_split.\n"
+		"6   Pitch  transpose up and down.\n"
+		"\n"
+		"frq_split is frequency above or below which transposition takes place.\n"
+		"transpos  is transposition above or below freq_split.\n"
+		"transpos1 is transposition above freq_split. (semitones)\n"
+		"transpos2 is transposition below freq_split. (semitones)\n"
+		"depth     transposition effect on source (from 0(no effect) to 1(full effect))\n"
+		"\n"
+		"depth,frq_split,transpos1 & transpos2 can vary over time.\n");
+	} else if(!strcmp(str,"tune")) {
+		fprintf(stdout,
+		"pitch tune mode infile outfile pitch_template\n"
+		"               [-ffocus] [-cclarity] [-ttrace] [-bbcut] \n"
+		"\n"
+		"REPLACE SPECTRAL FRQS BY HARMONICS OF SPECIFIED PITCH(ES)\n"
+		"\n"
+		"MODES :-\n"
+		"1   enter pitch_template data as frq (in Hz).\n"
+		"2   enter pitch_template data as (possibly fractional) MIDI values.\n"
+		"\n"
+		"pitch_template   a value, or a textfile containing values (as hz or midi).\n"
+		"\n"
+		"-f  FOCUS determines degree of focusing of partial pitches onto template.\n"
+	    "    (range 0-1: val or brkpnt file: default 1).\n"
+		"-c  CLARITY determines degree to which non-template partials are suppressed.\n"
+	    "    (range 0-1: val or brkpnt file: default 0).\n"
+		"-t  TRACE specifies no. of (window_by_window) most prominent channels\n"
+		"    to be replaced by template frqs.\n"
+		"-b  Ignore frqs below BCUT, Bass cutoff frq.\n"
+		"\n"
+		"All parameters may vary over time.\n");
+	} else if(!strcmp(str,"pick")) {
+		fprintf(stdout,
+		"pitch pick 1-3 infile outfile fundamental         [-cclarity]\n"
+		"pitch pick 4-5 infile outfile fundamental frqstep [-cclarity]\n"
+		"\n"
+		"ONLY RETAIN CHANNELS WHICH MIGHT HOLD SPECIFIED PARTIALS\n"
+		"\n"
+		"MODES :-\n"
+		"1   Harmonic Series.\n"
+		"2   Octaves.\n"
+		"3   Odd partials of harmonic series only.\n"
+		"4   Partials are successive linear steps (each of frqstep) from 'fundamental'.\n"
+		"5   Add linear displacement (frqstep) to harmonic partials over fundamental.\n"
+		"\n"
+		"fundamental  Fundamental frequency of harmonic series, (or of calculation).\n"
+		"frqstep      Frequency step to be added to another frequency.\n"
+		"clarity      extent to which data in other channels is suppressed.\n"
+	    "             Range 0-1: Default 1.\n"
+		"\n"
+		"clarity may vary over time.\n");
+	} else if(!strcmp(str,"chordf")) {
+		fprintf(stdout,
+		"pitch chordf infile outfile -fN|-pN [-i] transpose_file [-bbot] [-ttop] [-x]\n"
+		"\n"
+		"TRANSPOSED VERSIONS OF SPECTRUM SUPERIMPOSED WITHIN EXISTING SPECTRAL ENVELOPE\n"
+		"\n"
+		"-f   extract spectral envelope linear-freqwise, using N chans per point.\n"
+		"-p   extract spectral envelope linear-pitchwise, using N bands per octave.\n"
+		"     (recommeded value 1.0)\n"
+		"-i   quicksearch for formants (less accurate).\n"
+		"\n"
+		"transpose_file is file of (possibly fractional) semitone transposition values.\n"
+		"\n"
+		"-b   BOT = bottom frq, below which data is filtered out.\n"
+		"-t   TOP = top frq, above which data is filtered out.\n"
+		"-x   Fuller spectrum.\n"
+		"\n"
+		"top frq and bottom frq may vary over time.\n"
+		"\n");
+	} else if(!strcmp(str,"chord")) {
+		fprintf(stdout,
+		"pitch chord infile outfile transpose_file [-bbot] [-ttop] [-x]\n"
+		"\n"
+		"TRANSPOSED VERSIONS OF SOUND SUPERIMPOSED ON ORIGINAL\n"
+		"\n"
+		"transpose_file is file of (possibly fractional) semitone transposition values.\n"
+		"\n"
+		"-t   TOP = top frq, above which data is filtered out.\n"
+		"-b   BOT = bottom frq, below which data is filtered out.\n"
+		"-x   Fuller spectrum.\n"
+		"\n"
+		"top frq and bottom frq may vary over time.\n"
+		"\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);
+}
+

+ 242 - 0
dev/pitch/main.c

@@ -0,0 +1,242 @@
+/*
+ * 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 <pitch.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->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);
+}
+

+ 571 - 0
dev/pitch/pitch.c

@@ -0,0 +1,571 @@
+/*
+ * 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 <pnames.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <globcon.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <flags.h>
+#include <pitch.h>
+#include <cdpmain.h>
+#include <formants.h>
+#include <speccon.h>
+#include <sfsys.h>
+#include <pitch.h>
+#include <memory.h>
+
+static int  do_spectral_shiftp(dataptr dz);
+static int  replace_partial_by_tuned_partial(int cc,int vc,dataptr dz);
+static int  focus_partial_towards_tuned_value(int vc, int cc,dataptr dz);
+static int  gotnewfrq(int *newvc,int vc,double *thisamp,double *thisfrq, double thisspecamp,int n, dataptr dz);
+static int  gotnewfrq2(int *newvc,int vc,double *thisamp,double *thisfrq,int n, dataptr dz);
+static int  remove_unwanted_frq_areas(double lofrq_limit,double hifrq_limit,dataptr dz);
+
+/********************************** SPECALT **********************************/
+ 
+int specalt(int *pitchcnt,dataptr dz)
+{
+	int n = 1, cc, vc;
+	int exit_status;				/* RWD: for specbare() retval ! */
+	double pitch;
+	if((exit_status = specbare(pitchcnt,dz))<0)		 
+		return exit_status;
+	(*pitchcnt)--;
+	pitch = dz->pitches[(*pitchcnt)++];
+	if(pitch < 0.0)				/*   UNPITCHED WINDOW : IGNORE */
+		return(FINISHED);
+	switch(dz->mode) {
+	case(DELETE_ODD):
+		for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
+			if(dz->flbufptr[0][vc]>0.0) {
+				if(ODD(n))
+					dz->flbufptr[0][vc] = 0.0F;
+				n++;
+			}
+		}
+		break;
+	case(DELETE_EVEN):
+		for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2)  {
+			if(dz->flbufptr[0][vc]>0.0) {
+				if(EVEN(n))
+					dz->flbufptr[0][vc] = 0.0F;
+				n++;
+			}
+		}
+		break;
+	default:
+		sprintf(errstr,"Invalid option in specalt()\n");
+		return(PROGRAM_ERROR);
+	break;
+	}
+	return(FINISHED);
+}
+
+
+/**************************** SPECOCT ****************************
+ *
+ * (1)	TRANSPOSE UPWARDS.
+ *		(a)	Delete all channels that are NOT harmonics.
+ *		(b)	Delete all harmonics that are not EVEN (or *3 or *4 etc) harmonics.
+ * (2)	TRANSPOSE DOWNWARDS.
+ *		Insert harmonics below and between the original fundamental and harmonics.
+ */
+ 	
+int specoct(dataptr dz)
+{
+	int exit_status;
+	double pre_totalamp, post_totalamp, thisfrq, basefrq, baseamp, thisamp;
+	int n, specenvcnt, vc, truecc, truevc;
+	if((thisfrq = dz->pitches[dz->total_windows]) <= 0.0)
+		return(FINISHED);
+	if((exit_status = get_totalamp(&pre_totalamp,dz->flbufptr[0],dz->wanted))<0)
+		return(exit_status);
+	switch(dz->mode) {
+	case(OCT_UP):		/* UPWARDS: DELETING ALTERNATE HARMONICS */
+		thisfrq *= (double)dz->iparam[OCT_HMOVE];
+		for(vc = 0; vc < dz->wanted; vc += 2) {
+			if((exit_status = is_harmonic(&n,(double)dz->flbufptr[0][FREQ],thisfrq))<0)
+				return(exit_status);
+			if(exit_status==FALSE)
+				dz->flbufptr[0][AMPP] = 0.0f;
+		}
+		break;
+	case(OCT_DN):		/* DNWARDS: INSERT INTERVENING HARMONICS */
+	case(OCT_DN_BASS):	/* DITTO WITH BASS REINFORCE */
+		if((exit_status = extract_specenv_over_partials(&specenvcnt,thisfrq,0,dz))<0)
+			return(exit_status);
+		basefrq = thisfrq/(double)dz->iparam[OCT_HMOVE];
+		if((exit_status = getspecenvamp(&baseamp,basefrq,0,dz))<0)
+			return(exit_status);
+		thisfrq = basefrq;
+		n = 1;
+		while(thisfrq < dz->nyquist) {
+			if((exit_status = get_channel_corresponding_to_frq(&truecc,thisfrq,dz))<0)
+				return(exit_status);
+			truevc = truecc * 2;
+			if(dz->mode==OCT_DN_BASS && (thisfrq < basefrq))
+				dz->flbufptr[0][truevc] = 
+				(float)(dz->param[OCT_BREI] - ((dz->param[OCT_BREI] - 1.0)*((double)n/(double)dz->iparam[OCT_HMOVE])));
+			else {
+				if((exit_status = getspecenvamp(&thisamp,thisfrq,0,dz))<0)
+					return(exit_status);
+				dz->flbufptr[0][truevc] = (float)thisamp;
+			}
+			truevc++;
+			dz->flbufptr[0][truevc]   = (float)thisfrq;
+			do {
+				n++;
+			} while(n%dz->iparam[OCT_HMOVE]==0);
+			thisfrq = basefrq * (double)n;
+		}
+		break;
+	default:
+		sprintf(errstr,"Unknown mode in specoct()\n");
+		return(PROGRAM_ERROR);
+	}					/* NORMALISE */
+	if((exit_status = get_totalamp(&post_totalamp,dz->flbufptr[0],dz->wanted))<0)
+		return(exit_status);
+	return normalise(pre_totalamp,post_totalamp,dz);
+}														 
+
+/****************************** SPECSHIFTP ****************************
+ *
+ * transpose (part of) spectrum.
+ */
+
+int specshiftp(dataptr dz)
+{
+	int exit_status;
+	if(dz->vflag[SHP_IS_DEPTH] && flteq(dz->param[SHIFTP_DEPTH],0.0))
+		return(FINISHED);
+	if(dz->brksize[SHIFTP_FFRQ] || dz->brksize[SHIFTP_SHF1] || dz->brksize[SHIFTP_SHF2]) {
+		convert_shiftp_vals(dz);
+		if((exit_status = adjust_params_and_setup_internal_params_for_shiftp(dz))<0)
+			return(exit_status);
+	}
+	if((exit_status = get_amp_and_frq(dz->flbufptr[0],dz))<0)
+		return(exit_status);		
+	if(dz->vflag[SHP_IS_DEPTH])  {
+		if((exit_status = reset_shiftps_according_to_depth_value(dz))<0)
+			return(exit_status);
+	}
+	if((exit_status = do_spectral_shiftp(dz))<0)
+		return(exit_status);
+	if((exit_status = put_amp_and_frq(dz->flbufptr[0],dz))<0)
+		return(exit_status);
+	return(FINISHED);
+}
+
+/************************ DO_SPECTRAL_SHIFTP **********************/
+
+int do_spectral_shiftp(dataptr dz)
+{
+	double shft = dz->param[SHIFTP_NS1];
+	int   j, k, kk;
+	switch(dz->mode)  {
+	case(P_OCT_UP):	 /* MOVE SPECTRUM, above fdcno, UP AN OCTAVE */
+	case(P_OCT_UP_AND_DN):
+		k = dz->iparam[SHIFTP_FDCNO]*2;
+		for(j = dz->clength-1; j>= k; j += -2) {
+			dz->amp[j]    = dz->amp[j/2];
+			dz->freq[j]   = (float)(2.0 * dz->freq[j/2]);
+			dz->amp[j-1]  = 0.0f;
+			dz->freq[j-1] = 0.0f;
+		}
+		for(j = dz->iparam[SHIFTP_FDCNO]; j<k; j++) {
+			dz->amp[j]    = 0.0f;
+			dz->freq[j]   = 0.0f;
+		}
+		if(dz->mode==P_OCT_UP)	
+	    		break;
+  	case(P_OCT_DN):	 /* MOVE SPECTRUM, below fdcno, DOWN AN OCTAVE */
+		kk = dz->iparam[SHIFTP_FDCNO]-1;
+		j = round((double)kk/2.0);
+		if( kk != (2*j))
+			kk = kk-1;
+		for(j = 0; j <= kk; j += 2) {
+			k = j/2;	
+			dz->amp[k]    = dz->amp[j];
+			dz->freq[k]   = (float)(dz->freq[j]/2.0);
+			dz->amp[k+1]  = 0.0f;
+			dz->freq[k+1] = 0.0f;
+		}
+		kk = kk/2;
+		kk = kk+2;
+		for(j = kk; j<dz->iparam[SHIFTP_FDCNO]; j++) {
+			dz->amp[j]  = 0.0f;
+			dz->freq[j] = 0.0f;
+		}
+		break;
+	case(P_SHFT_UP):	 /* MOVE SPECTRUM, above fdcno, UP BY SHIFT */
+	case(P_SHFT_UP_AND_DN):
+		if( shft > 1.0) {
+			j = dz->clength-1;
+			k  = round((double)j/shft);
+			while( k >= dz->iparam[SHIFTP_FDCNO]) {
+				dz->amp[j]  = dz->amp[k];
+				dz->freq[j] = (float)(shft * dz->freq[k]);
+				j-- ;
+				k  = round((double)j/shft);
+			}
+			for( k=j; k>dz->iparam[SHIFTP_FDCNO];k-- ) {
+				dz->amp[k]  = 0.0f;
+				dz->freq[k] = 0.0f;
+			}				
+		} else {
+			j = dz->iparam[SHIFTP_FDCNO];
+			k  = round((double)j/shft);
+			while( k <= (dz->clength-1)) {
+				dz->amp[j]  = dz->amp[k];
+				dz->freq[j] = (float)(shft * dz->freq[k]);
+				j++ ;
+				k  = round((double)j/shft);
+			}
+			for( k=j; k<dz->clength; k++ ) {
+				dz->amp[k]  = 0.0f;
+				dz->freq[k] = 0.0f;
+			}				
+		}
+		if(dz->mode==P_SHFT_UP)
+			break;
+		else
+			shft = dz->param[SHIFTP_NS2];
+	case(P_SHFT_DN):   /* MOVE SPECTRUM, below fdcno, DOWN BY SHIFT */
+		if( shft > 1.0) {
+			j = dz->iparam[SHIFTP_FDCNO]-1; 
+			k = round((double)j/shft);
+			while( k > 0) {
+				dz->amp[j]  = dz->amp[k];
+				dz->freq[j] = (float)(shft * dz->freq[k]);
+				j-- ;
+				k = round((double)j/shft);
+			}
+			for( k=j; k>0 ;k-- ) {
+				dz->amp[k]  = 0.0f;	  /* AMP AND FREQ AT 0 Hz ARE RETAINED */
+				dz->freq[k] = 0.0f;
+			}				
+		} else {
+			j = 1;
+			k = round((double)j/shft);
+			while( k <= dz->iparam[SHIFTP_FDCNO]-1) {
+				dz->amp[j]  = dz->amp[k];
+				dz->freq[j] = (float)(shft * dz->freq[k]);
+				j++ ;
+				k = round((double)j/shft);
+			}
+			for( k=j; k<dz->iparam[SHIFTP_FDCNO]; k++ ) {
+				dz->amp[k]  = 0.0f;
+				dz->freq[k] = 0.0f;
+			}				
+		}
+		break;
+	default:
+		sprintf(errstr,"unknown mode in do_spectral_shiftp()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/**********************************  SPECTUNE ********************************/
+
+int spectune(dataptr dz)
+{
+	int exit_status;
+	chvptr loudest;
+	int cc, vc;
+	if(dz->vflag[TUNE_FBOT]) {
+		for(cc = 0, vc = 0; vc < dz->wanted; cc++, vc += 2) {
+			if(dz->flbufptr[0][FREQ] < dz->param[TUNE_BFRQ])
+				dz->flbufptr[0][AMPP] = 0.0f;
+		}
+	}
+	if(dz->vflag[TUNE_TRACE]) {
+		if((exit_status = initialise_ring_vals(dz->iparam[TUNE_INDX],-1.0,dz))<0)
+			return(exit_status);
+		for(cc = 0, vc = 0; vc < dz->wanted; cc++, vc += 2) {
+			if((exit_status = if_one_of_loudest_chans_store_in_ring(vc,dz))<0)
+				return(exit_status);
+		}
+
+		memset((char *)(dz->iparray[TUNE_LOUD]),0,dz->clength * sizeof(int));
+		loudest = dz->ringhead;
+		do {
+			dz->iparray[TUNE_LOUD][loudest->loc] = 1;
+		}  while((loudest = loudest->next)!=dz->ringhead);
+		for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
+			if(dz->iparray[TUNE_LOUD][cc]) {
+				if((exit_status = replace_partial_by_tuned_partial(cc,vc,dz))<0)
+					return(exit_status);
+			} else
+				dz->flbufptr[0][vc] = (float)(dz->flbufptr[0][vc] * dz->param[TUNE_CLAR]);
+		}
+	} else {
+		for(cc = 0, vc = 0; vc < dz->wanted; cc++, vc += 2) {
+			if(dz->frq_template[cc]>0.0) {
+				if((exit_status = focus_partial_towards_tuned_value(FREQ,cc,dz))<0)
+					return(exit_status);
+			} else
+				dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[TUNE_CLAR]);
+		}
+	}
+	return(FINISHED);
+}
+
+/************************** REPLACE_PARTIAL_BY_TUNED_PARTIAL *******************************/
+
+int replace_partial_by_tuned_partial(int cc,int vc,dataptr dz)
+{
+	int exit_status;
+	int aa = cc, bb = cc, here, there;
+	double upratio, dnratio;
+	if(dz->frq_template[cc]>0.0) 						/* if loudchan is a validfrq chan */
+		return focus_partial_towards_tuned_value(FREQ,cc,dz);	
+														/* when loudchan NOT validfrq chan */
+	while(aa>=0 && dz->frq_template[aa]<=0.0)			/* search downwards */
+		aa--;				
+	while(bb<dz->clength && dz->frq_template[bb]<=0.0) 	/* and upwards */
+		bb++;								 			/* for closest validfrq chans */
+	if(aa<0 && bb<dz->clength) {	
+		here = bb*2;					  				/* if none below, use one above */
+		aa   = bb;
+	} else if(bb>=dz->clength && aa>=0) {				/* if none above, use one below */
+		here  = aa*2;
+	} else {			
+		here  = aa*2;	  								/* otherwise, choose nearest validfrq */
+		there = bb*2;
+		upratio = dz->flbufptr[0][there+1]/dz->flbufptr[0][FREQ];
+		dnratio = dz->flbufptr[0][FREQ]/dz->flbufptr[0][here+1];
+		if(upratio < dnratio) {
+			here = there;
+			aa   = bb;
+		}
+	}				
+	if((exit_status = focus_partial_towards_tuned_value(here+1,aa,dz))<0)
+		return(exit_status);
+	dz->flbufptr[0][here] = dz->flbufptr[0][AMPP];  		/* and gets ampl of nearest loudchan,    */
+	dz->flbufptr[0][AMPP] = 0.0F;	    				/* while actual loudchan is zeroed out.  */
+	return(FINISHED);
+}
+
+/********************************* FOCUS_PARTIAL_TOWARDS_TUNED_VALUE *******************************/
+
+int focus_partial_towards_tuned_value(int vc, int cc,dataptr dz)
+{
+	double frqshift;
+	frqshift  = dz->frq_template[cc] - dz->flbufptr[0][vc];
+	frqshift *= dz->param[TUNE_FOC]; 
+	dz->flbufptr[0][vc] = (float)(dz->flbufptr[0][vc] + frqshift);
+	return(FINISHED);
+}
+
+/****************************** SPECPICK ****************************/
+
+int specpick(dataptr dz)
+{
+	int exit_status;
+	int mask = 1;
+	int cc, vc, bflagno;
+	for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2)  {
+		if((exit_status = choose_bflagno_and_reset_mask_if_ness
+		(&bflagno,cc,&mask,dz->iparam[PICK_LONGPOW2],dz->iparam[PICK_DIVMASK]))<0)
+			return(exit_status);
+		if(!(dz->lparray[PICK_BFLG][bflagno] & mask)) 		/* if bit NOT set, modify amplitude */
+			dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[PICK_CLAR]);
+		mask <<= 1;										/* move bitmask upwards */
+	}		
+	return(FINISHED);
+}
+
+/***************************** SPECCHORD2 *********************************/
+
+int specchord2(dataptr dz)
+{
+	int exit_status;
+	int newvc, cc, vc, n;
+	double pre_amptotal, post_amptotal;
+	double thisamp, thisfrq;
+	double hifrq = dz->param[CHORD_HIFRQ];
+	double lofrq = dz->param[CHORD_LOFRQ];
+	if(dz->brksize[CHORD_HIFRQ] || dz->brksize[CHORD_LOFRQ]) {
+		if(hifrq < lofrq)
+			swap(&hifrq,&lofrq);
+	}
+	if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
+		return(exit_status);
+	for(vc = 0; vc < dz->wanted; vc += 2)
+		dz->windowbuf[0][AMPP] = 0.0F;
+	for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
+		for(n=0;n<dz->itemcnt;n++) {	  /* for each note of chord */
+			if((exit_status = gotnewfrq2(&newvc,vc,&thisamp,&thisfrq,n,dz))<0)
+				return(exit_status);
+			if(exit_status==FALSE)
+				continue;
+			switch(dz->vflag[CHORD_BODY]) {
+			case(CHD_LESSFUL):
+				if((exit_status = move_data_into_appropriate_channel(vc,newvc,(float)thisamp,(float)thisfrq,dz))<0)
+					return(exit_status);
+				break;
+			case(CHD_NORMAL):  
+				if((exit_status = move_data_into_some_appropriate_channel(newvc,(float)thisamp,(float)thisfrq,dz))<0)
+					return(exit_status);
+				break;
+			default:
+				sprintf(errstr,"Unknown case in dz->vflag[CHROD_BODY]: specchord()\n");
+				return(PROGRAM_ERROR); 
+			}
+		}
+	}
+	for(vc = 0; vc < dz->wanted; vc+=2)
+		dz->flbufptr[0][AMPP] = dz->windowbuf[0][AMPP];
+	if(dz->vflag[CHORD_FBOT] || dz->vflag[CHORD_FTOP]) {
+		if((exit_status = remove_unwanted_frq_areas(lofrq,hifrq,dz))<0)
+			return(exit_status);
+	}
+	if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
+		return(exit_status);
+	return normalise(pre_amptotal,post_amptotal,dz);
+}
+
+/*************************** GOTNEWFRQ2 *************************/
+
+int gotnewfrq2(int *newvc,int vc,double *thisamp,double *thisfrq,int n, dataptr dz)
+{
+	int newcc;
+	if((*thisfrq = fabs(dz->flbufptr[0][FREQ] * dz->transpos[n])) > dz->nyquist)
+		return(FALSE);
+	*thisamp = dz->flbufptr[0][AMPP];
+	if((newcc  = (int)((*thisfrq + dz->halfchwidth)/dz->chwidth)) >= dz->clength) /* TRUNCATE */
+		return(FALSE);
+	*newvc = newcc * 2; 
+	return(TRUE);
+}
+
+/************************* REMOVE_UNWANTED_FRQ_AREAS ***************************/
+
+int remove_unwanted_frq_areas(double lofrq_limit,double hifrq_limit,dataptr dz)
+{
+	int cc, vc;
+	if(dz->vflag[CHORD_FBOT]) {
+		if(dz->vflag[CHORD_FTOP]) {
+			for(cc = 0,vc = 0; cc < dz->clength; cc++, vc += 2) {
+				if(dz->flbufptr[0][FREQ] < lofrq_limit || dz->flbufptr[0][FREQ] > hifrq_limit)
+					dz->flbufptr[0][AMPP] = 0.0f;
+			}
+		} else {
+			for(cc = 0,vc = 0; cc < dz->clength; cc++, vc += 2) {
+				if(dz->flbufptr[0][FREQ] < lofrq_limit)
+					dz->flbufptr[0][AMPP] = 0.0f;
+			}
+		}
+	} else if(dz->vflag[CHORD_FTOP]) {
+		for(cc = 0,vc = 0; cc < dz->clength; cc++, vc += 2) {
+			if(dz->flbufptr[0][FREQ] > hifrq_limit)
+				dz->flbufptr[0][AMPP] = 0.0f;
+		}
+	}
+	return(FINISHED);
+}
+
+/***************************** SPECCHORD *********************************/
+
+int specchord(dataptr dz)
+{
+	int exit_status;
+	int newvc, cc, vc, n;
+	double pre_amptotal, post_amptotal;
+	double thisamp, thisfrq, thisspecamp;
+	double hifrq = dz->param[CHORD_HIFRQ];
+	double lofrq = dz->param[CHORD_LOFRQ];
+	if(dz->brksize[CHORD_HIFRQ] || dz->brksize[CHORD_LOFRQ]) {
+		if(hifrq < lofrq)
+			swap(&hifrq,&lofrq);
+	}
+	if((exit_status = extract_specenv(0,0,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)
+		dz->windowbuf[0][AMPP] = 0.0F;
+	for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
+		if((exit_status = getspecenvamp(&thisspecamp,(double)dz->flbufptr[0][FREQ],0,dz))<0)
+			return(exit_status);
+		if(thisspecamp < VERY_TINY_VAL)
+			continue;
+		for(n=0;n<dz->itemcnt;n++) {	  /* for each note of chord */
+			if((exit_status = gotnewfrq(&newvc,vc,&thisamp,&thisfrq,thisspecamp,n,dz))<0)
+				return(exit_status);
+			if(exit_status==FALSE)
+				continue;
+			switch(dz->vflag[CHORD_BODY]) {
+			case(CHD_LESSFUL):
+				if((exit_status = move_data_into_appropriate_channel(vc,newvc,(float)thisamp,(float)thisfrq,dz))<0)
+					return(exit_status);
+				break;
+			case(CHD_NORMAL):  
+				if((exit_status = move_data_into_some_appropriate_channel(newvc,(float)thisamp,(float)thisfrq,dz))<0)
+					return(exit_status);
+				break;
+			default:
+				sprintf(errstr,"Unknown case in dz->vflag[CHROD_BODY]: specchord()\n");
+				return(PROGRAM_ERROR); 
+			}
+		}
+	}
+	for(vc = 0; vc < dz->wanted; vc+=2)
+		dz->flbufptr[0][AMPP] = dz->windowbuf[0][AMPP];
+	if(dz->vflag[CHORD_FBOT] || dz->vflag[CHORD_FTOP]) {
+		if((exit_status = remove_unwanted_frq_areas(lofrq,hifrq,dz))<0)
+			return(exit_status);
+	}
+	if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
+		return(exit_status);
+	return normalise(pre_amptotal,post_amptotal,dz);
+}
+
+/*************************** GOTNEWFRQ *************************/
+
+int gotnewfrq(int *newvc,int vc,double *thisamp,double *thisfrq, double thisspecamp,int n, dataptr dz)
+{
+	int exit_status;
+	int newcc;
+	double newspecamp;
+	if((*thisfrq = fabs(dz->flbufptr[0][FREQ] * dz->transpos[n])) > dz->nyquist)
+		return(FALSE);
+	if((exit_status = getspecenvamp(&newspecamp,(double)(*thisfrq),0,dz))<0)
+		return(exit_status);
+	if(newspecamp < VERY_TINY_VAL)
+		return(FALSE);
+	if((*thisamp = dz->flbufptr[0][AMPP]*newspecamp/thisspecamp)<VERY_TINY_VAL)
+		return(FALSE);
+	if((newcc  = (int)((*thisfrq + dz->halfchwidth)/dz->chwidth)) >= dz->clength) /* TRUNCATE */
+		return(FALSE);
+	*newvc = newcc * 2; 
+	return(TRUE);
+}

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

+ 528 - 0
dev/pitchinfo/ap_pinfo.c

@@ -0,0 +1,528 @@
+/*
+ * 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 <specpinfo.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_data_for_pwrite(dataptr dz);
+static int	are_pitch_zeros(dataptr dz);
+
+/********************************************************************************************/
+/********************************** FORMERLY IN preprocess.c ********************************/
+/********************************************************************************************/
+
+static int  phear_preprocess(dataptr dz);
+static int  establish_pinfo_internal_param_default_vals(dataptr dz);
+static int  setup_internal_params_for_pwrite(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(P_INFO):     		dz->extra_bufcnt =  0; dz->bptrcnt = 0; 	is_spec = TRUE;		break;
+	case(P_ZEROS):    		dz->extra_bufcnt =  0; dz->bptrcnt = 0; 	is_spec = TRUE;		break;
+	case(P_SEE):      		dz->extra_bufcnt =  0; dz->bufcnt = 1;	 	is_spec = FALSE;	break;
+	case(P_HEAR):     		dz->extra_bufcnt =  3; dz->bptrcnt = 2; 	is_spec = TRUE;		break;
+	case(P_WRITE):    		dz->extra_bufcnt =  0; dz->bptrcnt = 0; 	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(P_INFO):   dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(P_ZEROS):  dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(P_SEE):    dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(P_HEAR): 	dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	case(P_WRITE):  dz->array_cnt =1;  dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0;	break;
+	}
+
+/*** WARNING ***
+ANY APPLICATION DEALING WITH A NUMLIST INPUT: MUST establish AT LEAST 1 double array: i.e. dz->array_cnt = at least 1
+**** WARNING ***/
+
+
+	if(dz->array_cnt < 0 || dz->iarray_cnt < 0 || dz->larray_cnt < 0 || dz->ptr_cnt < 0 || dz->fptr_cnt < 0) {
+		sprintf(errstr,"array_cnt not set in setup_internal_arrays_and_array_pointers()\n");	   
+		return(PROGRAM_ERROR);
+	}
+
+	if(dz->array_cnt > 0) {  
+		if((dz->parray  = (double **)malloc(dz->array_cnt * sizeof(double *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal double arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->array_cnt;n++)
+			dz->parray[n] = NULL;
+	}
+	if(dz->iarray_cnt > 0) {
+		if((dz->iparray = (int     **)malloc(dz->iarray_cnt * sizeof(int *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal int arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->iarray_cnt;n++)
+			dz->iparray[n] = NULL;
+	}
+	if(dz->larray_cnt > 0) {	  
+		if((dz->lparray = (int    **)malloc(dz->larray_cnt * sizeof(int *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal long arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->larray_cnt;n++)
+			dz->lparray[n] = NULL;
+	}
+	if(dz->ptr_cnt > 0)   {  	  
+		if((dz->ptr    	= (double  **)malloc(dz->ptr_cnt  * sizeof(double *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal pointer arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->ptr_cnt;n++)
+			dz->ptr[n] = NULL;
+	}
+	if(dz->fptr_cnt > 0)   {  	  
+		if((dz->fptr = (float  **)malloc(dz->fptr_cnt * sizeof(float *)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for internal float-pointer arrays.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->fptr_cnt;n++)
+			dz->fptr[n] = NULL;
+	}
+	return(FINISHED);
+}
+
+/****************************** ASSIGN_PROCESS_LOGIC *********************************/
+
+int assign_process_logic(dataptr dz)
+{						 
+	switch(dz->process) {
+	case(P_INFO):	  	setup_process_logic(PITCHFILE_ONLY,		  	SCREEN_MESSAGE,		NO_OUTPUTFILE,	dz);	break;
+	case(P_ZEROS):	  	setup_process_logic(PITCHFILE_ONLY,		  	SCREEN_MESSAGE,		NO_OUTPUTFILE,	dz);	break;
+	case(P_SEE):	  	setup_process_logic(PITCH_OR_TRANSPOS,	  	PITCH_TO_PSEUDOSND,	SNDFILE_OUT,	dz);	break;
+	case(P_HEAR):	  	setup_process_logic(PITCHFILE_ONLY,		  	PITCH_TO_ANAL,		ANALFILE_OUT,	dz);	break;
+	case(P_WRITE):	  	setup_process_logic(PITCH_OR_TRANSPOS,	  	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(P_INFO): 	  	exit_status = set_internalparam_data("ddddd",ap);				break;
+	case(P_ZEROS):    	return(FINISHED);
+	case(P_SEE):   	  	return(FINISHED);
+	case(P_HEAR): 	  	return(FINISHED);
+	case(P_WRITE):    	return(FINISHED);
+	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(P_HEAR):	    return phear_preprocess(dz);
+	case(P_INFO):		return establish_pinfo_internal_param_default_vals(dz);	
+	case(P_WRITE):		return setup_internal_params_for_pwrite(dz);
+
+	case(P_ZEROS):	case(P_SEE):		
+		return(FINISHED);
+	default:
+		sprintf(errstr,"PROGRAMMING PROBLEM: Unknown process in param_preprocess()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/************************** PHEAR_PREPROCESS ******************************/
+
+int phear_preprocess(dataptr dz)
+{
+	int exit_status;
+	if((exit_status = establish_testtone_amps(dz))<0)
+		return(exit_status);
+	return establish_bottom_frqs_of_channels(dz);
+}
+
+/********************** ESTABLISH_PINFO_INTERNAL_PARAM_DEFAULT_VALS **********************/
+
+int establish_pinfo_internal_param_default_vals(dataptr dz)
+{
+	dz->param[PINF_MEAN] = 0.0;
+	dz->param[PINF_MAX]  = 0.0;
+	dz->param[PINF_MIN]  = dz->nyquist;
+	return(FINISHED);
+}
+
+/************ SETUP_INTERNAL_PARAMS_FOR_PWRITE *************/
+
+int setup_internal_params_for_pwrite(dataptr dz)
+{
+	dz->param[PW_DRED] /= 12.0;
+	dz->param[PW_DRED] = pow(2.0,dz->param[PW_DRED]);
+	dz->is_sharp = dz->param[PW_DRED];
+	if(dz->is_sharp==0.0) {
+		sprintf(errstr,"param not set in setup_internal_params_for_pwrite()\n");
+		return(PROGRAM_ERROR);
+	}
+	dz->is_flat  = 1.0/dz->is_sharp;
+	return(FINISHED);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN procspec.c **********************************/
+/********************************************************************************************/
+
+/**************************** SPEC_PROCESS_FILE ****************************/
+
+int spec_process_file(dataptr dz)
+{	
+	dz->total_windows = 0;
+
+	switch(dz->process) {
+	case(P_INFO):	return specpinfo(dz);
+	case(P_ZEROS):	return specpinfo(dz);
+	case(P_SEE):	return specpsee(dz);
+	case(P_HEAR):	return specphear(dz);
+	case(P_WRITE):	return specpwrite(dz);
+	default:
+		sprintf(errstr,"Unknown process in spec_process_file()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);	/* NOTREACHED */
+}
+
+/***************************** 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(P_WRITE):	   return check_data_for_pwrite(dz);
+	case(P_SEE):
+		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(P_HEAR):
+		chans = dz->infile->channels;
+		dz->infile->channels = dz->infile->origchans;
+		if((exit_status = create_sized_outfile(dz->wordstor[0],dz))<0)
+			return(exit_status);
+		dz->infile->channels = chans;
+		break;
+	}
+	return(FINISHED);
+}
+
+/************ CHECK_DATA_FOR_PWRITE *************/
+
+int check_data_for_pwrite(dataptr dz)
+{
+	if(dz->is_transpos==FALSE && are_pitch_zeros(dz))
+		return(DATA_ERROR);
+	return(FINISHED);
+}
+
+/************************** ARE_PITCH_ZEROS ************************/
+
+int are_pitch_zeros(dataptr dz)
+{
+	int n;
+   	for(n=0;n<dz->wlength;n++) {
+	    if(dz->pitches[n] < 0.0) {
+ 	        sprintf(errstr,"Input file contains unpitched windows: cannot proceed.\n");
+	     	return(TRUE);
+	    }
+	}
+	return(FALSE);
+}
+
+/********************************************************************************************/
+/********************************** FORMERLY IN buffers.c ***********************************/
+/********************************************************************************************/
+
+/**************************** ALLOCATE_LARGE_BUFFERS ******************************/
+
+int allocate_large_buffers(dataptr dz)
+{
+	switch(dz->process) {
+	case(P_SEE):
+		return create_sndbufs(dz);
+	case(P_HEAR):	
+		return allocate_single_buffer_plus_extra_pointer(dz);
+	case(P_INFO):	case(P_ZEROS):	case(P_WRITE):	
+		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,"info"))     		dz->process = P_INFO;
+	else if(!strcmp(prog_identifier_from_cmdline,"zeros"))    		dz->process = P_ZEROS;
+	else if(!strcmp(prog_identifier_from_cmdline,"see"))  	   		dz->process = P_SEE;
+	else if(!strcmp(prog_identifier_from_cmdline,"hear"))     		dz->process = P_HEAR;
+	else if(!strcmp(prog_identifier_from_cmdline,"convert"))    	dz->process = P_WRITE;
+	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 BINARY PITCH FILE\n\n"
+	"USAGE: pitchinfo NAME infile (outfile) parameters: \n"
+	"\n"
+	"where NAME can be any one of\n"
+	"\n"
+	"info     zeros     see      hear      convert\n\n"
+	"Type 'pitchinfo info' for more info on pitchinfo info..ETC.\n");
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE2 ********************************/
+
+int usage2(char *str)
+{
+	if(!strcmp(str,"info")) {
+		sprintf(errstr,
+    	"pitchinfo info pitchfile\n\n"
+		"DISPLAY INFORMATION ABOUT PITCHDATA IN PITCHFILE.\n\n"
+		"Finds mean pitch, max and min pitch (with timings), as Hz and MIDI.\n"
+		"Also displays total range, in octaves and semitones.\n");
+	} else if(!strcmp(str,"zeros")) {
+		sprintf(errstr,
+    	"pitchinfo zeros pitchfile\n\n"
+		"SHOWS WHETHER PITCHFILE CONTAINS UNINTERPOLATED ZEROS (UNPITCHED WINDOWS).\n");
+	} else if(!strcmp(str,"see")) {
+		fprintf(stdout,
+		"pitchinfo see 1 pitchfile    outsndfile scalefact\n"
+		"pitchinfo see 2 transposfile outsndfile\n\n"
+		"CONVERT BINARY PITCHFILE OR TRANSPOSITION-FILE TO PSEUDO-SNDFILE, FOR VIEWING.\n\n"
+		"MODES....\n"
+		"(1) PITCHFILE is a binary pitchdata file.\n"
+		"    SCALEFACT (> 0.0) multiplies pitch vals, for ease of viewing.\n"
+		"    Pitch data scaled by (e.g.) 100 can be read directly from 'sndfile'\n"
+		"    (Remembering to divide numeric values by 100).\n\n"
+		"(2) TRANSPOSFILE is a binary transposition-data file.\n"
+		"    Transposition data is automatically scaled to half max range,\n"
+		"    And displayed in log format (0 = no transposition, + = up, - = down),\n"
+		"    giving a schematic idea ONLY, of transposition data.\n");
+	} else if(!strcmp(str,"hear")) {
+		sprintf(errstr,
+		"pitchinfo hear pitchfile outfile [-ggain]\n\n"
+		"CONVERT BINARY PITCHFILE TO ANALYSIS TESTTONE FILE.\n"
+		"           (RESYNTHESISE TO HEAR PITCH).\n\n"
+		"-g  gain > 0.0 (default: 1.0)\n");
+	} else if(!strcmp(str,"convert")) {
+		sprintf(errstr,
+		"pitchinfo convert pitchfile outtextfile [-dI]\n\n"
+		"CONVERT A BINARY PITCH-DATAFILE TO A TIME/FRQ BRKPNT TEXTFILE.\n\n"
+		"-d  I = acceptable pitch error in brkpntfile data-reduction. (semitones)\n"
+		"    (Range > 0.0 : Default = eighth_tone = %lf)\n",LOG2(EIGHTH_TONE)*SEMITONES_PER_OCTAVE);
+	} else
+		sprintf(errstr,"Unknown option '%s'\n",str);
+	return(USAGE_ONLY);
+}
+
+/******************************** USAGE3 ********************************/
+
+int usage3(char *str1,char *str2)
+{
+	if(!strcmp(str1,"info"))		
+		return(CONTINUE);
+	else if(!strcmp(str1,"zeros"))
+		return(CONTINUE);
+	else
+		sprintf(errstr,"Insufficient parameters on command line.\n");
+	return(USAGE_ONLY);
+}
+
+

+ 235 - 0
dev/pitchinfo/main.c

@@ -0,0 +1,235 @@
+/*
+ * 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 <specpinfo.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->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);
+}
+

+ 395 - 0
dev/pitchinfo/specpinfo.c

@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
+ * http://www.trevorwishart.co.uk
+ * http://www.composersdesktop.com
+ *
+ This file is part of the CDP System.
+
+    The CDP System is free software; you can redistribute it
+    and/or modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    The CDP System is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with the CDP System; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA
+ *
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <structures.h>
+#include <tkglobals.h>
+#include <pnames.h>
+#include <globcon.h>
+#include <processno.h>
+#include <modeno.h>
+#include <arrays.h>
+#include <specpinfo.h>
+#include <cdpmain.h>
+#include <formants.h>
+#include <speccon.h>
+#include <sfsys.h>
+#include <osbind.h>
+#include <float.h>
+#include <specpinfo.h>
+
+static int  do_specpinfo(dataptr dz);
+static int  specpzeros(dataptr dz);
+static int  prescale_transposition_data(dataptr dz);
+static int  generate_noise_in_buffer(double noischan_amp,dataptr dz);
+static int  generate_tone_in_buffer(double pre_totalamp,double thisfrq,dataptr dz);
+static int  preset_chanfrqs_to_chancentres(dataptr dz);
+static int  construct_screen_message(dataptr dz);
+
+/**************************** SPECPINFO *********************/
+
+int specpinfo(dataptr dz)
+{
+	int exit_status, valid_pitch_data = FALSE;
+	int n;
+	if(dz->is_transpos) {
+		if((dz->transpos = (float *)malloc(dz->wlength * sizeof(float)))==NULL) {
+			sprintf(errstr,"INSUFFICIENT MEMORY for transposition array.\n");
+			return(MEMORY_ERROR);
+		}
+		for(n=0;n<dz->wlength;n++)
+			dz->transpos[n] = 1.0f;	/* DEFAULT: no transposition */
+	}
+	for(n=0;n<dz->wlength;n++) {
+		if(dz->pitches[n] > FLTERR) {
+			valid_pitch_data = 1;
+			break;
+		}
+	}
+	if(!valid_pitch_data) {
+		sprintf(errstr,"No valid pitches found in input data.\n");
+		return(DATA_ERROR);
+	}
+	switch(dz->process) {
+	case(P_INFO): 	  	
+		if((exit_status = do_specpinfo(dz))<0)
+			return(exit_status);
+		break;
+	case(P_ZEROS):	  	
+		if((exit_status = specpzeros(dz))<0)
+			return(exit_status);
+		break;
+	default:
+		sprintf(errstr,"Unknown process in specpinfo()\n");
+		return(PROGRAM_ERROR);
+	}
+	return(FINISHED);
+}
+
+/************************************* DO_SPECPINFO ******************************/
+
+int do_specpinfo(dataptr dz)
+{
+	int exit_status;
+	int n, minpos = -1, maxpos = -1;
+	for(n=0;n<dz->wlength;n++) {
+		if(dz->pitches[n]<MINPITCH)
+			continue;
+		if(dz->pitches[n] > dz->param[PINF_MAX]) {
+			dz->param[PINF_MAX] = dz->pitches[n];
+			maxpos = n;
+		}
+		if(dz->pitches[n] < dz->param[PINF_MIN]) {
+			dz->param[PINF_MIN] = dz->pitches[n];
+			minpos = n;
+		}
+		dz->param[PINF_MEAN] += dz->pitches[n];
+	}
+	dz->param[PINF_MEAN] /= (double)dz->wlength;
+	dz->param[PINF_MAXPOS] = (double)maxpos * dz->frametime;
+	dz->param[PINF_MINPOS] = (double)minpos * dz->frametime;
+	if(maxpos < 0) {
+		sprintf(errstr,"No valid pitch information found.\n");
+		return(GOAL_FAILED);
+	}
+	if(minpos < 0) {
+		sprintf(errstr,"No valid pitch below the nyquist frq found.\n");
+		return(GOAL_FAILED);
+	}
+	if((exit_status = construct_screen_message(dz))<0)
+		return(exit_status);
+	return(FINISHED);
+}
+			
+/***************************** SPECPZEROS *****************/
+
+int specpzeros(dataptr dz)
+{
+	int n;
+	dz->zeroset = FALSE;
+	for(n=0;n<dz->wlength;n++) {
+		if(dz->pitches[n]<MINPITCH) {
+			dz->zeroset = TRUE;
+			break;
+		}
+	}
+	if(dz->zeroset)
+		sprintf(errstr,"File contains unpitched windows.\n");
+	else
+		sprintf(errstr,"File does NOT contain unpitched windows.\n");
+	return(FINISHED);
+}
+	
+/*************************************** SPECPSEE *************************/
+
+int specpsee(dataptr dz)
+{
+	int exit_status;
+	int wc; 
+	double val;
+ 	if(dz->is_transpos) {
+		if((exit_status = prescale_transposition_data(dz))<0)
+			return(exit_status);
+    	for(wc=0;wc<dz->wlength;wc++) {
+			*(dz->sbufptr[0]++) = dz->transpos[wc];
+			if(dz->sbufptr[0] >= dz->sampbuf[1]) {
+				if((exit_status = write_exact_samps(dz->bigbuf,dz->buflen,dz))<0)
+					return(exit_status);
+				dz->sbufptr[0] = dz->bigbuf;
+			} 
+		}
+	} else {
+		for(wc=0;wc<dz->wlength;wc++) {
+			if((val = dz->pitches[wc] * dz->param[PSEE_SCF]) > F_MAXSAMP) {
+				if(!dz->zeroset) {
+					fprintf(stdout,"WARNING: output value(s) too big: truncated.\n");
+					dz->zeroset = TRUE;
+				}
+				val = F_MAXSAMP;
+			}
+			if(val < F_MINSAMP) {
+				if(!dz->zeroset) {
+					fprintf(stdout,"WARNING: output value(s) too small: truncated.\n");
+					dz->zeroset = TRUE;
+				}
+				val = F_MINSAMP;
+			}
+			*(dz->sbufptr[0]++) = (float)val;
+			if(dz->sbufptr[0] >= dz->sampbuf[1]) {
+				if((exit_status = write_exact_samps(dz->bigbuf,dz->buflen,dz))<0)
+					return(exit_status);
+				dz->sbufptr[0] = dz->bigbuf;
+			} 
+		}
+	}
+	if(dz->sbufptr[0] != dz->bigbuf) {
+		if((exit_status = write_samps(dz->bigbuf,dz->sbufptr[0] - dz->bigbuf,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/*************************** PRESCALE_TRANSPOSITION_DATA ********************/
+
+int prescale_transposition_data(dataptr dz)
+{
+	int n;
+	double scalefact;
+	double mintransp = DBL_MAX;
+	double maxtransp = -DBL_MAX;
+	for(n=0;n<dz->wlength;n++) {
+		if(dz->transpos[n] <= 0.0) {
+			sprintf(errstr,"Anomaly in transposition data: prescale_transposition_data()\n");
+			return(PROGRAM_ERROR);
+		} 
+		dz->transpos[n] = (float)log10(dz->transpos[n]);
+		if(dz->transpos[n] < mintransp)
+			mintransp = dz->transpos[n];
+		if(dz->transpos[n] > maxtransp)
+			maxtransp = dz->transpos[n];
+	}
+	maxtransp = max(fabs(maxtransp),fabs(mintransp));
+	scalefact = F_MAXSAMP/2.0/maxtransp;
+	for(n=0;n<dz->wlength;n++)
+		dz->transpos[n] = (float)(dz->transpos[n] * scalefact);
+	return(FINISHED);
+}
+
+/************************* SPECPHEAR *************************/
+
+int specphear(dataptr dz)
+{
+#define WINDOW_AMP 		(0.50)	/* AVOID OVERLOAD */
+
+	int exit_status;
+	double pre_totalamp, noischan_amp;
+	double thisfrq;
+	int n = 0;
+	int vc;
+	pre_totalamp = WINDOW_AMP * dz->param[PH_GAIN];
+
+	noischan_amp = pre_totalamp/(double)dz->clength;
+	memset((char *)dz->bigfbuf,0,(size_t)(dz->big_fsize * sizeof(float)));
+	dz->flbufptr[0] = dz->bigfbuf;
+	dz->infile->channels = dz->infile->origchans;	/* setup channel count for outfile */
+	dz->wanted  = dz->infile->channels;
+
+	while(n < dz->wlength) {
+		thisfrq = (double)dz->pitches[n];
+		if(thisfrq < 0.0) {		/* NO PITCH FOUND : GENERATE NOISE */
+			if((exit_status = generate_noise_in_buffer(noischan_amp,dz))<0)
+				return(exit_status);
+		} else {				/* GENERATE TESTTONE AT FOUND PITCH */
+			if((exit_status = preset_chanfrqs_to_chancentres(dz))<0)
+				return(exit_status);
+			if((exit_status = generate_tone_in_buffer(pre_totalamp,thisfrq,dz))<0)
+				return(exit_status);
+		}
+		if(n==0) {
+			for(vc = 0; vc < dz->wanted ; vc += 2)
+			dz->flbufptr[0][AMPP] = 0.0f;
+		}			
+		if((dz->flbufptr[0] += dz->wanted) >= dz->flbufptr[1]) {
+			if((exit_status = write_exact_samps(dz->bigfbuf,dz->big_fsize,dz))<0)
+				return(exit_status);
+			memset((char *)dz->bigfbuf,0,(size_t)(dz->big_fsize * sizeof(float)));
+			dz->flbufptr[0] = dz->bigfbuf;
+		}
+		n++;
+	}
+	if(dz->flbufptr[0] != dz->bigfbuf) {
+		if((exit_status = write_samps(dz->bigfbuf,dz->flbufptr[0] - dz->bigfbuf,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/*************************** GENERATE_NOISE_IN_BUFFER *********************/
+
+int generate_noise_in_buffer(double noischan_amp,dataptr dz)
+{
+	int cc, vc;	
+	dz->flbufptr[0][0] = (float)noischan_amp;
+	dz->flbufptr[0][1] = (float)(drand48() * dz->halfchwidth);
+	for(cc = 1, vc = 2; cc < dz->clength-1; cc++, vc += 2) {
+		dz->flbufptr[0][FREQ] = (float)((drand48() * dz->chwidth) + dz->windowbuf[CHBOT][cc]);
+		dz->flbufptr[0][AMPP] = (float)noischan_amp;
+	}
+	dz->flbufptr[0][FREQ] = (float)((drand48() * dz->halfchwidth) + dz->windowbuf[CHBOT][cc]);
+	dz->flbufptr[0][AMPP] = (float)noischan_amp;
+	return(FINISHED);
+}
+
+/********************** GENERATE_TONE_IN_BUFFER ***************************/
+
+int generate_tone_in_buffer(double pre_totalamp,double thisfrq,dataptr dz)
+{
+	int exit_status;
+	int cc, vc, m, ampadjusted = 0;
+	int lastvc = -1;
+	double post_totalamp;
+	for(m=0;m<PARTIALS_IN_TEST_TONE;m++) {
+		cc = (int)((thisfrq + dz->halfchwidth)/dz->chwidth); 	/* TRUNCATE */
+		vc = cc * 2;
+		if(vc != lastvc) { /* AVOID OVERWRITING ALREADY GENERATED LOWER PARTIALS */
+			dz->flbufptr[0][AMPP] = dz->windowbuf[TESTPAMP][m];
+			dz->flbufptr[0][FREQ] = (float)thisfrq;
+		}
+		lastvc = vc;
+		if((thisfrq = thisfrq * 2.0) > dz->nyquist) {
+			post_totalamp = (double)dz->windowbuf[TOTPAMP][m];
+
+					  /* THIS NORMALISATION DOESN'T QUITE WORK */
+			if((exit_status = normalise(pre_totalamp,post_totalamp,dz))<0)
+				return(exit_status);
+			ampadjusted = 1; /* IF PITCH IS LESS THAN CHAN SPACING */
+			break;	   /* BUT THAT'S MINOR AESTHETIC QUIBBLE ONLY */
+		}
+	}
+	if(!ampadjusted) {
+		post_totalamp = (double)dz->windowbuf[TOTPAMP][PARTIALS_IN_TEST_TONE-1];
+		if((exit_status = normalise(pre_totalamp,post_totalamp,dz))<0)
+			return(exit_status);
+	}
+	return(FINISHED);
+}
+
+/**************************** PRESET_CHANFRQS_TO_CHANCENTRES **********************
+ *
+ * Preset all frqs to centre of channels.
+ */
+
+int preset_chanfrqs_to_chancentres(dataptr dz)
+{
+	int cc, vc;	
+	dz->flbufptr[0][1] = (float)(dz->halfchwidth/2.0);
+	for(cc = 1, vc = 2; cc < dz->clength-1; cc++, vc += 2)
+		dz->flbufptr[0][FREQ] = (float)(dz->windowbuf[CHBOT][cc] + dz->halfchwidth);
+	dz->flbufptr[0][FREQ]=(float)(dz->windowbuf[CHBOT][dz->clength-1]+(dz->halfchwidth/2.0));
+	return(FINISHED);
+}
+
+/****************************** SPECPWRITE *********************************/
+
+int specpwrite(dataptr dz)
+{
+	int exit_status;
+	int brkcnt;
+	if((dz->parray[PW_BRK] = (double *)malloc(dz->wlength * 2 * sizeof(double)))==NULL) {
+		sprintf(errstr,"INSUFFICIENT MEMORY for pitch brkpnt array.\n");
+		return(MEMORY_ERROR);
+	}
+	if(dz->is_transpos)	{
+		if((exit_status = convert_pch_or_transpos_data_to_brkpnttable(&brkcnt,dz->transpos,dz->frametime,PW_BRK,dz))<0)
+			return(exit_status);
+	} else {
+		if((exit_status = convert_pch_or_transpos_data_to_brkpnttable(&brkcnt,dz->pitches,dz->frametime,PW_BRK,dz))<0)
+			return(exit_status);
+	}
+	return write_brkfile(dz->fp,brkcnt,PW_BRK,dz);
+}
+    
+/****************************** CONSTRUCT_SCREEN_MESSAGE *********************************/
+
+int construct_screen_message(dataptr dz)
+{
+	int exit_status;
+	int oct = 0;
+	double z1, z2, z3, z4, z5;
+	if((exit_status = hztomidi(&z1,dz->param[PINF_MAX]))<0)
+		return(exit_status);
+	if((exit_status = hztomidi(&z2,dz->param[PINF_MIN]))<0)
+		return(exit_status);
+	if((exit_status = hztomidi(&z3,dz->param[PINF_MEAN]))<0)
+		return(exit_status);
+	if((exit_status = hztomidi(&z4,dz->param[PINF_MAX]))<0)
+		return(exit_status);
+	if((exit_status = hztomidi(&z5,dz->param[PINF_MIN]))<0)
+		return(exit_status);
+	z4 -= z5;
+	if(z4 > 12.0)  {
+		oct = (int)(z4/12.0); /* TRUNCATE */
+		z4  -= (double)(oct * 12);
+	}
+	if(oct > 0)	{
+		sprintf(errstr,"MAX PITCH : %.2lfHZ\tMIDI : %.2lf\tTIME %.2lf\n"			
+				"MIN PITCH : %.2lfHZ\tMIDI : %.2lf\tTIME %.2lf\n"			
+				"MEAN PITCH: %.2lfHZ\tMIDI : %.2lf\n\n"			
+				"TOTAL RANGE: %d OCTAVES and %.2lf SEMITONES\n",
+				dz->param[PINF_MAX],z1,dz->param[PINF_MAXPOS],dz->param[PINF_MIN],z2,dz->param[PINF_MINPOS],
+				dz->param[PINF_MEAN],z3, oct, z4);			
+	} else {
+		sprintf(errstr,"MAX PITCH : %.2lfHZ\tMIDI : %.2lf\tTIME %.2lf\n"			
+				"MIN PITCH : %.2lfHZ\tMIDI : %.2lf\tTIME %.2lf\n"			
+				"MEAN PITCH: %.2lfHZ\tMIDI : %.2lf\n\n"			
+				"TOTAL RANGE: %.2lf SEMITONES\n",
+				dz->param[PINF_MAX],z1,dz->param[PINF_MAXPOS],dz->param[PINF_MIN],z2,dz->param[PINF_MINPOS],
+				dz->param[PINF_MEAN],z3,z4);			
+	}
+	return(FINISHED);
+}