/* * Copyright (c) 1983-2023 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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;niparam[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;jiparam[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;niparam[HP1_HFCNT]-1;n++) { for(m = n+1; miparam[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;niparam[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;nsampbuf[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;jbuflen - 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;nsampbuf[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;jbuflen - 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_grp = 0; for(n=0;ntempsize,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;ntempsize,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; jiparam[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; jvflag[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; jvflag[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; jvflag[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;jprocess == HF_PERM1) thispitch = fmod(hfset[j][note],12.0); else thispitch = hfset[j][note]; for(k=j+1;kprocess == 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;jvflag[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 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) 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 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 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 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 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++; } }