/* * Copyright (c) 1983-2023 Trevor Wishart and Composers Desktop Project Ltd * http://www.trevorwishart.co.uk * http://www.composersdesktop.com * This file is part of the CDP System. The CDP System is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The CDP System is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the CDP System; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* floatsam version: no changes */ #include #include #include #include #include #include #include #include #include #include #include #include #include static int get_times(double *timestor,dataptr dz); static int adjust_stereo(int lineno,int total_words,int wordcnt,double param,dataptr dz); static int adjust_position(char **thisword,double param,dataptr dz); static int treat_short_mono_line(int lineno,int wordno,double param,dataptr dz); static int treat_short_stereo_line(int lineno,int wordno,double param,dataptr dz); static int investigate_timings(double *duration,double *min_time,dataptr dz); /************************* MIX_SHUFL ******************************/ int mix_shufl(dataptr dz) { switch(dz->mode) { case(MSH_OMIT_ALT): case(MSH_OMIT): return do_time_manip(dz); case(MSH_DUPLICATE): case(MSH_DUPL_AND_RENAME): return do_time_and_name_copy(dz); case(MSH_SCATTER): return randomise_names(dz); case(MSH_REVERSE_N): return do_name_reverse(dz); case(MSH_FIXED_N): return do_name_freeze(dz); default: sprintf(errstr,"Unknown mode in mix_shufl()\n"); return(PROGRAM_ERROR); } return(FINISHED); /* NOTREACHED */ } /************************* MIX_TIMEWARP ******************************/ int mix_timewarp(dataptr dz) { switch(dz->mode) { case(MTW_REVERSE_NT): return do_name_and_time_reverse(dz); case(MTW_FREEZE_NT): return do_name_and_time_freeze(dz); case(MTW_REVERSE_T): case(MTW_FREEZE_T): case(MTW_SCATTER): case(MTW_DOMINO): case(MTW_CREATE_TG_1): case(MTW_CREATE_TG_2): case(MTW_CREATE_TG_3): case(MTW_CREATE_TG_4): case(MTW_ENLARGE_TG_1): case(MTW_ENLARGE_TG_2): case(MTW_ENLARGE_TG_3): case(MTW_ENLARGE_TG_4): case(MTW_ADD_TO_TG): case(MTW_TIMESORT): return do_time_manip(dz); default: sprintf(errstr,"Unknown mode in mix_timewarp()\n"); return(PROGRAM_ERROR); } return(FINISHED); /* NOTREACHED */ } /************************* MIX_SPACEWARP ******************************/ int mix_spacewarp(dataptr dz) { int exit_status; int n, total_words; int is_even = TRUE; double position = 0.0; int *maxwordsize; double duration = 0.0, min_time = 0.0, *timestor = NULL; double spacerange = 0.0, leftedge = 0.0; switch(dz->mode) { case(MSW_TWISTALL): case(MSW_TWISTONE): return mix_twisted(dz); case(MSW_LEFTWARDS): case(MSW_RIGHTWARDS): if((exit_status = investigate_timings(&duration,&min_time,dz))<0) return(exit_status); timestor = dz->parray[MSW_TIMESTOR]; /* fall thro */ case(MSW_RANDOM): case(MSW_RANDOM_ALT): spacerange = fabs(dz->param[MSW_POS2] - dz->param[MSW_POS1]); leftedge = min(dz->param[MSW_POS1],dz->param[MSW_POS2]); break; case(MSW_NARROWED): case(MSW_FIXED): break; default: sprintf(errstr,"Unknown mode in mix_spacewarp()\n"); return(PROGRAM_ERROR); } total_words = 0; for(n=0;niparam[MSH_STARTLINE];n++) total_words += dz->wordcnt[n]; for(n=dz->iparam[MSH_STARTLINE];niparam[MSH_ENDLINE];n++) { switch(dz->mode) { case(MSW_NARROWED): if((exit_status = adjust_stereo(n,total_words,dz->wordcnt[n],dz->param[MSW_NARROWING],dz))<0) return(exit_status); break; case(MSW_FIXED): if((exit_status = adjust_stereo(n,total_words,dz->wordcnt[n],dz->param[MSW_POS1],dz))<0) return(exit_status); break; default: switch(dz->mode) { case(MSW_RANDOM): position = (drand48() * POSITIONS)/POSITIONS; break; case(MSW_RANDOM_ALT): switch(is_even) { case(TRUE): position = (drand48() * HALF_POSTNS)/POSITIONS; break; /* Force Left */ case(FALSE):position = (POSITIONS - (drand48() * HALF_POSTNS))/POSITIONS; break; /* Force Right */ } is_even = !is_even; break; case(MSW_LEFTWARDS): //TW UPDATE if(duration > FLTERR) position = (timestor[n] - min_time)/duration; else { sprintf(errstr,"Files do not Progress in Time : Hence cannot MOVE Leftwards\n"); return(USER_ERROR); } position = 1.0 - position; break; case(MSW_RIGHTWARDS): //TW UPDATE if(duration > FLTERR) position = (timestor[n] - min_time)/duration; else { sprintf(errstr,"Files do not Progress in Time : Hence cannot MOVE Rightwards\n"); return(USER_ERROR); } break; } position *= spacerange; position += leftedge; if((exit_status = adjust_stereo(n,total_words,dz->wordcnt[n],position,dz))<0) return(exit_status); break; } total_words += dz->wordcnt[n]; } if((exit_status = get_maxwordsize(&maxwordsize,dz))<0) return(exit_status); if((exit_status = output_mixfile_lines(maxwordsize,dz))<0) return(exit_status); free(maxwordsize); return(FINISHED); } /*************************** GET_TIMES ***************************/ int get_times(double *timestor,dataptr dz) { int n, timeloc; int total_wordcnt = 0; for(n=0;nlinecnt;n++) { if(dz->wordcnt[n] < 2) { sprintf(errstr,"PRoblem getting line times: get_times_and_timediffs()\n"); return(PROGRAM_ERROR); } timeloc = total_wordcnt + MIX_TIMEPOS; if(sscanf(dz->wordstor[timeloc],"%lf",&(timestor[n]))!=1) { sprintf(errstr,"Problem reading time: get_times_and_timediffs()\n"); return(PROGRAM_ERROR); } total_wordcnt += dz->wordcnt[n]; } return(FINISHED); } /************************** ADJUST_STEREO **************************/ int adjust_stereo(int lineno,int total_words,int wordcnt,double param,dataptr dz) { int exit_status; char *thisword; int chans; int levelwordno = total_words + MIX_LEVELPOS; int lpanwordno = total_words + MIX_PANPOS; int rpanwordno = total_words + MIX_RPANPOS; int chanwordno = total_words + MIX_CHANPOS; switch(wordcnt) { case(MIX_MINLINE): thisword = dz->wordstor[chanwordno]; if(sscanf(thisword,"%d",&chans)!=1) { sprintf(errstr,"Failed to get channel count: adjust_stereo()\n"); return(PROGRAM_ERROR); } switch(chans) { case(MONO): switch(dz->mode) { case(MSW_NARROWED): return(FINISHED); /* mono, unpanned, files can't be narrowed */ default: return treat_short_mono_line(lineno,levelwordno,param,dz); } /* mono, unpanned, wordstor has to be extended to take 1 new vals */ break; /* stereo, unpanned, wordstor has to be extended to take 3 new vals */ case(STEREO): return treat_short_stereo_line(lineno,levelwordno,param,dz); default: sprintf(errstr,"Invalid channel count: adjust_stereo()\n"); return(PROGRAM_ERROR); } break; case(MIX_MAXLINE): if((exit_status = adjust_position(&(dz->wordstor[rpanwordno]),param,dz))<0) return(exit_status); /* fall thro */ case(MIX_MIDLINE): return adjust_position(&(dz->wordstor[lpanwordno]),param,dz); break; default: sprintf(errstr,"Impossible wordcnt: adjust_stereo()\n"); return(PROGRAM_ERROR); } return(FINISHED); /* NOTREACHED */ } /************************* ADJUST_POSITION ******************************/ int adjust_position(char **thisword,double param,dataptr dz) { double position; int newlen; if(dz->mode==MSW_NARROWED) { if(!strcmp(*thisword,"C")) position = 0.0; else if(!strcmp(*thisword,"L")) position = -1.0; else if(!strcmp(*thisword,"R")) position = 1.0; else if(sscanf(*thisword,"%lf",&position)!=1) { sprintf(errstr,"Failed to get pan value: adjust_position()\n"); return(PROGRAM_ERROR); } param *= position; } sprintf(errstr,"%.4lf",param); newlen = strlen(errstr); if(newlen > (int)strlen(*thisword)) { if((*thisword = (char *)realloc(*thisword,(newlen+1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate thisword store.\n"); return(MEMORY_ERROR); } } strcpy(*thisword,errstr); return(FINISHED); } /************************* TREAT_SHORT_STEREO_LINE ******************************/ int treat_short_stereo_line(int lineno,int wordno,double param,dataptr dz) { #define STEREO_EXTRA_WORDS (3) int n, m; int wordlen; if((dz->wordstor = (char **)realloc(dz->wordstor,(dz->all_words + STEREO_EXTRA_WORDS) * sizeof(char *)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate word store.\n"); return(MEMORY_ERROR); } for(n=0,m=dz->all_words;nwordstor[m] = NULL; dz->all_words += STEREO_EXTRA_WORDS; for(n=dz->all_words-STEREO_EXTRA_WORDS-1;n>wordno;n--) dz->wordstor[n+STEREO_EXTRA_WORDS] = dz->wordstor[n]; dz->wordcnt[lineno] += STEREO_EXTRA_WORDS; for(n=wordno+1;n<=wordno+STEREO_EXTRA_WORDS;n++) dz->wordstor[n] = NULL; switch(dz->mode) { case(MSW_NARROWED): sprintf(errstr,"%.4lf",-param); break; default: sprintf(errstr,"%.4lf",param); break; } wordlen = strlen(errstr); if((dz->wordstor[wordno+1] = (char *)malloc((wordlen+1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to allocate wordstore %d\n",wordno+1+1); return(MEMORY_ERROR); } strcpy(dz->wordstor[wordno+1],errstr); wordlen = strlen(dz->wordstor[wordno]); if((dz->wordstor[wordno+2] = (char *)malloc((wordlen+1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to allocate wordstore %d\n",wordno+2+1); return(MEMORY_ERROR); } strcpy(dz->wordstor[wordno+2],dz->wordstor[wordno]); sprintf(errstr,"%.4lf",param); wordlen = strlen(errstr); if((dz->wordstor[wordno+3] = (char *)malloc((wordlen+1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to allocate wordstore %d\n",wordno+3+1); return(MEMORY_ERROR); } strcpy(dz->wordstor[wordno+3],errstr); return(FINISHED); } /************************* TREAT_SHORT_MONO_LINE ******************************/ int treat_short_mono_line(int lineno,int wordno,double param,dataptr dz) { #define MONO_EXTRA_WORDS (1) int n, m; int wordlen; if((dz->wordstor = (char **)realloc(dz->wordstor,(dz->all_words + MONO_EXTRA_WORDS) * sizeof(char *)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for word stores.\n"); return(MEMORY_ERROR); } for(n=0,m=dz->all_words;nwordstor[m] = NULL; dz->all_words += MONO_EXTRA_WORDS; for(n=dz->all_words-MONO_EXTRA_WORDS-1;n>wordno;n--) dz->wordstor[n+MONO_EXTRA_WORDS] = dz->wordstor[n]; dz->wordcnt[lineno] += MONO_EXTRA_WORDS; dz->wordstor[wordno+1] = NULL; sprintf(errstr,"%.4lf",param); wordlen = strlen(errstr); if((dz->wordstor[wordno+1] = (char *)malloc((wordlen+1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for word store %d\n",wordno+1+1); return(MEMORY_ERROR); } strcpy(dz->wordstor[wordno+1],errstr); return(FINISHED); } /************************* INVESTIGATE_TIMINGS ******************************/ int investigate_timings(double *duration,double *min_time,dataptr dz) { int exit_status; int n; double *timestor; double max_time; if((dz->parray[MSW_TIMESTOR] = (double *)malloc(dz->linecnt * sizeof(double)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for times store.\n"); return(MEMORY_ERROR); } timestor = dz->parray[MSW_TIMESTOR]; if((exit_status = get_times(timestor,dz))<0) return(exit_status); max_time = timestor[dz->iparam[MSH_STARTLINE]]; *min_time = timestor[dz->iparam[MSH_STARTLINE]]; for(n=dz->iparam[MSH_STARTLINE]+1;niparam[MSH_ENDLINE];n++) { max_time = max(timestor[n],max_time); *min_time = min(timestor[n],*min_time); } *duration = max_time - *min_time; return(FINISHED); } //TW UPDATE: NEW FUNCTION /************************* PANMIX ******************************/ int panmix(dataptr dz) { int newlen, exit_status; int baspos = 0, basposnext = 0, n, linelen; /*RWD Nov 2003 added init for basposnext */ int levelwordno, lpanwordno, rpanwordno; double time, level; char temp[200]; int *maxwordsize; for(n=0;nlinecnt;n++) { basposnext += dz->wordcnt[n]; levelwordno = baspos + MIX_LEVELPOS; lpanwordno = baspos + MIX_PANPOS; rpanwordno = baspos + MIX_RPANPOS; //chanwordno = baspos + MIX_CHANPOS; time = atof(dz->wordstor[baspos + 1]); if(dz->brksize[PAN_PAN]) { if((exit_status = read_value_from_brktable(time,PAN_PAN,dz))<0) return(exit_status); } linelen = basposnext - baspos; switch(linelen) { case(MIX_MINLINE): /* STEREO CASE : SHORT LINE */ level = atof(dz->wordstor[levelwordno]); level /= 2.0; sprintf(errstr,"%.4lf",level); strcat(errstr," "); sprintf(temp,"%.4lf",dz->param[PAN_PAN]); strcat(temp," "); strcat(errstr,temp); strcpy(temp,errstr); strcat(errstr,temp); newlen = strlen(errstr); if(newlen > (int)strlen(dz->wordstor[levelwordno])) { if((dz->wordstor[levelwordno] = (char *)realloc(dz->wordstor[levelwordno],(newlen+1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate thisword store.\n"); return(MEMORY_ERROR); } } strcpy(dz->wordstor[levelwordno],errstr); break; case(MIX_MAXLINE): /* STEREO CASE : LONG LINE */ level = atof(dz->wordstor[levelwordno]); level += atof(dz->wordstor[levelwordno+2]); level /= 4.0; /* Average level: = (level_left + level-right) / 2.0 */ /* This average level from BOTH channels is to be put at SAME position */ /* Therefore, divide by two again */ sprintf(errstr,"%.4lf",level); newlen = strlen(errstr); if(newlen > (int)strlen(dz->wordstor[levelwordno])) { if((dz->wordstor[levelwordno] = (char *)realloc(dz->wordstor[levelwordno],(newlen+1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate thisword store.\n"); return(MEMORY_ERROR); } } if(newlen > (int)strlen(dz->wordstor[levelwordno+2])) { if((dz->wordstor[levelwordno+2] = (char *)realloc(dz->wordstor[levelwordno+2],(newlen+1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate thisword store.\n"); return(MEMORY_ERROR); } } strcpy(dz->wordstor[levelwordno],errstr); strcpy(dz->wordstor[levelwordno+2],errstr); sprintf(errstr,"%.4lf",dz->param[PAN_PAN]); if(newlen > (int)strlen(dz->wordstor[lpanwordno])) { if((dz->wordstor[lpanwordno] = (char *)realloc(dz->wordstor[lpanwordno],(newlen+1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate thisword store.\n"); return(MEMORY_ERROR); } } if(newlen > (int)strlen(dz->wordstor[rpanwordno])) { if((dz->wordstor[rpanwordno] = (char *)realloc(dz->wordstor[rpanwordno],(newlen+1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate thisword store.\n"); return(MEMORY_ERROR); } } strcpy(dz->wordstor[lpanwordno],errstr); strcpy(dz->wordstor[rpanwordno],errstr); break; case(MIX_MIDLINE): /* MONO CASE */ sprintf(errstr,"%.4lf",dz->param[PAN_PAN]); newlen = strlen(errstr); if(newlen > (int)strlen(dz->wordstor[lpanwordno])) { if((dz->wordstor[lpanwordno] = (char *)realloc(dz->wordstor[lpanwordno],(newlen+1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to reallocate thisword store.\n"); return(MEMORY_ERROR); } } strcpy(dz->wordstor[lpanwordno],errstr); break; } baspos = basposnext; } if((exit_status = get_maxwordsize(&maxwordsize,dz))<0) return(exit_status); if((exit_status = output_mixfile_lines(maxwordsize,dz))<0) return(exit_status); free(maxwordsize); return(FINISHED); }