|
|
@@ -0,0 +1,2117 @@
|
|
|
+/*
|
|
|
+ * 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 <string.h>
|
|
|
+#include <memory.h>
|
|
|
+#include <sfsys.h>
|
|
|
+#include <osbind.h>
|
|
|
+#include <ctype.h>
|
|
|
+#include <structures.h>
|
|
|
+#include <pnames.h>
|
|
|
+#include <processno.h>
|
|
|
+#include <flags.h>
|
|
|
+#include <modeno.h>
|
|
|
+#include <cdpmain.h>
|
|
|
+#include <globcon.h>
|
|
|
+#include <tkglobals.h>
|
|
|
+#include <logic.h>
|
|
|
+#include <math.h>
|
|
|
+#include <hfperm.h>
|
|
|
+
|
|
|
+#if defined unix || defined __GNUC__
|
|
|
+#define round(x) lround((x))
|
|
|
+#endif
|
|
|
+
|
|
|
+#define BY_STACKING (0)
|
|
|
+#define BY_DENSITY (1)
|
|
|
+
|
|
|
+#define SMALLEST_FIRST (0)
|
|
|
+#define LARGEST_FIRST (1)
|
|
|
+
|
|
|
+#define ROOT (0)
|
|
|
+#define TOPNOTE (1)
|
|
|
+
|
|
|
+#define KEEP_OCT_EQUIVS (0)
|
|
|
+#define ELIMINATE_OCT_EQUIVS (1)
|
|
|
+
|
|
|
+#define ROLLOFF (0.66)
|
|
|
+
|
|
|
+static int generate_perms(double ***combo,int **combolen,int *combocnt,dataptr dz);
|
|
|
+static int set_element(int element_no,int total_elements,int field_cnt,int *element,
|
|
|
+ double ***combo,int **combolen,int *combocnt);
|
|
|
+static int store_combo(double ***combo,int *combocnt,int **combolen,int *element,int total_elements);
|
|
|
+static void substitute_midivals_in_perms(double **combo,int *combolen,int combocnt,dataptr dz);
|
|
|
+static int generate_hfsets(int combocnt,double **combo,int *combolen,
|
|
|
+ double ***hfset,int **hfsetlen,int *hfsetcnt,dataptr dz);
|
|
|
+static int transpose_element(int element_no,double *thiscombo,int thiscombolen,double *origval,
|
|
|
+ double ***hfset,int **hfsetlen,int *hfsetcnt,dataptr dz);
|
|
|
+static int store_transposition(double ***hfset,int **hfsetlen,int *hfsetcnt,double *thiscombo,int thiscombolen);
|
|
|
+static int sort_hfsets(double **hfset,int *hfsetlen,int *hfsetcnt,int *grping,dataptr dz);
|
|
|
+static int gen_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz);
|
|
|
+static int gen_outputs(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz);
|
|
|
+static int gen_text_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz);
|
|
|
+static int gen_midi_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz);
|
|
|
+static void print_grouping_structure(int n,int *grping,int *grping_cnt,int *in_grp,int hfsetcnt);
|
|
|
+static void printout_grouping_structure(int n,int *grping,int *grping_cnt,int *in_grp,int hfsetcnt,dataptr dz);
|
|
|
+static void set_pitch_to_print(int midi);
|
|
|
+static void set_midi_to_print(int midi);
|
|
|
+static void print_pitchset(void);
|
|
|
+static void printout_pitchset(dataptr dz);
|
|
|
+static int sort_by_chord(double **hfset,int *hfsetlen,double *intv,int *hfsetcnt,int *grping,dataptr dz);
|
|
|
+static int sort_by_pitchclass_equivalence
|
|
|
+ (double **hfset,int *hfsetlen,double *pich,int hfsetcnt,int *grping,int *intcnt,
|
|
|
+ double *intv,int *intvcnt,double *intv2,int *intvcnt2,dataptr dz);
|
|
|
+static int sort_by_reference_note_equivalence
|
|
|
+ (double **hfset,int *hfsetlen,int hfsetcnt,int *grping,dataptr dz);
|
|
|
+static void sort_by_maxint(double **hfset,int n,int m,int setlen,dataptr dz);
|
|
|
+static void sort_by_density(double **hfset,int n,int m,int setlen,int lowest);
|
|
|
+static void sort_by_density_regardless_of_size
|
|
|
+ (double **hfset,double *intv,int *intcnt,double *intv2,int *intcnt2,int n,int m,int setlen,int densest_first);
|
|
|
+static void sort_by_maxintsize_and_density(double **hfset,int n,int m,int setlen,int lowest);
|
|
|
+static void sort_by_octave_equivalence(double **hfset,int n,int m,int setlen);
|
|
|
+static void sort_by_interval_stacking(double **hfset,int n,int m,int setlen,int highest_first);
|
|
|
+static void eliminate_oct_duplicated_sets(double **hfset,int *hfsetcnt,int *hfsetlen,int *grping,int *grping_cnt,int type);
|
|
|
+static int setup_naming(char **thisfilename,dataptr dz);
|
|
|
+static int create_outfile_name(int ccnt,char *thisfilename,dataptr dz);
|
|
|
+static void gen_note(int maxjitter,double *tabstart,double *tabend,double **tabmin, double **tabmax,double **hfset,
|
|
|
+ double tabscale,double sintabsize,int splicelen, double *sintab,int n, int j);
|
|
|
+int next_file(int *samps_written,char *thisfilename,int *ccnt,unsigned int *space_needed,
|
|
|
+ int *samp_space_available, dataptr dz);
|
|
|
+static void gen_note2(double *tabstart,double *tabend,double midival,
|
|
|
+ double tabscale,double sintabsize,int splicelen, double *sintab);
|
|
|
+//static void gen_note3(double *tabstart,double *tabend,double midival,int tabsize,int splicelen, short *intab);
|
|
|
+static void gen_note3(double *tabstart,double *tabend,double midival,int tabsize,int splicelen, float *intab);
|
|
|
+int gen_dp_output(dataptr dz);
|
|
|
+
|
|
|
+#define LEAVESPACE (10*1024)
|
|
|
+
|
|
|
+int sorting_type = 0;
|
|
|
+
|
|
|
+int do_hfperm(dataptr dz)
|
|
|
+{
|
|
|
+ int exit_status;
|
|
|
+ char temp[48];
|
|
|
+ double **hfset = 0, **combo, secs;
|
|
|
+ int *combolen, combocnt = 0;
|
|
|
+ int hfsetcnt = 0, hrs = 0, mins = 0;
|
|
|
+ int *hfsetlen = 0;
|
|
|
+ int *grping = NULL;
|
|
|
+ int grping_cnt;
|
|
|
+ if((exit_status = generate_perms(&combo,&combolen,&combocnt,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ substitute_midivals_in_perms(combo,combolen,combocnt,dz);
|
|
|
+ switch(dz->process) {
|
|
|
+ case(HF_PERM1) :
|
|
|
+ if((exit_status = generate_hfsets(combocnt,combo,combolen,&hfset,&hfsetlen,&hfsetcnt,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ break;
|
|
|
+ case(HF_PERM2):
|
|
|
+ hfset = combo;
|
|
|
+ hfsetcnt = combocnt;
|
|
|
+ hfsetlen = combolen;
|
|
|
+ }
|
|
|
+ if((grping = (int *)malloc(hfsetcnt * sizeof(int)))==NULL)
|
|
|
+ print_outwarning_flush("Insufficient memory to store grouping information.\n");
|
|
|
+ grping_cnt = sort_hfsets(hfset,hfsetlen,&hfsetcnt,grping,dz);
|
|
|
+ grping_cnt /= 2;
|
|
|
+ dz->tempsize = hfsetcnt * (dz->iparam[HP1_ELEMENT_SIZE] + dz->iparam[HP1_GAP_SIZE]);
|
|
|
+ dz->tempsize += grping_cnt * dz->iparam[HP1_GGAP_SIZE];
|
|
|
+ if(dz->true_outfile_stype == SAMP_FLOAT)
|
|
|
+ dz->tempsize *= sizeof(float);
|
|
|
+ else
|
|
|
+ dz->tempsize *= sizeof(short);
|
|
|
+ if(dz->mode == HFP_SNDOUT || dz->mode == HFP_SNDSOUT) {
|
|
|
+ if(dz->mode == HFP_SNDOUT && ((unsigned int)dz->tempsize > (getdrivefreespace(dz->outfilename) - LEAVESPACE))) {
|
|
|
+ sprintf(errstr,"dz->tempsize = %d dz->outfilesize = %d Insufficient space on the hard disk to store the output file.\n",
|
|
|
+ dz->tempsize,dz->outfilesize);
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ } else {
|
|
|
+ sprintf(errstr,"Generating %d chords\n",hfsetcnt);
|
|
|
+ print_outmessage(errstr);
|
|
|
+ if((secs = dz->tempsize/(double)dz->infile->srate) > 60.0) {
|
|
|
+ mins = (int)floor(secs/60.0);
|
|
|
+ secs -= (mins * 60.0);
|
|
|
+ if(mins > 60) {
|
|
|
+ hrs = mins/60;
|
|
|
+ mins -= (hrs * 60);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sprintf(errstr,"Duration of output file: ");
|
|
|
+ if(hrs) {
|
|
|
+ sprintf(temp,"%d hrs ",hrs);
|
|
|
+ strcat(errstr,temp);
|
|
|
+ }
|
|
|
+ if(mins) {
|
|
|
+ sprintf(temp,"%d mins ",mins);
|
|
|
+ strcat(errstr,temp);
|
|
|
+ }
|
|
|
+ sprintf(temp,"%.2lf secs\n",secs);
|
|
|
+ strcat(errstr,temp);
|
|
|
+ print_outmessage_flush(errstr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ switch(dz->mode) {
|
|
|
+ case(HFP_SNDOUT):
|
|
|
+ if((exit_status = gen_output(hfsetcnt,hfset,hfsetlen,grping,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ break;
|
|
|
+ case(HFP_SNDSOUT):
|
|
|
+ if((exit_status = gen_outputs(hfsetcnt,hfset,hfsetlen,grping,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ break;
|
|
|
+ case(HFP_TEXTOUT):
|
|
|
+ if((exit_status = gen_text_output(hfsetcnt,hfset,hfsetlen,grping,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ break;
|
|
|
+ case(HFP_MIDIOUT):
|
|
|
+ if((exit_status = gen_midi_output(hfsetcnt,hfset,hfsetlen,grping,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** GENERATE_PERMS **************************/
|
|
|
+
|
|
|
+int generate_perms(double ***combo,int **combolen,int *combocnt,dataptr dz)
|
|
|
+{
|
|
|
+ int exit_status;
|
|
|
+ int n, j, maxsize;
|
|
|
+ int *element;
|
|
|
+ if(dz->iparam[HP1_HFCNT] == dz->iparam[HP1_MINSET]) {
|
|
|
+ if((*combo = (double **)malloc(sizeof(double *)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for harmonic combinations.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ if((*combolen = (int *)malloc(sizeof(int)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for harmonic combination counts.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ if(((*combo)[0] = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for harmonic combinations.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ for(n=0;n<dz->iparam[HP1_HFCNT];n++)
|
|
|
+ (*combo)[0][n] = n;
|
|
|
+ (*combolen)[0] = dz->iparam[HP1_HFCNT];
|
|
|
+ *combocnt = 1;
|
|
|
+ return(FINISHED);
|
|
|
+ } else {
|
|
|
+ if((element = (int *)malloc(dz->iparam[HP1_HFCNT] * sizeof(int)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for permutation elements.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ if(dz->vflag[HP1_MINONLY])
|
|
|
+ maxsize = dz->iparam[HP1_MINSET];
|
|
|
+ else
|
|
|
+ maxsize = dz->iparam[HP1_HFCNT];
|
|
|
+
|
|
|
+ for(n=dz->iparam[HP1_MINSET];n<=maxsize;n++) {
|
|
|
+ for(j=0;j<n;j++) /* initialise perm elements */
|
|
|
+ element[j] = j-1;
|
|
|
+ if((exit_status = set_element(0,n,dz->iparam[HP1_HFCNT],element,combo,combolen,combocnt))<0) {
|
|
|
+ free(element);
|
|
|
+ return(exit_status);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ free(element);
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** SET_ELEMENT **************************
|
|
|
+ *
|
|
|
+ * Recursive function to set successive elements of a permutation.
|
|
|
+ */
|
|
|
+
|
|
|
+int set_element(int element_no,int total_elements,int field_cnt,int *element,double ***combo,int **combolen,int *combocnt)
|
|
|
+{
|
|
|
+ int exit_status, k;
|
|
|
+ int limit = field_cnt - total_elements + element_no;
|
|
|
+ for(;;) {
|
|
|
+ element[element_no]++; /* incr the element number */
|
|
|
+ if(element[element_no] > limit) { /* if it's now beyond max for this element */
|
|
|
+ if(element_no > 0) { /* reset this, & all elements above it */
|
|
|
+ k = element_no; /* to be in ascending sequence from element below */
|
|
|
+ while(k < total_elements) { /* ready for incrementation of next lowest element */
|
|
|
+ element[k] = element[k-1] + 1;
|
|
|
+ k++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return(CONTINUE); /* then return to next lowest element */
|
|
|
+ }
|
|
|
+ if(element_no >= total_elements-1) { /* if all elements have been set, store the combination */
|
|
|
+ if((exit_status = store_combo(combo,combocnt,combolen,element,total_elements))<0)
|
|
|
+ return(exit_status);
|
|
|
+ } else { /* but if not, go on to set the next element */
|
|
|
+ if((exit_status = set_element(element_no+1,total_elements,field_cnt,element,combo,combolen,combocnt))<0)
|
|
|
+ return(exit_status);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return(CONTINUE); /* NOTREACHED */
|
|
|
+}
|
|
|
+
|
|
|
+/************************** STORE_COMBO **************************/
|
|
|
+
|
|
|
+int store_combo(double ***combo,int *combocnt,int **combolen,int *element,int total_elements)
|
|
|
+{
|
|
|
+ int n, j;
|
|
|
+ j = *combocnt;
|
|
|
+ (*combocnt)++; /* incr count of combinations */
|
|
|
+ if(*combocnt == 1) { /* create a new combo_store location */
|
|
|
+ if((*combo = (double **)malloc(sizeof(double *)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for harmonic combinations.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ } /* create a new combo_store_cnt location */
|
|
|
+ if((*combolen = (int *)malloc(sizeof(int)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for harmonic combinations.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if((*combo = (double **)realloc((char *)(*combo),(*combocnt) * sizeof(double *)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for harmonic combinations.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ if((*combolen = (int *)realloc((char *)(*combolen),(*combocnt) * sizeof(int)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for harmonic combinations.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ } /* create the new combo_store */
|
|
|
+ if(((*combo)[j] = (double *)malloc(total_elements * sizeof(double)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for harmonic combinations.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ for(n=0; n < total_elements; n++) /* store the new combo */
|
|
|
+ (*combo)[j][n] = (double)element[n];
|
|
|
+ (*combolen)[j] = total_elements; /* store the count of the new combo */
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** ELIMINATE_OCTAVE_DUPLICATIONS **************************/
|
|
|
+
|
|
|
+int eliminate_octave_duplications(dataptr dz)
|
|
|
+{
|
|
|
+ double *hf = dz->parray[0];
|
|
|
+ int n, m, k, octaves_eliminated = 0;
|
|
|
+ for(n=0;n< dz->iparam[HP1_HFCNT]-1;n++) {
|
|
|
+ for(m=n+1;m< dz->iparam[HP1_HFCNT];m++) {
|
|
|
+ if(flteq(fmod(hf[n],12.0),fmod(hf[m],12.0))) {
|
|
|
+ octaves_eliminated = 1;
|
|
|
+ k = m;
|
|
|
+ dz->iparam[HP1_HFCNT]--;
|
|
|
+ while(k < dz->iparam[HP1_HFCNT]) {
|
|
|
+ hf[k] = hf[k+1];
|
|
|
+ k++;
|
|
|
+ }
|
|
|
+ m--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return octaves_eliminated;
|
|
|
+}
|
|
|
+
|
|
|
+/**************************** SUBSTITUTE_MIDIVALS_IN_PERMS *******************************/
|
|
|
+
|
|
|
+void substitute_midivals_in_perms(double **combo,int *combolen,int combocnt,dataptr dz)
|
|
|
+{
|
|
|
+ double *hf = dz->parray[0];
|
|
|
+ int n, m, k;
|
|
|
+ for(n=0;n<combocnt;n++) {
|
|
|
+ for(m=0;m < combolen[n];m++) {
|
|
|
+ k = (int)combo[n][m];
|
|
|
+ combo[n][m] = hf[k];
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**************************** BUBLSORT_HF *******************************/
|
|
|
+
|
|
|
+void bublsort_hf(double *hf,dataptr dz)
|
|
|
+{
|
|
|
+ int n, m;
|
|
|
+ double temp;
|
|
|
+ for(n=0;n<dz->iparam[HP1_HFCNT]-1;n++) {
|
|
|
+ for(m = n+1; m<dz->iparam[HP1_HFCNT]; m++) {
|
|
|
+ if(hf[m] < hf[n]) {
|
|
|
+ temp = hf[n];
|
|
|
+ hf[n] = hf[m];
|
|
|
+ hf[m] = temp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**************************** GENERATE_OCTS *******************************/
|
|
|
+
|
|
|
+int transpose_element(int element_no,double *thiscombo,int thiscombolen,double *origval,
|
|
|
+ double ***hfset,int **hfsetlen,int *hfsetcnt,dataptr dz)
|
|
|
+{
|
|
|
+ int exit_status;
|
|
|
+ for(;;) {
|
|
|
+ thiscombo[element_no] += 12.0;
|
|
|
+ if(thiscombo[element_no] > (double)dz->iparam[HP1_TOPNOTE]) {
|
|
|
+ thiscombo[element_no] = origval[element_no];
|
|
|
+ return CONTINUE;
|
|
|
+ }
|
|
|
+ if(element_no >= thiscombolen-1) { /* if all elements have been set, store the hfset */
|
|
|
+ if((exit_status = store_transposition(hfset,hfsetlen,hfsetcnt,thiscombo,thiscombolen))<0)
|
|
|
+ return(exit_status);
|
|
|
+ } else { /* but if not, go on to set the next element */
|
|
|
+ if((exit_status =
|
|
|
+ transpose_element(element_no+1,thiscombo,thiscombolen,origval,hfset,hfsetlen,hfsetcnt,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return(CONTINUE); /* NOTREACHED */
|
|
|
+}
|
|
|
+
|
|
|
+/**************************** STORE_TRANSPOSITION *******************************/
|
|
|
+
|
|
|
+int store_transposition(double ***hfset,int **hfsetlen,int *hfsetcnt,double *thiscombo,int thiscombolen)
|
|
|
+{
|
|
|
+ int n, j;
|
|
|
+ j = *hfsetcnt;
|
|
|
+ (*hfsetcnt)++; /* incr count of hfset */
|
|
|
+ if(*hfsetcnt == 1) { /* create a new hfset_store location */
|
|
|
+ if((*hfset = (double **)malloc(sizeof(double *)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for final sets.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ } /* create a new hfset_store_cnt location */
|
|
|
+ if((*hfsetlen = (int *)malloc(sizeof(int)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for final sets.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if((*hfset = (double **)realloc((char *)(*hfset),(*hfsetcnt) * sizeof(double *)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for final sets.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ if((*hfsetlen = (int *)realloc((char *)(*hfsetlen),(*hfsetcnt) * sizeof(int)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for final sets.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ } /* create the new hfset store */
|
|
|
+ if(((*hfset)[j] = (double *)malloc(thiscombolen * sizeof(double)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for final sets.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ for(n=0; n < thiscombolen; n++) /* store the new hfset */
|
|
|
+ (*hfset)[j][n] = thiscombo[n];
|
|
|
+ (*hfsetlen)[j] = thiscombolen; /* store the count of the new hfset */
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** GENERATE_HFSETS **************************/
|
|
|
+
|
|
|
+int generate_hfsets(int combocnt,double **combo,int *combolen,double ***hfset,int **hfsetlen,int *hfsetcnt,dataptr dz)
|
|
|
+{
|
|
|
+ int exit_status;
|
|
|
+ int n, j;
|
|
|
+ double *origval;
|
|
|
+ if((origval = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
|
|
|
+ sprintf(errstr,"Out of memory for storing original comobo vals.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ for(n=0;n<combocnt;n++) {
|
|
|
+ for(j=0;j<combolen[n];j++) {
|
|
|
+ combo[n][j] -= 12.0;
|
|
|
+ origval[j] = combo[n][j];
|
|
|
+ }
|
|
|
+ if((exit_status = transpose_element(0,combo[n],combolen[n],origval,hfset,hfsetlen,hfsetcnt,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ }
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** SORT_HFSETS **************************/
|
|
|
+
|
|
|
+int sort_hfsets(double **hfset,int *hfsetlen,int *hfsetcnt,int *grping,dataptr dz)
|
|
|
+{
|
|
|
+ int n, m, j;
|
|
|
+ double temp;
|
|
|
+ int itemp;
|
|
|
+ double *intv, *intv2, *pich;
|
|
|
+ int *intvcnt, *intvcnt2;
|
|
|
+// int grping_cnt = 0, in_grp = 0;
|
|
|
+ int grping_cnt = 0;
|
|
|
+ int *minint = NULL, *intcnt = NULL;
|
|
|
+ int hfsetcount = *hfsetcnt;
|
|
|
+
|
|
|
+ grping[0] = -1; /* flags output not to do grouping */
|
|
|
+
|
|
|
+ for(j = 0;j<hfsetcount;j++) { /* Sort the individual sets themselves, so pitches are in ascending order */
|
|
|
+ for(n=0;n<hfsetlen[j]-1;n++) {
|
|
|
+ for(m = n+1; m<hfsetlen[j]; m++) {
|
|
|
+ if(hfset[j][m] < hfset[j][n]) {
|
|
|
+ temp = hfset[j][n];
|
|
|
+ hfset[j][n] = hfset[j][m];
|
|
|
+ hfset[j][m] = temp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ print_outmessage_flush("Sorting chords by note-count.\n");
|
|
|
+ for(n=0;n<hfsetcount-1;n++) { /* Sort the sets by size */
|
|
|
+ for(m = n+1; m<hfsetcount; m++) {
|
|
|
+ if(hfsetlen[m] < hfsetlen[n]) {
|
|
|
+ itemp = hfsetlen[n];
|
|
|
+ hfsetlen[n] = hfsetlen[m];
|
|
|
+ hfsetlen[m] = itemp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ switch(dz->iparam[HP1_SORT1]) {
|
|
|
+ case(ROOT):
|
|
|
+ case(TOP):
|
|
|
+ case(PCLASS):
|
|
|
+ if ((intv = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
|
|
|
+ print_outwarning_flush("Insufficient memory to sort chords in terms of pitch equivalence.\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if ((intv2 = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
|
|
|
+ print_outwarning_flush("Insufficient memory to sort chords in terms of pitch equivalence.\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if ((intvcnt = (int *)malloc(dz->iparam[HP1_HFCNT] * sizeof(int)))==NULL) {
|
|
|
+ print_outwarning_flush("Insufficient memory to sort chords in terms of pitch equivalence.\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if ((intvcnt2 = (int *)malloc(dz->iparam[HP1_HFCNT] * sizeof(int)))==NULL) {
|
|
|
+ print_outwarning_flush("Insufficient memory to sort chords in terms of pitch equivalence.\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if ((pich = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
|
|
|
+ print_outwarning_flush("Insufficient memory to sort chords in terms of pitch equivalence.\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if(dz->vflag[HP1_DENS] == OTHER_SORT) {
|
|
|
+ if ((minint = (int *)malloc(hfsetcount * sizeof(int)))==NULL)
|
|
|
+ print_outwarning_flush("Insufficient memory to sort chord-groups.\n");
|
|
|
+ else if ((intcnt = (int *)malloc(hfsetcount * sizeof(int)))==NULL)
|
|
|
+ print_outwarning_flush("Insufficient memory to sort chord-groups.\n");
|
|
|
+ }
|
|
|
+ switch(dz->iparam[HP1_SORT1]) {
|
|
|
+ case(PCLASS):
|
|
|
+ print_outmessage_flush("Sorting chords by pitchclass-equivalence.\n");
|
|
|
+ grping_cnt = sort_by_pitchclass_equivalence
|
|
|
+ (hfset,hfsetlen,pich,hfsetcount,grping,intcnt,intv,intvcnt,intv2,intvcnt2,dz);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ print_outmessage_flush("Sorting chords by reference-note-equivalence.\n");
|
|
|
+ grping_cnt = sort_by_reference_note_equivalence(hfset,hfsetlen,hfsetcount,grping,dz);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case(CHORDTYPE):
|
|
|
+ case(CHORD_1):
|
|
|
+ if ((intv = (double *)malloc(dz->iparam[HP1_HFCNT] * sizeof(double)))==NULL) {
|
|
|
+ print_outwarning_flush("Insufficient memory to sort chords in terms of interval equivalence.\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ print_outmessage_flush("Sorting chords by interval-equivalence.\n");
|
|
|
+ grping_cnt = sort_by_chord(hfset,hfsetlen,intv,hfsetcnt,grping,dz);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ sprintf(errstr,"Unknown chord sort type.\n");
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
+ }
|
|
|
+ if(dz->vflag[HP1_ELIMOCTS] && (dz->iparam[HP1_SORT1] != CHORD_1))
|
|
|
+ eliminate_oct_duplicated_sets(hfset,hfsetcnt,hfsetlen,grping,&grping_cnt,sorting_type);
|
|
|
+ return grping_cnt;
|
|
|
+}
|
|
|
+
|
|
|
+/************************** GEN_OUTPUT **************************/
|
|
|
+
|
|
|
+int gen_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz)
|
|
|
+{
|
|
|
+ int exit_status;
|
|
|
+// short *obuf = dz->sampbuf[0];
|
|
|
+ float *obuf = dz->sampbuf[0];
|
|
|
+ double *tab = (double *)dz->sampbuf[2];
|
|
|
+ double *tabend = tab + dz->iparam[HP1_ELEMENT_SIZE];
|
|
|
+ double tabscale = (double)HFP_TABSIZE/dz->infile->srate;
|
|
|
+ double *sintab = (double *)dz->sampbuf[1];
|
|
|
+ double sintabsize = (double)HFP_TABSIZE;
|
|
|
+ double element_level;
|
|
|
+ int samps_written = 0, samp_space_available, samps_to_write, gap_size;
|
|
|
+ int n, i, j, grping_cnt = 0;
|
|
|
+ int maxjitter = (int)round(drand48() * HFP_MAXJITTER * MS_TO_SECS * (double)dz->infile->srate);
|
|
|
+ unsigned int element_byte_len = dz->iparam[HP1_ELEMENT_SIZE] * sizeof(double);
|
|
|
+ unsigned int element_full_len = element_byte_len + (maxjitter * sizeof(double));
|
|
|
+ double *tabmax = 0, *tabmin = tab + dz->iparam[HP1_ELEMENT_SIZE] + maxjitter;
|
|
|
+ int splicelen = (int)round(HP1_SPLICELEN * MS_TO_SECS * (double)dz->infile->srate);
|
|
|
+ int in_group = 0, in_grp = 0;
|
|
|
+
|
|
|
+ print_outmessage_flush("Synthesis beginning.\n");
|
|
|
+ memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
|
|
|
+ for(n=0;n<hfsetcnt;n++) {
|
|
|
+ memset((char *)dz->sampbuf[2],0,element_full_len);
|
|
|
+
|
|
|
+ if(grping!=NULL && grping[0] != -1)
|
|
|
+ print_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt);
|
|
|
+ errstr[0] = ENDOFSTR;
|
|
|
+
|
|
|
+ for(j=0;j<hfsetlen[n];j++) {
|
|
|
+ set_pitch_to_print((int)hfset[n][j]);
|
|
|
+ gen_note(maxjitter,tab,tabend,&tabmin,&tabmax,hfset,tabscale,sintabsize,splicelen,sintab,n,j);
|
|
|
+ }
|
|
|
+ print_pitchset();
|
|
|
+ element_level = HFP_OUTLEVEL/hfsetlen[n];
|
|
|
+ tab = tabmin;
|
|
|
+ while(tab < tabmax)
|
|
|
+ *tab++ *= element_level;
|
|
|
+ /* DO OUTPUT */
|
|
|
+ samp_space_available = dz->buflen - samps_written;
|
|
|
+ gap_size = dz->iparam[HP1_GAP_SIZE];
|
|
|
+ if(grping!=NULL && grping[0] != -1) {
|
|
|
+ if(grping[grping_cnt]==n) {
|
|
|
+ in_group = 1;
|
|
|
+ gap_size += dz->iparam[HP1_GGAP_SIZE]; /* make gap at start */
|
|
|
+ grping_cnt++;
|
|
|
+ } else if(grping[grping_cnt]==-n) {
|
|
|
+ in_group = 0;
|
|
|
+ gap_size += dz->iparam[HP1_GGAP_SIZE]; /* make gap at end */
|
|
|
+ grping_cnt++; /* if grp end coincides with gp start */
|
|
|
+ if(grping[grping_cnt]==n) { /* skip a grping value */
|
|
|
+ in_group = 1;
|
|
|
+ grping_cnt++;
|
|
|
+ }
|
|
|
+ } else if (!in_group)
|
|
|
+ gap_size += dz->iparam[HP1_GGAP_SIZE]; /* make gap between non-grouped entries */
|
|
|
+ }
|
|
|
+ if(n!=0) { /* no gap at start */
|
|
|
+ while(gap_size >= samp_space_available) {
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
|
|
|
+ gap_size -= samp_space_available;
|
|
|
+ samp_space_available = dz->buflen;
|
|
|
+ samps_written = 0;
|
|
|
+ }
|
|
|
+ samps_written += gap_size;
|
|
|
+ samp_space_available = dz->buflen - samps_written;
|
|
|
+ }
|
|
|
+ i = 0;
|
|
|
+ tab = tabmin;
|
|
|
+ samp_space_available = dz->buflen - samps_written;
|
|
|
+ samps_to_write = tabmax - tabmin;
|
|
|
+ while(i < samps_to_write) {
|
|
|
+ if(samp_space_available > samps_to_write) {
|
|
|
+ while(i < samps_to_write)
|
|
|
+// obuf[samps_written++] = (short)round(tab[i++] * MAXSAMP);
|
|
|
+ obuf[samps_written++] = (float)tab[i++];
|
|
|
+ } else {
|
|
|
+ while(samps_written < dz->buflen)
|
|
|
+// obuf[samps_written++] = (short)round(tab[i++] * MAXSAMP);
|
|
|
+ obuf[samps_written++] = (float)tab[i++];
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
|
|
|
+ samps_written = 0;
|
|
|
+ samp_space_available = dz->buflen;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(grping!=NULL && grping[0] != -1)
|
|
|
+ print_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt);
|
|
|
+ samps_written += dz->iparam[HP1_GAP_SIZE];
|
|
|
+ while(samps_written >= dz->buflen) {
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ samps_written -= dz->buflen;
|
|
|
+ }
|
|
|
+ if(samps_written > 0) {
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],samps_written,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ }
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** GEN_OUTPUTS **************************/
|
|
|
+
|
|
|
+int gen_outputs(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz)
|
|
|
+{
|
|
|
+ int exit_status;
|
|
|
+ float *obuf = dz->sampbuf[0];
|
|
|
+ double *tab = (double *)dz->sampbuf[2];
|
|
|
+ double *tabend = tab + dz->iparam[HP1_ELEMENT_SIZE];
|
|
|
+ double tabscale = (double)HFP_TABSIZE/dz->infile->srate;
|
|
|
+ double *sintab = (double *)dz->sampbuf[1];
|
|
|
+ double sintabsize = (double)HFP_TABSIZE;
|
|
|
+ double element_level;
|
|
|
+ int samps_written = 0, samp_space_available, samps_to_write, gap_size;
|
|
|
+ int n, i, j, grping_cnt = 0;
|
|
|
+ int maxjitter = (int)round(drand48() * HFP_MAXJITTER * MS_TO_SECS * (double)dz->infile->srate);
|
|
|
+ unsigned int element_byte_len = dz->iparam[HP1_ELEMENT_SIZE] * sizeof(double);
|
|
|
+ unsigned int element_full_len = element_byte_len + (maxjitter * sizeof(double));
|
|
|
+ double *tabmax = 0, *tabmin = tab + dz->iparam[HP1_ELEMENT_SIZE] + maxjitter;
|
|
|
+ int splicelen = (int)round(HP1_SPLICELEN * MS_TO_SECS * (double)dz->infile->srate);
|
|
|
+ int in_group = 0, in_grp = 0;
|
|
|
+ char *thisfilename;
|
|
|
+ int ccnt = 0;
|
|
|
+ unsigned int space_needed = dz->tempsize;
|
|
|
+
|
|
|
+ superzargo = 0;
|
|
|
+ if((exit_status = setup_naming(&thisfilename,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ if((exit_status = create_outfile_name(0,thisfilename,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ dz->process_type = UNEQUAL_SNDFILE; /* allow sndfile to be created */
|
|
|
+ if((exit_status = create_sized_outfile(thisfilename,dz))<0) {
|
|
|
+ fprintf(stdout, "WARNING: Soundfile %s already exists.\n", thisfilename);
|
|
|
+ fflush(stdout);
|
|
|
+ dz->process_type = OTHER_PROCESS;
|
|
|
+ dz->ofd = -1;
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
+ }
|
|
|
+ if((unsigned int)dz->outfilesize < space_needed) {
|
|
|
+ sprintf(errstr,"Insufficient space on the hard disk to store the output files.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ dz->total_samps_written = 0;
|
|
|
+ print_outmessage_flush("Synthesis beginning.\n");
|
|
|
+ memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
|
|
|
+ for(n=0;n<hfsetcnt;n++) {
|
|
|
+ memset((char *)dz->sampbuf[2],0,element_full_len);
|
|
|
+
|
|
|
+ if(grping!=NULL && grping[0] != -1)
|
|
|
+ print_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt);
|
|
|
+ errstr[0] = ENDOFSTR;
|
|
|
+
|
|
|
+ for(j=0;j<hfsetlen[n];j++) {
|
|
|
+ set_pitch_to_print((int)hfset[n][j]);
|
|
|
+ gen_note(maxjitter,tab,tabend,&tabmin,&tabmax,hfset,tabscale,sintabsize,splicelen,sintab,n,j);
|
|
|
+ }
|
|
|
+ print_pitchset();
|
|
|
+ element_level = HFP_OUTLEVEL/hfsetlen[n];
|
|
|
+ tab = tabmin;
|
|
|
+ while(tab < tabmax)
|
|
|
+ *tab++ *= element_level;
|
|
|
+ /* DO OUTPUT */
|
|
|
+ samp_space_available = dz->buflen - samps_written;
|
|
|
+ gap_size = dz->iparam[HP1_GAP_SIZE];
|
|
|
+ if(grping!=NULL && grping[0] != -1) {
|
|
|
+ if(grping[grping_cnt]==n) {
|
|
|
+ if(in_group == 0 && n!=0) {
|
|
|
+ if((exit_status = next_file(&samps_written,thisfilename,&ccnt,&space_needed,&samp_space_available,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ }
|
|
|
+ in_group = 1;
|
|
|
+ grping_cnt++;
|
|
|
+ } else if(grping[grping_cnt]==-n) { /* if at end of group */
|
|
|
+ in_group = 0;
|
|
|
+ if((exit_status = next_file(&samps_written,thisfilename,&ccnt,&space_needed,&samp_space_available,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ grping_cnt++; /* if grp end coincides with gp start */
|
|
|
+ if(grping[grping_cnt]==n) { /* skip a grping value */
|
|
|
+ in_group = 1;
|
|
|
+ grping_cnt++;
|
|
|
+ }
|
|
|
+ } else if(in_group == 0 && n!=0) { /* if not a grouped chord */
|
|
|
+ if((exit_status = next_file(&samps_written,thisfilename,&ccnt,&space_needed,&samp_space_available,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(n!=0) { /* no gap at start */
|
|
|
+ while(gap_size >= samp_space_available) {
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
|
|
|
+ gap_size -= samp_space_available;
|
|
|
+ samp_space_available = dz->buflen;
|
|
|
+ samps_written = 0;
|
|
|
+ }
|
|
|
+ samps_written += gap_size;
|
|
|
+ samp_space_available = dz->buflen - samps_written;
|
|
|
+ }
|
|
|
+ i = 0;
|
|
|
+ tab = tabmin;
|
|
|
+ samp_space_available = dz->buflen - samps_written;
|
|
|
+ samps_to_write = tabmax - tabmin;
|
|
|
+ while(i < samps_to_write) {
|
|
|
+ if(samp_space_available > samps_to_write) {
|
|
|
+ while(i < samps_to_write)
|
|
|
+ obuf[samps_written++] = (float)tab[i++];
|
|
|
+ } else {
|
|
|
+ while(samps_written < dz->buflen)
|
|
|
+ obuf[samps_written++] = (float)tab[i++];
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
|
|
|
+ samps_written = 0;
|
|
|
+ samp_space_available = dz->buflen;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(grping!=NULL && grping[0] != -1)
|
|
|
+ print_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt);
|
|
|
+ samps_written += dz->iparam[HP1_GAP_SIZE];
|
|
|
+ while(samps_written >= dz->buflen) {
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ samps_written -= dz->buflen;
|
|
|
+ }
|
|
|
+ if(samps_written > 0) {
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],samps_written,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ }
|
|
|
+ /* CLOSE FILE */
|
|
|
+ dz->outfiletype = SNDFILE_OUT; /* allows header to be written */
|
|
|
+ if((exit_status = headwrite(dz->ofd,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ dz->process_type = OTHER_PROCESS;
|
|
|
+ dz->outfiletype = NO_OUTPUTFILE;
|
|
|
+ if((exit_status = reset_peak_finder(dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ if(sndcloseEx(dz->ofd) < 0) {
|
|
|
+ fprintf(stdout,"WARNING: Can't close output soundfile %s\n",thisfilename);
|
|
|
+ fflush(stdout);
|
|
|
+ }
|
|
|
+ dz->ofd = -1;
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** GEN_TEXT_OUTPUT **************************/
|
|
|
+
|
|
|
+int gen_text_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz)
|
|
|
+{
|
|
|
+ int n, j, grping_cnt = 0;
|
|
|
+ int in_group = 0, in_grp = 0;
|
|
|
+
|
|
|
+ for(n=0;n<hfsetcnt;n++) {
|
|
|
+ if(grping!=NULL && grping[0] != -1) {
|
|
|
+ printout_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt,dz);
|
|
|
+ }
|
|
|
+ errstr[0] = ENDOFSTR;
|
|
|
+ for(j=0;j<hfsetlen[n];j++) {
|
|
|
+ set_pitch_to_print((int)hfset[n][j]);
|
|
|
+ }
|
|
|
+ printout_pitchset(dz);
|
|
|
+ if(grping!=NULL && grping[0] != -1) {
|
|
|
+ if(grping[grping_cnt]==n) {
|
|
|
+ in_group = 1;
|
|
|
+ grping_cnt++;
|
|
|
+ } else if(grping[grping_cnt]==-n) { /* if at end of group */
|
|
|
+ in_group = 0;
|
|
|
+ grping_cnt++; /* if grp end coincides with gp start */
|
|
|
+ if(grping[grping_cnt]==n) { /* skip a grping value */
|
|
|
+ in_group = 1;
|
|
|
+ grping_cnt++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(grping!=NULL && grping[0] != -1) {
|
|
|
+ printout_grouping_structure(n,grping,&grping_cnt,&in_grp,hfsetcnt,dz);
|
|
|
+ }
|
|
|
+ display_virtual_time(dz->tempsize,dz);
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** GEN_MIDI_OUTPUT **************************/
|
|
|
+
|
|
|
+int gen_midi_output(int hfsetcnt,double **hfset,int *hfsetlen,int *grping,dataptr dz)
|
|
|
+{
|
|
|
+ int n, j, grping_cnt = 0;
|
|
|
+// int in_group = 0, in_grp = 0;
|
|
|
+ int in_group = 0;
|
|
|
+
|
|
|
+ for(n=0;n<hfsetcnt;n++) {
|
|
|
+ errstr[0] = ENDOFSTR;
|
|
|
+ for(j=0;j<hfsetlen[n];j++)
|
|
|
+ set_midi_to_print((int)hfset[n][j]);
|
|
|
+ printout_pitchset(dz);
|
|
|
+ if(grping!=NULL && grping[0] != -1) {
|
|
|
+ if(grping[grping_cnt]==n) {
|
|
|
+ in_group = 1;
|
|
|
+ grping_cnt++;
|
|
|
+ } else if(grping[grping_cnt]==-n) { /* if at end of group, or not a grouped chord */
|
|
|
+ in_group = 0;
|
|
|
+ grping_cnt++; /* if grp end coincides with gp start */
|
|
|
+ if(grping[grping_cnt]==n) { /* skip a grping value */
|
|
|
+ in_group = 1;
|
|
|
+ grping_cnt++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ display_virtual_time(dz->tempsize,dz);
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** PRINT_GROUPING_STRUCTURE **************************/
|
|
|
+
|
|
|
+void print_grouping_structure(int n,int *grping,int *grping_cnt,int *in_grp,int hfsetcnt)
|
|
|
+{
|
|
|
+ if(grping[*grping_cnt]==-n && (n!=0)) { /* if end of group marked */
|
|
|
+ *in_grp = 0;
|
|
|
+ print_outmessage_flush("))- - - - - - -\n");
|
|
|
+ if(grping[(*grping_cnt)+1]==n) { /* if start of group ALSO marked */
|
|
|
+ *in_grp = 1;
|
|
|
+ print_outmessage_flush("-------------((\n");
|
|
|
+ }
|
|
|
+ } else if(grping[*grping_cnt]==n) { /* if start of group marked */
|
|
|
+ *in_grp = 1;
|
|
|
+ print_outmessage_flush("-------------((\n");
|
|
|
+ } else if(!(*in_grp)) { /* not inside a group */
|
|
|
+ print_outmessage_flush("-----\n");
|
|
|
+ } else if(n >= hfsetcnt) { /* inside a group at end of whole pass */
|
|
|
+ print_outmessage_flush("))- - - - - - -\n");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/************************** PRINTOUT_GROUPING_STRUCTURE **************************/
|
|
|
+
|
|
|
+void printout_grouping_structure(int n,int *grping,int *grping_cnt,int *in_grp,int hfsetcnt,dataptr dz)
|
|
|
+{
|
|
|
+ if(grping[*grping_cnt]==-n && (n!=0)) { /* if end of group marked */
|
|
|
+ *in_grp = 0;
|
|
|
+ print_outmessage_flush("))- - - - - - -\n");
|
|
|
+ fprintf(dz->fp,"))- - - - - - -\n");
|
|
|
+ if(grping[(*grping_cnt)+1]==n) { /* if start of group ALSO marked */
|
|
|
+ *in_grp = 1;
|
|
|
+ print_outmessage_flush("-------------((\n");
|
|
|
+ fprintf(dz->fp,"-------------((\n");
|
|
|
+ }
|
|
|
+ } else if(grping[*grping_cnt]==n) { /* if start of group marked */
|
|
|
+ *in_grp = 1;
|
|
|
+ print_outmessage_flush("-------------((\n");
|
|
|
+ fprintf(dz->fp,"-------------((\n");
|
|
|
+ } else if(!(*in_grp)) { /* not inside a group */
|
|
|
+ print_outmessage_flush("-----\n");
|
|
|
+ fprintf(dz->fp,"-----\n");
|
|
|
+ } else if(n >= hfsetcnt) { /* inside a group at end of whole pass */
|
|
|
+ print_outmessage_flush("))- - - - - - -\n");
|
|
|
+ fprintf(dz->fp,"))- - - - - - -\n");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/************************** SET_PITCH_TO_PRINT **************************/
|
|
|
+
|
|
|
+void set_pitch_to_print(int midi)
|
|
|
+{
|
|
|
+ int oct = (midi/12)-5;
|
|
|
+ char temp[12];
|
|
|
+ midi = midi%12;
|
|
|
+ switch(midi) {
|
|
|
+ case(0): sprintf(temp,"C%d ",oct); break;
|
|
|
+ case(1): sprintf(temp,"C#%d ",oct); break;
|
|
|
+ case(2): sprintf(temp,"D%d ",oct); break;
|
|
|
+ case(3): sprintf(temp,"Eb%d ",oct); break;
|
|
|
+ case(4): sprintf(temp,"E%d ",oct); break;
|
|
|
+ case(5): sprintf(temp,"F%d ",oct); break;
|
|
|
+ case(6): sprintf(temp,"F#%d ",oct); break;
|
|
|
+ case(7): sprintf(temp,"G%d ",oct); break;
|
|
|
+ case(8): sprintf(temp,"Ab%d ",oct); break;
|
|
|
+ case(9): sprintf(temp,"A%d ",oct); break;
|
|
|
+ case(10): sprintf(temp,"Bb%d ",oct); break;
|
|
|
+ case(11): sprintf(temp,"B%d ",oct); break;
|
|
|
+ }
|
|
|
+ if(oct>=0)
|
|
|
+ strcat(temp," ");
|
|
|
+ strcat(errstr,temp);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** SET_MIDI_TO_PRINT **************************/
|
|
|
+
|
|
|
+void set_midi_to_print(int midi)
|
|
|
+{
|
|
|
+ char temp[12];
|
|
|
+ sprintf(temp,"%d ",midi);
|
|
|
+ strcat(errstr,temp);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** PRINT_PITCHSET **************************/
|
|
|
+
|
|
|
+void print_pitchset(void)
|
|
|
+{
|
|
|
+ char temp[12];
|
|
|
+ sprintf(temp,"\n");
|
|
|
+ strcat(errstr,temp);
|
|
|
+ print_outmessage_flush(errstr);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** PRINTOUT_PITCHSET **************************/
|
|
|
+
|
|
|
+void printout_pitchset(dataptr dz)
|
|
|
+{
|
|
|
+ char temp[12];
|
|
|
+ sprintf(temp,"\n");
|
|
|
+ strcat(errstr,temp);
|
|
|
+ print_outmessage_flush(errstr);
|
|
|
+ fprintf(dz->fp,"%s",errstr);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** SORT_BY_CHORD ***************************
|
|
|
+ *
|
|
|
+ * Sort size-ordered then pitch-ordered sets, by equivalence of chords they make up.
|
|
|
+ */
|
|
|
+
|
|
|
+int sort_by_chord(double **hfset,int *hfsetlen,double *intv,int *hfsetcnt,int *grping,dataptr dz)
|
|
|
+{
|
|
|
+ int a, b, m, n, j, lastmatch, was_a_match;
|
|
|
+ double *tempoint;
|
|
|
+ int grping_cnt = 0, matching_intervals = 0;
|
|
|
+
|
|
|
+ for(n=0;n<(*hfsetcnt)-1;n++) {
|
|
|
+ for(j = 0; j<hfsetlen[n]-1; j++)
|
|
|
+ intv[j] = hfset[n][j+1] - hfset[n][j]; /* set up intervals of first set as a comparison set */
|
|
|
+ lastmatch = n;
|
|
|
+ was_a_match = 0;
|
|
|
+ for(m = n+1; m<=*hfsetcnt; m++) {
|
|
|
+ if(m==*hfsetcnt || hfsetlen[m] != hfsetlen[n]){ /* if got to end of group-of-sets of same size */
|
|
|
+
|
|
|
+ if(was_a_match) { /* if a matching-group has just been put together */
|
|
|
+ for(a=n;a<lastmatch;a++) {
|
|
|
+ for(b = a+1; b<=lastmatch; b++) { /* sort matching chords into pitch-ascending order */
|
|
|
+ if(hfset[b][0] < hfset[a][0]) {
|
|
|
+ tempoint = hfset[a];
|
|
|
+ hfset[a] = hfset[b];
|
|
|
+ hfset[b] = tempoint;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(grping!=NULL && n!=0) {
|
|
|
+ grping[grping_cnt++] = n; /* ....mark group start */
|
|
|
+ grping[grping_cnt++] = -(lastmatch+1); /* mark group end */
|
|
|
+ }
|
|
|
+ if(lastmatch != m-1) { /* if match-group didn't end at end of last samesize-group */
|
|
|
+ n = lastmatch+1; /* baktrak n to position AFTER END of matching set */
|
|
|
+ for(j = 0; j<hfsetlen[n]-1; j++) /* set this set's intervals as comparison intervals */
|
|
|
+ intv[j] = hfset[n][j+1] - hfset[n][j];
|
|
|
+ m = n; /* reset m to run over sets after n */
|
|
|
+ lastmatch = n;
|
|
|
+ was_a_match = 0; /* search for further matching sets */
|
|
|
+ continue;
|
|
|
+ /* ELSE last match ended at end of group-of-sets */
|
|
|
+ } else if(m < (*hfsetcnt)-1) { /* SO, if we're not at last set */
|
|
|
+ for(j = 0; j<hfsetlen[m]-1; j++) /* establish interval comparison set for new setsize */
|
|
|
+ intv[j] = hfset[m][j+1] - hfset[m][j];
|
|
|
+ lastmatch = m; /* reset the base pointer of matching sets */
|
|
|
+ was_a_match = 0;
|
|
|
+ n = m; /* skip n-index to base of next group samesize sets */
|
|
|
+ }
|
|
|
+ } else { /* matching set not been made in this pass */
|
|
|
+ m = *hfsetcnt; /* force n to advance */
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ matching_intervals = 1; /* compare samesize (sorted) sets for matching intervals */
|
|
|
+ for(j = 0; j<hfsetlen[m]-1; j++) {
|
|
|
+ if (!flteq(intv[j],hfset[m][j+1] - hfset[m][j])) {
|
|
|
+ matching_intervals = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(matching_intervals) { /* if all intervals match */
|
|
|
+ was_a_match = 1; /* note tha a match has been found in this pass */
|
|
|
+ lastmatch++; /* incr pointer to last match position */
|
|
|
+ if(m != lastmatch) { /* if the matching set is not AT this position */
|
|
|
+ tempoint = hfset[lastmatch]; /* move it to that position */
|
|
|
+ hfset[lastmatch] = hfset[m];
|
|
|
+ hfset[m] = tempoint;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(dz->iparam[HP1_SORT1] == CHORD_1) {
|
|
|
+ for(b = 0; b < grping_cnt; b+=2) {
|
|
|
+ m = grping[b] + 1;
|
|
|
+ n = -(grping[b+1]);
|
|
|
+ j = n - m;
|
|
|
+ while(n < *hfsetcnt)
|
|
|
+ hfset[m++] = hfset[n++];
|
|
|
+ *hfsetcnt -= j;
|
|
|
+ }
|
|
|
+ grping_cnt = 0;
|
|
|
+ grping[0] = -1;
|
|
|
+ }
|
|
|
+ return grping_cnt;
|
|
|
+}
|
|
|
+
|
|
|
+/************************** SORT_BY_PITCHCLASS_EQUIVALENCE ***************************
|
|
|
+ *
|
|
|
+ * Sort size-ordered THEN pitch-ordered sets, by pitch-class equivalence of root note in each size-group.
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+int sort_by_pitchclass_equivalence
|
|
|
+ (double **hfset,int *hfsetlen,double *pich,int hfsetcnt,int *grping,int *intcnt,
|
|
|
+ double *intv,int *intvcnt,double *intv2,int *intvcnt2,dataptr dz)
|
|
|
+{
|
|
|
+ int j, k, m, n;
|
|
|
+ int in_grp = 0, grping_cnt = 0, matching_pitches, setlen;
|
|
|
+
|
|
|
+ n = 0;
|
|
|
+ setlen = hfsetlen[n];
|
|
|
+ for(j = 0; j<setlen; j++)
|
|
|
+ pich[j] = fmod(hfset[n][j],12.0); /* set up pitches of first set, as a comparison set */
|
|
|
+ for(m=1;m<hfsetcnt;m++) {
|
|
|
+ if(hfsetlen[m] != setlen) {
|
|
|
+ if(in_grp) {
|
|
|
+ grping[grping_cnt++] = -m; /* mark end of group */
|
|
|
+ in_grp = 0;
|
|
|
+ }
|
|
|
+ if(intcnt != NULL) {
|
|
|
+ if(dz->vflag[HP1_DENS] == DENSE_SORT)
|
|
|
+ sort_by_density_regardless_of_size(hfset,intv,intvcnt,intv2,intvcnt2,n,m,setlen,1);
|
|
|
+ else
|
|
|
+ sort_by_maxintsize_and_density(hfset,n,m,setlen,0);
|
|
|
+ }
|
|
|
+ n = m;
|
|
|
+ setlen = hfsetlen[n];
|
|
|
+ for(j = 0; j<setlen; j++)
|
|
|
+ pich[j] = fmod(hfset[n][j],12.0); /* set up pitches of new comparison set */
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ matching_pitches = 1; /* no pitch-class duplication in sets */
|
|
|
+ for(j=0;j<hfsetlen[m];j++) {
|
|
|
+ matching_pitches = 0;
|
|
|
+ for(k=0;k<hfsetlen[m];k++) {
|
|
|
+ if(flteq(fmod(hfset[m][j],12.0),pich[k])) {
|
|
|
+ matching_pitches = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(!matching_pitches)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(matching_pitches) {
|
|
|
+ if(!in_grp) {
|
|
|
+ grping[grping_cnt++] = (m-1); /* mark start of group */
|
|
|
+ in_grp = 1;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if(in_grp) {
|
|
|
+ grping[grping_cnt++] = -m; /* mark end of group */
|
|
|
+ in_grp = 0;
|
|
|
+ }
|
|
|
+ if(intcnt != NULL) {
|
|
|
+ if(dz->vflag[HP1_DENS] == DENSE_SORT)
|
|
|
+ sort_by_density_regardless_of_size(hfset,intv,intvcnt,intv2,intvcnt2,n,m,setlen,1);
|
|
|
+ else
|
|
|
+ sort_by_maxintsize_and_density(hfset,n,m,setlen,0);
|
|
|
+ }
|
|
|
+ n = m;
|
|
|
+ setlen = hfsetlen[n];
|
|
|
+ for(j = 0; j<setlen; j++)
|
|
|
+ pich[j] = fmod(hfset[n][j],12.0); /* set up pitches of new comparison set */
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(intcnt != NULL) {
|
|
|
+ if(dz->vflag[HP1_DENS] == DENSE_SORT)
|
|
|
+ sort_by_density_regardless_of_size(hfset,intv,intvcnt,intv2,intvcnt2,n,m,setlen,1);
|
|
|
+ else
|
|
|
+ sort_by_maxintsize_and_density(hfset,n,m,setlen,0);
|
|
|
+ }
|
|
|
+ return(grping_cnt);
|
|
|
+}
|
|
|
+
|
|
|
+/************************** SORT_BY_REFERENCE_NOTE_EQUIVALENCE ***************************
|
|
|
+ *
|
|
|
+ * Sort pitch-ordered by pitch-class equivalence of root note.
|
|
|
+ */
|
|
|
+
|
|
|
+int sort_by_reference_note_equivalence(double **hfset,int *hfsetlen,int hfsetcnt,int *grping,dataptr dz)
|
|
|
+{
|
|
|
+ int j, k, m, n;
|
|
|
+ int in_grp = 0, grping_cnt = 0, setlen, end, note = 0;
|
|
|
+ double *tempoint, thispitch, thatpitch;
|
|
|
+
|
|
|
+ n = 0;
|
|
|
+ m = n+1;
|
|
|
+ while(m < hfsetcnt) {
|
|
|
+ setlen = hfsetlen[n];
|
|
|
+ end = setlen - 1;
|
|
|
+ switch(dz->iparam[HP1_SORT1]) {
|
|
|
+ case(ROOT): note = 0; break;
|
|
|
+ case(TOP): note = end; break;
|
|
|
+ }
|
|
|
+ while(hfsetlen[m] == setlen) { /* find sets of same size */
|
|
|
+ if(++m >= hfsetcnt)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ for(j=n;j<m-1;j++) { /* sort all these samesize sets into root pitchclass order */
|
|
|
+ if(dz->process == HF_PERM1)
|
|
|
+ thispitch = fmod(hfset[j][note],12.0);
|
|
|
+ else
|
|
|
+ thispitch = hfset[j][note];
|
|
|
+ for(k=j+1;k<m;k++) {
|
|
|
+ if(dz->process == HF_PERM1)
|
|
|
+ thatpitch = fmod(hfset[k][note],12.0);
|
|
|
+ else
|
|
|
+ thatpitch = hfset[k][note];
|
|
|
+ if(thatpitch < thispitch) {
|
|
|
+ tempoint = hfset[k];
|
|
|
+ hfset[k] = hfset[j];
|
|
|
+ hfset[j] = tempoint;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ k = n; /* sort all these into same-root sets */
|
|
|
+ j = k+1;
|
|
|
+ if(j >= hfsetcnt)
|
|
|
+ break;
|
|
|
+ in_grp = 0;
|
|
|
+ while(j < m) {
|
|
|
+ if(dz->process == HF_PERM1) {
|
|
|
+ thispitch = fmod(hfset[k][note],12.0);
|
|
|
+ thatpitch = fmod(hfset[j][note],12.0);
|
|
|
+ } else {
|
|
|
+ thispitch = hfset[k][note];
|
|
|
+ thatpitch = hfset[j][note];
|
|
|
+ }
|
|
|
+ while(flteq(thatpitch,thispitch)) {
|
|
|
+ if(!in_grp) {
|
|
|
+ grping[grping_cnt++] = k; /* mark start of group */
|
|
|
+ in_grp = 1;
|
|
|
+ }
|
|
|
+ if(++j >= m)
|
|
|
+ break;
|
|
|
+ if(dz->process == HF_PERM1) {
|
|
|
+ thispitch = fmod(hfset[k][note],12.0);
|
|
|
+ thatpitch = fmod(hfset[j][note],12.0);
|
|
|
+ } else {
|
|
|
+ thispitch = hfset[k][note];
|
|
|
+ thatpitch = hfset[j][note];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(in_grp) { /* sort all these into density:tessitura order */
|
|
|
+ grping[grping_cnt++] = -j; /* mark end of group */
|
|
|
+ sort_by_maxint(hfset,k,j,setlen,dz);
|
|
|
+ in_grp = 0; /* sort same-root sets into interval size and stack order */
|
|
|
+ }
|
|
|
+ k = j;
|
|
|
+ j = k+1;
|
|
|
+ }
|
|
|
+ n = m;
|
|
|
+ m = n+1;
|
|
|
+ }
|
|
|
+ return(grping_cnt);
|
|
|
+}
|
|
|
+
|
|
|
+/********************************* SORT_BY_MAXINT *********************************
|
|
|
+ *
|
|
|
+ * Sort pitch-ordered sets of FIXED SIZE by size of largest interval, then by interval density
|
|
|
+ */
|
|
|
+
|
|
|
+void sort_by_maxint(double **hfset,int n,int m,int setlen,dataptr dz)
|
|
|
+{
|
|
|
+ int j, k;
|
|
|
+ double j_maxint, k_maxint, *tempoint;
|
|
|
+ int end = setlen - 1;
|
|
|
+ int in_grp;
|
|
|
+
|
|
|
+ for(j=n;j<m-1;j++) { /* sort all by size of largest interval */
|
|
|
+ j_maxint = hfset[j][end] - hfset[j][0];
|
|
|
+ for(k=j+1;k<m;k++) {
|
|
|
+ k_maxint = hfset[k][end] - hfset[k][0];
|
|
|
+ switch(dz->vflag[HP1_SPAN]) {
|
|
|
+ case(MAXSPAN_FIRST):
|
|
|
+ if(k_maxint < j_maxint) {
|
|
|
+ tempoint = hfset[j];
|
|
|
+ hfset[j] = hfset[k];
|
|
|
+ hfset[k] = tempoint;
|
|
|
+ j_maxint = k_maxint;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case(MAXSPAN_LAST):
|
|
|
+ if(k_maxint > j_maxint) {
|
|
|
+ tempoint = hfset[j];
|
|
|
+ hfset[j] = hfset[k];
|
|
|
+ hfset[k] = tempoint;
|
|
|
+ j_maxint = k_maxint;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ k = n;
|
|
|
+ j = k+1;
|
|
|
+ in_grp = 0;
|
|
|
+ while(j < m) { /* sort largest-interval sets by internal interval arrangement */
|
|
|
+ in_grp = 0;
|
|
|
+ k_maxint = hfset[k][end] - hfset[k][0];
|
|
|
+ j_maxint = hfset[j][end] - hfset[j][0];
|
|
|
+ while(flteq(j_maxint,k_maxint)) {
|
|
|
+ in_grp = 1;
|
|
|
+ if(++j >= m)
|
|
|
+ break;
|
|
|
+ j_maxint = hfset[j][end] - hfset[j][0];
|
|
|
+ }
|
|
|
+ if(in_grp) {
|
|
|
+ switch(dz->vflag[HP1_DENS]) {
|
|
|
+ case(DENSE_SORT): sort_by_density(hfset,k,j,setlen,0); break;
|
|
|
+ case(OTHER_SORT): sort_by_interval_stacking(hfset,k,j,setlen,0); break;
|
|
|
+ }
|
|
|
+ sort_by_octave_equivalence(hfset,n,m,setlen);
|
|
|
+ }
|
|
|
+ k = j;
|
|
|
+ j = k+1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/********************************* SORT_BY_DENSITY *********************************
|
|
|
+ *
|
|
|
+ * Sort pitch-ordered sets of FIXED SIZE , WITH FIXED MAX INTERVAL by density...
|
|
|
+ * measure the deviation from the mean inteval size between adjacent notes.
|
|
|
+ * Minimum deviation = minimum density.
|
|
|
+ */
|
|
|
+
|
|
|
+void sort_by_density(double **hfset,int n,int m,int setlen,int lowest)
|
|
|
+{
|
|
|
+ int j, k, x;
|
|
|
+ double j_deviation, k_deviation, y, average_intsize;
|
|
|
+ double *tempoint;
|
|
|
+
|
|
|
+ average_intsize = (hfset[n][setlen-1] - hfset[n][0])/(setlen-1);
|
|
|
+
|
|
|
+ for(j=n;j<m-1;j++) {
|
|
|
+ j_deviation = 0;
|
|
|
+ for(x = 1; x < setlen; x++) {
|
|
|
+ y = hfset[j][x] - hfset[j][x-1];
|
|
|
+ y = fabs(y - average_intsize);
|
|
|
+ j_deviation += y; /* no advantage in taking rms */
|
|
|
+ }
|
|
|
+ for(k=j+1;k<m;k++) {
|
|
|
+ k_deviation = 0;
|
|
|
+ for(x = 1; x < setlen; x++) {
|
|
|
+ y = hfset[k][x] - hfset[k][x-1];
|
|
|
+ y = fabs(y - average_intsize);
|
|
|
+ k_deviation += y; /* no advantage in taking rms */
|
|
|
+ }
|
|
|
+ if(lowest) {
|
|
|
+ if(k_deviation < j_deviation) {
|
|
|
+ tempoint = hfset[k];
|
|
|
+ hfset[k] = hfset[j];
|
|
|
+ hfset[j] = tempoint;
|
|
|
+ j_deviation = k_deviation;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if(k_deviation > j_deviation) {
|
|
|
+ tempoint = hfset[k];
|
|
|
+ hfset[k] = hfset[j];
|
|
|
+ hfset[j] = tempoint;
|
|
|
+ j_deviation = k_deviation;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/********************************* SORT_BY_MAXINTSIZE_AND_DENSITY *********************************
|
|
|
+ *
|
|
|
+ * Sort pitch-ordered sets of FIXED SIZE , NOT of FIXED MAX INTERVAL by density...
|
|
|
+ * measure the deviation from the mean inteval size between adjacent notes.
|
|
|
+ * Minimum deviation = minimum density.
|
|
|
+ */
|
|
|
+
|
|
|
+void sort_by_maxintsize_and_density(double **hfset,int n,int m,int setlen,int lowest)
|
|
|
+{
|
|
|
+ int j, k, end = setlen - 1, in_grp;
|
|
|
+ double j_intsize, k_intsize;
|
|
|
+ double *tempoint;
|
|
|
+
|
|
|
+ for(j=n;j<m-1;j++) { /* sort by max-intsize */
|
|
|
+ j_intsize = hfset[j][end] - hfset[j][0];
|
|
|
+ for(k=j+1;k<m;k++) {
|
|
|
+ k_intsize = hfset[k][end] - hfset[k][0];
|
|
|
+ if(k_intsize < j_intsize) {
|
|
|
+ tempoint = hfset[k];
|
|
|
+ hfset[k] = hfset[j];
|
|
|
+ hfset[j] = tempoint;
|
|
|
+ j_intsize = k_intsize;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ j = n;
|
|
|
+ k = j+1;
|
|
|
+ while(k < m) {
|
|
|
+ j_intsize = hfset[j][end] - hfset[j][0];
|
|
|
+ in_grp = 0;
|
|
|
+ while(flteq(hfset[k][end] - hfset[k][0],j_intsize)) {
|
|
|
+ in_grp = 1;
|
|
|
+ if(++k >= m)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(in_grp)
|
|
|
+ sort_by_density(hfset,j,k,setlen,lowest);
|
|
|
+ j = k;
|
|
|
+ k = j+1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/********************************* SORT_BY_OCTAVE_EQUIVALENCE *********************************
|
|
|
+ *
|
|
|
+ * Sort pitch-ordered sets of FIXED SIZE by equivalence at octave transposition, putting lower tessitura item first.
|
|
|
+ */
|
|
|
+
|
|
|
+void sort_by_octave_equivalence
|
|
|
+ (double **hfset,int n,int m,int setlen)
|
|
|
+{
|
|
|
+ int i, j, j_base, j_adj, k, oct_equivalence;
|
|
|
+ double *tempoint, int_diff;
|
|
|
+
|
|
|
+ for(j=n;j<m-1;j++) {
|
|
|
+ j_base = j;
|
|
|
+ j_adj = j+1; /* if sets are separate by multiple of an octave */
|
|
|
+ for(k=j+1;k<m;k++) {
|
|
|
+ if(flteq(fmod((int_diff = hfset[k][0] - hfset[j][0]),12.0),0.0)) {
|
|
|
+ oct_equivalence = 1;
|
|
|
+ for(n=1;n<setlen;n++) {
|
|
|
+ if(!flteq(hfset[k][n] - hfset[j][n],int_diff)) {
|
|
|
+ oct_equivalence = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(oct_equivalence) { /* if oct-equivalent */
|
|
|
+ if(k != j_adj) { /* if NOT adjacent */
|
|
|
+ tempoint = hfset[j_adj];
|
|
|
+ hfset[j_adj] = hfset[k]; /* move oct-equiv set to be adjacent to j */
|
|
|
+ hfset[k] = tempoint;
|
|
|
+ }
|
|
|
+ i = j;
|
|
|
+ while(hfset[j_adj][0] < hfset[i][0]) {
|
|
|
+ if(--i < j_base)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ i++;
|
|
|
+ if(i<=j) {
|
|
|
+ tempoint = hfset[i];
|
|
|
+ hfset[i] = hfset[j_adj]; /* move lower register item to correct place in group */
|
|
|
+ hfset[j_adj] = tempoint;
|
|
|
+ }
|
|
|
+ j++; /* advance to new oct-equiv position */
|
|
|
+ j_adj++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/********************************* SORT_BY_INTERVAL_STACKING *********************************
|
|
|
+ *
|
|
|
+ * Sort pitch-ordered sets of FIXED SIZE , WITH FIXED MAX INTERVAL by sequnce of pitches within...
|
|
|
+ * NORMALLY - start with chord having the lowest pitches (on average)
|
|
|
+ * ... if 'highest-first' flag set, start with chord with highest pitches (on average)
|
|
|
+ */
|
|
|
+
|
|
|
+void sort_by_interval_stacking(double **hfset,int n,int m,int setlen,int highest_first)
|
|
|
+{
|
|
|
+ int j, k, x;
|
|
|
+ double j_height, k_height;
|
|
|
+ double *tempoint;
|
|
|
+
|
|
|
+ for(j=n;j<m-1;j++) {
|
|
|
+ j_height = 0;
|
|
|
+ for(x = 1; x < setlen; x++)
|
|
|
+ j_height += hfset[j][x] - hfset[j][0];
|
|
|
+ for(k=j+1;k<m;k++) {
|
|
|
+ k_height = 0;
|
|
|
+ for(x = 1; x < setlen; x++)
|
|
|
+ k_height += hfset[k][x] - hfset[k][0];
|
|
|
+ if(highest_first) {
|
|
|
+ if(k_height > j_height) {
|
|
|
+ tempoint = hfset[k];
|
|
|
+ hfset[k] = hfset[j];
|
|
|
+ hfset[j] = tempoint;
|
|
|
+ j_height = k_height;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if(k_height < j_height) {
|
|
|
+ tempoint = hfset[k];
|
|
|
+ hfset[k] = hfset[j];
|
|
|
+ hfset[j] = tempoint;
|
|
|
+ j_height = k_height;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/********************************* ELIMINATE_OCT_DUPLICATED_SETS *********************************
|
|
|
+ *
|
|
|
+ * Sort ordered-by-size, then pitch-ordered sets, eliniating stes dupliated at 8vas.
|
|
|
+ */
|
|
|
+
|
|
|
+void eliminate_oct_duplicated_sets(double **hfset,int *hfsetcnt,int *hfsetlen,int *grping,int *grping_cnt,int type)
|
|
|
+{
|
|
|
+ int a, b, n, m, j, k, oct_equivalence, setlen;
|
|
|
+ double *tempoint, int_diff;
|
|
|
+
|
|
|
+ n=0;
|
|
|
+ m = n+1;
|
|
|
+ setlen = hfsetlen[n];
|
|
|
+ while(n < *hfsetcnt) {
|
|
|
+ while(hfsetlen[m] == setlen) { /* find equal-size sets */
|
|
|
+ if(++m >= *hfsetcnt)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(m == n+1) {
|
|
|
+ n++;
|
|
|
+ if((m = n+1) >= *hfsetcnt)
|
|
|
+ break;
|
|
|
+ setlen = hfsetlen[n];
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ for(j=n;j<m-1;j++) {
|
|
|
+ for(k = j+1;k<m;k++) {
|
|
|
+ if(flteq(fmod((int_diff = hfset[k][0] - hfset[j][0]),12.0),0.0)) {
|
|
|
+ oct_equivalence = 1;
|
|
|
+ for(a=1;a<setlen;a++) {
|
|
|
+ if(!flteq(hfset[k][a] - hfset[j][a],int_diff)) {
|
|
|
+ oct_equivalence = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(oct_equivalence) { /* if oct-equivalent */
|
|
|
+ if(type == TOPNOTE) {
|
|
|
+ if(hfset[k][0] > hfset[j][0]) {
|
|
|
+ tempoint = hfset[j];
|
|
|
+ hfset[j] = hfset[k]; /* keep the higher-register item */
|
|
|
+ hfset[k] = tempoint;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if(hfset[k][0] < hfset[j][0]) {
|
|
|
+ tempoint = hfset[j];
|
|
|
+ hfset[j] = hfset[k]; /* keep the lower-register item */
|
|
|
+ hfset[k] = tempoint;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for(a=k,b=k+1;b<*hfsetcnt;a++,b++) /* delete unwanted set */
|
|
|
+ hfset[a] = hfset[b];
|
|
|
+ if(grping != NULL) { /* reposition grouping marks */
|
|
|
+ for(a=0;a<*grping_cnt;a++) {
|
|
|
+ /* if start or end of short group */
|
|
|
+ if(((grping[a] == k) && (a+1 < *grping_cnt) && (grping[a+1] >= -(k+2)))
|
|
|
+ || ((grping[a] == k-1) && (a+1 < *grping_cnt) && (grping[a+1] >= -(k+1)))) {
|
|
|
+ if(a+2 < *grping_cnt) { /* eliminate both */
|
|
|
+ for(b = a+2; b < *grping_cnt;b++)
|
|
|
+ grping[b-2] = grping[b];
|
|
|
+ }
|
|
|
+ *grping_cnt -= 2;
|
|
|
+ a -= 1; /* step back to resume parse */
|
|
|
+ }
|
|
|
+ else if(grping[a] > k) /* decrement all markers beyond */
|
|
|
+ grping[a]--;
|
|
|
+ else if(grping[a] < -k)
|
|
|
+ grping[a]++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ (*hfsetcnt)--; /* decrement all counters */
|
|
|
+ m--;
|
|
|
+ k--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ n = m;
|
|
|
+ if((m = n+1) >= *hfsetcnt)
|
|
|
+ break;
|
|
|
+ setlen = hfsetlen[n];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/********************************* SORT_BY_DENSITY_REGARDLESS_OF_SIZE *********************************
|
|
|
+ *
|
|
|
+ * Sort pitch-ordered sets of FIXED LENGTH . by density, regardless of MAX INTERVAL...
|
|
|
+ * .... sort on basis of maximum number of minsize intervals.
|
|
|
+ */
|
|
|
+
|
|
|
+void sort_by_density_regardless_of_size
|
|
|
+ (double **hfset,double *interv,int *intervcnt,double *interv2,int *intervcnt2,int n,int m,int setlen,int densest_first)
|
|
|
+{
|
|
|
+ int a, j, k, x, q, do_swap, equivalent;
|
|
|
+ double tempdb, *tempoint;
|
|
|
+ int intsetlen1 = setlen - 1;
|
|
|
+ int intsetlen2 = setlen - 1;
|
|
|
+ int tempoi, end = setlen - 1;
|
|
|
+ double *intv = interv, *intv2 = interv2;
|
|
|
+ int *intvcnt = intervcnt, *intvcnt2 = intervcnt2, *tempii;
|
|
|
+
|
|
|
+ for(j=n;j<m-1;j++) {
|
|
|
+ intsetlen1 = setlen - 1;
|
|
|
+ for(x=1;x<setlen;x++) {
|
|
|
+ intv[x-1] = hfset[j][x] - hfset[j][x-1]; /* find each interval and count it */
|
|
|
+ intvcnt[x-1] = 1;
|
|
|
+ }
|
|
|
+ for(x=0;x<intsetlen1-1;x++) {
|
|
|
+ for(q=x+1;q<intsetlen1;q++) {
|
|
|
+ if(flteq(intv[q],intv[x])) { /* compare intervals */
|
|
|
+ intvcnt[x]++; /* if same, incr count of first */
|
|
|
+ a = q;
|
|
|
+ while(a< intsetlen1-1) { /* and eliminate other from set */
|
|
|
+ intv[a] = intv[a+1];
|
|
|
+ a++;
|
|
|
+ }
|
|
|
+ intsetlen1--;
|
|
|
+ q--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for(x=0;x<intsetlen1-1;x++) { /* sort intervals by size */
|
|
|
+ for(q=x+1;q<intsetlen1;q++) {
|
|
|
+ if(intv[q] < intv[x]) {
|
|
|
+ tempdb = intv[q];
|
|
|
+ intv[q] = intv[x];
|
|
|
+ intv[x] = tempdb;
|
|
|
+ tempoi = intvcnt[q];
|
|
|
+ intvcnt[q] = intvcnt[x];
|
|
|
+ intvcnt[x] = tempoi;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for(k=j+1;k<m;k++) {
|
|
|
+ intsetlen2 = setlen - 1;
|
|
|
+ for(x=1;x<setlen;x++) {
|
|
|
+ intv2[x-1] = hfset[k][x] - hfset[k][x-1];
|
|
|
+ intvcnt2[x-1] = 1;
|
|
|
+ }
|
|
|
+ for(x=0;x<intsetlen2-1;x++) {
|
|
|
+ for(q=x+1;q<intsetlen2;q++) {
|
|
|
+ if(flteq(intv2[q],intv2[x])) {
|
|
|
+ intvcnt2[x]++;
|
|
|
+ a = q;
|
|
|
+ while(a < intsetlen2-1) {
|
|
|
+ intv2[a] = intv2[a+1];
|
|
|
+ a++;
|
|
|
+ }
|
|
|
+ intsetlen2--;
|
|
|
+ q--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for(x=0;x<intsetlen2-1;x++) {
|
|
|
+ for(q=x+1;q<intsetlen2;q++) {
|
|
|
+ if(intv2[q] < intv2[x]) {
|
|
|
+ tempdb = intv2[q];
|
|
|
+ intv2[q] = intv2[x];
|
|
|
+ intv2[x] = tempdb;
|
|
|
+ tempoi = intvcnt2[q];
|
|
|
+ intvcnt2[q] = intvcnt2[x];
|
|
|
+ intvcnt2[x] = tempoi;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ do_swap = 0;
|
|
|
+ equivalent = 1;
|
|
|
+ if(densest_first) {
|
|
|
+ for(a=0;a<min(intsetlen1,intsetlen2);a++) {
|
|
|
+ if(intv2[a] > intv[a]) {
|
|
|
+ equivalent = 0;
|
|
|
+ break;
|
|
|
+ } else if(intv2[a] < intv[a]) {
|
|
|
+ equivalent = 0;
|
|
|
+ do_swap = 1;
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ if(intvcnt2[a] > intvcnt[a]) {
|
|
|
+ equivalent = 0;
|
|
|
+ do_swap = 1;
|
|
|
+ break;
|
|
|
+ } else if(intvcnt2[a] < intvcnt[a]) {
|
|
|
+ equivalent = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for(a=0;a<min(intsetlen1,intsetlen2);a++) {
|
|
|
+ if(intv2[a] < intv[a]) {
|
|
|
+ equivalent = 0;
|
|
|
+ break;
|
|
|
+ } else if(intv2[a] > intv[a]) {
|
|
|
+ equivalent = 0;
|
|
|
+ do_swap = 1;
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ if(intvcnt2[a] < intvcnt[a]) {
|
|
|
+ equivalent = 0;
|
|
|
+ do_swap = 1;
|
|
|
+ break;
|
|
|
+ } else if(intvcnt2[a] > intvcnt[a]) {
|
|
|
+ equivalent = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if((!do_swap) && equivalent) { /* swap if total range is greater */
|
|
|
+ if(hfset[j][end] - hfset[j][0] > hfset[k][end] - hfset[k][0])
|
|
|
+ do_swap = 1;
|
|
|
+ else if(hfset[j][0] > hfset[k][0]) /* swap if root is lower */
|
|
|
+ do_swap = 1;
|
|
|
+ }
|
|
|
+ if(do_swap) {
|
|
|
+ tempoint = hfset[k];
|
|
|
+ hfset[k] = hfset[j];
|
|
|
+ hfset[j] = tempoint;
|
|
|
+ tempoint = intv;
|
|
|
+ intv = intv2;
|
|
|
+ intv2 = tempoint;
|
|
|
+ tempii = intvcnt ;
|
|
|
+ intvcnt = intvcnt2;
|
|
|
+ intvcnt2 = tempii;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/******************************* SETUP_NAMING ******************************/
|
|
|
+
|
|
|
+int setup_naming(char **thisfilename,dataptr dz)
|
|
|
+{
|
|
|
+ int innamelen = strlen(dz->wordstor[0]);
|
|
|
+ int numlen = 5;
|
|
|
+// FEB 2010 TW
|
|
|
+ if((*thisfilename = (char *)malloc((innamelen + numlen + 10) * sizeof(char)))==NULL) {
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for outfilename.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/********************************** CREATE_OUTFILE_NAME ********************************/
|
|
|
+
|
|
|
+int create_outfile_name(int ccnt,char *thisfilename,dataptr dz)
|
|
|
+{
|
|
|
+ strcpy(thisfilename,dz->wordstor[0]);
|
|
|
+// FEB 2010 TW
|
|
|
+ if(!sloom)
|
|
|
+ insert_separator_on_sndfile_name(thisfilename,1);
|
|
|
+ insert_new_number_at_filename_end(thisfilename,ccnt,1);
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/********************************** GEN_NOTE ********************************/
|
|
|
+
|
|
|
+void gen_note(int maxjitter,double *tabstart,double *tabend,double **tabmin, double **tabmax,double **hfset,
|
|
|
+ double tabscale,double sintabsize,int splicelen, double *sintab,int n, int j)
|
|
|
+{
|
|
|
+ int jitter, initial_phase, i;
|
|
|
+ double *this_tabend, *startsplice_end, *endsplice_start, *tab;
|
|
|
+ double sintabpos, sintabincr;
|
|
|
+ int intpos, nxtpos;
|
|
|
+ double frac, vallo, valhi, valdif;
|
|
|
+
|
|
|
+ jitter = (int)round(drand48() * maxjitter);
|
|
|
+ tab = tabstart + jitter;
|
|
|
+ this_tabend = tabend + jitter;
|
|
|
+ *tabmin = min(tab,*tabmin);
|
|
|
+ *tabmax = max(this_tabend,*tabmax);
|
|
|
+ tab++; /* 1st val = 0 */
|
|
|
+ /* START POSITION IN TABLE TO READ TO GENERATE SOUND */
|
|
|
+ initial_phase = (int)round(drand48() * HFP_TABSIZE);
|
|
|
+ sintabincr = (miditohz(hfset[n][j]) * tabscale);
|
|
|
+ sintabpos = sintabincr + initial_phase;
|
|
|
+ sintabpos = fmod(sintabpos,sintabsize);
|
|
|
+ startsplice_end = tab + splicelen;
|
|
|
+ endsplice_start = this_tabend - splicelen;
|
|
|
+ /* START OF EACH CONSTITUENT MUST BE SPLICED */
|
|
|
+ i = 0;
|
|
|
+ while(tab < startsplice_end) {
|
|
|
+ intpos = (int)floor(sintabpos);
|
|
|
+ nxtpos = intpos+1;
|
|
|
+ frac = sintabpos - (double)intpos;
|
|
|
+ vallo = sintab[intpos];
|
|
|
+ valhi = sintab[nxtpos];
|
|
|
+ valdif= valhi - vallo;
|
|
|
+ *tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
|
|
|
+ i++;
|
|
|
+ sintabpos += sintabincr;
|
|
|
+ sintabpos = fmod(sintabpos,sintabsize);
|
|
|
+ tab++;
|
|
|
+ }
|
|
|
+ while(tab < endsplice_start) {
|
|
|
+ intpos = (int)floor(sintabpos);
|
|
|
+ nxtpos = intpos+1;
|
|
|
+ frac = sintabpos - (double)intpos;
|
|
|
+ vallo = sintab[intpos];
|
|
|
+ valhi = sintab[nxtpos];
|
|
|
+ valdif= valhi - vallo;
|
|
|
+ *tab += vallo + (valdif * frac);
|
|
|
+ sintabpos += sintabincr;
|
|
|
+ sintabpos = fmod(sintabpos,sintabsize);
|
|
|
+ tab++;
|
|
|
+ }
|
|
|
+ /* END OF EACH CONSTITUENT MUST BE SPLICED */
|
|
|
+ i = splicelen - 1;
|
|
|
+ while(tab < this_tabend) {
|
|
|
+ intpos = (int)floor(sintabpos);
|
|
|
+ nxtpos = intpos+1;
|
|
|
+ frac = sintabpos - (double)intpos;
|
|
|
+ vallo = sintab[intpos];
|
|
|
+ valhi = sintab[nxtpos];
|
|
|
+ valdif= valhi - vallo;
|
|
|
+ *tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
|
|
|
+ i--;
|
|
|
+ sintabpos += sintabincr;
|
|
|
+ sintabpos = fmod(sintabpos,sintabsize);
|
|
|
+ tab++;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/********************************** NEXT_FILE ********************************/
|
|
|
+
|
|
|
+int next_file(int *samps_written,char *thisfilename,int *ccnt,unsigned int *space_needed,
|
|
|
+int *samp_space_available,dataptr dz)
|
|
|
+{
|
|
|
+ int exit_status;
|
|
|
+ /* FLUSH BUFS */
|
|
|
+ *samps_written += dz->iparam[HP1_GAP_SIZE];
|
|
|
+ while(*samps_written >= dz->buflen) {
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ *samps_written -= dz->buflen;
|
|
|
+ }
|
|
|
+ if(*samps_written > 0) {
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],*samps_written,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ }
|
|
|
+ /* CLOSE FILE */
|
|
|
+ dz->outfiletype = SNDFILE_OUT; /* allows header to be written */
|
|
|
+ if((exit_status = headwrite(dz->ofd,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ dz->process_type = OTHER_PROCESS; /* restore true status */
|
|
|
+ dz->outfiletype = NO_OUTPUTFILE; /* restore true status */
|
|
|
+ superzargo += dz->total_samps_written; /* accumulator of total samples written */
|
|
|
+ if((exit_status = reset_peak_finder(dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ if(sndcloseEx(dz->ofd) < 0) {
|
|
|
+ fprintf(stdout,"WARNING: Can't close output soundfile %s\n",thisfilename);
|
|
|
+ fflush(stdout);
|
|
|
+ }
|
|
|
+ dz->ofd = -1;
|
|
|
+ (*ccnt)++;
|
|
|
+ /* OPEN NEW FILE */
|
|
|
+ if((exit_status = create_outfile_name(*ccnt,thisfilename,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ dz->process_type = UNEQUAL_SNDFILE; /* allow sndfile to be created */
|
|
|
+ if((exit_status = create_sized_outfile(thisfilename,dz))<0) {
|
|
|
+ fprintf(stdout, "WARNING: Soundfile %s already exists.\n",thisfilename);
|
|
|
+ fflush(stdout);
|
|
|
+ dz->process_type = OTHER_PROCESS;
|
|
|
+ dz->ofd = -1;
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
+ }
|
|
|
+ *space_needed -= dz->total_samps_written;
|
|
|
+ if((unsigned int)dz->outfilesize < *space_needed) {
|
|
|
+ sprintf(errstr,"Insufficient space on the hard disk to store the next output file.\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ /* RESET BUFFERS */
|
|
|
+ dz->total_samps_written = 0;
|
|
|
+ memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
|
|
|
+ *samp_space_available = dz->buflen;
|
|
|
+ *samps_written = 0;
|
|
|
+//NEW TW
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/********************************** GEN_DP_OUTPUT ********************************/
|
|
|
+
|
|
|
+int gen_dp_output(dataptr dz)
|
|
|
+{
|
|
|
+ int exit_status;
|
|
|
+ float *obuf = dz->sampbuf[0];
|
|
|
+ double *tabend, *tab = (double *)dz->sampbuf[3];
|
|
|
+ double *accumtab = (double *)dz->sampbuf[2];
|
|
|
+ double *perm = dz->parray[1];
|
|
|
+ double tabscale = (double)HFP_TABSIZE/dz->infile->srate;
|
|
|
+ double *sintab = (double *)dz->sampbuf[1];
|
|
|
+ float *intab = dz->sampbuf[1];
|
|
|
+ double sintabsize, pad;
|
|
|
+ int intabsize;
|
|
|
+ int samps_written = 0, samp_space_available, samps_to_write;
|
|
|
+ int note_being_permed, noteno, index_in_new_perm, index_in_last_perm, i, j, no_of_perms, permcounter, transpos_cnt;
|
|
|
+ int maxjitter = (int)round(drand48() * HFP_MAXJITTER * MS_TO_SECS * (double)dz->infile->srate);
|
|
|
+ unsigned int element_byte_len = dz->iparam[DP_DUR] * sizeof(double);
|
|
|
+ unsigned int element_full_len = element_byte_len + (maxjitter * sizeof(double));
|
|
|
+ double *tabmin = accumtab, *tabmax = accumtab + dz->iparam[DP_DUR] + maxjitter;
|
|
|
+ int splicelen = (int)round(HP1_SPLICELEN * MS_TO_SECS * (double)dz->infile->srate);
|
|
|
+ double ampmult = 1.0/(double)(dz->iparam[DP_CYCCNT] + 1);
|
|
|
+ double *permset, thistranspos;
|
|
|
+ int accumtabstart, accumtabend, a, b;
|
|
|
+ int jitter, endindex_of_last_perm, endindex_of_last_perm_but_one, endindex_in_new_perm = 0, len, thislen;
|
|
|
+
|
|
|
+/* JUNE 2004 */
|
|
|
+sprintf(errstr,"ERROR: This program is currently malfunctioning.\n");
|
|
|
+return(PROGRAM_ERROR);
|
|
|
+/* JUNE 2004 */
|
|
|
+ switch(dz->process) {
|
|
|
+ case(DEL_PERM):
|
|
|
+ sintabsize = (double)HFP_TABSIZE;
|
|
|
+ ampmult *= MAXSAMP;
|
|
|
+ break;
|
|
|
+ case(DEL_PERM2):
|
|
|
+ intabsize = dz->iparam[DP_DUR];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ dz->tempsize = dz->iparam[DP_DUR] * (dz->iparam[DP_NOTECNT] + dz->iparam[DP_CYCCNT]);
|
|
|
+
|
|
|
+ if((permset =
|
|
|
+ (double *)malloc((unsigned int)round(pow(dz->iparam[DP_PERMCNT],dz->iparam[DP_CYCCNT])) * sizeof(double))) == NULL) {
|
|
|
+ sprintf(errstr,"No memory for permutations of notes\n");
|
|
|
+ return(MEMORY_ERROR);
|
|
|
+ }
|
|
|
+ for(noteno = 0; noteno < dz->iparam[DP_NOTECNT]/* + dz->iparam[DP_CYCCNT]*/; noteno++) {
|
|
|
+ sprintf(errstr,"Expanding note %d\n",noteno+1);
|
|
|
+ print_outmessage_flush(errstr);
|
|
|
+ memset(accumtab,0,element_full_len);
|
|
|
+ for(note_being_permed = noteno, no_of_perms = 0;
|
|
|
+ note_being_permed >= max(0,noteno - dz->iparam[DP_CYCCNT]);
|
|
|
+ note_being_permed--, no_of_perms++) {
|
|
|
+ if(note_being_permed >= dz->iparam[DP_NOTECNT])
|
|
|
+ continue;
|
|
|
+ jitter = (int)(drand48() * maxjitter);
|
|
|
+ accumtabstart = jitter;
|
|
|
+ permset[0] = dz->parray[1][note_being_permed];
|
|
|
+ endindex_of_last_perm = 0;
|
|
|
+ endindex_of_last_perm_but_one = 0;
|
|
|
+ for(permcounter = 0; permcounter < no_of_perms; permcounter++) {
|
|
|
+ index_in_last_perm = endindex_of_last_perm;
|
|
|
+ endindex_in_new_perm = ((index_in_last_perm+1) * dz->iparam[DP_PERMCNT]) - 1;
|
|
|
+ index_in_new_perm = endindex_in_new_perm;
|
|
|
+ while(index_in_last_perm >= 0) {
|
|
|
+ for(transpos_cnt = dz->iparam[DP_PERMCNT]-1; transpos_cnt >= 0; transpos_cnt--)
|
|
|
+ permset[index_in_new_perm--] = permset[index_in_last_perm] + perm[transpos_cnt];
|
|
|
+ index_in_last_perm--;
|
|
|
+ }
|
|
|
+ endindex_of_last_perm_but_one = endindex_of_last_perm;
|
|
|
+ endindex_of_last_perm = endindex_in_new_perm;
|
|
|
+ }
|
|
|
+ tab = (double *)dz->sampbuf[3];
|
|
|
+ if(no_of_perms > 0) {
|
|
|
+ if((len = (int)round((double)dz->iparam[DP_DUR]/(double)(endindex_of_last_perm_but_one+1))) <= splicelen * 2) {
|
|
|
+ sprintf(errstr,"Notes have become too short for splices to be made.\n");
|
|
|
+ return(GOAL_FAILED);
|
|
|
+ }
|
|
|
+ for(i = 0, j = 0; i <= endindex_of_last_perm; i++, j++) {
|
|
|
+ j %= dz->iparam[DP_PERMCNT];
|
|
|
+ switch(dz->process) {
|
|
|
+ case(DEL_PERM):
|
|
|
+ thislen = (int)round(len * dz->parray[2][j]);
|
|
|
+ if(thislen <= splicelen * 2) {
|
|
|
+ sprintf(errstr,"Notes have become too short for splices to be made.\n");
|
|
|
+ return(GOAL_FAILED);
|
|
|
+ }
|
|
|
+ tabend = tab + thislen;
|
|
|
+ memset((char *)tab,0,element_byte_len);
|
|
|
+
|
|
|
+ gen_note2(tab,tabend,permset[i],tabscale,sintabsize,splicelen,sintab); break;
|
|
|
+ case(DEL_PERM2):
|
|
|
+ thistranspos = pow(2.0,(permset[i]/12.0));
|
|
|
+ thislen = (int)round(len/thistranspos);
|
|
|
+ thislen = min(thislen,len);
|
|
|
+ if(thislen <= splicelen * 2) {
|
|
|
+ sprintf(errstr,"Notes have become too short for splices to be made.\n");
|
|
|
+ return(GOAL_FAILED);
|
|
|
+ }
|
|
|
+ tabend = tab + thislen;
|
|
|
+ memset((char *)tab,0,element_byte_len);
|
|
|
+ gen_note3(tab,tabend,thistranspos,intabsize,splicelen,intab); break;
|
|
|
+ }
|
|
|
+ accumtabstart = accumtabstart + thislen;
|
|
|
+ accumtabend = accumtabstart + thislen;
|
|
|
+ pad = pow(ROLLOFF,no_of_perms);
|
|
|
+ accumtabstart += thislen;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ len = dz->iparam[DP_DUR];
|
|
|
+ tabend = tab + len;
|
|
|
+ memset(tab,0,element_byte_len);
|
|
|
+ switch(dz->process) {
|
|
|
+ case(DEL_PERM): gen_note2(tab,tabend,permset[0],tabscale,sintabsize,splicelen,sintab); break;
|
|
|
+ case(DEL_PERM2): gen_note3(tab,tabend,permset[0],intabsize,splicelen,intab); break;
|
|
|
+ }
|
|
|
+ accumtabend = accumtabstart + len;
|
|
|
+ for(a=accumtabstart, b = 0; a < accumtabend;a++,b++)
|
|
|
+ accumtab[a] += tab[b];
|
|
|
+ accumtabstart += len;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* DO OUTPUT */
|
|
|
+ samp_space_available = dz->buflen - samps_written;
|
|
|
+ i = 0;
|
|
|
+ samps_to_write = tabmax - tabmin;
|
|
|
+ while(i < samps_to_write) {
|
|
|
+ if(samp_space_available > samps_to_write) {
|
|
|
+ while(i < samps_to_write)
|
|
|
+ obuf[samps_written++] = (float)(accumtab[i++] * ampmult);
|
|
|
+ } else {
|
|
|
+ while(samps_written < dz->buflen)
|
|
|
+ obuf[samps_written++] = (float)(accumtab[i++] * ampmult);
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ memset((char *)dz->sampbuf[0],0,(size_t)dz->buflen * sizeof(float));
|
|
|
+ samps_written = 0;
|
|
|
+ samp_space_available = dz->buflen;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ while(samps_written >= dz->buflen) {
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],dz->buflen,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ samps_written -= dz->buflen;
|
|
|
+ }
|
|
|
+ if(samps_written > 0) {
|
|
|
+ if((exit_status = write_samps(dz->sampbuf[0],samps_written,dz))<0)
|
|
|
+ return(exit_status);
|
|
|
+ }
|
|
|
+ return(FINISHED);
|
|
|
+}
|
|
|
+
|
|
|
+/********************************** GEN_NOTE2 ********************************/
|
|
|
+
|
|
|
+void gen_note2(double *tabstart,double *tabend,double midival,
|
|
|
+ double tabscale,double sintabsize,int splicelen, double *sintab)
|
|
|
+{
|
|
|
+ int initial_phase, i;
|
|
|
+ double *startsplice_end, *endsplice_start, *tab;
|
|
|
+ double sintabpos, sintabincr;
|
|
|
+ int intpos, nxtpos;
|
|
|
+ double frac, vallo, valhi, valdif;
|
|
|
+
|
|
|
+ tab = tabstart;
|
|
|
+ *tab++ = 0; /* 1st val = 0 */
|
|
|
+ /* START POSITION IN TABLE TO READ TO GENERATE SOUND */
|
|
|
+ initial_phase = (int)round(drand48() * HFP_TABSIZE);
|
|
|
+ sintabincr = (miditohz(midival) * tabscale);
|
|
|
+ sintabpos = sintabincr + initial_phase;
|
|
|
+ sintabpos = fmod(sintabpos,sintabsize);
|
|
|
+ startsplice_end = tab + splicelen;
|
|
|
+ endsplice_start = tabend - splicelen;
|
|
|
+ /* START OF EACH CONSTITUENT MUST BE SPLICED */
|
|
|
+ i = 0;
|
|
|
+ while(tab < startsplice_end) {
|
|
|
+ intpos = (int)floor(sintabpos);
|
|
|
+ nxtpos = intpos+1;
|
|
|
+ frac = sintabpos - (double)intpos;
|
|
|
+ vallo = sintab[intpos];
|
|
|
+ valhi = sintab[nxtpos];
|
|
|
+ valdif= valhi - vallo;
|
|
|
+ *tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
|
|
|
+ i++;
|
|
|
+ sintabpos += sintabincr;
|
|
|
+ sintabpos = fmod(sintabpos,sintabsize);
|
|
|
+ tab++;
|
|
|
+ }
|
|
|
+ while(tab < endsplice_start) {
|
|
|
+ intpos = (int)floor(sintabpos);
|
|
|
+ nxtpos = intpos+1;
|
|
|
+ frac = sintabpos - (double)intpos;
|
|
|
+ vallo = sintab[intpos];
|
|
|
+ valhi = sintab[nxtpos];
|
|
|
+ valdif= valhi - vallo;
|
|
|
+ *tab += vallo + (valdif * frac);
|
|
|
+ sintabpos += sintabincr;
|
|
|
+ sintabpos = fmod(sintabpos,sintabsize);
|
|
|
+ tab++;
|
|
|
+ }
|
|
|
+ /* END OF EACH CONSTITUENT MUST BE SPLICED */
|
|
|
+ i = splicelen - 1;
|
|
|
+ while(tab < tabend) {
|
|
|
+ intpos = (int)floor(sintabpos);
|
|
|
+ nxtpos = intpos+1;
|
|
|
+ frac = sintabpos - (double)intpos;
|
|
|
+ vallo = sintab[intpos];
|
|
|
+ valhi = sintab[nxtpos];
|
|
|
+ valdif= valhi - vallo;
|
|
|
+ *tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
|
|
|
+ i--;
|
|
|
+ sintabpos += sintabincr;
|
|
|
+ sintabpos = fmod(sintabpos,sintabsize);
|
|
|
+ tab++;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/********************************** GEN_NOTE3 ********************************/
|
|
|
+
|
|
|
+//void gen_note3(double *tabstart,double *tabend,double midival,int intabsize,int splicelen, short *intab)
|
|
|
+void gen_note3(double *tabstart,double *tabend,double midival,int intabsize,int splicelen, float *intab)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ double *startsplice_end, *endsplice_start, *tab;
|
|
|
+ double tabpos, tabincr, effective_len;
|
|
|
+ int intpos, nxtpos;
|
|
|
+ double frac, vallo, valhi, valdif;
|
|
|
+
|
|
|
+ tab = tabstart;
|
|
|
+ *tab++ = 0; /* 1st val = 0 */
|
|
|
+ tabincr = (miditohz(midival)/miditohz(60.0));
|
|
|
+ effective_len = (double)(tabend - tabstart);
|
|
|
+ if(effective_len * tabincr > (double)intabsize) {
|
|
|
+ effective_len /= tabincr;
|
|
|
+ tabend = tabstart + (int)effective_len;
|
|
|
+ }
|
|
|
+ tabpos = tabincr;
|
|
|
+ startsplice_end = tab + splicelen;
|
|
|
+ endsplice_start = tabend - splicelen;
|
|
|
+ /* START OF EACH CONSTITUENT MUST BE SPLICED */
|
|
|
+ i = 0;
|
|
|
+ while(tab < startsplice_end) {
|
|
|
+ intpos = (int)floor(tabpos);
|
|
|
+ nxtpos = intpos+1;
|
|
|
+ frac = tabpos - (double)intpos;
|
|
|
+ vallo = intab[intpos];
|
|
|
+ valhi = intab[nxtpos];
|
|
|
+ valdif= valhi - vallo;
|
|
|
+ *tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
|
|
|
+ i++;
|
|
|
+ tabpos += tabincr;
|
|
|
+ tab++;
|
|
|
+ }
|
|
|
+ while(tab < endsplice_start) {
|
|
|
+ intpos = (int)floor(tabpos);
|
|
|
+ nxtpos = intpos+1;
|
|
|
+ frac = tabpos - (double)intpos;
|
|
|
+ vallo = intab[intpos];
|
|
|
+ valhi = intab[nxtpos];
|
|
|
+ valdif= valhi - vallo;
|
|
|
+ *tab += vallo + (valdif * frac);
|
|
|
+ tabpos += tabincr;
|
|
|
+ tab++;
|
|
|
+ }
|
|
|
+ /* END OF EACH CONSTITUENT MUST BE SPLICED */
|
|
|
+ i = splicelen - 1;
|
|
|
+ while(tab < tabend) {
|
|
|
+ intpos = (int)floor(tabpos);
|
|
|
+ nxtpos = intpos+1;
|
|
|
+ frac = tabpos - (double)intpos;
|
|
|
+ vallo = intab[intpos];
|
|
|
+ valhi = intab[nxtpos];
|
|
|
+ valdif= valhi - vallo;
|
|
|
+ *tab += (vallo + (valdif * frac)) * (i/(double)splicelen);
|
|
|
+ i--;
|
|
|
+ tabpos += tabincr;
|
|
|
+ tab++;
|
|
|
+ }
|
|
|
+}
|