/* * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd * http://www.trevorwishart.co.uk * http://www.composersdesktop.com * This file is part of the CDP System. The CDP System is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The CDP System is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the CDP System; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include #include #include #include #include #include //#if defined unix #define round(x) lround((x)) //#endif #define RANDSET (32) /* reduce no.of segs to small finite no, so start and end seg have chance to be chosen */ #define FORWARDS (1) #define BACKWARDS (-1) static int setup_zigzag_splice(int paramno,dataptr dz); static int make_zigsplice(int paramno,dataptr dz); static int create_zigzag_splicebuffer(dataptr dz); static int generate_zigzag_table(dataptr dz); static int sort_zigs(dataptr dz); static int eliminate_n_steps(int *this_zigtime,int *next_zigtime,int **ziglistend,int *cnt,dataptr dz); static int eliminate_step(int *next_zigtime,int **ziglistend,int *cnt,dataptr dz); static int insert_extra_zig (int direction,int **this_zigtime,int **next_zigtime,int **ziglistend,int len,dataptr dz); static int split_up_steps_too_large_for_buffer(dataptr dz); static int update_and_check_ziglist_params(int **next_zigtime,int **this_zigtime,int *ziglistend,int direction); static int generate_loop_table(dataptr dz); static int sort_loops(dataptr dz); static int insert_extra_loop_element (int direction,int **this_zigtime,int **next_zigtime,int **ziglistend,int len,dataptr dz); static int generate_scramble_table(dataptr dz); static int scramble_rand(int arraysize,dataptr dz); static int preprocess_scramble_shred(dataptr dz); static int scramble_shred(int arraysize,dataptr dz); static int get_basis_lengths(int chunkcnt,int worklen,int *unit_len, int *endlen, int *scatgrpcnt, int *endscat, int *range, int *endrange, dataptr dz); static int normal_scat(int unit_len,int endlen,int chunkcnt_less_one,dataptr dz); static int heavy_scat(int scatgrpcnt,int range,int endscat,int endrange,dataptr dz); static void permute_chunks(int chunkcnt,dataptr dz); static void insert(int n,int t,int chunkcnt,dataptr dz); static void prefix(int n,int chunkcnt,dataptr dz); static void shuflup(int k,int chunkcnt,dataptr dz); static int ptr_sort(int end,dataptr dz); static int get_maxvalue_of_rand(double *maxrand,dataptr dz); static int get_maxvalue_of_pscat(double *maxpscat,dataptr dz); static int get_minvalue_of_delay(double *mindelay,dataptr dz); static void reverse_fadevals(dataptr dz); static void set_default_gain(int mindelay_samps,dataptr dz); static void set_default_delays(dataptr dz); static void setup_iter_process_type(int is_unity_gain,dataptr dz); static int make_drnk_splicetab(dataptr dz); static int convert_sec_steps_to_grain_steps(dataptr dz); /***************************** ZIGZAG_PREPROCESS ******************************/ int zigzag_preprocess(dataptr dz) { int exit_status; int n = 0; if(dz->mode == ZIGZAG_SELF) initialise_random_sequence(IS_ZIG_RSEED,ZIGZAG_RSEED,dz); if((exit_status = setup_zigzag_splice(ZIGZAG_SPLEN,dz))<0) return(exit_status); if(dz->insams[0] <= dz->iparam[ZIG_SPLSAMPS] * dz->infile->channels * 2) { sprintf(errstr,"Infile too short for splices.\n"); return(DATA_ERROR); } if(dz->mode == ZIGZAG_SELF) { if((exit_status = generate_zigzag_table(dz))<0) return(exit_status); } if((exit_status = sort_zigs(dz))<0) return(exit_status); if(sloom) { dz->tempsize = 0L; for(n=1;nitemcnt;n++) /*RWD treat tempszie as in samps */ dz->tempsize += abs(dz->lparray[ZIGZAG_TIMES][n] - dz->lparray[ZIGZAG_TIMES][n-1]); } return(FINISHED); } /*********************** SETUP_ZIGZAG_SPLICE ***************************/ int setup_zigzag_splice(int paramno,dataptr dz) { int exit_status; if((exit_status = make_zigsplice(paramno,dz))<0) return(exit_status); return create_zigzag_splicebuffer(dz); } /*********************** MAKE_ZIGSPLICE ***************************/ int make_zigsplice(int paramno,dataptr dz) { int n; int framesize = dz->infile->channels; dz->iparam[ZIG_SPLICECNT] = (int)round(dz->param[paramno] * MS_TO_SECS * dz->infile->srate); dz->iparam[ZIG_SPLSAMPS] = dz->iparam[ZIG_SPLICECNT] * framesize; if(dz->iparam[ZIG_SPLSAMPS] >= dz->buflen) { sprintf(errstr,"Splicelength too long for available memory.\n"); return(GOAL_FAILED); } if((dz->parray[ZIGZAG_SPLICE] = (double *)malloc(dz->iparam[ZIG_SPLICECNT] * sizeof(double)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to make splicer buffer.\n"); return(MEMORY_ERROR); } for(n=0;niparam[ZIG_SPLICECNT];n++) dz->parray[ZIGZAG_SPLICE][n] = (double)n/(double)dz->iparam[ZIG_SPLICECNT]; return(FINISHED); } /*********************** CREATE_ZIGZAG_SPLICEBUFFER ***************************/ int create_zigzag_splicebuffer(dataptr dz) { if(dz->extrabuf == (float **)0) { sprintf(errstr,"extrabuf has not been created: create_zigzag_splicebuffer()\n"); return(PROGRAM_ERROR); } if((dz->extrabuf[ZIGZAG_SPLBUF] = (float *)malloc(sizeof(float) * dz->iparam[ZIG_SPLSAMPS]))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to make splicing buffer.\n"); return(MEMORY_ERROR); } memset((char *)dz->extrabuf[ZIGZAG_SPLBUF],0,sizeof(float) * dz->iparam[ZIG_SPLSAMPS]); return(FINISHED); } /***************************** GENERATE_ZIGZAG_TABLE ***************************/ int generate_zigzag_table(dataptr dz) { int OK; int arraysize = BIGARRAY; double infiledur = (double)(dz->insams[0]/dz->infile->channels)/(double)(dz->infile->srate); double totaltime = dz->param[ZIGZAG_START]; double goaltime = dz->param[ZIGZAG_DUR] - (infiledur - dz->param[ZIGZAG_END]); double diff, randlen = 0.0, here = dz->param[ZIGZAG_START]; int direction = FORWARDS; if((dz->lparray[ZIGZAG_TIMES] = (int *)malloc(arraysize * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to store times.\n"); return(MEMORY_ERROR); } dz->lparray[ZIGZAG_TIMES][0] = 0; dz->itemcnt = 1; do { OK = TRUE; switch(direction) { case(FORWARDS): diff = min(dz->param[ZIGZAG_MAX],dz->param[ZIGZAG_END] - here); if(diff<=dz->param[ZIGZAG_MIN]) OK = FALSE; else { randlen = drand48(); /* generate segment length at random */ randlen *= (diff - dz->param[ZIGZAG_MIN]); /* scale it to range required */ randlen += dz->param[ZIGZAG_MIN]; /* and add mindur */ here = (here + randlen); } break; case(BACKWARDS): diff = min(dz->param[ZIGZAG_MAX],here - dz->param[ZIGZAG_START]); if(diff<=dz->param[ZIGZAG_MIN]) OK = FALSE; else { randlen = drand48(); /* generate segment length at random */ randlen *= (diff - dz->param[ZIGZAG_MIN]); /* scale it to range required */ randlen += dz->param[ZIGZAG_MIN]; /* and add mindur */ here = (here - randlen); } break; } direction = -direction; /* invert time-direction */ if(!OK) continue; totaltime += randlen; dz->lparray[ZIGZAG_TIMES][dz->itemcnt] = round(here * (double)dz->infile->srate) * dz->infile->channels; if(++dz->itemcnt >= arraysize) { arraysize += BIGARRAY; if((dz->lparray[ZIGZAG_TIMES] = (int *)realloc((char *)dz->lparray[ZIGZAG_TIMES],arraysize*sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate times store.\n"); return(MEMORY_ERROR); } } } while(totaltimelparray[ZIGZAG_TIMES][dz->itemcnt] = dz->insams[0]; dz->itemcnt++; if(dz->itemcnt < arraysize) { if((dz->lparray[ZIGZAG_TIMES] = (int *)realloc((char *)dz->lparray[ZIGZAG_TIMES],dz->itemcnt*sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate times store.\n"); return(MEMORY_ERROR); } } return(FINISHED); } /****************************** SORT_ZIGS ************************************/ int sort_zigs(dataptr dz) { int exit_status; int zigsize; int safety = round(ZIG_MIN_UNSPLICED * MS_TO_SECS * (double)dz->infile->srate) * dz->infile->channels; int cnt = 0, firstime = TRUE, direction, previous_direction = FORWARDS; int *this_zigtime = dz->lparray[ZIGZAG_TIMES]; int *next_zigtime = dz->lparray[ZIGZAG_TIMES] + 1; int *ziglistend = dz->lparray[ZIGZAG_TIMES] + dz->itemcnt; int minzig = (dz->iparam[ZIG_SPLSAMPS] * 2) + safety; int file_samplen = dz->insams[0]; double convert_to_time = 1.0/(double)dz->infile->channels/(double)dz->infile->srate; if(minzig > (dz->buflen/2)-1) { sprintf(errstr,"splicelen too long to work with available memory\n" "Longest splicelen available %ld msecs.\n", round((double)(((((dz->buflen/2)-1) - safety)/2)/(double)dz->infile->channels/(double)dz->infile->srate) * SECS_TO_MS)-1); return(GOAL_FAILED); } if(*this_zigtime < 0 || *this_zigtime > file_samplen) { sprintf(errstr,"Invalid 1st zigtime %lf\n",(*this_zigtime) * convert_to_time); return(DATA_ERROR); } if(*(ziglistend-1) >= file_samplen) { *(ziglistend-1) = file_samplen; dz->iparam[ZIG_RUNSTOEND] = 1; } else dz->iparam[ZIG_RUNSTOEND] = 0; while(next_zigtime < ziglistend - dz->iparam[ZIG_RUNSTOEND]) { if(*next_zigtime < 0 || *next_zigtime > file_samplen) { sprintf(errstr,"Invalid zigtime %lf\n",(*next_zigtime) * convert_to_time); return(DATA_ERROR); } while((zigsize = abs(*next_zigtime - *this_zigtime)) < minzig) { if(++next_zigtime == ziglistend - dz->iparam[ZIG_RUNSTOEND]) break; } if(next_zigtime - this_zigtime > 1) { if(dz->mode == ZIGZAG_USER) { sprintf(errstr,"Some zigs too short to use with specified splicelen.\n"); return(DATA_ERROR); } eliminate_n_steps(this_zigtime,next_zigtime,&ziglistend,&cnt,dz); next_zigtime = this_zigtime + 1; } if(*next_zigtime > *this_zigtime) direction = FORWARDS; else direction = BACKWARDS; if(!firstime && (direction == previous_direction)) { if((exit_status = eliminate_step(next_zigtime,&ziglistend,&cnt,dz))<0) return(exit_status); continue; } previous_direction = direction; firstime = FALSE; this_zigtime++; next_zigtime++; } if(cnt>0) { fprintf(stdout,"WARNING: %d steps eliminated (too small relative to spliclength\n",cnt); //TW : CAN'T SPLIT LINES SENT TO SLOOM - 'WARNING' is a flag to SLOOM - possibly my error, since updated fprintf(stdout,"WARNING: or moving in same direction as previous step)\n"); fflush(stdout); if((dz->lparray[ZIGZAG_TIMES] = (int *)realloc((char *)dz->lparray[ZIGZAG_TIMES],dz->itemcnt * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate times store.\n"); return(MEMORY_ERROR); } } if(dz->iparam[ZIG_RUNSTOEND]) { if(*(ziglistend-1) - *(ziglistend-2) < dz->iparam[ZIG_SPLSAMPS] + safety) { sprintf(errstr,"Final zig too short for splicelen.\n"); return(GOAL_FAILED); } } return split_up_steps_too_large_for_buffer(dz); } /**************************** ELIMINATE_N_STEPS ***************************/ int eliminate_n_steps(int *this_zigtime,int *next_zigtime,int **ziglistend,int *cnt,dataptr dz) { int *here = this_zigtime + 1; int *there = next_zigtime; int elimination_cnt = (int)( next_zigtime - this_zigtime - 1); while(there < *ziglistend) { *here = *there; here++; there++; } if((dz->itemcnt -= elimination_cnt) < 2) { sprintf(errstr,"All zigsteps either too small for splices: or moving in same direction.\n"); return(DATA_ERROR); } *ziglistend -= elimination_cnt; (*cnt) += elimination_cnt; return(FINISHED); } /***************************** ELIMINATE_STEP ***************************/ int eliminate_step(int *next_zigtime,int **ziglistend,int *cnt,dataptr dz) { int *here = next_zigtime; while(here < *ziglistend) { *(here-1) = *here; here++; } if(--dz->itemcnt < 2) { sprintf(errstr,"All zigsteps either too small for splices: or moving in same direction.\n"); return(DATA_ERROR); } (*ziglistend)--; (*cnt)++; return(FINISHED); } /***************************** INSERT_EXTRA_ZIG ***************************/ int insert_extra_zig(int direction,int **this_zigtime,int **next_zigtime,int **ziglistend,int len,dataptr dz) { int *here; int zthis = *this_zigtime - dz->lparray[ZIGZAG_TIMES]; int znext = *next_zigtime - dz->lparray[ZIGZAG_TIMES]; dz->itemcnt++; if((dz->lparray[ZIGZAG_TIMES] = (int *)realloc((char *)dz->lparray[ZIGZAG_TIMES],dz->itemcnt * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate times store.\n"); return(MEMORY_ERROR); } *this_zigtime = dz->lparray[ZIGZAG_TIMES] + zthis; *next_zigtime = dz->lparray[ZIGZAG_TIMES] + znext; *ziglistend = dz->lparray[ZIGZAG_TIMES] + dz->itemcnt; here = *ziglistend - 1; while(here > *next_zigtime) { *here = *(here-1); here--; } switch(direction) { case(FORWARDS): *here = **this_zigtime + len; break; case(BACKWARDS): *here = **this_zigtime - len; break; } if(*here < 0.0 || (int)*here > dz->insams[0]) { sprintf(errstr,"Error in logic of sample arithmetic: insert_extra_zig()\n"); return(PROGRAM_ERROR); } return(FINISHED); } /**************************** SPLIT_UP_STEPS_TOO_LARGE_FOR_BUFFER ***************************/ int split_up_steps_too_large_for_buffer(dataptr dz) { int zigsize; int direction, n, longbufs, shortbufs; int safety = round(ZIG_MIN_UNSPLICED * MS_TO_SECS * (double)dz->infile->srate) * dz->infile->channels; int minzig = (dz->iparam[ZIG_SPLSAMPS] * 2) + safety; int *this_zigtime = dz->lparray[ZIGZAG_TIMES]; int *next_zigtime = this_zigtime + 1; int *ziglistend = dz->lparray[ZIGZAG_TIMES] + dz->itemcnt; int max_effective_length = dz->buflen - F_SECSIZE; int pre_endbuflen, endbuflen; while(next_zigtime < ziglistend) { zigsize = *next_zigtime - *this_zigtime; if(zigsize > 0.0) direction = FORWARDS; else direction = BACKWARDS; zigsize = abs(zigsize); if((longbufs = zigsize/max_effective_length) > 0) { /* TRUNCATE */ shortbufs = -1; pre_endbuflen = 0; while((endbuflen = zigsize%max_effective_length) > 0 && endbuflen < minzig) { longbufs--; if(longbufs<0) { sprintf(errstr,"splicelen is too long for available memory.\n"); return(GOAL_FAILED); } shortbufs++; pre_endbuflen = max_effective_length + endbuflen - minzig; if(pre_endbuflen > minzig) break; zigsize -= minzig; } for(n = 0; n < longbufs;n++) { insert_extra_zig(direction,&this_zigtime,&next_zigtime,&ziglistend,max_effective_length,dz); update_and_check_ziglist_params(&next_zigtime,&this_zigtime,ziglistend,direction); } if(pre_endbuflen > 0) { insert_extra_zig(direction,&this_zigtime,&next_zigtime,&ziglistend,pre_endbuflen,dz); update_and_check_ziglist_params(&next_zigtime,&this_zigtime,ziglistend,direction); } if(shortbufs > 0) { for(n = 0; n < shortbufs; n++) { insert_extra_zig(direction,&this_zigtime,&next_zigtime,&ziglistend,minzig,dz); update_and_check_ziglist_params(&next_zigtime,&this_zigtime,ziglistend,direction); } } } next_zigtime++; this_zigtime++; } return(FINISHED); } /***************************** UPDATE_AND_CHECK_ZIGLIST_PARAMS ***************************/ int update_and_check_ziglist_params(int **next_zigtime,int **this_zigtime,int *ziglistend,int direction) { int zigsize; (*next_zigtime)++; (*this_zigtime)++; if(*this_zigtime >= ziglistend - 1) { sprintf(errstr,"Error in counting logic: update_and_check_ziglist_params()\n"); return(PROGRAM_ERROR); } zigsize = **next_zigtime - **this_zigtime; if((zigsize > 0.0 && direction != FORWARDS) || (zigsize < 0.0 && direction != BACKWARDS)) { sprintf(errstr,"Error in counting logic(2): update_and_check_ziglist_params()\n"); return(PROGRAM_ERROR); } return(FINISHED); } /*********************** LOOP_PREPROCESS ***************************/ int loop_preprocess(dataptr dz) { int exit_status; initrand48(); if(dz->param[LOOP_LEN] <= dz->param[LOOP_SPLEN] * 2) { sprintf(errstr,"Loop length too short for splices.\n"); return(DATA_ERROR); } if((exit_status = setup_zigzag_splice(LOOP_SPLEN,dz))<0) return(exit_status); if(dz->insams[0] <= dz->iparam[ZIG_SPLSAMPS] * 2) { sprintf(errstr,"Infile too short for splices.\n"); return(DATA_ERROR); } if((exit_status = generate_loop_table(dz))<0) return(exit_status); return sort_loops(dz); } /***************************** GENERATE_LOOP_TABLE ***************************/ int generate_loop_table(dataptr dz) { int searchsamps, tmpstart; unsigned int file_endsamp = dz->insams[0]; int i, arraysize = BIGARRAY; int startsamp = dz->infile->channels * (int) (dz->infile->srate * dz->param[LOOP_START]); int looplen = dz->infile->channels * (int) (dz->infile->srate * dz->param[LOOP_LEN] * MS_TO_SECS); int stepsamps = dz->infile->channels * (int) (dz->infile->srate * dz->param[LOOP_STEP] * MS_TO_SECS); int lsfield = dz->infile->channels * (int) (dz->infile->srate * dz->param[LOOP_SRCHF] * MS_TO_SECS); int samplen, excess, totallen, endsamp, n; /* NEW APR 16 --> */ looplen += dz->iparam[ZIG_SPLSAMPS]; /* allow for splice overlaps in calcs */ dz->itemcnt = 0; if((dz->lparray[ZIGZAG_TIMES] = (int *)malloc(arraysize * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to store times.\n"); return(MEMORY_ERROR); } if((dz->iparray[ZIGZAG_PLAY] = (int *)malloc(arraysize * sizeof(int )))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to store section markers.\n"); return(MEMORY_ERROR); } searchsamps = 0; tmpstart = startsamp; for(i = 0; i < dz->iparam[LOOP_REPETS] ;i++) { if(dz->itemcnt + 2 > arraysize) { arraysize += BIGARRAY; if((dz->lparray[ZIGZAG_TIMES] = (int *)realloc(dz->lparray[ZIGZAG_TIMES],arraysize * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate times.\n"); return(MEMORY_ERROR); } if((dz->iparray[ZIGZAG_PLAY] = (int *)realloc(dz->iparray[ZIGZAG_PLAY],arraysize * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate markers.\n"); return(MEMORY_ERROR); } } dz->iparray[ZIGZAG_PLAY][dz->itemcnt] = TRUE; if(i==0 && dz->vflag[IS_KEEP_START]) dz->lparray[ZIGZAG_TIMES][dz->itemcnt] = 0; else dz->lparray[ZIGZAG_TIMES][dz->itemcnt] = tmpstart; dz->itemcnt++; dz->iparray[ZIGZAG_PLAY][dz->itemcnt] = FALSE; if((unsigned int)(dz->lparray[ZIGZAG_TIMES][dz->itemcnt] = tmpstart + looplen) >= file_endsamp) { dz->iparam[ZIG_RUNSTOEND] = TRUE; dz->itemcnt++; break; } dz->itemcnt++; startsamp += stepsamps; if(lsfield) searchsamps = round((double) lsfield * drand48()); tmpstart = (startsamp + searchsamps); } if(dz->iparam[ZIG_RUNSTOEND]) dz->lparray[ZIGZAG_TIMES][dz->itemcnt-1] = file_endsamp; /* Force read to end */ else if(dz->mode==LOOP_OUTLEN) { samplen = dz->infile->channels * round(dz->infile->srate * dz->param[LOOP_OUTDUR]); totallen = 0; /* Force to correct outlen */ for(n=1;nitemcnt;n+=2) totallen += dz->lparray[ZIGZAG_TIMES][n] - dz->lparray[ZIGZAG_TIMES][n-1] - dz->iparam[ZIG_SPLSAMPS]; if((excess = samplen - totallen) > 0) { endsamp = min(dz->lparray[ZIGZAG_TIMES][dz->itemcnt-1] + excess,(int)file_endsamp); dz->lparray[ZIGZAG_TIMES][dz->itemcnt-1] = endsamp; if(endsamp == (int)file_endsamp) dz->iparam[ZIG_RUNSTOEND] = TRUE; } } if((dz->lparray[ZIGZAG_TIMES] = (int *)realloc(dz->lparray[ZIGZAG_TIMES],dz->itemcnt * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate times.\n"); return(MEMORY_ERROR); } if((dz->iparray[ZIGZAG_PLAY] = (int *)realloc(dz->iparray[ZIGZAG_PLAY], dz->itemcnt * sizeof(int )))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate markers.\n"); return(MEMORY_ERROR); } return(FINISHED); } /****************************** SORT_LOOPS ************************************/ int sort_loops(dataptr dz) { int zigsize; int direction, n, longbufs, shortbufs; int safety = round(ZIG_MIN_UNSPLICED * MS_TO_SECS * (double)dz->infile->srate) * dz->infile->channels; int minzig = (dz->iparam[ZIG_SPLSAMPS] * 2) + safety; int *this_zigtime = dz->lparray[ZIGZAG_TIMES]; int *next_zigtime = this_zigtime + 1; int *ziglistend = dz->lparray[ZIGZAG_TIMES] + dz->itemcnt; int max_effective_length = dz->buflen - F_SECSIZE; int pre_endbuflen, endbuflen; int m = 0; while(next_zigtime < ziglistend) { zigsize = *next_zigtime - *this_zigtime; if(zigsize > 0.0) direction = FORWARDS; else direction = BACKWARDS; zigsize = abs(zigsize); if((longbufs = zigsize/max_effective_length) > 0) { /* TRUNCATE */ shortbufs = -1; pre_endbuflen = 0; while((endbuflen = zigsize%max_effective_length) > 0 && endbuflen < minzig) { longbufs--; if(longbufs<0) { sprintf(errstr,"splicelen is too long for available memory.\n"); return(GOAL_FAILED); } shortbufs++; pre_endbuflen = max_effective_length + endbuflen - minzig; if(pre_endbuflen > minzig) break; zigsize -= minzig; } for(n = 0; n < longbufs;n++) { insert_extra_loop_element(direction,&this_zigtime,&next_zigtime,&ziglistend,max_effective_length,dz); update_and_check_ziglist_params(&next_zigtime,&this_zigtime,ziglistend,direction); } if(pre_endbuflen > 0) { insert_extra_loop_element(direction,&this_zigtime,&next_zigtime,&ziglistend,pre_endbuflen,dz); update_and_check_ziglist_params(&next_zigtime,&this_zigtime,ziglistend,direction); } if(shortbufs > 0) { for(n = 0; n < shortbufs; n++) { insert_extra_loop_element(direction,&this_zigtime,&next_zigtime,&ziglistend,minzig,dz); update_and_check_ziglist_params(&next_zigtime,&this_zigtime,ziglistend,direction); } } } next_zigtime++; this_zigtime++; } if(sloom) { dz->tempsize = 0L; for(n=0,m=1;mitemcnt;n++,m++) { if(dz->iparray[ZIGZAG_PLAY][n]) dz->tempsize += abs(dz->lparray[ZIGZAG_TIMES][m] - dz->lparray[ZIGZAG_TIMES][n]); } /* abs for SAFETY: should be unnecessary as all plays should be forwards!! */ } return(FINISHED); } /***************************** INSERT_EXTRA_LOOP_ELEMENT ***************************/ int insert_extra_loop_element(int direction,int **this_zigtime,int **next_zigtime,int **ziglistend,int len,dataptr dz) { int *here; int *there, *playlistend, *nextplaytime; int zthis = *this_zigtime - dz->lparray[ZIGZAG_TIMES]; int znext = *next_zigtime - dz->lparray[ZIGZAG_TIMES]; dz->itemcnt++; if((dz->lparray[ZIGZAG_TIMES] = (int *)realloc(dz->lparray[ZIGZAG_TIMES],dz->itemcnt * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to insert extra loop time.\n"); return(MEMORY_ERROR); } if((dz->iparray[ZIGZAG_PLAY] = (int *)realloc(dz->iparray[ZIGZAG_PLAY], dz->itemcnt * sizeof(int )))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to insert extra loopmarker.\n"); return(MEMORY_ERROR); } *this_zigtime = dz->lparray[ZIGZAG_TIMES] + zthis; *next_zigtime = dz->lparray[ZIGZAG_TIMES] + znext; *ziglistend = dz->lparray[ZIGZAG_TIMES] + dz->itemcnt; here = *ziglistend - 1; while(here > *next_zigtime) { *here = *(here-1); here--; } nextplaytime = dz->iparray[ZIGZAG_PLAY] + (*next_zigtime - dz->lparray[ZIGZAG_TIMES]); playlistend = dz->iparray[ZIGZAG_PLAY] + dz->itemcnt; there = playlistend - 1; while(there > nextplaytime) { *there = *(there-1); there--; } switch(dz->process) { case(LOOP): /* COMMENT: this old LOOPcode may be unnecessary, as SCRAMBLE version may be OK for both */ switch(direction) { case(FORWARDS): *here = **this_zigtime + len; *there = TRUE; break; case(BACKWARDS): *here = **this_zigtime - len; *there = FALSE; break; } break; case(SCRAMBLE): switch(direction) { case(FORWARDS): *here = **this_zigtime + len; break; case(BACKWARDS): *here = **this_zigtime - len; break; } *there = *(there-1); break; } // if(*here < 0.0 || (unsigned int)*here > dz->insams[0]) { if(*here < 0.0 || (int)*here > dz->insams[0]) { sprintf(errstr,"Error in logic of sample arithmetic: insert_extra_loop_element()\n"); return(PROGRAM_ERROR); } return(FINISHED); } /***************************** SCRAMBLE_PREPROCESS ***************************/ int scramble_preprocess(dataptr dz) { int exit_status; initialise_random_sequence(IS_SCRAMBLE_RSEED,SCRAMBLE_SEED,dz); if((exit_status = setup_zigzag_splice(SCRAMBLE_SPLEN,dz))<0) return(exit_status); if(dz->insams[0] <= dz->iparam[ZIG_SPLSAMPS] * dz->infile->channels * 2) { sprintf(errstr,"Infile too short for splices.\n"); return(DATA_ERROR); } if((exit_status = generate_scramble_table(dz))<0) return(exit_status); return sort_loops(dz); } /***************************** GENERATE_SCRAMBLE_TABLE **************************/ int generate_scramble_table(dataptr dz) { int exit_status; int arraysize = BIGARRAY; if((dz->lparray[ZIGZAG_TIMES] = (int *)malloc(arraysize*sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for times store.\n"); return(MEMORY_ERROR); } if((dz->iparray[ZIGZAG_PLAY] = (int *)malloc(arraysize * sizeof(int )))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for markers store.\n"); return(MEMORY_ERROR); } switch(dz->mode) { case(SCRAMBLE_RAND): exit_status = scramble_rand(arraysize,dz); break; case(SCRAMBLE_SHRED): if((exit_status = preprocess_scramble_shred(dz))<0) return(exit_status); exit_status = scramble_shred(arraysize,dz); break; default: sprintf(errstr,"Unknown mode in generate_scramble_table()\n"); return(PROGRAM_ERROR); } if(dz->vflag[IS_SCR_KEEP_START]) dz->lparray[ZIGZAG_TIMES][0] = 0; if(dz->vflag[IS_SCR_KEEP_END]) dz->lparray[ZIGZAG_TIMES][dz->itemcnt-1] = dz->insams[0]; return(exit_status); } /***************************** SCRAMBLE_RAND **************************/ int scramble_rand(int arraysize,dataptr dz) { int lenrange = round((dz->param[SCRAMBLE_MAX] - dz->param[SCRAMBLE_MIN]) * dz->infile->srate); int minlen = round(dz->param[SCRAMBLE_MIN] * dz->infile->srate); int infilelen = dz->insams[0]; int thislen, outlen = 0, effective_range, thispos; int finished = 0, zz; double thisfrac; dz->iparam[SCRAMBLE_OUTLEN] = round(dz->param[SCRAMBLE_DUR] * dz->infile->srate) * dz->infile->channels; dz->itemcnt = 0; while(!finished) { if(dz->itemcnt + 2 >= arraysize) { arraysize += BIGARRAY; if((dz->lparray[ZIGZAG_TIMES] =(int *)realloc(dz->lparray[ZIGZAG_TIMES],arraysize*sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate times store.\n"); return(MEMORY_ERROR); } if((dz->iparray[ZIGZAG_PLAY] = (int *)realloc(dz->iparray[ZIGZAG_PLAY], arraysize*sizeof(int )))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate markers store.\n"); return(MEMORY_ERROR); } } thislen = (round(drand48() * lenrange) + minlen) * dz->infile->channels; effective_range = infilelen - dz->iparam[ZIG_SPLSAMPS] - thislen; zz = round(drand48() * RANDSET); thisfrac = (double)zz/(double)RANDSET; thispos = round(thisfrac * effective_range); if(ODD(thispos)) thispos--; dz->lparray[ZIGZAG_TIMES][dz->itemcnt] = thispos; dz->iparray[ZIGZAG_PLAY][dz->itemcnt++] = TRUE; dz->lparray[ZIGZAG_TIMES][dz->itemcnt] = thispos + thislen + dz->iparam[ZIG_SPLSAMPS]; dz->iparray[ZIGZAG_PLAY][dz->itemcnt++] = FALSE; if((outlen += thislen) >= dz->iparam[SCRAMBLE_OUTLEN]) finished = 1; } if((dz->lparray[ZIGZAG_TIMES] = (int *)realloc(dz->lparray[ZIGZAG_TIMES],dz->itemcnt * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate times store.\n"); return(MEMORY_ERROR); } if((dz->iparray[ZIGZAG_PLAY] = (int *)realloc(dz->iparray[ZIGZAG_PLAY], dz->itemcnt * sizeof(int )))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate markers store.\n"); return(MEMORY_ERROR); } return(FINISHED); } /***************************** PREPROCESS_SCRAMBLE_SHRED **************************/ int preprocess_scramble_shred(dataptr dz) { // double infiledur; int chunksamps; //infiledur = (double)(dz->insams[0]/dz->infile->channels)/(double)(dz->infile->srate); chunksamps = round(dz->param[SCRAMBLE_LEN] * dz->infile->srate) * dz->infile->channels; dz->iparam[SCRAMBLE_CHCNT] = dz->insams[0]/chunksamps; /* truncate */ if(dz->iparam[SCRAMBLE_CHCNT]<2) { sprintf(errstr,"Too long chunklen not trapped earlier.\n"); return(PROGRAM_ERROR); } dz->iparam[SCRAMBLE_OUTLEN] = round(dz->param[SCRAMBLE_DUR] * dz->infile->srate) * dz->infile->channels; if((dz->lparray[SCRAMBLE_CHUNKPTR] = (int *)malloc(dz->iparam[SCRAMBLE_CHCNT] * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to store scramble chunk pointers.\n"); return(MEMORY_ERROR); } if((dz->lparray[SCRAMBLE_CHUNKLEN] = (int *)malloc(dz->iparam[SCRAMBLE_CHCNT] * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to store scramble chunk lengths.\n"); return(MEMORY_ERROR); } if((dz->iparray[SCRAMBLE_PERM] = (int *)malloc(dz->iparam[SCRAMBLE_CHCNT] * sizeof(int )))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to store scramble permutation.\n"); return(MEMORY_ERROR); } return(FINISHED); } /******************************* SCRAMBLE_SHRED ***************************/ int scramble_shred(int arraysize,dataptr dz) { int n, exit_status; int finished = 0; int chunkcnt = dz->iparam[SCRAMBLE_CHCNT]; int worklen = dz->insams[0]; int total_len = 0; int chunkcnt_less_one = chunkcnt - 1; int unit_len, endlen, scatgrpcnt=0, endscat=0, range=0, endrange=0; int *perm = dz->iparray[SCRAMBLE_PERM]; dz->itemcnt = 0; if((exit_status = get_basis_lengths(chunkcnt,worklen,&unit_len,&endlen,&scatgrpcnt,&endscat,&range,&endrange,dz))<0) return(exit_status); while(!finished) { if(dz->iparam[SCRAMBLE_SCAT]) { if((exit_status = heavy_scat(scatgrpcnt,range,endscat,endrange,dz))<0) return(exit_status); } else { if((exit_status = normal_scat(unit_len,endlen,chunkcnt_less_one,dz))<0) return(exit_status); } for(n=0;nlparray[SCRAMBLE_CHUNKLEN][n] = dz->lparray[SCRAMBLE_CHUNKPTR][n+1] - dz->lparray[SCRAMBLE_CHUNKPTR][n]; dz->lparray[SCRAMBLE_CHUNKLEN][n] = worklen - dz->lparray[SCRAMBLE_CHUNKPTR][n]; /* 2A */ permute_chunks(chunkcnt,dz); /* 3 */ for(n=0;n < chunkcnt; n++) { if(dz->itemcnt + 2 >= arraysize) { arraysize += BIGARRAY; if((dz->lparray[ZIGZAG_TIMES] =(int *)realloc(dz->lparray[ZIGZAG_TIMES],arraysize*sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate times store.\n"); return(MEMORY_ERROR); } if((dz->iparray[ZIGZAG_PLAY] = (int *)realloc(dz->iparray[ZIGZAG_PLAY], arraysize*sizeof(int )))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate markers store.\n"); return(MEMORY_ERROR); } } dz->lparray[ZIGZAG_TIMES][dz->itemcnt] = dz->lparray[SCRAMBLE_CHUNKPTR][perm[n]]; dz->iparray[ZIGZAG_PLAY][dz->itemcnt] = TRUE; dz->lparray[ZIGZAG_TIMES][dz->itemcnt+1] = dz->lparray[ZIGZAG_TIMES][dz->itemcnt] + dz->lparray[SCRAMBLE_CHUNKLEN][perm[n]]; /* APR 1998 */ dz->lparray[ZIGZAG_TIMES][dz->itemcnt+1] += dz->iparam[ZIG_SPLSAMPS]; if(dz->lparray[ZIGZAG_TIMES][dz->itemcnt+1] > worklen) { dz->lparray[ZIGZAG_TIMES][dz->itemcnt+1] = worklen; dz->lparray[ZIGZAG_TIMES][dz->itemcnt] = worklen - dz->lparray[SCRAMBLE_CHUNKLEN][perm[n]]; } /* APR 1998 */ dz->iparray[ZIGZAG_PLAY][dz->itemcnt+1] = FALSE; if((total_len += dz->lparray[SCRAMBLE_CHUNKLEN][perm[n]]) > dz->iparam[SCRAMBLE_OUTLEN]) { finished = 1; break; } dz->itemcnt += 2; } } if((dz->lparray[ZIGZAG_TIMES] = (int *)realloc(dz->lparray[ZIGZAG_TIMES],dz->itemcnt * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate times store.\n"); return(MEMORY_ERROR); } if((dz->iparray[ZIGZAG_PLAY] = (int *)realloc(dz->iparray[ZIGZAG_PLAY], dz->itemcnt * sizeof(int )))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate markers store.\n"); return(MEMORY_ERROR); } return(FINISHED); } /*********************** GET_BASIS_LENGTHS ***********************/ int get_basis_lengths(int chunkcnt,int worklen,int *unit_len, int *endlen, int *scatgrpcnt, int *endscat, int *range, int *endrange, dataptr dz) { int excess; *unit_len = (int)round(worklen/chunkcnt); if(ODD(*unit_len)) (*unit_len)--; /* Allow for stereo case */ excess = worklen - ((*unit_len) * chunkcnt); if(ODD(excess) && dz->infile->channels==2) { sprintf(errstr,"Problem in buffer accounting: get_basis_lengths()\n"); return(PROGRAM_ERROR); } *endlen = *unit_len + excess; if(dz->param[SCRAMBLE_SCAT] >= 1.0) { dz->iparam[SCRAMBLE_SCAT] = round(dz->param[SCRAMBLE_SCAT]); *scatgrpcnt = (int)(chunkcnt/dz->iparam[SCRAMBLE_SCAT]); *endscat = (int)(chunkcnt - ((*scatgrpcnt) * dz->iparam[SCRAMBLE_SCAT])); *range = (*unit_len) * dz->iparam[SCRAMBLE_SCAT]; *endrange = ((*endscat - 1) * (*unit_len)) + *endlen; } else { dz->iparam[SCRAMBLE_SCAT] = 0; } return(FINISHED); } /************************** NORMAL_SCAT *******************************/ int normal_scat(int unit_len,int endlen,int chunkcnt_less_one,dataptr dz) { double this_scatter; int n; int new_chunklen, total_len = unit_len; for(n=1;nparam[SCRAMBLE_SCAT]; /* range +- .5 reduced by *scatter */ new_chunklen = (int)(this_scatter * (double)unit_len); if(ODD(new_chunklen)) new_chunklen--; /* in case stereo?? */ dz->lparray[SCRAMBLE_CHUNKPTR][n] = total_len + new_chunklen; /* position chunk-pointer */ total_len += unit_len; /* step to next BASE position */ } this_scatter = (drand48() - 0.5) * dz->param[SCRAMBLE_SCAT]; /* as final chunk may be unique length */ if(this_scatter<0.0) { /* if scatter is -ve, scatter is frac of penultimate length */ new_chunklen = (int)(this_scatter * (double)unit_len); if(ODD(new_chunklen)) new_chunklen--; dz->lparray[SCRAMBLE_CHUNKPTR][n] = total_len - new_chunklen; } else { /* else, scatter is frac of final length */ new_chunklen = (int)(this_scatter * (double)endlen); if(ODD(new_chunklen)) new_chunklen--; dz->lparray[SCRAMBLE_CHUNKPTR][n] = total_len + new_chunklen; } return(FINISHED); } /*********************** HEAVY_SCAT *************************** * * (1) Start at the chunk (this=1) AFTER the first (which can't be moved). * (2) STARTPTR marks the start of the chunk GROUP (and will be advanced * by RANGE, which is length of chunk-group). * (3) The loop will generate a set of positions for the chunks in * a chunk-group. In the first chunkgroup the position of the * first chunk (start of file) can't be moved, so loop starts at * (first=) 1. Subsequemt loop passes start at 0. * (4) For eveery chunk-group. * (5) Set the index of the first chunk in this group (start) to the * current index (this). * (6) For every member of this chunk-group. * (7) Generate a random-position within the chunk-grp's range * and check it is not too close ( < SPLICELEN) to the others. * Set a checking flag (OK). * (8) Generate a position within the range, and after the startptr. * (9) Compare it with all previously generated positions in this * chunk-grp AND with last position of previous chunk-group!! * If it's closer than SPLICELEN, set OK = 0, drop out of checking loop and generate another position instead. * (10) If the position is OK, drop out of position generating loop.. * (11) Advance to next chunk in this group. * (12) Once all this group is done, advance the group startpoint by RANGE. * (13) After FIRST grp, all positions can by varied, so set the initial * loop counter to (first=)0. * (14) If there are chunks left over (endscat!=0).. * Follow the same procedure for chunks in end group, using the * alternative variables, endscat and endrange. */ int heavy_scat(int scatgrpcnt,int range,int endscat,int endrange,dataptr dz) { int thiss = 0, that, start, n, m, OK; /* 1 */ int startptr = 0; /* 2 */ int minlen = (dz->iparam[ZIG_SPLSAMPS] * 2); int filend = dz->insams[0]; int first = 1; /* 3 */ /* TW OCT 1997 */ int latest_ptr = 0; dz->lparray[SCRAMBLE_CHUNKPTR][thiss++] = 0; /* TW OCT 1997 */ for(n=0;niparam[SCRAMBLE_SCAT];m++) { /* 6 */ do { /* 7 */ OK = 1; dz->lparray[SCRAMBLE_CHUNKPTR][thiss] = (int)(drand48()*range); /* TRUNCATE */ dz->lparray[SCRAMBLE_CHUNKPTR][thiss] += startptr; /* 8 */ if(ODD(dz->lparray[SCRAMBLE_CHUNKPTR][thiss])) dz->lparray[SCRAMBLE_CHUNKPTR][thiss]--; /* TW OCT 1997 -->*/ if(abs(dz->lparray[SCRAMBLE_CHUNKPTR][thiss] - latest_ptr)< minlen) { OK = 0; continue; } for(that=start; thatlparray[SCRAMBLE_CHUNKPTR][thiss] - dz->lparray[SCRAMBLE_CHUNKPTR][that])lparray[SCRAMBLE_CHUNKPTR][thiss]))< minlen) { /* TW OCT 1997 */ OK = 0; /* 9 */ break; } } } while(!OK); /* 10 */ thiss++; /* 11 */ } /* TW OCT 1997 --> */ for(m=0;mlparray[SCRAMBLE_CHUNKPTR][m] > latest_ptr) latest_ptr = dz->lparray[SCRAMBLE_CHUNKPTR][m]; } /* TW OCT 1997 */ startptr += range; /* 12 */ first = 0; /* 13 */ } if(endscat) { /* 14 */ start = thiss; for(m=0;mlparray[SCRAMBLE_CHUNKPTR][thiss] = (int)(drand48() * endrange); /* TRUNCATE */ dz->lparray[SCRAMBLE_CHUNKPTR][thiss] += startptr; if(ODD(dz->lparray[SCRAMBLE_CHUNKPTR][thiss])) dz->lparray[SCRAMBLE_CHUNKPTR][thiss]--; /* TW OCT 1997 */ if(abs(dz->lparray[SCRAMBLE_CHUNKPTR][thiss] - latest_ptr)< minlen) { OK = 0; continue; } /* TW OCT 1997 */ for(that=start; thatlparray[SCRAMBLE_CHUNKPTR][thiss] - dz->lparray[SCRAMBLE_CHUNKPTR][that])< minlen /* TW OCT 1997 */ || abs(filend - abs(dz->lparray[SCRAMBLE_CHUNKPTR][thiss]))< minlen) { /* TW OCT 1997 */ OK = 0; break; } } } while(!OK); thiss++; } } return ptr_sort(thiss,dz); } /*************************** PERMUTE_CHUNKS ***************************/ void permute_chunks(int chunkcnt,dataptr dz) { int n, t; for(n=0;niparray[SCRAMBLE_PERM][t+1] = n; } /****************************** PREFIX ****************************/ void prefix(int n,int chunkcnt,dataptr dz) { shuflup(0,chunkcnt,dz); dz->iparray[SCRAMBLE_PERM][0] = n; } /****************************** SHUFLUP ****************************/ void shuflup(int k,int chunkcnt,dataptr dz) { int n; int *i; int z = chunkcnt-1; i = &(dz->iparray[SCRAMBLE_PERM][z]); for(n = z; n > k; n--) { *i = *(i-1); i--; } } /************************** PTR_SORT ***************************/ int ptr_sort(int end,dataptr dz) { int i,j; int a; for(j=1;jlparray[SCRAMBLE_CHUNKPTR][j]; i = j-1; while(i >= 0 && dz->lparray[SCRAMBLE_CHUNKPTR][i] > a) { dz->lparray[SCRAMBLE_CHUNKPTR][i+1]=dz->lparray[SCRAMBLE_CHUNKPTR][i]; i--; } dz->lparray[SCRAMBLE_CHUNKPTR][i+1] = a; } return(FINISHED); } /**************************** ITERATE_PREPROCESS ******************************/ int iterate_preprocess(dataptr dz) { int exit_status; double maxrand, maxpscat, mindelay, temp; int is_unity_gain = FALSE; int mindelay_samps; if(dz->process == ITERATE_EXTEND) { if(dz->iparam[ITER_RRSEED] > 0) srand((int)dz->iparam[ITER_RRSEED]); else initrand48(); } else { if(dz->iparam[ITER_RSEED] > 0) srand((int)dz->iparam[ITER_RSEED]); else initrand48(); } if((exit_status = get_maxvalue_of_rand(&maxrand,dz))<0) return(exit_status); if((exit_status = get_maxvalue_of_pscat(&maxpscat,dz))<0) return(exit_status); if((exit_status = get_minvalue_of_delay(&mindelay,dz))<0) return(exit_status); mindelay_samps = round(mindelay * (double)dz->infile->srate); if(dz->process == ITERATE_EXTEND) { dz->iparam[CHUNKSTART] = (int)round(dz->param[CHUNKSTART] * dz->infile->srate) * dz->infile->channels; dz->iparam[CHUNKEND] = (int)round(dz->param[CHUNKEND] * dz->infile->srate) * dz->infile->channels; if(dz->param[CHUNKSTART] > dz->param[CHUNKEND]) { temp = dz->param[CHUNKSTART]; dz->param[CHUNKSTART] = dz->param[CHUNKEND]; dz->param[CHUNKEND] = temp; } if(dz->iparam[CHUNKEND] - dz->iparam[CHUNKSTART] <= ITX_SPLICELEN * dz->infile->channels * 2) { sprintf(errstr,"FROZEN SEGMENT (%d samples) TOO SHORT FOR SPLICING (needs %d samples)\n", dz->iparam[CHUNKEND] - dz->iparam[CHUNKSTART],ITX_SPLICELEN * dz->infile->channels * 2); return(DATA_ERROR); } if(dz->iparam[CHUNKEND] - dz->iparam[CHUNKSTART] < mindelay_samps * dz->infile->channels) { sprintf(errstr,"FROZEN SEGMENT (%d samples) TOO SHORT FOR (MINIMUM) DELAY TIME SPECIFIED (%d samples)\n", dz->iparam[CHUNKEND] - dz->iparam[CHUNKSTART],mindelay_samps * dz->infile->channels); return(DATA_ERROR); } } if((dz->process != ITERATE_EXTEND) && (dz->param[ITER_GAIN]==DEFAULT_ITER_GAIN)) set_default_gain(mindelay_samps,dz); set_default_delays(dz); if (dz->process == ITERATE_EXTEND) { dz->param[ITER_SSTEP] = 1.0; /* 1st sound is exact copy of orig */ } else { reverse_fadevals(dz); dz->param[ITER_STEP] = 1.0; /* 1st sound is exact copy of orig */ } if((dz->process != ITERATE_EXTEND) && flteq(dz->param[ITER_GAIN],1.0)) is_unity_gain = TRUE; setup_iter_process_type(is_unity_gain,dz); return create_iterbufs(maxpscat,dz); } /*************************** GET_MAXVALUE_OF_RAND ****************************/ int get_maxvalue_of_rand(double *maxrand,dataptr dz) { int exit_status; if(dz->brksize[ITER_RANDOM]) { if((exit_status = get_maxvalue_in_brktable(maxrand,ITER_RANDOM,dz))<0) return(exit_status); } else *maxrand = dz->param[ITER_RANDOM]; return(FINISHED); } /************************* GET_MAXVALUE_OF_PSCAT ****************************/ int get_maxvalue_of_pscat(double *maxpscat,dataptr dz) { int exit_status; if(dz->brksize[ITER_PSCAT]) { if((exit_status = get_maxvalue_in_brktable(maxpscat,ITER_PSCAT,dz))<0) return(exit_status); } else *maxpscat = dz->param[ITER_PSCAT]; return(FINISHED); } /************************* GET_MINVALUE_OF_DELAY ****************************/ int get_minvalue_of_delay(double *mindelay,dataptr dz) { int exit_status; if(dz->brksize[ITER_DELAY]) { if((exit_status = get_minvalue_in_brktable(mindelay,ITER_DELAY,dz))<0) return(exit_status); } else *mindelay = dz->param[ITER_DELAY]; return(FINISHED); } /************************* REVERSE_FADEVALS ****************************/ void reverse_fadevals(dataptr dz) { double *p, *pend; if(dz->brksize[ITER_FADE]==0) dz->param[ITER_FADE] = 1.0 - dz->param[ITER_FADE]; else { p = dz->brk[ITER_FADE] + 1; pend = dz->brk[ITER_FADE] + (dz->brksize[ITER_FADE] * 2); while(p < pend) { *p = 1.0 - *p; p += 2; } } } /************************** SET_DEFAULT_GAIN ****************************/ void set_default_gain(int mindelay_samps,dataptr dz) { int inmsampsize; int maxoverlay_cnt; inmsampsize = dz->insams[0]/dz->infile->channels; maxoverlay_cnt = round(((double)inmsampsize/(double)mindelay_samps)+1.0); if(dz->vflag[IS_ITER_RAND]) maxoverlay_cnt++; dz->param[ITER_GAIN] = 1.0/(double)maxoverlay_cnt; } /*********************** SET_DEFAULT_DELAYS ****************************/ void set_default_delays(dataptr dz) { if(dz->process==ITERATE_EXTEND) { if(!dz->brksize[ITER_DELAY]) dz->iparam[ITER_MSAMPDEL] = round(dz->param[ITER_DELAY] * (double)dz->infile->srate); return; } if(dz->vflag[IS_ITER_DELAY]) { if(!dz->brksize[ITER_DELAY]) dz->iparam[ITER_MSAMPDEL] = round(dz->param[ITER_DELAY] * (double)dz->infile->srate); } else dz->iparam[ITER_MSAMPDEL] = dz->insams[0]/dz->infile->channels; /* default */ } /********************* SETUP_ITER_PROCESS_TYPE ********************************/ void setup_iter_process_type(int is_unity_gain,dataptr dz) { if(dz->process==ITERATE_EXTEND) { if(dz->param[ITER_PSCAT] > 0.0) { if(dz->infile->channels>1) dz->iparam[ITER_PROCESS] = ST_INTP_SHIFT; else dz->iparam[ITER_PROCESS] = MN_INTP_SHIFT; } else { if(dz->infile->channels>1) dz->iparam[ITER_PROCESS] = STEREO; else dz->iparam[ITER_PROCESS] = MONO; } if(flteq(dz->param[ITER_ASCAT],0.0)) { dz->iparam[ITER_PROCESS] += FIXED_AMP; } return; } dz->iparam[ITER_DO_SCALE] = TRUE; if(dz->vflag[IS_ITER_PSCAT]) { if(dz->infile->channels>1) dz->iparam[ITER_PROCESS] = ST_INTP_SHIFT; else dz->iparam[ITER_PROCESS] = MN_INTP_SHIFT; } else { if(dz->infile->channels>1) dz->iparam[ITER_PROCESS] = STEREO; else dz->iparam[ITER_PROCESS] = MONO; } if(!dz->vflag[IS_ITER_ASCAT]) { if(is_unity_gain) dz->iparam[ITER_DO_SCALE] = FALSE; dz->iparam[ITER_PROCESS] += FIXED_AMP; } } /***************************** DRUNK_PREPROCESS ************************* * * Splicelen & cloktiks have been converted to SAMPLES in pconsistency.c */ int drunk_preprocess(dataptr dz) { int exit_status; dz->iparam[DRNK_LAST_LOCUS] = -1; initialise_random_sequence(IS_DRNK_RSEED,DRNK_RSEED,dz); if((exit_status = create_drunk_buffers(dz))<0) /* 1 */ return(exit_status); if((exit_status = make_drnk_splicetab(dz))<0) return(exit_status); if(dz->insams[0] <= dz->iparam[DRNK_SPLICELEN] * dz->infile->channels * 2) { sprintf(errstr,"Infile too short for splices.\n"); return(DATA_ERROR); } dz->iparam[DRNK_LGRAIN] = round((double)dz->infile->srate * DRNK_GRAIN); dz->iparam[DRNK_TOTALDUR] = round(dz->param[DRNK_TOTALDUR] * (double)(dz->infile->srate * dz->infile->channels)); if((exit_status = convert_time_and_vals_to_samplecnts(DRNK_LOCUS,dz))<0) return(exit_status); if((exit_status = convert_time_and_vals_to_samplecnts(DRNK_AMBITUS,dz))<0) return(exit_status); if((exit_status = convert_time_to_samplecnts(DRNK_CLOKRND,dz))<0) return(exit_status); if((exit_status = convert_time_to_samplecnts(DRNK_OVERLAP,dz))<0) return(exit_status); if((exit_status = get_maxvalue(DRNK_OVERLAP,&dz->param[DRNK_MAX_OVLAP],dz))<0) return(exit_status); if((exit_status = convert_time_to_samplecnts(DRNK_GSTEP,dz))<0) return(exit_status); if((exit_status = convert_sec_steps_to_grain_steps(dz))<0) return(exit_status); if(dz->mode==HAS_SOBER_MOMENTS) { if((exit_status = convert_time_and_vals_to_samplecnts(DRNK_MIN_PAUS,dz))<0) return(exit_status); if((exit_status = convert_time_and_vals_to_samplecnts(DRNK_MAX_PAUS,dz))<0) return(exit_status); if((exit_status = convert_time_to_samplecnts(DRNK_MIN_DRNKTIK,dz))<0) return(exit_status); if((exit_status = convert_time_to_samplecnts(DRNK_MAX_DRNKTIK,dz))<0) return(exit_status); } return(FINISHED); } /********************** MAKE_DRNK_SPLICETAB *********************/ int make_drnk_splicetab(dataptr dz) { int n; if((dz->parray[DRNK_SPLICETAB] = (double *)malloc(dz->iparam[DRNK_SPLICELEN] * sizeof(double)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to make splicetable.\n"); return(MEMORY_ERROR); } for(n=0;niparam[DRNK_SPLICELEN];n++) dz->parray[DRNK_SPLICETAB][n] = (double)n/(double)dz->iparam[DRNK_SPLICELEN]; return(FINISHED); } /************************* CONVERT_SEC_STEPS_TO_GRAIN_STEPS *********************/ int convert_sec_steps_to_grain_steps(dataptr dz) { double *p, *pend; int lval; if(dz->iparam[DRNK_LGRAIN]<=0) { sprintf(errstr,"Invalid DRNK_LGRAIN val: convert_sec_steps_to_grain_steps()\n"); return(PROGRAM_ERROR); } if(dz->brksize[DRNK_GSTEP]) { p = dz->brk[DRNK_GSTEP] + 1; pend = dz->brk[DRNK_GSTEP] + (dz->brksize[DRNK_GSTEP] * 2); while(p < pend) { lval = round(*p * (double)dz->infile->srate); lval = (lval+(dz->iparam[DRNK_LGRAIN]/2))/dz->iparam[DRNK_LGRAIN]; *p = (double)lval; p += 2; } } else { dz->iparam[DRNK_GSTEP] = round(dz->param[DRNK_GSTEP] * (double)dz->infile->srate); dz->iparam[DRNK_GSTEP] = (dz->iparam[DRNK_GSTEP]+(dz->iparam[DRNK_LGRAIN]/2))/dz->iparam[DRNK_LGRAIN]; dz->param[DRNK_GSTEP] = (double)dz->iparam[DRNK_GSTEP]; } return(FINISHED); }