|
@@ -21,6 +21,14 @@
|
|
|
02111-1307 USA
|
|
02111-1307 USA
|
|
|
*
|
|
*
|
|
|
*/
|
|
*/
|
|
|
|
|
+
|
|
|
|
|
+// see HEREH
|
|
|
|
|
+// TEST cmdline =
|
|
|
|
|
+// _cdprogs\fractal wave 1 sin_cycle.wav testfrac.wav fracshape.brk 4 -m2
|
|
|
|
|
+// Only getting 1/2-way through the pattern ... why??
|
|
|
|
|
+// look at "seedata.txt" to check times advance!!!!
|
|
|
|
|
+// _cdprogs\fractal spectrum zzz.ana testfrac.ana fracshape5.brk
|
|
|
|
|
+
|
|
|
#include <stdio.h>
|
|
#include <stdio.h>
|
|
|
#include <stdlib.h>
|
|
#include <stdlib.h>
|
|
|
#include <structures.h>
|
|
#include <structures.h>
|
|
@@ -36,6 +44,7 @@
|
|
|
#include <mixxcon.h>
|
|
#include <mixxcon.h>
|
|
|
#include <osbind.h>
|
|
#include <osbind.h>
|
|
|
#include <standalone.h>
|
|
#include <standalone.h>
|
|
|
|
|
+#include <science.h>
|
|
|
#include <ctype.h>
|
|
#include <ctype.h>
|
|
|
#include <sfsys.h>
|
|
#include <sfsys.h>
|
|
|
#include <string.h>
|
|
#include <string.h>
|
|
@@ -45,7 +54,36 @@
|
|
|
#ifdef unix
|
|
#ifdef unix
|
|
|
#define round(x) lround((x))
|
|
#define round(x) lround((x))
|
|
|
#endif
|
|
#endif
|
|
|
-#define maxfraccnt rampbrksize
|
|
|
|
|
|
|
+#ifndef HUGE
|
|
|
|
|
+#define HUGE 3.40282347e+38F
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#define FRAC_SPLICELEN 50 // Ms
|
|
|
|
|
+#define FRAC_FORMANTS 4 // No of formants used
|
|
|
|
|
+
|
|
|
|
|
+#define FRAC_SHRINK 0
|
|
|
|
|
+#define FRAC_OUTIMES 1
|
|
|
|
|
+
|
|
|
|
|
+#define mintime timemark // Minimum possible duration of any fractal element
|
|
|
|
|
+#define startfrq frametime // Frq of first pitch in (Mode 1) fractal_pitch-pattern
|
|
|
|
|
+#define maxtrnsp is_flat // Maximum possible upward-transpostion of any fractal element
|
|
|
|
|
+#define arraysize rampbrksize // Array size for totally fractalised pattern
|
|
|
|
|
+#define fracdur minbrk // Input duration of the fractal template
|
|
|
|
|
+#define minstep scalefact // Minimum element-duration in fractal template
|
|
|
|
|
+#define minfracratio halfchwidth // Time shrinkage of smallest element in fractal template, when proceeding from one fractal level to next
|
|
|
|
|
+#define maxfractalise ringsize // Maximum degree of fractalisation
|
|
|
|
|
+#define timevary is_transpos // Inicates that fractal patterning varies through time
|
|
|
|
|
+#define fracsize fzeroset // Number of elements in current totally-fractalised pattern
|
|
|
|
|
+#define convertor chwidth
|
|
|
|
|
+#define total_splice specenv_type // Total number of samples used in (any) end-splice
|
|
|
|
|
+#define splicesmps deal_with_chan_data // No of grouped-samples in (any) end-splice
|
|
|
|
|
+#define maxtransshrink is_sharp // Time-shrinkage of the element with maximum upward transposition, when proceeding from one fractal level to next
|
|
|
|
|
+#define mintransshrink minnum // Time-shrinkage of the element with maximum downward transposition, when proceeding from one fractal level to next
|
|
|
|
|
+
|
|
|
|
|
+#define FRACDUR 0
|
|
|
|
|
+#define FRACMAX 1
|
|
|
|
|
+#define FRACTSTR 2
|
|
|
|
|
+#define FRACISTR 3
|
|
|
|
|
|
|
|
char errstr[2400];
|
|
char errstr[2400];
|
|
|
|
|
|
|
@@ -72,11 +110,22 @@ static int mark_parameter_types(dataptr dz,aplptr ap);
|
|
|
static int assign_file_data_storage(int infilecnt,dataptr dz);
|
|
static int assign_file_data_storage(int infilecnt,dataptr dz);
|
|
|
static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
|
|
static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
|
|
|
static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
|
|
static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
|
|
|
-//static int get_the_mode_from_cmdline(char *str,dataptr dz);
|
|
|
|
|
|
|
+static int get_the_mode_from_cmdline(char *str,dataptr dz);
|
|
|
static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
|
|
static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
|
|
|
-static int float_array_for_fractal(int nnn,int n, float **ptr);
|
|
|
|
|
-static int generate_fractal_pattern(dataptr dz);
|
|
|
|
|
|
|
+static int handle_the_special_data(char *str,dataptr dz);
|
|
|
static int create_fractal_sndbufs(dataptr dz);
|
|
static int create_fractal_sndbufs(dataptr dz);
|
|
|
|
|
+static void get_max_fractalisation(dataptr dz);
|
|
|
|
|
+static int fractalise(dataptr dz);
|
|
|
|
|
+static int fractal_initialise_specenv(int *arraycnt,dataptr dz);
|
|
|
|
|
+static int fractal_set_specenv_frqs(int arraycnt,dataptr dz);
|
|
|
|
|
+static int fractal_setup_octaveband_steps(double **interval,dataptr dz);
|
|
|
|
|
+static int fractal_setup_low_octave_bands(int arraycnt,dataptr dz);
|
|
|
|
|
+static int fractal_extract_specenv(dataptr dz);
|
|
|
|
|
+static int fractal_tranpose_within_formant_envelope(int vc,double transpose,dataptr dz);
|
|
|
|
|
+static int fractal_reposition_partials_in_appropriate_channels(double transpose,dataptr dz);
|
|
|
|
|
+static int fractal_spectrnsf(double transpose,dataptr dz);
|
|
|
|
|
+static int fractal_getspecenvamp(double *thisamp,double thisfrq,dataptr dz);
|
|
|
|
|
+static int fractal_get_channel_corresponding_to_frq(int *chan,double thisfrq,dataptr dz);
|
|
|
|
|
|
|
|
/**************************************** MAIN *********************************************/
|
|
/**************************************** MAIN *********************************************/
|
|
|
|
|
|
|
@@ -86,7 +135,8 @@ int main(int argc,char *argv[])
|
|
|
dataptr dz = NULL;
|
|
dataptr dz = NULL;
|
|
|
char **cmdline;
|
|
char **cmdline;
|
|
|
int cmdlinecnt;
|
|
int cmdlinecnt;
|
|
|
- int n;
|
|
|
|
|
|
|
+ int arraycnt = 0;
|
|
|
|
|
+ char specialname[1200];
|
|
|
// aplptr ap;
|
|
// aplptr ap;
|
|
|
int is_launched = FALSE;
|
|
int is_launched = FALSE;
|
|
|
if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
|
|
if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
|
|
@@ -128,8 +178,16 @@ int main(int argc,char *argv[])
|
|
|
return(FAILED);
|
|
return(FAILED);
|
|
|
cmdline++;
|
|
cmdline++;
|
|
|
cmdlinecnt--;
|
|
cmdlinecnt--;
|
|
|
- dz->maxmode = 0;
|
|
|
|
|
- // get_the_mode_from_cmdline
|
|
|
|
|
|
|
+ if(dz->process == FRACTAL) {
|
|
|
|
|
+ dz->maxmode = 2;
|
|
|
|
|
+ if((exit_status = get_the_mode_from_cmdline(cmdline[0],dz))<0) {
|
|
|
|
|
+ print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ cmdline++;
|
|
|
|
|
+ cmdlinecnt--;
|
|
|
|
|
+ } else
|
|
|
|
|
+ dz->maxmode = 0;
|
|
|
// setup_particular_application =
|
|
// setup_particular_application =
|
|
|
if((exit_status = setup_fractal_application(dz))<0) {
|
|
if((exit_status = setup_fractal_application(dz))<0) {
|
|
|
print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
@@ -165,7 +223,22 @@ int main(int argc,char *argv[])
|
|
|
}
|
|
}
|
|
|
cmdlinecnt--;
|
|
cmdlinecnt--;
|
|
|
cmdline++;
|
|
cmdline++;
|
|
|
-
|
|
|
|
|
|
|
+ if(dz->process == FRACSPEC) {
|
|
|
|
|
+ dz->nyquist = dz->infile->origrate/2.0;
|
|
|
|
|
+ dz->frametime = (float)(1.0/dz->infile->arate);
|
|
|
|
|
+ dz->clength = dz->wanted / 2;
|
|
|
|
|
+ dz->chwidth = dz->nyquist/(double)(dz->clength-1);
|
|
|
|
|
+ dz->halfchwidth = dz->chwidth/2.0;
|
|
|
|
|
+ if((exit_status = fractal_initialise_specenv(&arraycnt,dz))<0) {
|
|
|
|
|
+ print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
|
|
|
+ return(FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->formant_bands = FRAC_FORMANTS;
|
|
|
|
|
+ if((exit_status = fractal_set_specenv_frqs(arraycnt,dz))<0) {
|
|
|
|
|
+ print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
|
|
|
+ return(FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
// handle_extra_infiles() : redundant
|
|
// handle_extra_infiles() : redundant
|
|
|
// handle_outfile() =
|
|
// handle_outfile() =
|
|
|
if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,dz))<0) {
|
|
if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,dz))<0) {
|
|
@@ -176,36 +249,35 @@ int main(int argc,char *argv[])
|
|
|
// handle_formants() redundant
|
|
// handle_formants() redundant
|
|
|
// handle_formant_quiksearch() redundant
|
|
// handle_formant_quiksearch() redundant
|
|
|
// handle_special_data() redundant
|
|
// handle_special_data() redundant
|
|
|
|
|
+
|
|
|
|
|
+ strcpy(specialname,cmdline[0]);
|
|
|
|
|
+ cmdlinecnt--;
|
|
|
|
|
+ cmdline++;
|
|
|
if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
|
|
if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
|
|
|
print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
|
return(FAILED);
|
|
return(FAILED);
|
|
|
}
|
|
}
|
|
|
-// check_param_validity_and_consistency....
|
|
|
|
|
|
|
+ if((exit_status = handle_the_special_data(specialname,dz))<0) {
|
|
|
|
|
+ print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
|
|
|
+ return(FAILED);
|
|
|
|
|
+ }
|
|
|
|
|
+// check_param_validity_and_consistency ..
|
|
|
if((exit_status = check_fractal_param_validity_and_consistency(dz))<0) {
|
|
if((exit_status = check_fractal_param_validity_and_consistency(dz))<0) {
|
|
|
print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
|
return(FAILED);
|
|
return(FAILED);
|
|
|
}
|
|
}
|
|
|
is_launched = TRUE;
|
|
is_launched = TRUE;
|
|
|
- dz->bufcnt = 3;
|
|
|
|
|
- if((dz->sampbuf = (float **)malloc(sizeof(float *) * (dz->bufcnt+1)))==NULL) {
|
|
|
|
|
- sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers.\n");
|
|
|
|
|
- return(MEMORY_ERROR);
|
|
|
|
|
- }
|
|
|
|
|
- if((dz->sbufptr = (float **)malloc(sizeof(float *) * dz->bufcnt))==NULL) {
|
|
|
|
|
- sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffer pointers.\n");
|
|
|
|
|
- return(MEMORY_ERROR);
|
|
|
|
|
- }
|
|
|
|
|
- for(n = 0;n <dz->bufcnt; n++)
|
|
|
|
|
- dz->sampbuf[n] = dz->sbufptr[n] = (float *)0;
|
|
|
|
|
- dz->sampbuf[n] = (float *)0;
|
|
|
|
|
-
|
|
|
|
|
- if((exit_status = create_fractal_sndbufs(dz))<0) { // CDP LIB
|
|
|
|
|
|
|
+ if(dz->process == FRACTAL)
|
|
|
|
|
+ dz->bufcnt = 4;
|
|
|
|
|
+ else
|
|
|
|
|
+ dz->bufcnt = 2;
|
|
|
|
|
+ if((exit_status = create_fractal_sndbufs(dz))<0) {
|
|
|
print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
|
return(FAILED);
|
|
return(FAILED);
|
|
|
}
|
|
}
|
|
|
//param_preprocess() redundant
|
|
//param_preprocess() redundant
|
|
|
//spec_process_file =
|
|
//spec_process_file =
|
|
|
- if((exit_status = generate_fractal_pattern(dz))<0) {
|
|
|
|
|
|
|
+ if((exit_status = fractalise(dz))<0) {
|
|
|
print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
print_messages_and_close_sndfiles(exit_status,is_launched,dz);
|
|
|
return(FAILED);
|
|
return(FAILED);
|
|
|
}
|
|
}
|
|
@@ -498,16 +570,42 @@ int setup_fractal_application(dataptr dz)
|
|
|
return(FAILED);
|
|
return(FAILED);
|
|
|
ap = dz->application;
|
|
ap = dz->application;
|
|
|
// SEE parstruct FOR EXPLANATION of next 2 functions
|
|
// SEE parstruct FOR EXPLANATION of next 2 functions
|
|
|
- if((exit_status = set_param_data(ap,0 ,1,1,"i"))<0)
|
|
|
|
|
|
|
+ if(dz->process == FRACTAL) {
|
|
|
|
|
+ if (dz->mode == 0)
|
|
|
|
|
+ exit_status = set_param_data(ap,FRACSHAPE,1,0,"0");
|
|
|
|
|
+ else
|
|
|
|
|
+ exit_status = set_param_data(ap,FRACSHAPE,1,1,"d");
|
|
|
|
|
+ } else
|
|
|
|
|
+ exit_status = set_param_data(ap,FRACSHAPE,1,0,"0");
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ if(exit_status<0)
|
|
|
return(FAILED);
|
|
return(FAILED);
|
|
|
- if((exit_status = set_vflgs(ap,"s",1,"i","",0,0,""))<0)
|
|
|
|
|
|
|
+ if(dz->process == FRACTAL) {
|
|
|
|
|
+ if(dz->mode == 0)
|
|
|
|
|
+ exit_status = set_vflgs(ap,"mti",3,"IDD","so",2,0,"00");
|
|
|
|
|
+ else
|
|
|
|
|
+ exit_status = set_vflgs(ap,"mti",3,"IDD","s",1,0,"0");
|
|
|
|
|
+ } else
|
|
|
|
|
+ exit_status = set_vflgs(ap,"mti",3,"IDD","sn",2,0,"00");
|
|
|
|
|
+ if(exit_status<0)
|
|
|
return(FAILED);
|
|
return(FAILED);
|
|
|
// set_legal_infile_structure -->
|
|
// set_legal_infile_structure -->
|
|
|
dz->has_otherfile = FALSE;
|
|
dz->has_otherfile = FALSE;
|
|
|
// assign_process_logic -->
|
|
// assign_process_logic -->
|
|
|
- dz->input_data_type = SNDFILES_ONLY;
|
|
|
|
|
- dz->process_type = UNEQUAL_SNDFILE;
|
|
|
|
|
- dz->outfiletype = SNDFILE_OUT;
|
|
|
|
|
|
|
+ if(dz->process == FRACSPEC) {
|
|
|
|
|
+ dz->input_data_type = ANALFILE_ONLY;
|
|
|
|
|
+ dz->process_type = BIG_ANALFILE;
|
|
|
|
|
+ dz->outfiletype = ANALFILE_OUT;
|
|
|
|
|
+ dz->maxmode = 0;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dz->input_data_type = SNDFILES_ONLY;
|
|
|
|
|
+ dz->process_type = UNEQUAL_SNDFILE;
|
|
|
|
|
+ dz->outfiletype = SNDFILE_OUT;
|
|
|
|
|
+ dz->maxmode = 2;
|
|
|
|
|
+ }
|
|
|
return application_init(dz); //GLOBAL
|
|
return application_init(dz); //GLOBAL
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -521,13 +619,25 @@ int parse_infile_and_check_type(char **cmdline,dataptr dz)
|
|
|
if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
|
|
if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
|
|
|
sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
|
|
sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
|
|
|
return(MEMORY_ERROR);
|
|
return(MEMORY_ERROR);
|
|
|
- } else if((exit_status = cdparse(cmdline[0],infile_info))<0) {
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = cdparse(cmdline[0],infile_info))<0) {
|
|
|
sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]);
|
|
sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]);
|
|
|
return(PROGRAM_ERROR);
|
|
return(PROGRAM_ERROR);
|
|
|
- } else if(infile_info->filetype != SNDFILE) {
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->process == FRACTAL) {
|
|
|
|
|
+ if(infile_info->filetype != SNDFILE) {
|
|
|
|
|
+ sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->mode == 1 && infile_info->channels != 1) {
|
|
|
|
|
+ sprintf(errstr,"File %s is not of correct type (must be mono for mode %d)\n",cmdline[0],dz->mode+1);
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if(infile_info->filetype != ANALFILE) {
|
|
|
sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
|
|
sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
|
|
|
return(DATA_ERROR);
|
|
return(DATA_ERROR);
|
|
|
- } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
|
|
|
sprintf(errstr,"Failed to copy file parsing information\n");
|
|
sprintf(errstr,"Failed to copy file parsing information\n");
|
|
|
return(PROGRAM_ERROR);
|
|
return(PROGRAM_ERROR);
|
|
|
}
|
|
}
|
|
@@ -548,13 +658,24 @@ int setup_fractal_param_ranges_and_defaults(dataptr dz)
|
|
|
if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
|
|
if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
|
|
|
return(FAILED);
|
|
return(FAILED);
|
|
|
// get_param_ranges()
|
|
// get_param_ranges()
|
|
|
- ap->lo[0] = 2;
|
|
|
|
|
- ap->hi[0] = 100;
|
|
|
|
|
- ap->default_val[0] = 8;
|
|
|
|
|
- ap->lo[1] = 2;
|
|
|
|
|
- ap->hi[1] = 50;
|
|
|
|
|
- ap->default_val[1] = 15;
|
|
|
|
|
- dz->maxmode = 0;
|
|
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1) {
|
|
|
|
|
+ ap->lo[FRACDUR] = 1;
|
|
|
|
|
+ ap->hi[FRACDUR] = FRAC_MAXDUR;
|
|
|
|
|
+ ap->default_val[FRACDUR] = 10;
|
|
|
|
|
+ }
|
|
|
|
|
+ ap->lo[FRACMAX] = 0;
|
|
|
|
|
+ ap->hi[FRACMAX] = FRAC_MAXFRACT;
|
|
|
|
|
+ ap->default_val[FRACMAX] = 0;
|
|
|
|
|
+ ap->lo[FRACTSTR] = 1;
|
|
|
|
|
+ ap->hi[FRACTSTR] = 2;
|
|
|
|
|
+ ap->default_val[FRACTSTR] = 1;
|
|
|
|
|
+ ap->lo[FRACISTR] = 0;
|
|
|
|
|
+ ap->hi[FRACISTR] = 8;
|
|
|
|
|
+ ap->default_val[FRACISTR] = 0;
|
|
|
|
|
+ if(dz->process == FRACTAL)
|
|
|
|
|
+ dz->maxmode = 2;
|
|
|
|
|
+ else
|
|
|
|
|
+ dz->maxmode = 0;
|
|
|
if(!sloom)
|
|
if(!sloom)
|
|
|
put_default_vals_in_all_params(dz);
|
|
put_default_vals_in_all_params(dz);
|
|
|
return(FINISHED);
|
|
return(FINISHED);
|
|
@@ -959,40 +1080,26 @@ int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
|
|
|
|
|
|
|
|
int usage1(void)
|
|
int usage1(void)
|
|
|
{
|
|
{
|
|
|
- usage2("fractal");
|
|
|
|
|
|
|
+ fprintf(stderr,
|
|
|
|
|
+ "USAGE: fractal NAME (mode) infile outfile parameters\n"
|
|
|
|
|
+ "\n"
|
|
|
|
|
+ "where NAME can be any one of\n"
|
|
|
|
|
+ "\n"
|
|
|
|
|
+ "wave spectrum\n"
|
|
|
|
|
+ "\n"
|
|
|
|
|
+ "Type 'fractal wave' for more info on fractal wave option... ETC.\n");
|
|
|
return(USAGE_ONLY);
|
|
return(USAGE_ONLY);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/**************************** CHECK_FRACTAL_PARAM_VALIDITY_AND_CONSISTENCY *****************************/
|
|
|
|
|
-
|
|
|
|
|
-int check_fractal_param_validity_and_consistency(dataptr dz)
|
|
|
|
|
-{
|
|
|
|
|
- int gpsamplen, minfracsize, maxsegcnt, maxcutcnt;
|
|
|
|
|
- gpsamplen = dz->insams[0]/dz->infile->channels; // Length of file in sample-groups
|
|
|
|
|
- dz->iparam[FRACSPLICE] = (int)round(dz->param[FRACSPLICE] * MS_TO_SECS * dz->infile->srate);
|
|
|
|
|
- minfracsize = dz->iparam[FRACSPLICE] * 3; // Assume splicelen is in groupsamples
|
|
|
|
|
- // Assume min size = 3 X splicelen
|
|
|
|
|
- maxsegcnt = (int)floor((double)gpsamplen/(double)(minfracsize));// Number of segments obtained by cutting file into minlength chunks
|
|
|
|
|
- maxcutcnt = 1;
|
|
|
|
|
- dz->maxfraccnt = 2; // Count how many successive cuts-in-half are needed
|
|
|
|
|
- while(dz->maxfraccnt < maxsegcnt) { // To generate NO MORE THAN maxfraccnt segments.
|
|
|
|
|
- dz->maxfraccnt *= 2;
|
|
|
|
|
- maxcutcnt++; // calculate the maximum number of divisions by 2
|
|
|
|
|
- } // which will fit INSIDE the maxsegcnt
|
|
|
|
|
- dz->maxfraccnt /= 2;
|
|
|
|
|
- maxcutcnt--;
|
|
|
|
|
- if(dz->iparam[FRACDEPTH] > maxcutcnt) {
|
|
|
|
|
- sprintf(errstr,"INFO: Maximum number of fractal cuts for this file = %d\n",maxcutcnt);
|
|
|
|
|
- return DATA_ERROR;
|
|
|
|
|
- }
|
|
|
|
|
- return FINISHED;
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
/********************************************************************************************/
|
|
/********************************************************************************************/
|
|
|
|
|
|
|
|
int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
|
|
int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
|
|
|
{
|
|
{
|
|
|
- if(!strcmp(prog_identifier_from_cmdline,"fractal")) dz->process = FRACTAL;
|
|
|
|
|
|
|
+ if(!strcmp(prog_identifier_from_cmdline,"wave"))
|
|
|
|
|
+ dz->process = FRACTAL;
|
|
|
|
|
+ else if(!strcmp(prog_identifier_from_cmdline,"spectrum"))
|
|
|
|
|
+ dz->process = FRACSPEC;
|
|
|
else {
|
|
else {
|
|
|
sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
|
|
sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
|
|
|
return(USAGE_ONLY);
|
|
return(USAGE_ONLY);
|
|
@@ -1046,24 +1153,65 @@ int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt)
|
|
|
|
|
|
|
|
int usage2(char *str)
|
|
int usage2(char *str)
|
|
|
{
|
|
{
|
|
|
- if(!strcmp(str,"fractal")) {
|
|
|
|
|
|
|
+ if(!strcmp(str,"wave")) {
|
|
|
|
|
+ fprintf(stderr,
|
|
|
|
|
+ "USAGE:\n"
|
|
|
|
|
+ "fractal wave 1 inf outf shape [-mmaxfrac] [-tstr] [-iwarp] [-s] [-o]\n"
|
|
|
|
|
+ "fractal wave 2 inf outf shape dur [-mmaxfrac] [-tstr] [-iwarp] [-s]\n"
|
|
|
|
|
+ "\n"
|
|
|
|
|
+ "Fractally distort (1 or more channel) input sound (Mode 1).\n"
|
|
|
|
|
+ "OR generate fractal wave from (mono) input wavecycle (Mode 2)\n"
|
|
|
|
|
+ "Fractal is time-pattern of transpositions (and, in Mode 1\n"
|
|
|
|
|
+ "causes corresponding time contractions and expansions).\n"
|
|
|
|
|
+ "Transposition happens over total duration specified in \"SHAPE\"\n"
|
|
|
|
|
+ "and is then repeated over every resulting sub-unit of pattern,\n"
|
|
|
|
|
+ "over every sub-sub-unit, etc. until smallest time-unit reached.\n"
|
|
|
|
|
+ "\n"
|
|
|
|
|
+ "SHAPE Breakpoint textfile of\n"
|
|
|
|
|
+ " (Mode 1) time-(semitone)transposition pairs, (Range -12 to 12)\n"
|
|
|
|
|
+ " (Mode 2) time-MIDIpitch pairs, (Range 0 to 127)\n"
|
|
|
|
|
+ " defining pitch-time contour of the (largest) fractal shape.\n"
|
|
|
|
|
+ " Times must start at zero and increase,\n"
|
|
|
|
|
+ " with final time indicating duration of pattern.\n"
|
|
|
|
|
+ " (Value at final time will be ignored).\n"
|
|
|
|
|
+ "\n"
|
|
|
|
|
+ "DUR (Mode 2) Output duration (secs) (max 2 hours).\n"
|
|
|
|
|
+ "MAXFRAC Max degree of fractalisation. (Time-variable). If not set (or zero),\n"
|
|
|
|
|
+ " fractalisation proceeds until min possible wavelength reached.\n"
|
|
|
|
|
+ "STR Time stretch of fractal pattern (Time-variable : values >= 1).\n"
|
|
|
|
|
+ " If set to zero, no timestretching is done.\n"
|
|
|
|
|
+ "WARP Interval warping of fractal pattern (Time-variable).\n"
|
|
|
|
|
+ " If set to zero, no warping is done.\n"
|
|
|
|
|
+ "\n"
|
|
|
|
|
+ "-s Shrink pitch-intervals as fractal time-scales shrink.\n"
|
|
|
|
|
+ "-o Brkpnt data read using time in outfile (default: Use time in infile).\n"
|
|
|
|
|
+ "\n");
|
|
|
|
|
+ } else if(!strcmp(str,"spectrum")) {
|
|
|
fprintf(stderr,
|
|
fprintf(stderr,
|
|
|
"USAGE:\n"
|
|
"USAGE:\n"
|
|
|
- "fractal fractal infile outfile layers [-ssplicelen]\n"
|
|
|
|
|
|
|
+ "fractal spectrum inf outf shape [-mmaxfrac] [-tstr] [-iwarp] [-s] [-n]\n"
|
|
|
"\n"
|
|
"\n"
|
|
|
- "Create fractalised version of sound.\n"
|
|
|
|
|
|
|
+ "Fractally distort input spectrum by transposition.\n"
|
|
|
|
|
+ "Transposition happens over total duration specified in \"SHAPE\"\n"
|
|
|
|
|
+ "and is then repeated over every resulting sub-unit of pattern,\n"
|
|
|
|
|
+ "over every sub-sub-unit, etc. until smallest time-unit reached.\n"
|
|
|
"\n"
|
|
"\n"
|
|
|
- "SPLICELEN Length of splices in mS.\n"
|
|
|
|
|
|
|
+ "SHAPE Breakpoint textfile of\n"
|
|
|
|
|
+ " Time-(semitone)transposition pairs, (Range -12 to 12)\n"
|
|
|
|
|
+ " defining pitch-time contour of the (largest) fractal shape.\n"
|
|
|
|
|
+ " Times must start at zero and increase,\n"
|
|
|
|
|
+ " with final time indicating duration of pattern.\n"
|
|
|
|
|
+ " (Value at final time will be ignored).\n"
|
|
|
"\n"
|
|
"\n"
|
|
|
- "LAYERS Number of fractal layers in the output sound.\n"
|
|
|
|
|
- " Note that the maximum number of layers possible\n"
|
|
|
|
|
- " depends on the duration of the input sound\n"
|
|
|
|
|
- " and the size of splices used\n"
|
|
|
|
|
- " and cannot be easily predicted in advance\n"
|
|
|
|
|
|
|
+ "MAXFRAC Max degree of fractalisation. (Time-variable). If not set (or zero),\n"
|
|
|
|
|
+ " fractalisation proceeds until min possible wavelength reached.\n"
|
|
|
|
|
+ "STR Time stretch of fractal pattern (Time-variable : values >= 1).\n"
|
|
|
|
|
+ " If set to zero, no timestretching is done.\n"
|
|
|
|
|
+ "WARP Interval warping of fractal pattern (Time-variable).\n"
|
|
|
|
|
+ " If set to zero, no warping is done.\n"
|
|
|
"\n"
|
|
"\n"
|
|
|
- "WARNINGS\n"
|
|
|
|
|
- "(1) Specifying many layers will produce very long output sounds.\n"
|
|
|
|
|
- "(2) Don't use very long input sounds, or you will run out of memory,\n"
|
|
|
|
|
|
|
+ "-s Shrink pitch-intervals as fractal time-scales shrink.\n"
|
|
|
|
|
+ "-n Transposition only (default, retain formant envelope).\n"
|
|
|
"\n");
|
|
"\n");
|
|
|
} else
|
|
} else
|
|
|
fprintf(stdout,"Unknown option '%s'\n",str);
|
|
fprintf(stdout,"Unknown option '%s'\n",str);
|
|
@@ -1076,285 +1224,1168 @@ int usage3(char *str1,char *str2)
|
|
|
return(USAGE_ONLY);
|
|
return(USAGE_ONLY);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/************************** GENERATE_FRACTAL_PATTERN *************************/
|
|
|
|
|
|
|
+/****************************** GET_MODE *********************************/
|
|
|
|
|
|
|
|
-int generate_fractal_pattern(dataptr dz)
|
|
|
|
|
|
|
+int get_the_mode_from_cmdline(char *str,dataptr dz)
|
|
|
{
|
|
{
|
|
|
- int exit_status, chans, segcnt, grpcnt, fracdepth, tailsize, cutcnt, splicelen;
|
|
|
|
|
- int gpsamplen, patterncnt, segsize, total_used_len, obufpos, endfilestt, bufsize, starttail, origbuflen;
|
|
|
|
|
- int n, j, m, z, c, thiscut, cutstt, cutend, thissegsize, patcnt, segno, insams;
|
|
|
|
|
- double spliceincr;
|
|
|
|
|
- float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1], *ovflwbuf = dz->sampbuf[2];
|
|
|
|
|
- float *splicebuf, *tailbuf, **buf;
|
|
|
|
|
- int *patterna, *patternb, *pattern1, *pattern2, *cutsegsize;
|
|
|
|
|
-
|
|
|
|
|
- chans = dz->infile->channels;
|
|
|
|
|
- gpsamplen = dz->insams[0]/chans;
|
|
|
|
|
- fracdepth = dz->iparam[FRACDEPTH];
|
|
|
|
|
- splicelen = dz->iparam[FRACSPLICE];
|
|
|
|
|
- obufpos = 0;
|
|
|
|
|
-
|
|
|
|
|
- // CREATE SPLICE VALUES IN BUFFER
|
|
|
|
|
-
|
|
|
|
|
- memset((char *)obuf,0,dz->buflen * 2 * sizeof(float)); // Initialise obuf, and ovflwbuf to zero
|
|
|
|
|
- origbuflen = dz->buflen;
|
|
|
|
|
- dz->buflen = dz->insams[0];
|
|
|
|
|
- if((exit_status = read_samps(ibuf,dz))<0) // Fill the input buffer
|
|
|
|
|
- return(exit_status);
|
|
|
|
|
- dz->buflen = origbuflen;
|
|
|
|
|
|
|
+ char temp[200], *p;
|
|
|
|
|
+ if(sscanf(str,"%s",temp)!=1) {
|
|
|
|
|
+ sprintf(errstr,"Cannot read mode of program.\n");
|
|
|
|
|
+ return(USAGE_ONLY);
|
|
|
|
|
+ }
|
|
|
|
|
+ p = temp + strlen(temp) - 1;
|
|
|
|
|
+ while(p >= temp) {
|
|
|
|
|
+ if(!isdigit(*p)) {
|
|
|
|
|
+ fprintf(stderr,"Invalid mode of program entered.\n");
|
|
|
|
|
+ return(USAGE_ONLY);
|
|
|
|
|
+ }
|
|
|
|
|
+ p--;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(sscanf(str,"%d",&dz->mode)!=1) {
|
|
|
|
|
+ fprintf(stderr,"Cannot read mode of program.\n");
|
|
|
|
|
+ return(USAGE_ONLY);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->mode <= 0 || dz->mode > dz->maxmode) {
|
|
|
|
|
+ fprintf(stderr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode);
|
|
|
|
|
+ return(USAGE_ONLY);
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** HANDLE_THE_SPECIAL_DATA ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int handle_the_special_data(char *str,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status, n, m, cnt;
|
|
|
|
|
+ FILE *fp;
|
|
|
|
|
+ char temp[200], *p;
|
|
|
|
|
+ double dummy = 0, lasttime = 0.0, lastmintrans = 0, lastmaxtrans = 0, mintrans = 0, maxtrans = 0, fracmax = 0.0;
|
|
|
|
|
+ double firstmidi = 0, lastmaxpitch = 0, lastminpitch = 0, maxpitch = 0, minpitch = 0, max_step, min_step, srate = (double)dz->infile->srate;
|
|
|
|
|
+ double *fractemplate, *fracintvl, *fractimes;
|
|
|
|
|
+ double mindur_maxtrans, mindur_mintrans, maxelement, minelement, thisdur, min_step_now, max_step_now;
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->process == FRACTAL)
|
|
|
|
|
+ dz->mintime = (float)(4.0/srate); // Minimum duration of fractal pattern (> 4 samples)
|
|
|
|
|
+ else {
|
|
|
|
|
+ dz->frametime = (float)(1.0/dz->infile->arate);
|
|
|
|
|
+ dz->mintime = dz->frametime; // Minimum duration of fractal pattern (> 1 analysis window)
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->maxtrnsp = 256.0; // 8 octaves
|
|
|
|
|
+ dz->maxfractalise = 0;
|
|
|
|
|
+ dz->minstep = HUGE;
|
|
|
|
|
+ if((fp = fopen(str,"r"))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"Cannot open file %s to read clip lengths.\n",str);
|
|
|
|
|
+ return(DATA_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ cnt = 0;
|
|
|
|
|
+ lasttime = 0;
|
|
|
|
|
+ while(fgets(temp,200,fp)!=NULL) {
|
|
|
|
|
+ p = temp;
|
|
|
|
|
+ while(isspace(*p))
|
|
|
|
|
+ p++;
|
|
|
|
|
+ if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
|
|
|
|
|
+ continue;
|
|
|
|
|
+ while(get_float_from_within_string(&p,&dummy)) {
|
|
|
|
|
+
|
|
|
|
|
+ if (EVEN(cnt)) { // TIMES MUST START AT ZERO AND INCREASE
|
|
|
|
|
+ if(cnt == 0) {
|
|
|
|
|
+ if(dummy != 0.0) {
|
|
|
|
|
+ sprintf(errstr,"Invalid initial time (%lf) in file %s. (Should be zero).\n",dummy,str);
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if(dummy <= lasttime) {
|
|
|
|
|
+ sprintf(errstr,"Times do not increase at (%lf %lf) in file %s.\n",lasttime,dummy,str);
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->minstep = min(dz->minstep,dummy - lasttime);// Find smallest time-step in fractal-pattern
|
|
|
|
|
+ }
|
|
|
|
|
+ lasttime = dummy;
|
|
|
|
|
+ } else { // VALUES MUSY LIE WITHIN RANGE
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1) { // as pitch-pattern
|
|
|
|
|
+ if(dummy < FRAC_MINMIDI || dummy > FRAC_MAXMIDI) {
|
|
|
|
|
+ sprintf(errstr,"MIDIpitch (%lf) out of range (%lf to %lf) in file %s.\n",dummy,FRAC_MINMIDI,FRAC_MAXMIDI,str);
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(cnt == 1) {
|
|
|
|
|
+ firstmidi = dummy; // Note initial MIDI pitch
|
|
|
|
|
+ lastmaxpitch = dummy; // And search for max and min pitches
|
|
|
|
|
+ lastminpitch = dummy; // NB maximum and minimum search IGNORES last value in table
|
|
|
|
|
+ } else {
|
|
|
|
|
+ maxpitch = lastmaxpitch;
|
|
|
|
|
+ minpitch = lastminpitch;
|
|
|
|
|
+ lastmaxpitch = max(lastmaxpitch,dummy);
|
|
|
|
|
+ lastminpitch = min(lastminpitch,dummy);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else { // as semitone-transposition-pattern
|
|
|
|
|
+ if(dummy < FRAC_MINTRNS || dummy > FRAC_MAXTRNS) {
|
|
|
|
|
+ sprintf(errstr,"Transposition (%lf semitones) out of range (%lf to %lf) in file %s.\n",dummy,FRAC_MINTRNS,FRAC_MAXTRNS,str);
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(cnt == 1) {
|
|
|
|
|
+ lastmintrans = dummy; // Search for max and min transpositions
|
|
|
|
|
+ lastmaxtrans = dummy; // NB maximum and minimum search IGNORES last value in table
|
|
|
|
|
+ } else {
|
|
|
|
|
+ mintrans = lastmintrans;
|
|
|
|
|
+ maxtrans = lastmaxtrans;
|
|
|
|
|
+ lastmintrans = min(lastmintrans,dummy);
|
|
|
|
|
+ lastmaxtrans = max(lastmaxtrans,dummy);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ cnt++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(cnt == 0) { // Check data count
|
|
|
|
|
+ sprintf(errstr,"No data found in file %s.\n",str);
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(ODD(cnt)) {
|
|
|
|
|
+ sprintf(errstr,"Values not correctly paired in file %s.\n",str);
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(cnt < 4) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient values for a fractal shape (needs 2 times and 2 vals = 4 total) in file %s.\n",str);
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->fracdur = lasttime; // Last time in data indicates total duration of fractal-shape
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1)
|
|
|
|
|
+ dz->startfrq = (float)miditohz(firstmidi); // In mode 1 (fractal-template of pitches), find initial frq of pattern
|
|
|
|
|
|
|
|
- if((exit_status = float_array_for_fractal(splicelen,-2,&splicebuf)) < 0)
|
|
|
|
|
- return exit_status; // Create buffer to store splice values
|
|
|
|
|
- spliceincr = 1.0/(double)splicelen; // Fill the splice buffer
|
|
|
|
|
- for(m = 0; m < splicelen; m++)
|
|
|
|
|
- splicebuf[m] = (float)((double)m * spliceincr);
|
|
|
|
|
|
|
+ dz->itemcnt = cnt/2;
|
|
|
|
|
|
|
|
- // FIND HOW MANY SEGMENTS NEEDED (segcnt) AND THEIR SIZE (segsize) in gpsamples
|
|
|
|
|
- // For cut-stage 0 need 2^0 = 1 segment
|
|
|
|
|
- // For cut-stage 1 need 2^1 = 2 segments
|
|
|
|
|
- // For cut-stage 2 need 2^2 = 4 segments
|
|
|
|
|
- // For cut N need 2^N segments.
|
|
|
|
|
|
|
+ if((dz->parray = (double **)malloc(6 * sizeof(double *)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to create fractalisation calculation arrays.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->parray[3] = (double *)malloc((dz->itemcnt * 2) * sizeof(double)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to store fractalisation data.\n"); // fractemplate : original (input) fractal template data
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ fractemplate = dz->parray[3]; // Original fractal template time-val pairs
|
|
|
|
|
+
|
|
|
|
|
+ cnt = 0;
|
|
|
|
|
+ fseek(fp,0,0);
|
|
|
|
|
+ while(fgets(temp,200,fp)!=NULL) {
|
|
|
|
|
+ p = temp;
|
|
|
|
|
+ while(isspace(*p))
|
|
|
|
|
+ p++;
|
|
|
|
|
+ if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
|
|
|
|
|
+ continue;
|
|
|
|
|
+ while(get_float_from_within_string(&p,&dummy))
|
|
|
|
|
+ fractemplate[cnt++] = dummy;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1) {
|
|
|
|
|
+ for(n=1;n<dz->itemcnt*2;n+=2) // Convert pitch input to transpositions of initial pitch
|
|
|
|
|
+ fractemplate[n] -= firstmidi;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- segcnt = 1;
|
|
|
|
|
- for(n = 1;n < fracdepth; n++)
|
|
|
|
|
- segcnt *= 2;
|
|
|
|
|
|
|
+ // CHECK TIME LIMITS
|
|
|
|
|
|
|
|
- // HOW int ARE THE SEGMENTS, IN SAMPLES : WHAT IS THE BUFFER SIZE REQUIRED
|
|
|
|
|
-
|
|
|
|
|
- segsize = gpsamplen/segcnt; // Sizeof segments (truncated)
|
|
|
|
|
- bufsize = (segsize + splicelen) * chans;
|
|
|
|
|
-
|
|
|
|
|
- // STORE UNUSED TAIL OF FILE IN ITS OWN BUFFER
|
|
|
|
|
-
|
|
|
|
|
- total_used_len = segcnt * segsize * chans; // How much of file used in making fractal
|
|
|
|
|
- tailsize = dz->insams[0] - total_used_len; // How much is left
|
|
|
|
|
- tailsize += splicelen * chans; // Add room for upsplice
|
|
|
|
|
- starttail = total_used_len - (splicelen * chans); // Find start of portion extended-tail-portion to copy
|
|
|
|
|
- if((exit_status = float_array_for_fractal(tailsize,-1,&tailbuf)) < 0)
|
|
|
|
|
- return exit_status; // Create buffer to store tail
|
|
|
|
|
- for(n = 0, m = starttail;n < tailsize; n++,m++) // Copy tail into buffer
|
|
|
|
|
- tailbuf[n] = ibuf[m];
|
|
|
|
|
- for(m = 0; m < splicelen; m++) { // Put upsplice on tail
|
|
|
|
|
- j = m * 2;
|
|
|
|
|
- for(c = 0; c < chans; c++) {
|
|
|
|
|
- tailbuf[j] = (float)(tailbuf[j] * splicebuf[m]);
|
|
|
|
|
- j++;
|
|
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1) {
|
|
|
|
|
+ if(dz->fracdur > FRAC_MAXDUR) {
|
|
|
|
|
+ fprintf(stdout,"WARNING: Pattern total duration (%lf) greater than %.2lf hours, in file %s.\n",dz->fracdur,FRAC_MAXDUR/3600.0,str);
|
|
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
}
|
|
|
- if(j == tailsize) // Break, if tail is shorter than full splice
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->brksize[FRACTSTR]) { // If fractal-shape time-stretched anywhere, get maximal tstretch,
|
|
|
|
|
+ if((exit_status = get_maxvalue_in_brktable(&fracmax,FRACTSTR,dz))<0)
|
|
|
|
|
+ return exit_status;
|
|
|
|
|
+ dz->param[FRACTSTR] = (int)round(fracmax);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // SET UP ARRAY OF BUFFERS TO STORE SEGMENTS
|
|
|
|
|
-
|
|
|
|
|
- if((buf = (float **)malloc(segcnt * sizeof(float *)))==NULL) {
|
|
|
|
|
- sprintf(errstr,"Insufficient memory to store cut segments 1.\n");
|
|
|
|
|
- return(MEMORY_ERROR);
|
|
|
|
|
|
|
+ // CHECK MAXIMUM FRACTALISATION
|
|
|
|
|
+
|
|
|
|
|
+ dz->minfracratio = dz->minstep/dz->fracdur;
|
|
|
|
|
+ get_max_fractalisation(dz);
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->maxfractalise < 1) {
|
|
|
|
|
+ sprintf(errstr,"Smallest time-unit in pattern (%lf) too short to allow fractalisation.\n",dz->minstep);
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
}
|
|
}
|
|
|
- for(n = 0; n < segcnt; n++) {
|
|
|
|
|
- if((exit_status = float_array_for_fractal(bufsize,-1,&buf[n])) < 0) // Create buffers to store segments
|
|
|
|
|
|
|
+ if(dz->brksize[FRACMAX]) { // If maximum fractalisation is preset by user
|
|
|
|
|
+ if((exit_status = get_maxvalue_in_brktable(&fracmax,FRACMAX,dz))<0)
|
|
|
|
|
+ return exit_status;
|
|
|
|
|
+ dz->iparam[FRACMAX] = (int)round(fracmax);
|
|
|
|
|
+ } // compare it with the max possible fractalisation
|
|
|
|
|
+ if(dz->iparam[FRACMAX] > dz->maxfractalise) {
|
|
|
|
|
+ fprintf(stdout,"WARNING: Max fractalisation will be restricted to %d because of time proportions in given shape data.\n",dz->maxfractalise);
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ } else if (dz->iparam[FRACMAX] > 0 && dz->iparam[FRACMAX] < dz->maxfractalise)
|
|
|
|
|
+ dz->maxfractalise = dz->iparam[FRACMAX];
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->brksize[FRACISTR]) {
|
|
|
|
|
+ if((exit_status = get_maxvalue_in_brktable(&fracmax,FRACISTR,dz))<0)
|
|
|
return exit_status;
|
|
return exit_status;
|
|
|
|
|
+ dz->param[FRACISTR] = fracmax;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // FIND FINAL SIZE OF FRACTAL PATTERN, AND SET UP ARRAYS TO STORE (GROWING) PATTERN
|
|
|
|
|
- // At every cut, the initial_pattern of segments is copied (and reversed), and appended, to make pattern twice as int
|
|
|
|
|
- // So total pattern of segments doubles in size at every cut
|
|
|
|
|
|
|
+ // CHECK RESTRICTIONS ON FRACTALISATION TRANSPOSITION-DEPTH CAUSED BY CHAINED-TRANSPOSITIONS
|
|
|
|
|
|
|
|
- patterncnt = segcnt;
|
|
|
|
|
- for(n = 0;n < fracdepth; n++)
|
|
|
|
|
- patterncnt *= 2;
|
|
|
|
|
- if((patterna = (int *)malloc(patterncnt * sizeof(int)))==NULL) {
|
|
|
|
|
- sprintf(errstr,"Insufficient memory to store pattern array 1.\n");
|
|
|
|
|
- return(MEMORY_ERROR);
|
|
|
|
|
|
|
+ // FinD time-shrinkage at maximum amd minimum pitch (transposition) elements of fractal shape
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->vflag[FRAC_SHRINK]) {
|
|
|
|
|
+ mindur_maxtrans = HUGE;
|
|
|
|
|
+ mindur_mintrans = HUGE;
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1) {
|
|
|
|
|
+ maxelement = maxpitch - firstmidi;
|
|
|
|
|
+ minelement = minpitch - firstmidi;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ maxelement = maxtrans;
|
|
|
|
|
+ minelement = mintrans;
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n = 1; n < (dz->itemcnt -1) * 2; n+= 2) {
|
|
|
|
|
+ if(fractemplate[n] == maxelement) {
|
|
|
|
|
+ thisdur = fractemplate[n+1] - fractemplate[n-1];
|
|
|
|
|
+ mindur_maxtrans = min(mindur_maxtrans,thisdur);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(fractemplate[n] == minelement) {
|
|
|
|
|
+ thisdur = fractemplate[n+1] - fractemplate[n-1];
|
|
|
|
|
+ mindur_mintrans = min(mindur_mintrans,thisdur);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(mindur_maxtrans == HUGE || mindur_mintrans == HUGE) {
|
|
|
|
|
+ sprintf(errstr,"Problem determining duration of max:min elements in fractal.\n");
|
|
|
|
|
+ return PROGRAM_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->maxtransshrink = mindur_maxtrans/dz->fracdur;
|
|
|
|
|
+ dz->mintransshrink = mindur_mintrans/dz->fracdur;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Check what happens to maximum and minimum transpositions, after maximium fractalisation.
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1)
|
|
|
|
|
+ max_step = maxpitch - firstmidi; // Base-pitch assumed to be first pitch of pattern
|
|
|
|
|
+ else
|
|
|
|
|
+ max_step = maxtrans;
|
|
|
|
|
+ if(dz->param[FRACISTR] > 1.0)
|
|
|
|
|
+ max_step *= dz->param[FRACISTR];
|
|
|
|
|
+ if(max_step > 0.0) { // If highest pitch in fractal-shape is above initial pitch
|
|
|
|
|
+ if(dz->vflag[FRAC_SHRINK]) {
|
|
|
|
|
+ max_step_now = max_step;
|
|
|
|
|
+ max_step = 0;
|
|
|
|
|
+ for(n = 0;n < dz->maxfractalise;n++) {
|
|
|
|
|
+ max_step += max_step_now;
|
|
|
|
|
+ max_step_now *= dz->maxtransshrink;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else
|
|
|
|
|
+ max_step *= dz->maxfractalise; // calculate how mich this will step upwards in successive fractalisations
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1) {
|
|
|
|
|
+ maxpitch += max_step ;
|
|
|
|
|
+ if(maxpitch > MIDIMAX) {
|
|
|
|
|
+ sprintf(errstr,"Max pitch after max fractalisation (%d times) (MIDI %.2lf) exceeds limit (127).\n",dz->maxfractalise,maxpitch);
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else { // Convert to frq ratio
|
|
|
|
|
+ maxtrans = pow(2.0,(max_step/SEMITONES_PER_OCTAVE));
|
|
|
|
|
+ if(maxtrans > dz->maxtrnsp) {
|
|
|
|
|
+ sprintf(errstr,"Max transpos after max fractalisation (%d times) (%lf octaves) exceeds limit (8).\n",dz->maxfractalise,LOG2(maxtrans));
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- if((patternb = (int *)malloc(patterncnt * sizeof(int)))==NULL) {
|
|
|
|
|
- sprintf(errstr,"Insufficient memory to store pattern array 2.\n");
|
|
|
|
|
- return(MEMORY_ERROR);
|
|
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1)
|
|
|
|
|
+ min_step = minpitch - firstmidi;
|
|
|
|
|
+ else
|
|
|
|
|
+ min_step = mintrans;
|
|
|
|
|
+ if(dz->param[FRACISTR] > 1.0)
|
|
|
|
|
+ min_step *= dz->param[FRACISTR];
|
|
|
|
|
+ if(min_step < 0.0) { // If lowest pitch in fractal-shape is below initial pitch
|
|
|
|
|
+ if(dz->vflag[FRAC_SHRINK]) {
|
|
|
|
|
+ min_step_now = min_step;
|
|
|
|
|
+ min_step = 0;
|
|
|
|
|
+ for(n = 0;n < dz->maxfractalise;n++) {
|
|
|
|
|
+ min_step += min_step_now;
|
|
|
|
|
+ min_step_now *= dz->mintransshrink;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else
|
|
|
|
|
+ min_step *= dz->maxfractalise; // calculate how mich this will step downwardsupwards in successive fractalisations
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1) {
|
|
|
|
|
+ minpitch += min_step;
|
|
|
|
|
+ if(minpitch < 0) {
|
|
|
|
|
+ sprintf(errstr,"Min pitch after max fractalisation (%d times) (MIDI %lf) falls below low limit (0).\n",dz->maxfractalise,minpitch);
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ mintrans = pow(2.0,(mintrans/SEMITONES_PER_OCTAVE));
|
|
|
|
|
+ mintrans = pow(mintrans,dz->maxfractalise);
|
|
|
|
|
+ if(mintrans < 1.0/dz->maxtrnsp) {
|
|
|
|
|
+ sprintf(errstr,"Max transpos down after max fractalisation (%d times) (%lf octaves) exceeds limit (-8).\n",dz->maxfractalise,LOG2(mintrans));
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // CREATE ARRAY TO STORE SIZES OF STORED SEGMENTS
|
|
|
|
|
-
|
|
|
|
|
- if((cutsegsize = (int *)malloc(segcnt * sizeof(int)))==NULL) { // Stores lengths of cut-segs, after splices added (or not)
|
|
|
|
|
- sprintf(errstr,"Insufficient memory to store gating points.\n");
|
|
|
|
|
- return(MEMORY_ERROR);
|
|
|
|
|
|
|
+ // CREATE WORKING ARRAYS, now we know maximum depth of fractalisation (dz->maxfractalise)
|
|
|
|
|
+
|
|
|
|
|
+ dz->arraysize = dz->itemcnt - 1; // Number of fractal elements
|
|
|
|
|
+ dz->arraysize = (int)round(pow(dz->arraysize,dz->maxfractalise)); // Number of entries needed for (largest) fractalisation
|
|
|
|
|
+ dz->arraysize *= 2; // .. then include space for timing entries ....
|
|
|
|
|
+ dz->arraysize += 64; // SAFETY
|
|
|
|
|
+
|
|
|
|
|
+ if((dz->parray[0] = (double *)malloc(dz->arraysize * sizeof(double)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to create fractalisation array.\n");
|
|
|
|
|
+ return(MEMORY_ERROR); // fracpattern : Stores final conmplete fractalisation of data
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->parray[1] = (double *)malloc(dz->arraysize * sizeof(double)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to create swap buffer 1.\n");
|
|
|
|
|
+ return(MEMORY_ERROR); // swapbuffer1 : 1st itermediate buffers to calc fractalisation, stage by stage
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->parray[2] = (double *)malloc(dz->arraysize * sizeof(double)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to create swap buffer 2.\n");
|
|
|
|
|
+ return(MEMORY_ERROR); // swapbuffer2 : 2nd itermediate buffers to calc fractalisation, stage by stage
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->parray[4] = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to store transposing data.\n"); // fracintvl : Mode 0 : Intvls in fractal template
|
|
|
|
|
+ return(MEMORY_ERROR); // Mode 1 : Intvls btwn pitches in orig fractal pitch-template
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->parray[5] = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to store element duations.\n");
|
|
|
|
|
+ return(MEMORY_ERROR); // fractimes : Onset times of each element in fractal template
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // FILL THE PATTERN ARRAY
|
|
|
|
|
|
|
+ fracintvl = dz->parray[4]; // Intervals between pitches in original fractal pitch-template
|
|
|
|
|
+ fractimes = dz->parray[5]; // Fractal template element-start-times
|
|
|
|
|
|
|
|
- pattern1 = patterna;
|
|
|
|
|
- pattern2 = patternb;
|
|
|
|
|
|
|
+ for(n=0, m=0; n < (dz->itemcnt-1) * 2; n +=2, m++) { // Stores dz->itemcnt-1 items
|
|
|
|
|
+ fractimes[m] = fractemplate[n];
|
|
|
|
|
+ fracintvl[m] = fractemplate[n+1];
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->itemcnt--; // Last element of fractal template was needed only to specify total pattern's duration. So now ignore
|
|
|
|
|
+ // dz->itemcnt is number of elements in fractal-template
|
|
|
|
|
|
|
|
- for(n = 0; n < segcnt; n++) // Initiate pattern : put all (numbered) segments in numeric order
|
|
|
|
|
- pattern1[n] = n;
|
|
|
|
|
- grpcnt = segcnt; // Start off repatterning all existing segments
|
|
|
|
|
- cutcnt = 1;
|
|
|
|
|
- patcnt = 0;
|
|
|
|
|
- for(n = 0;n < fracdepth; n++) { // For every cut-stage : loop-n
|
|
|
|
|
- thiscut = 0; // Specify start and end of first-cut of cutcnt repatternings
|
|
|
|
|
- cutend = grpcnt;
|
|
|
|
|
- patcnt = 0; // Initialise pattern counter at start of every repatterning
|
|
|
|
|
|
|
+ return FINISHED;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************************* CREATE_FRACTAL_PATTERN ***************************/
|
|
|
|
|
|
|
|
- for(j = 0; j < cutcnt;j ++) { // For the number of cuts to be made at this stage : loop-j
|
|
|
|
|
- if(patcnt + (grpcnt * 2) > patterncnt) {
|
|
|
|
|
- sprintf(errstr,"ERROR: Error in pattern generation counting.\n");
|
|
|
|
|
|
|
+int create_fractal_pattern(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int fractalcnt = dz->itemcnt, total_fractalcnt, k, n, nn, t, v, ocnt = 0;
|
|
|
|
|
+ double *fracpattern = dz->parray[0]; // Stores final conmplete fractalisation of data
|
|
|
|
|
+ double *swapbuffer1 = dz->parray[1]; // Intermediate buffers to calc fractalisation, stage by stage
|
|
|
|
|
+ double *swapbuffer2 = dz->parray[2];
|
|
|
|
|
+ double *thisbuf = NULL, *thatbuf = NULL;
|
|
|
|
|
+ double *fractemplate = dz->parray[3]; // Original fractal template time-val pairs
|
|
|
|
|
+ double *fracintvl = dz->parray[4]; // Intervals between pitches in original fractal pitch-template
|
|
|
|
|
+ double *fractimes = dz->parray[5]; // Fractal template element-start-times
|
|
|
|
|
+ double starttime, startval, duration, shrinkage;
|
|
|
|
|
+
|
|
|
|
|
+ memset((char *)fracpattern,0,dz->arraysize * sizeof(double));
|
|
|
|
|
+ memset((char *)swapbuffer1,0,dz->arraysize * sizeof(double));
|
|
|
|
|
+ memset((char *)swapbuffer2,0,dz->arraysize * sizeof(double));
|
|
|
|
|
+ memcpy((char *)swapbuffer1,(char *)fractemplate,(dz->itemcnt+1) * 2 * sizeof(double)); // Get original fractal-shape, with wraparound time
|
|
|
|
|
+ // mode 0 = semitone transpos : mode1 = MIDIpitch
|
|
|
|
|
+ total_fractalcnt = fractalcnt; // If fractalise only once, this is enough
|
|
|
|
|
+ if(dz->maxfractalise == 1)
|
|
|
|
|
+ thatbuf = swapbuffer1;
|
|
|
|
|
+ else {
|
|
|
|
|
+ for(k = 1; k < dz->maxfractalise;k++) {
|
|
|
|
|
+ ocnt = 0;
|
|
|
|
|
+ if(ODD(k)) {
|
|
|
|
|
+ thisbuf = swapbuffer1;
|
|
|
|
|
+ thatbuf = swapbuffer2;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ thisbuf = swapbuffer2;
|
|
|
|
|
+ thatbuf = swapbuffer1;
|
|
|
|
|
+ }
|
|
|
|
|
+ memset((char *)thatbuf,0,dz->arraysize * sizeof(double));
|
|
|
|
|
+ for(n = 0, t = 0, v = 1; n < total_fractalcnt; n++,t+=2,v+=2) { // Fractalise every element of the "total_fractalcnt" elements existing at this stage.
|
|
|
|
|
+ starttime = thisbuf[t];
|
|
|
|
|
+ startval = thisbuf[v];
|
|
|
|
|
+ duration = thisbuf[t+2] - thisbuf[t]; // There is a wrap-around time-point in orig fractal-template
|
|
|
|
|
+ shrinkage = duration/dz->fracdur;
|
|
|
|
|
+ for(nn = 0; nn < fractalcnt; nn++) {
|
|
|
|
|
+ if(ocnt + 2 >= dz->arraysize) {
|
|
|
|
|
+ sprintf(errstr,"Array overrun in generating fractal.\n");
|
|
|
|
|
+ return PROGRAM_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ thatbuf[ocnt++] = starttime + (fractimes[nn] * shrinkage);
|
|
|
|
|
+ if(dz->vflag[FRAC_SHRINK])
|
|
|
|
|
+ thatbuf[ocnt++] = startval + (fracintvl[nn] * shrinkage);
|
|
|
|
|
+ else
|
|
|
|
|
+ thatbuf[ocnt++] = startval + fracintvl[nn];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ total_fractalcnt = ocnt/2; // No of fractal elements after this fractalisation now increaaed to new "total_fractalcnt"
|
|
|
|
|
+ if(ocnt >= dz->arraysize - 1) {
|
|
|
|
|
+ sprintf(errstr,"Array overrun in generating last timepoint of fractal.\n");
|
|
|
return PROGRAM_ERROR;
|
|
return PROGRAM_ERROR;
|
|
|
}
|
|
}
|
|
|
- for(m = thiscut; m <cutend;m++) // Copy pattern to new array abcd
|
|
|
|
|
- pattern2[patcnt++] = pattern1[m];
|
|
|
|
|
- for(m = cutend-1; m >= thiscut;m--) // Then copy it in reverse abcddbca
|
|
|
|
|
- pattern2[patcnt++] = pattern1[m];
|
|
|
|
|
- thiscut += grpcnt;
|
|
|
|
|
- cutend += grpcnt; // Advance start and end of cut in j-loop
|
|
|
|
|
|
|
+ thatbuf[ocnt++] = fractemplate[dz->itemcnt*2]; // Retain wraparound time-point
|
|
|
}
|
|
}
|
|
|
- if(EVEN(n)) {
|
|
|
|
|
- pattern1 = patternb; // Swap pattern pointers
|
|
|
|
|
- pattern2 = patterna;
|
|
|
|
|
- } else { // Final pattern always ends up as pattern1
|
|
|
|
|
- pattern1 = patterna;
|
|
|
|
|
- pattern2 = patternb;
|
|
|
|
|
- } // ONCE ALL segs at this level are reverse-copied and abutted
|
|
|
|
|
- grpcnt /= 2; // Gpsize to Cut gets smaller (by 1/2) BUT the total pattern has doubled in size
|
|
|
|
|
- cutcnt *= 4; // SO The number of cuts goes up by 2 X 2 !!
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // TRANSFER SEGMENTS TO BUFFERS, EXTENDING BACKWARDS FOR UPSPLICE, AND DO START AND END SPLICES
|
|
|
|
|
-
|
|
|
|
|
- // Segments extended backwards by splicelen, but not forwards
|
|
|
|
|
- // |_______ |
|
|
|
|
|
- // | /| \ |
|
|
|
|
|
- // |/ | \|
|
|
|
|
|
- // | | |
|
|
|
|
|
- // add | |
|
|
|
|
|
- // for | length |
|
|
|
|
|
- // splice|specified|
|
|
|
|
|
- // |_________|
|
|
|
|
|
- // |_______ |
|
|
|
|
|
- // /| \ |
|
|
|
|
|
- // / | next \|
|
|
|
|
|
- // | segment |
|
|
|
|
|
- // |
|
|
|
|
|
-
|
|
|
|
|
- for(n = 0; n < segcnt; n++) {
|
|
|
|
|
- cutstt = ((n * segsize) - splicelen) * chans; // Startcut is segment-index in pattern X segsize, MINUS room for splice
|
|
|
|
|
- cutstt = max(cutstt,0);
|
|
|
|
|
- cutend = (n + 1) * segsize * chans; // Startcut is segment-index+1
|
|
|
|
|
- cutend = min(cutend,dz->insams[0]);
|
|
|
|
|
- for(m = cutstt,thissegsize = 0; m < cutend; m++,thissegsize++) // Copy segment to Relevant buffer
|
|
|
|
|
- buf[n][thissegsize] = ibuf[m]; // Counting the segment size with thissegsize
|
|
|
|
|
- z = thissegsize - 1;
|
|
|
|
|
- for(m = 0; m < splicelen; m++) {
|
|
|
|
|
- if( n == 0) { // Start segment has no upsplice
|
|
|
|
|
- for(c = 0; c < chans; c++) {
|
|
|
|
|
- buf[n][z] = (float)(buf[n][z] * splicebuf[m]);
|
|
|
|
|
- z--;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n = 0, t = 0, v = 1; n < total_fractalcnt; n++,t+=2,v+=2) {
|
|
|
|
|
+ fracpattern[t] = thatbuf[t];
|
|
|
|
|
+ if((dz->brksize[FRACISTR] > 0) || (dz->param[FRACISTR] > 0.0)) // If fractal is interval warped, do it here
|
|
|
|
|
+ thatbuf[v] *= dz->param[FRACISTR];
|
|
|
|
|
+ fracpattern[v] = pow(2.0,(thatbuf[v]/SEMITONES_PER_OCTAVE)); // Convert to 8va-transpos
|
|
|
|
|
+ }
|
|
|
|
|
+ fracpattern[t] = thatbuf[t]; // Store wraparound time-point
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->param[FRACTSTR] > 0.0) {
|
|
|
|
|
+ for(t=0;t <= total_fractalcnt * 2; t+=2) // If fractal is time-warped, do the timewarp
|
|
|
|
|
+ fracpattern[t] *= dz->param[FRACTSTR];
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->fracsize = total_fractalcnt; // Remember length of fractal pattern
|
|
|
|
|
+ return FINISHED;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************************* CHECK_FRACTAL_PARAM_VALIDITY_AND_CONSISTENCY ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int check_fractal_param_validity_and_consistency(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double minwarp = 0.0;
|
|
|
|
|
+ dz->timevary = 0;
|
|
|
|
|
+ if(dz->brksize[FRACMAX] || dz->brksize[FRACTSTR] || dz->brksize[FRACISTR])
|
|
|
|
|
+ dz->timevary = 1;
|
|
|
|
|
+ if(dz->brksize[FRACTSTR]) {
|
|
|
|
|
+ if((exit_status = get_minvalue_in_brktable(&minwarp,FRACTSTR,dz))<0)
|
|
|
|
|
+ return exit_status;
|
|
|
|
|
+ if(minwarp < 1.0) {
|
|
|
|
|
+ sprintf(errstr,"Values in timewarp table must be >= 1.0\n");
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if(dz->param[FRACTSTR] > 0.0 && dz->param[FRACTSTR] < 1.0) {
|
|
|
|
|
+ sprintf(errstr,"Non-zero timewarp value must be >= 1.\n");
|
|
|
|
|
+ return DATA_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->process == FRACTAL) {
|
|
|
|
|
+ dz->splicesmps = (int)ceil(FRAC_SPLICELEN * MS_TO_SECS * (double)dz->infile->srate);
|
|
|
|
|
+ dz->total_splice = dz->splicesmps * dz->infile->channels;
|
|
|
|
|
+ if(dz->mode == 1) {
|
|
|
|
|
+ if(dz->insams[0] < dz->total_splice) {
|
|
|
|
|
+ fprintf(stdout,"WARNING: Infile too short to enable endsplice to be made.\n");
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+ dz->total_splice = 0; // Don't attempt endsplice
|
|
|
|
|
+ }
|
|
|
|
|
+ } else
|
|
|
|
|
+ dz->total_splice = 0; // No endsplice needed in mode 0
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dz->splicesmps = 0; // Probably redundant
|
|
|
|
|
+ dz->total_splice = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ return FINISHED;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************************* FRACTALISE ***************************/
|
|
|
|
|
+
|
|
|
|
|
+int fractalise(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status, chans = dz->infile->channels, done = 0, ch, nxt, n, m;
|
|
|
|
|
+ double intime = 0.0, outtime = 0.0, ztime, localtime, srate = (double)dz->infile->srate;
|
|
|
|
|
+ int ibufpos = 0, gpibufpos = 0, obufpos = 0, fracindex = 0, bufcnt = 0, abs_input_start_samp = 0, nextfracsampcnt, zsamps;
|
|
|
|
|
+ int gpbuflen = dz->buflen/chans, abs_window_cnt = 0, next_abs_window_cnt = 0;
|
|
|
|
|
+ double dibufpos = 0.0, localsampcnt, incr, frac, diff, spliceval, abs_time = 0, nexttime = 0.0, transpose = 1.0;
|
|
|
|
|
+ double *fracpattern = dz->parray[0];
|
|
|
|
|
+ float *ibuf, *obuf, *ovflwbuf = NULL;
|
|
|
|
|
+ double *val;
|
|
|
|
|
+ double *fractemplate = dz->parray[3];
|
|
|
|
|
+ if(dz->process == FRACTAL) {
|
|
|
|
|
+ ibuf = dz->sampbuf[0];
|
|
|
|
|
+ /* input overflow in = dz->sampbuf[1] */
|
|
|
|
|
+ obuf = dz->sampbuf[2];
|
|
|
|
|
+ ovflwbuf = dz->sampbuf[3];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ibuf = dz->sampbuf[0];
|
|
|
|
|
+ obuf = dz->sampbuf[1];
|
|
|
|
|
+ }
|
|
|
|
|
+ if((val = (double *)malloc(chans * sizeof(double))) == NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to create intermediate value storage.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!dz->timevary) { // If fractal does not vary
|
|
|
|
|
+ if((exit_status = create_fractal_pattern(dz)) < 0)
|
|
|
|
|
+ return exit_status; // Create fixed fractal pattern
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->process == FRACTAL) {
|
|
|
|
|
+ // FRACTAL reads a double buffer, so that we have wraparound points to use
|
|
|
|
|
+ if(dz->mode == 0) { // (If mode 1, source used as "table", and is already in buffer)
|
|
|
|
|
+ dz->buflen *= 2;
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ abs_input_start_samp = 0;
|
|
|
|
|
+ dz->buflen /= 2;
|
|
|
|
|
+ }
|
|
|
|
|
+ for(ch = 0;ch < chans; ch++) // Read initial src/table values to output value store
|
|
|
|
|
+ val[ch] = ibuf[ch];
|
|
|
|
|
+ } else { // FRACSPEC reads a single buffer of analysis samples
|
|
|
|
|
+ dz->flbufptr[0] = ibuf;
|
|
|
|
|
+ dz->flbufptr[1] = obuf;
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ memcpy((char *)obuf,(char *)ibuf,dz->wanted * sizeof(float));
|
|
|
|
|
+ abs_time = dz->frametime; // First window is copied (below)
|
|
|
|
|
+ abs_window_cnt = 1;
|
|
|
|
|
+ dz->flbufptr[0] += dz->wanted; // flbufptrs advance
|
|
|
|
|
+ dz->flbufptr[1] += dz->wanted;
|
|
|
|
|
+ }
|
|
|
|
|
+ while(!done) {
|
|
|
|
|
+ if(dz->timevary) { // If fractal varies in time
|
|
|
|
|
+ if(dz->mode == 1 || (dz->process == FRACTAL && dz->vflag[FRAC_OUTIMES])) { // Read brkpoint data using either time in infile or time in outfile
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables(outtime,dz))<0)
|
|
|
|
|
+ return exit_status;
|
|
|
} else {
|
|
} else {
|
|
|
- j = m*2; // Otherwise : do start and end splices simultaneously
|
|
|
|
|
- for(c = 0; c < chans; c++) {
|
|
|
|
|
- buf[n][j] = (float)(buf[n][j] * splicebuf[m]);
|
|
|
|
|
- j++;
|
|
|
|
|
- buf[n][z] = (float)(buf[n][z] * splicebuf[m]);
|
|
|
|
|
- z--;
|
|
|
|
|
|
|
+ if((exit_status = read_values_from_all_existing_brktables(intime,dz))<0)
|
|
|
|
|
+ return exit_status;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->iparam[FRACMAX] > 0) // Find maximum fractalisation
|
|
|
|
|
+ dz->maxfractalise = dz->iparam[FRACMAX];
|
|
|
|
|
+ else
|
|
|
|
|
+ get_max_fractalisation(dz);
|
|
|
|
|
+ if(dz->maxfractalise > 0) // Create the fractal pattern, and remember length of fractal-pattern (dz->fracsize)
|
|
|
|
|
+ create_fractal_pattern(dz);
|
|
|
|
|
+ }
|
|
|
|
|
+ ztime = fractemplate[dz->itemcnt * 2];
|
|
|
|
|
+ if(dz->maxfractalise == 0) {
|
|
|
|
|
+ if(dz->process == FRACTAL) {
|
|
|
|
|
+ zsamps = (int)round(ztime * srate);
|
|
|
|
|
+ gpibufpos = (int)round(dibufpos); // Approximation of interpolating pointer involved here
|
|
|
|
|
+ ibufpos = gpibufpos * chans;
|
|
|
|
|
+ for(n = 0; n <zsamps; n++) {
|
|
|
|
|
+ if(ibufpos >= dz->buflen) {
|
|
|
|
|
+ if(dz->mode == 0) { // If reading countinuous input, advance by buflen
|
|
|
|
|
+ memset((char *)ibuf,0,dz->buflen * 2 * sizeof(float));
|
|
|
|
|
+ bufcnt++;
|
|
|
|
|
+ if(dz->buflen * bufcnt >= dz->insams[0]) {
|
|
|
|
|
+ done = 1; // Exit if attempted samps_read looks beyound input file end
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ sndseekEx(dz->ifd[0],dz->buflen * bufcnt,0);
|
|
|
|
|
+ dz->buflen *= 2; // and read 2 * buflen (so we have wraparound)
|
|
|
|
|
+ abs_input_start_samp += dz->ssampsread/2;
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->buflen /= 2;
|
|
|
|
|
+ if(dz->ssampsread == 0) { // Exit if no more samples to read (should be redundant as trap at snd seek above)
|
|
|
|
|
+ done = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ibufpos -= dz->buflen;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(obufpos >= dz->buflen + dz->total_splice) { // Allow enough samples on end of output to perform splice. (ALPHA)
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status); // Write to outfile, then copy back ovflow into obuf
|
|
|
|
|
+ memset((char *)obuf,0,dz->buflen * sizeof(float));
|
|
|
|
|
+ memcpy((char *)obuf,(char *)ovflwbuf,dz->buflen * sizeof(float));
|
|
|
|
|
+ memset((char *)ovflwbuf,0,dz->buflen * sizeof(float));
|
|
|
|
|
+ obufpos -= dz->buflen; // and reset obufptr
|
|
|
|
|
+ }
|
|
|
|
|
+ for(ch = 0;ch<chans;ch++)
|
|
|
|
|
+ obuf[obufpos++] = ibuf[ibufpos++];
|
|
|
|
|
+ }
|
|
|
|
|
+ gpibufpos = ibufpos/chans;
|
|
|
|
|
+ dibufpos = (double)gpibufpos;
|
|
|
|
|
+ intime += ztime; // overflow point in fractal template contains its duration, so advance time in input file
|
|
|
|
|
+ outtime += ztime; // time in output file
|
|
|
|
|
+ } else { // FRACSPEC
|
|
|
|
|
+ next_abs_window_cnt = (int)round(ztime/dz->frametime);
|
|
|
|
|
+ while(abs_window_cnt < next_abs_window_cnt) {
|
|
|
|
|
+ memcpy((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],dz->wanted * sizeof(float));
|
|
|
|
|
+ dz->flbufptr[0] += dz->wanted;
|
|
|
|
|
+ dz->flbufptr[1] += dz->wanted;
|
|
|
|
|
+ if(dz->flbufptr[0] >= obuf) {
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ memset((char *)ibuf,0,dz->buflen * sizeof(float));
|
|
|
|
|
+ memset((char *)obuf,0,dz->buflen * sizeof(float));
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(dz->ssampsread == 0) {
|
|
|
|
|
+ done = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->flbufptr[0] = ibuf;
|
|
|
|
|
+ dz->flbufptr[1] = obuf;
|
|
|
|
|
+ }
|
|
|
|
|
+ abs_window_cnt++;
|
|
|
|
|
+ abs_time += dz->frametime;
|
|
|
|
|
+ if(abs_window_cnt >= dz->wlength) {
|
|
|
|
|
+ done = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if(dz->process == FRACTAL) {
|
|
|
|
|
+ localsampcnt = 0; // This is a count in gp-samples
|
|
|
|
|
+ fracindex = 0;
|
|
|
|
|
+ while(fracindex < dz->fracsize * 2) { // For each unit of the fractal (2 entries - time:val - per fractal element)
|
|
|
|
|
+ nextfracsampcnt = (int)round(fracpattern[fracindex + 2] * srate);
|
|
|
|
|
+ while(localsampcnt > nextfracsampcnt) {
|
|
|
|
|
+ fracindex += 2;
|
|
|
|
|
+ if(fracindex >= dz->fracsize)
|
|
|
|
|
+ break;
|
|
|
|
|
+ nextfracsampcnt = (int)round(fracpattern[fracindex + 2] * srate);
|
|
|
|
|
+ }
|
|
|
|
|
+ incr = fracpattern[fracindex + 1]; // Get current input-read increment
|
|
|
|
|
+ while(localsampcnt < nextfracsampcnt) { // While we're still using the current increment
|
|
|
|
|
+ for(ch = 0;ch < chans; ch++)
|
|
|
|
|
+ obuf[obufpos++] = (float)val[ch]; // Copy current value from input to output
|
|
|
|
|
+ if(obufpos >= dz->buflen + dz->total_splice) {// Allow enough samples on end of output to perform splice. (ALPHA)
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status); // Write to outfile, then copy back ovflow into obuf
|
|
|
|
|
+ memset((char *)obuf,0,dz->buflen * sizeof(float));
|
|
|
|
|
+ memcpy((char *)obuf,(char *)ovflwbuf,dz->buflen * sizeof(float));
|
|
|
|
|
+ memset((char *)ovflwbuf,0,dz->buflen * sizeof(float));
|
|
|
|
|
+ obufpos -= dz->buflen; // and reset obufptr
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->mode == 1) {
|
|
|
|
|
+ dibufpos += incr * dz->convertor; // Advance in table-read
|
|
|
|
|
+ gpibufpos = (int)floor(dibufpos);
|
|
|
|
|
+ ibufpos = gpibufpos; // Mono
|
|
|
|
|
+ }else {
|
|
|
|
|
+ dibufpos += incr; // Advance pointer in infile src
|
|
|
|
|
+ gpibufpos = (int)floor(dibufpos);
|
|
|
|
|
+ ibufpos = gpibufpos * chans; // In mode 1, if run off end of input file, quit
|
|
|
|
|
+ if(abs_input_start_samp + ibufpos >= dz->insams[0]) {
|
|
|
|
|
+ done = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ frac = dibufpos - (double)gpibufpos;
|
|
|
|
|
+ if(gpibufpos >= gpbuflen) {
|
|
|
|
|
+ if(dz->mode == 0) { // If reading countinuous input, advance by buflen
|
|
|
|
|
+ memset((char *)ibuf,0,dz->buflen * 2 * sizeof(float));
|
|
|
|
|
+ bufcnt++;
|
|
|
|
|
+ if(dz->buflen * bufcnt >= dz->insams[0]) {
|
|
|
|
|
+ done = 1; // Exit if attempted samps_read looks beyound input file end
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ sndseekEx(dz->ifd[0],dz->buflen * bufcnt,0);
|
|
|
|
|
+ dz->buflen *= 2; // and read 2 * buflen (so we have wraparound)
|
|
|
|
|
+ abs_input_start_samp += dz->ssampsread/2;
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->buflen /= 2;
|
|
|
|
|
+ if(dz->ssampsread == 0) { // Exit if no more samples to read (should be redundant as trap at snd seek above)
|
|
|
|
|
+ done = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ gpibufpos -= gpbuflen;
|
|
|
|
|
+ dibufpos -= (double)gpbuflen;
|
|
|
|
|
+ ibufpos = gpibufpos * chans;
|
|
|
|
|
+ } // Working in absolute sample-frame get interpolated value(s) from src/table
|
|
|
|
|
+ for(ch = 0,nxt = chans;ch < chans;ch++,nxt++) {
|
|
|
|
|
+ val[ch] = ibuf[ibufpos + ch];
|
|
|
|
|
+ diff = ibuf[ibufpos + nxt] - val[ch];
|
|
|
|
|
+ val[ch] += diff * frac;
|
|
|
|
|
+ }
|
|
|
|
|
+ localsampcnt += incr; // Advance by given samp-time incr
|
|
|
|
|
+ if(localsampcnt >= nextfracsampcnt) // If we reach time of next fractal (we will therefore exit inner loop)
|
|
|
|
|
+ fracindex += 2; // incr fracindex-value, hence advance in fractal pattern in outer loop
|
|
|
|
|
+ }
|
|
|
|
|
+ if(done)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ intime += fracpattern[dz->fracsize]; // overflow point in fractal table contains its duration, so advance time in input file
|
|
|
|
|
+ outtime = (double)((dz->total_samps_written + obufpos)/chans)/srate; // time in output file
|
|
|
|
|
+ if(dz->mode == 1) {
|
|
|
|
|
+ if(outtime >= dz->param[FRACDUR])
|
|
|
|
|
+ done = 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if(intime >= dz->duration)
|
|
|
|
|
+ done = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else { // FRACSPEC
|
|
|
|
|
+ localtime = 0.0;
|
|
|
|
|
+ fracindex = 0;
|
|
|
|
|
+ while(fracindex < dz->fracsize * 2) { // For each unit of the fractal (2 entries - time:val - per fractal element)
|
|
|
|
|
+ nexttime = fracpattern[fracindex + 2];
|
|
|
|
|
+ transpose = fracpattern[fracindex + 1];
|
|
|
|
|
+ while(localtime < nexttime) {
|
|
|
|
|
+ if((exit_status = fractal_spectrnsf(transpose,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ memcpy((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],dz->wanted * sizeof(float));
|
|
|
|
|
+ dz->flbufptr[0] += dz->wanted;
|
|
|
|
|
+ dz->flbufptr[1] += dz->wanted;
|
|
|
|
|
+ if(dz->flbufptr[0] >= obuf) { // obuf abutts to end of ibuf
|
|
|
|
|
+ if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ memset((char *)ibuf,0,dz->buflen * sizeof(float));
|
|
|
|
|
+ memset((char *)obuf,0,dz->buflen * sizeof(float));
|
|
|
|
|
+ if((exit_status = read_samps(ibuf,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(dz->ssampsread == 0) {
|
|
|
|
|
+ done = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->flbufptr[0] = ibuf;
|
|
|
|
|
+ dz->flbufptr[1] = obuf;
|
|
|
|
|
+ }
|
|
|
|
|
+ abs_window_cnt++;
|
|
|
|
|
+ abs_time += dz->frametime;
|
|
|
|
|
+ localtime += dz->frametime;
|
|
|
|
|
+ if(abs_time >= dz->duration) {
|
|
|
|
|
+ done = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ fracindex += 2;
|
|
|
|
|
+ if(done)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(obufpos > 0) {
|
|
|
|
|
+ if(dz->process == FRACTAL) {
|
|
|
|
|
+ if(dz->mode == 1 && dz->total_splice > 0) {
|
|
|
|
|
+ for(n=0,m = obufpos - chans;n < dz->splicesmps;n++,m -= chans) {
|
|
|
|
|
+ spliceval = (double)n/(double)dz->splicesmps;
|
|
|
|
|
+ for(ch = 0;ch < chans;ch++) // Splice end of output
|
|
|
|
|
+ obuf[m+ch] = (float)(obuf[m+ch] * spliceval);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- cutsegsize[n] = thissegsize;
|
|
|
|
|
|
|
+ if((exit_status = write_samps(obuf,obufpos,dz))<0)
|
|
|
|
|
+ return(exit_status); // Write last samples to outfile
|
|
|
}
|
|
}
|
|
|
|
|
+ return FINISHED;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- dz->tempsize = segsize * patcnt; // Approximate size of output
|
|
|
|
|
|
|
+/**************************** GET_MAX_FRACTALISATION ****************************/
|
|
|
|
|
|
|
|
- // JOIN SEGMENTS TOGETHER IN OUTBUF, IN ORDER OF PATTERN
|
|
|
|
|
|
|
+void get_max_fractalisation(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ double minlen = dz->minstep; // minimum duration in fractal-shape
|
|
|
|
|
+ dz->maxfractalise = 0;
|
|
|
|
|
+ if(dz->param[FRACTSTR] > 1.0) // If fractal-shape gets stretched anywhere, expand minlen appropriately
|
|
|
|
|
+ minlen *= dz->param[FRACTSTR];
|
|
|
|
|
+ while(minlen > dz->mintime) { // Calculate the max possible fractalisation
|
|
|
|
|
+ minlen *= dz->minfracratio;
|
|
|
|
|
+ dz->maxfractalise++;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- obufpos = splicelen * chans; // Preset ensures baktrak for splice doesn't run off start of infile
|
|
|
|
|
- for(n = 0; n < patterncnt; n++) {
|
|
|
|
|
- obufpos -= splicelen * chans; // baktrak to do splice
|
|
|
|
|
- segno = pattern1[n]; // Find segment indicated at position "n" in pattern
|
|
|
|
|
- // and therefore get its buffer number (segno)
|
|
|
|
|
- for(m = 0; m < cutsegsize[segno]; m++) {
|
|
|
|
|
- obuf[obufpos] = (float)(obuf[obufpos] + buf[segno][m]); // Add-Copy segment to obuf (automatically overlapping splices)
|
|
|
|
|
- if(++obufpos >= dz->buflen * 2) {
|
|
|
|
|
- insams = dz->insams[0]; // These two lines ensure that
|
|
|
|
|
- dz->insams[0] = dz->tempsize; // time-reports when program runs are correct
|
|
|
|
|
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
- return(exit_status);
|
|
|
|
|
- dz->insams[0] = insams;
|
|
|
|
|
- memcpy((char *)obuf,(char *)ovflwbuf,dz->buflen * sizeof(float));
|
|
|
|
|
- memset((char *)ovflwbuf,0,dz->buflen * sizeof(float));
|
|
|
|
|
- obufpos -= dz->buflen;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+/**************************** CREATE_FRACTAL_SNDBUFS ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int create_fractal_sndbufs(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status, n;
|
|
|
|
|
+ int bigbufsize, secsize, m;
|
|
|
|
|
+ int framesize = F_SECSIZE * dz->infile->channels;
|
|
|
|
|
+ double srate = (double)dz->infile->srate;
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->process == FRACTAL) {
|
|
|
|
|
+ if (dz->mode == 1) // Mode 1, source file is used as a table to read cyclically
|
|
|
|
|
+ bigbufsize = dz->insams[0] * sizeof(float);
|
|
|
|
|
+ else
|
|
|
|
|
+ bigbufsize = (int)Malloc(-1);
|
|
|
|
|
+ secsize = bigbufsize/framesize;
|
|
|
|
|
+ if(secsize * framesize < bigbufsize) {
|
|
|
|
|
+ secsize++;
|
|
|
|
|
+ bigbufsize = secsize * framesize;
|
|
|
}
|
|
}
|
|
|
|
|
+ } else
|
|
|
|
|
+ bigbufsize = dz->wanted * BUF_MULTIPLIER * sizeof(float);
|
|
|
|
|
+ dz->buflen = bigbufsize/sizeof(float);
|
|
|
|
|
+ if(bigbufsize * dz->bufcnt <= 0) {
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1)
|
|
|
|
|
+ sprintf(errstr,"Infile too large to create sound buffers.\n");
|
|
|
|
|
+ else
|
|
|
|
|
+ sprintf(errstr,"Insufficent memory to create sound buffers.\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
}
|
|
}
|
|
|
- // ADD TAIL OF SOUND
|
|
|
|
|
-
|
|
|
|
|
- endfilestt = ((segcnt * segsize) - splicelen) * chans;
|
|
|
|
|
- tailsize = dz->insams[0] - endfilestt;
|
|
|
|
|
- obufpos -= splicelen * chans;
|
|
|
|
|
- for(m = 0; m < tailsize; m++) {
|
|
|
|
|
- obuf[obufpos] = (float)(obuf[obufpos] + ibuf[m]);
|
|
|
|
|
- if(++obufpos >= dz->buflen * 2) {
|
|
|
|
|
- insams = dz->insams[0];
|
|
|
|
|
- dz->insams[0] = dz->tempsize;
|
|
|
|
|
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
|
|
|
|
|
- return(exit_status);
|
|
|
|
|
- dz->insams[0] = insams;
|
|
|
|
|
- memcpy((char *)obuf,(char *)ovflwbuf,dz->buflen * sizeof(float));
|
|
|
|
|
- memset((char *)ovflwbuf,0,dz->buflen * sizeof(float));
|
|
|
|
|
- obufpos -= dz->buflen;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if((dz->bigbuf = (float *)malloc(bigbufsize * dz->bufcnt)) == NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
}
|
|
}
|
|
|
- if(obufpos) {
|
|
|
|
|
- insams = dz->insams[0];
|
|
|
|
|
- dz->insams[0] = dz->tempsize;
|
|
|
|
|
- if((exit_status = write_samps(obuf,obufpos,dz))<0)
|
|
|
|
|
|
|
+ if((dz->sampbuf = (float **)malloc(sizeof(float *) * (dz->bufcnt+1)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->sbufptr = (float **)malloc(sizeof(float *) * dz->bufcnt))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffer pointers.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(dz->process == FRACSPEC) {
|
|
|
|
|
+ if((dz->flbufptr = (float **)malloc(sizeof(float *) * dz->bufcnt))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for float sample buffers.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ for(n = 0;n <dz->bufcnt; n++)
|
|
|
|
|
+ dz->flbufptr[n] = NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for(n=0;n<dz->bufcnt;n++)
|
|
|
|
|
+ dz->sbufptr[n] = dz->sampbuf[n] = dz->bigbuf + (dz->buflen * n);
|
|
|
|
|
+ dz->sampbuf[n] = dz->bigbuf + (dz->buflen * n);
|
|
|
|
|
+ // FRACTAL
|
|
|
|
|
+ // dz->sampbuf[0] ibuf
|
|
|
|
|
+ // dz->sampbuf[1] iovflwbuf
|
|
|
|
|
+ // dz->sampbuf[2] obuf
|
|
|
|
|
+ // dz->sampbuf[3] ovflwbuf dz->sampbuf[4] end of ovflwbuf
|
|
|
|
|
+ // FRACSPEC
|
|
|
|
|
+ // dz->sampbuf[0] ibuf
|
|
|
|
|
+ // dz->sampbuf[1] obuf
|
|
|
|
|
+
|
|
|
|
|
+ if(dz->process == FRACTAL && dz->mode == 1) {
|
|
|
|
|
+ if((exit_status = read_samps(dz->sampbuf[0],dz))<0) // Read source into buffer
|
|
|
return(exit_status);
|
|
return(exit_status);
|
|
|
- dz->insams[0] = insams;
|
|
|
|
|
|
|
+ for(n=0, m = dz->insams[0];n < dz->infile->channels;n++,m++)
|
|
|
|
|
+ dz->sampbuf[0][m] = 0; // wraparound points go into iovflwbuf
|
|
|
|
|
+ dz->convertor = (double)dz->insams[0]/srate; // Table-read convertor for a 1Hz read
|
|
|
|
|
+ dz->convertor *= dz->startfrq; // Table-read convertor for a fractal-startfrq read
|
|
|
}
|
|
}
|
|
|
return FINISHED;
|
|
return FINISHED;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/****************************** FLOAT_ARRAY ******************************/
|
|
|
|
|
|
|
+/********************************** SPECTRNSF **********************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * transpose spectrum, but retain original spectral envelope.
|
|
|
|
|
+ */
|
|
|
|
|
|
|
|
-int float_array_for_fractal(int nnn,int n, float **ptr)
|
|
|
|
|
-{ /* set up a floating point array length nnn. */
|
|
|
|
|
- *ptr = (float *) calloc(nnn,sizeof(float));
|
|
|
|
|
- if(*ptr==NULL){
|
|
|
|
|
- if(n == -2) {
|
|
|
|
|
- sprintf(errstr,"pvoc: insufficient memory to store splice values.\n");
|
|
|
|
|
- return(MEMORY_ERROR);
|
|
|
|
|
- } else if(n == -1) {
|
|
|
|
|
- sprintf(errstr,"pvoc: insufficient memory to store end-segment of sound\n");
|
|
|
|
|
- return(MEMORY_ERROR);
|
|
|
|
|
- } else {
|
|
|
|
|
- sprintf(errstr,"pvoc: insufficient memory for segment-of-pattern %d\n",n+1);
|
|
|
|
|
- return(MEMORY_ERROR);
|
|
|
|
|
|
|
+int fractal_spectrnsf(double transpose,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double pre_totalamp, post_totalamp;
|
|
|
|
|
+ int cc, vc;
|
|
|
|
|
+ rectify_window(dz->flbufptr[0],dz);
|
|
|
|
|
+ if((exit_status = fractal_extract_specenv(dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = get_totalamp(&pre_totalamp,dz->flbufptr[0],dz->wanted))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(dz->vflag[1]) {
|
|
|
|
|
+ for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2)
|
|
|
|
|
+ dz->flbufptr[0][FREQ] = (float)(fabs(dz->flbufptr[0][FREQ])*transpose);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2) {
|
|
|
|
|
+ if((exit_status = fractal_tranpose_within_formant_envelope(vc,transpose,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if((exit_status = fractal_reposition_partials_in_appropriate_channels(transpose,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = get_totalamp(&post_totalamp,dz->flbufptr[0],dz->wanted))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ return normalise(pre_totalamp,post_totalamp,dz);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+ /************************** TRANPOSE_WITHIN_FORMANT_ENVELOPE *****************************/
|
|
|
|
|
+
|
|
|
|
|
+int fractal_tranpose_within_formant_envelope(int vc,double transpose,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double thisspecamp, newspecamp, thisamp, formantamp_ratio;
|
|
|
|
|
+ if((exit_status = fractal_getspecenvamp(&thisspecamp,(double)dz->flbufptr[0][FREQ],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ dz->flbufptr[0][FREQ] = (float)(fabs(dz->flbufptr[0][FREQ])*transpose);
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] < dz->nyquist) {
|
|
|
|
|
+ if(thisspecamp < VERY_TINY_VAL)
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = 0.0f;
|
|
|
|
|
+ else {
|
|
|
|
|
+ if((exit_status = fractal_getspecenvamp(&newspecamp,(double)dz->flbufptr[0][FREQ],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if(newspecamp < VERY_TINY_VAL)
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = 0.0f;
|
|
|
|
|
+ else {
|
|
|
|
|
+ formantamp_ratio = newspecamp/thisspecamp;
|
|
|
|
|
+ if((thisamp = dz->flbufptr[0][AMPP] * formantamp_ratio) < VERY_TINY_VAL)
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = 0.0f;
|
|
|
|
|
+ else
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = (float)thisamp;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return(FINISHED);
|
|
return(FINISHED);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/****************************** CREATE_FRACTAL_SNDBUFS ******************************/
|
|
|
|
|
|
|
+/************************ REPOSITION_PARTIALS_IN_APPROPRIATE_CHANNELS *************************
|
|
|
|
|
+ *
|
|
|
|
|
+ * (1) At each pass, preset store-buffer channel amps to zero.
|
|
|
|
|
+ * (2) Move frq data into appropriate channels, carrying the
|
|
|
|
|
+ * amplitude information along with them.
|
|
|
|
|
+ * Work down spectrum for upward transposition, and
|
|
|
|
|
+ * (3) up spectrum for downward transposition,
|
|
|
|
|
+ * so that we do not overwrite transposed data before we move it.
|
|
|
|
|
+ * (4) Put new frqs back into src buff.
|
|
|
|
|
+ */
|
|
|
|
|
|
|
|
-int create_fractal_sndbufs(dataptr dz)
|
|
|
|
|
|
|
+int fractal_reposition_partials_in_appropriate_channels(double transpose,dataptr dz)
|
|
|
{
|
|
{
|
|
|
- int bigbufsize, splicelen;
|
|
|
|
|
- int framesize;
|
|
|
|
|
- framesize = F_SECSIZE * dz->infile->channels;
|
|
|
|
|
- if(dz->sbufptr == 0 || dz->sampbuf==0) {
|
|
|
|
|
- sprintf(errstr,"buffer pointers not allocated: create_sndbufs()\n");
|
|
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ int truecc,truevc;
|
|
|
|
|
+ int cc, vc;
|
|
|
|
|
+ for(vc = 0, cc= 0; vc < dz->wanted; vc+=2, cc++) { /* 1 */
|
|
|
|
|
+ dz->windowbuf[0][AMPP] = 0.0f;
|
|
|
|
|
+ dz->windowbuf[0][FREQ] = (float)(cc * dz->chwidth);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(transpose > 1.0f) { /* 2 */
|
|
|
|
|
+ for(cc=dz->clength-1,vc = dz->wanted-2; cc>=0; cc--, vc-=2) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] < dz->nyquist && dz->flbufptr[0][AMPP] > 0.0f) {
|
|
|
|
|
+ if((exit_status = fractal_get_channel_corresponding_to_frq(&truecc,(double)dz->flbufptr[0][FREQ],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ truevc = truecc * 2;
|
|
|
|
|
+ if((exit_status = move_data_into_appropriate_channel(vc,truevc,dz->flbufptr[0][AMPP],dz->flbufptr[0][FREQ],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for(vc = 0; vc < dz->wanted; vc++)
|
|
|
|
|
+ dz->flbufptr[0][vc] = dz->windowbuf[0][vc];
|
|
|
|
|
+ } else if(transpose < 1.0f){ /* 3 */
|
|
|
|
|
+ for(cc=0,vc = 0; cc < dz->clength; cc++, vc+=2) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] < dz->nyquist && dz->flbufptr[0][FREQ]>0.0) {
|
|
|
|
|
+ if((exit_status = fractal_get_channel_corresponding_to_frq(&truecc,(double)dz->flbufptr[0][FREQ],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ truevc = truecc * 2;
|
|
|
|
|
+ if((exit_status = move_data_into_appropriate_channel(vc,truevc,dz->flbufptr[0][AMPP],dz->flbufptr[0][FREQ],dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for(vc = 0; vc < dz->wanted; vc++)
|
|
|
|
|
+ dz->flbufptr[0][vc] = dz->windowbuf[0][vc]; /* 4 */
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/******************* ZERO_OUTOFRANGE_CHANNELS *****************/
|
|
|
|
|
+
|
|
|
|
|
+int fractal_zero_outofrange_channels(double *totalamp,double lofrq_limit,double hifrq_limit,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int cc, vc;
|
|
|
|
|
+ *totalamp = 0.0;
|
|
|
|
|
+ for(cc = 0,vc = 0; cc < dz->clength; cc++, vc += 2) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] < lofrq_limit || dz->flbufptr[0][FREQ] > hifrq_limit)
|
|
|
|
|
+ dz->flbufptr[0][AMPP] = 0.0f;
|
|
|
|
|
+ else
|
|
|
|
|
+ *totalamp += dz->flbufptr[0][AMPP];
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** GETSPECENVAMP *************************/
|
|
|
|
|
+
|
|
|
|
|
+int fractal_getspecenvamp(double *thisamp,double thisfrq,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ double pp, ratio, ampdiff;
|
|
|
|
|
+ int z = 1;
|
|
|
|
|
+ if(thisfrq<0.0) { /* NOT SURE THIS IS CORRECT */
|
|
|
|
|
+ *thisamp = 0.0; /* SHOULD WE PHASE INVERT & RETURN A -ve AMP ?? */
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(thisfrq<=1.0)
|
|
|
|
|
+ pp = 0.0;
|
|
|
|
|
+ else
|
|
|
|
|
+ pp = log10(thisfrq);
|
|
|
|
|
+ while( dz->specenvpch[z] < pp){
|
|
|
|
|
+ z++;
|
|
|
|
|
+ /*RWD may need to trap on size of array? */
|
|
|
|
|
+ if(z == dz->infile->specenvcnt -1)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ ratio = (pp - dz->specenvpch[z-1])/(dz->specenvpch[z] - dz->specenvpch[z-1]);
|
|
|
|
|
+ ampdiff = dz->specenvamp[z] - dz->specenvamp[z-1];
|
|
|
|
|
+ *thisamp = dz->specenvamp[z-1] + (ampdiff * ratio);
|
|
|
|
|
+ *thisamp = max(0.0,*thisamp);
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/********************** EXTRACT_SPECENV *******************/
|
|
|
|
|
+
|
|
|
|
|
+int fractal_extract_specenv(dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int n, cc, vc, specenvcnt_less_one;
|
|
|
|
|
+ int botchan, topchan;
|
|
|
|
|
+ double botfreq, topfreq;
|
|
|
|
|
+ double bwidth_in_chans;
|
|
|
|
|
+ specenvcnt_less_one = dz->infile->specenvcnt - 1;
|
|
|
|
|
+ vc = 0;
|
|
|
|
|
+ // RECTIFY_CHANNEL_FRQ_ORDER
|
|
|
|
|
+ for(n=0;n<dz->infile->specenvcnt;n++)
|
|
|
|
|
+ dz->specenvamp[n] = (float)0.0;
|
|
|
|
|
+ topfreq = 0.0f;
|
|
|
|
|
+ n = 0;
|
|
|
|
|
+ while(n < specenvcnt_less_one) {
|
|
|
|
|
+ botfreq = topfreq;
|
|
|
|
|
+ botchan = (int)((botfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
|
|
|
|
|
+ botchan -= 4; // CHAN_SRCHRANGE_F
|
|
|
|
|
+ botchan = max(botchan,0);
|
|
|
|
|
+ topfreq = dz->specenvtop[n];
|
|
|
|
|
+ topchan = (int)((topfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
|
|
|
|
|
+ topchan += 4; // CHAN_SRCHRANGE_F;
|
|
|
|
|
+ topchan = min(topchan,dz->clength);
|
|
|
|
|
+ for(cc = botchan,vc = botchan * 2; cc < topchan; cc++,vc += 2) {
|
|
|
|
|
+ if(dz->flbufptr[0][FREQ] >= botfreq && dz->flbufptr[0][FREQ] < topfreq)
|
|
|
|
|
+ dz->specenvamp[n] = (float)(dz->specenvamp[n] + dz->flbufptr[0][AMPP]);
|
|
|
|
|
+ }
|
|
|
|
|
+ bwidth_in_chans = (double)(topfreq - botfreq)/dz->chwidth;
|
|
|
|
|
+ dz->specenvamp[n] = (float)(dz->specenvamp[n]/bwidth_in_chans);
|
|
|
|
|
+ n++;
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************** INITIALISE_SPECENV *********************
|
|
|
|
|
+ *
|
|
|
|
|
+ * MAR 1998: not sure if the follwoing comment is relevant any more
|
|
|
|
|
+ * but I wont risk changing it at this stage.
|
|
|
|
|
+ *
|
|
|
|
|
+ * WANTED and CLENGTH are calculated from scratch here, as dz->wanted
|
|
|
|
|
+ * gets set equal to dz->specenvcnt for calculations on formant data,
|
|
|
|
|
+ * while dz->clength may not yet be set!!
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int fractal_initialise_specenv(int *arraycnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ *arraycnt = (dz->infile->channels/2) + 1;
|
|
|
|
|
+ if((dz->specenvfrq = (float *)malloc((*arraycnt) * sizeof(float)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for formant frq array.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->specenvpch = (float *)malloc((*arraycnt) * sizeof(float)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for formant pitch array.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ /*RWD zero the data */
|
|
|
|
|
+ memset(dz->specenvpch,0,*arraycnt * sizeof(float));
|
|
|
|
|
+
|
|
|
|
|
+ if((dz->specenvamp = (float *)malloc((*arraycnt) * sizeof(float)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for formant aplitude array.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->specenvtop = (float *)malloc((*arraycnt) * sizeof(float)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for formant frq limit array.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->windowbuf = (float **)malloc(sizeof(float *)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for extra float sample buffers.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if((dz->windowbuf[0] = (float *)malloc(dz->wanted * sizeof(float)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY for extra float sample buffer 0.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************************ FRACTAL_SET_SPECENV_FRQS ****************************/
|
|
|
|
|
+
|
|
|
|
|
+int fractal_set_specenv_frqs(int arraycnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int exit_status;
|
|
|
|
|
+ double bandbot;
|
|
|
|
|
+ double *interval;
|
|
|
|
|
+ int m, n, k = 0, cc;
|
|
|
|
|
+ // PICHWISE_FORMANTS
|
|
|
|
|
+ if((exit_status = fractal_setup_octaveband_steps(&interval,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ if((exit_status = fractal_setup_low_octave_bands(arraycnt,dz))<0)
|
|
|
|
|
+ return(exit_status);
|
|
|
|
|
+ k = 4; // TOP_OF_LOW_OCTAVE_BANDS
|
|
|
|
|
+ cc = 8; // CHAN_ABOVE_LOW_OCTAVES
|
|
|
|
|
+ while(cc <= dz->clength) {
|
|
|
|
|
+ m = 0;
|
|
|
|
|
+ if((bandbot = dz->chwidth * (double)cc) >= dz->nyquist)
|
|
|
|
|
+ break;
|
|
|
|
|
+ for(n=0;n<dz->formant_bands;n++) {
|
|
|
|
|
+ if(k >= arraycnt) {
|
|
|
|
|
+ sprintf(errstr,"Formant array too small: fractal_set_specenv_frqs()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->specenvfrq[k] = (float)(bandbot * interval[m++]);
|
|
|
|
|
+ dz->specenvpch[k] = (float)log10(dz->specenvfrq[k]);
|
|
|
|
|
+ dz->specenvtop[k++] = (float)(bandbot * interval[m++]);
|
|
|
|
|
+ }
|
|
|
|
|
+ cc *= 2; /* 8-16: 16-32: 32-64 etc as 8vas, then split into bands */
|
|
|
|
|
+ }
|
|
|
|
|
+ dz->specenvfrq[k] = (float)dz->nyquist;
|
|
|
|
|
+ dz->specenvpch[k] = (float)log10(dz->nyquist);
|
|
|
|
|
+ dz->specenvtop[k] = (float)dz->nyquist;
|
|
|
|
|
+ dz->specenvamp[k] = (float)0.0;
|
|
|
|
|
+ k++;
|
|
|
|
|
+ dz->infile->specenvcnt = k;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************* SETUP_OCTAVEBAND_STEPS ************************/
|
|
|
|
|
+
|
|
|
|
|
+int fractal_setup_octaveband_steps(double **interval,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ double octave_step;
|
|
|
|
|
+ int n = 1, m = 0, halfbands_per_octave = dz->formant_bands * 2;
|
|
|
|
|
+ if((*interval = (double *)malloc(halfbands_per_octave * sizeof(double)))==NULL) {
|
|
|
|
|
+ sprintf(errstr,"INSUFFICIENT MEMORY establishing interval array for formants.\n");
|
|
|
|
|
+ return(MEMORY_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ while(n < halfbands_per_octave) {
|
|
|
|
|
+ octave_step = (double)n++/(double)halfbands_per_octave;
|
|
|
|
|
+ (*interval)[m++] = pow(2.0,octave_step);
|
|
|
|
|
+ }
|
|
|
|
|
+ (*interval)[m] = 2.0;
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/************************ SETUP_LOW_OCTAVE_BANDS ***********************
|
|
|
|
|
+ *
|
|
|
|
|
+ * Lowest PVOC channels span larger freq steps and therefore we must
|
|
|
|
|
+ * group them in octave bands, rather than in anything smaller.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+int fractal_setup_low_octave_bands(int arraycnt,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ int n;
|
|
|
|
|
+ if(arraycnt < LOW_OCTAVE_BANDS) {
|
|
|
|
|
+ sprintf(errstr,"Insufficient array space for low_octave_bands\n");
|
|
|
return(PROGRAM_ERROR);
|
|
return(PROGRAM_ERROR);
|
|
|
}
|
|
}
|
|
|
- splicelen = (int)round(1.0 * MS_TO_SECS * (double)dz->infile->srate) * dz->infile->channels;
|
|
|
|
|
- dz->buflen = max(2 * splicelen,4096);
|
|
|
|
|
- dz->buflen = (dz->buflen / framesize) * framesize;
|
|
|
|
|
|
|
+ for(n=0;n<LOW_OCTAVE_BANDS;n++) {
|
|
|
|
|
+ switch(n) {
|
|
|
|
|
+ case(0):
|
|
|
|
|
+ dz->specenvfrq[0] = (float)1.0; /* frq whose log is 0 */
|
|
|
|
|
+ dz->specenvpch[0] = (float)0.0;
|
|
|
|
|
+ dz->specenvtop[0] = (float)dz->chwidth; /* 8VA wide bands */
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(1):
|
|
|
|
|
+ dz->specenvfrq[1] = (float)(dz->chwidth * 1.5); /* Centre Chs 1-2 */
|
|
|
|
|
+ dz->specenvpch[1] = (float)log10(dz->specenvfrq[1]);
|
|
|
|
|
+ dz->specenvtop[1] = (float)(dz->chwidth * 2.0);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(2):
|
|
|
|
|
+ dz->specenvfrq[2] = (float)(dz->chwidth * 3.0); /* Centre Chs 2-4 */
|
|
|
|
|
+ dz->specenvpch[2] = (float)log10(dz->specenvfrq[2]);
|
|
|
|
|
+ dz->specenvtop[2] = (float)(dz->chwidth * 4.0);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case(3):
|
|
|
|
|
+ dz->specenvfrq[3] = (float)(dz->chwidth * 6.0); /* Centre Chs 4-8 */
|
|
|
|
|
+ dz->specenvpch[3] = (float)log10(dz->specenvfrq[3]);
|
|
|
|
|
+ dz->specenvtop[3] = (float)(dz->chwidth * 8.0);
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ sprintf(errstr,"Insufficient low octave band setups in fractal_setup_low_octave_bands()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return(FINISHED);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**************************** GET_CHANNEL_CORRESPONDING_TO_FRQ ***************************/
|
|
|
|
|
|
|
|
- bigbufsize = dz->insams[0] + (2 * dz->buflen);
|
|
|
|
|
- bigbufsize *= sizeof(float);
|
|
|
|
|
- if((dz->bigbuf = (float *)malloc(bigbufsize)) == NULL) {
|
|
|
|
|
- sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers. Don't use very big infiles\n");
|
|
|
|
|
|
|
+int fractal_get_channel_corresponding_to_frq(int *chan,double thisfrq,dataptr dz)
|
|
|
|
|
+{
|
|
|
|
|
+ if(dz->chwidth <= 0.0) {
|
|
|
|
|
+ sprintf(errstr,"chwidth not set in fractal_get_channel_corresponding_to_frq()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(thisfrq < 0.0) {
|
|
|
|
|
+ sprintf(errstr,"-ve frequency in fractal_get_channel_corresponding_to_frq()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(thisfrq > dz->nyquist) {
|
|
|
|
|
+ sprintf(errstr,"frequency beyond nyquist in fractal_get_channel_corresponding_to_frq()\n");
|
|
|
|
|
+ return(PROGRAM_ERROR);
|
|
|
|
|
+ }
|
|
|
|
|
+ *chan = (int)((fabs(thisfrq) + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
|
|
|
|
|
+ if(*chan >= dz->clength) {
|
|
|
|
|
+ sprintf(errstr,"chan (%d) beyond clength-1 (%d) returned: fractal_get_channel_corresponding_to_frq()\n",
|
|
|
|
|
+ *chan,(dz->clength)-1);
|
|
|
return(PROGRAM_ERROR);
|
|
return(PROGRAM_ERROR);
|
|
|
}
|
|
}
|
|
|
- dz->sbufptr[0] = dz->sampbuf[0] = dz->bigbuf;
|
|
|
|
|
- dz->sbufptr[1] = dz->sampbuf[1] = dz->sampbuf[0] + dz->insams[0];
|
|
|
|
|
- dz->sbufptr[2] = dz->sampbuf[2] = dz->sampbuf[1] + dz->buflen;
|
|
|
|
|
- dz->sbufptr[3] = dz->sampbuf[3] = dz->sampbuf[2] + dz->buflen;
|
|
|
|
|
return(FINISHED);
|
|
return(FINISHED);
|
|
|
}
|
|
}
|
|
|
|
|
+
|