| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019 |
- /*
- * 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
- *
- */
- /* floatsam version */
- #include <stdio.h>
- #include <stdlib.h>
- #include <memory.h>
- #include <string.h>
- #include <structures.h>
- #include <tkglobals.h>
- #include <globcon.h>
- #include <arrays.h>
- #include <cdpmain.h>
- #include <modify.h>
- #include <modeno.h>
- //TW UPDATES
- #include <arrays.h>
- #include <flags.h>
- #include <sfsys.h>
- #include <osbind.h>
- //#ifdef unix
- #define round(x) lround((x))
- //#endif
- #ifndef HUGE
- #define HUGE 3.40282347e+38F
- #endif
- //extern int snd_makepath(char path[],const char *sfname);
- extern char *get_other_filename_x(char *filename,char c);
- #define SCRUB_FORWARDS (TRUE)
- #define SCRUB_BACKWARDS (FALSE)
- #define SCRUB_SAFE (.66)
- static void reverse_the_buffer(float *ibuf,int chans,long ssampsread);
- static int do_lowbit(float *maxsamp,float *postmaxsamp,dataptr dz);
- static int do_lowbit2(dataptr dz);
- static int shred(int current_buf,int work_len,dataptr dz);
- static int get_basis_lengths(int *worklen,dataptr dz);
- static void normal_scat(dataptr dz);
- static void heavy_scat(dataptr dz);
- static void permute_chunks(dataptr dz);
- static void insert(int n,int t,dataptr dz);
- static void prefix(int n,dataptr dz);
- static void shuflup(int k,dataptr dz);
- static void do_startsplice(float *i,float *j,dataptr dz);
- static void do_endsplice(float *i,float *j,dataptr dz);
- static void do_bufend_splices(int current_buf,dataptr dz);
- static void ptr_sort(int end,dataptr dz);
- static int check_for_too_small_buf(dataptr dz);
- static int create_sintable(dataptr dz);
- static double get_skew(void);
- static void get_speed(double *lospeed,double *speedrang,dataptr dz);
- static void get_end(int *direction,int *here,dataptr dz);
- static int gen_readtab(double skew,double lospeed,double speedrange,int scrublen_in_src,dataptr dz);
- static int scrub(int *hhere,int *tthere,int direction,int effective_tablen,dataptr dz);
- static int read_samps_for_scrub(int bufno,dataptr dz);
- static double read_rmod_tab(double dtabindex,dataptr dz);
- //TW UPDATES (converted to flotsams)
- static int get_obuf_sampoffset(int n,dataptr dz);
- static int transpos_and_add_to_obuf(int n,int *obufpos,double *inbufpos,float *lastival,int chans,dataptr dz);
- /******************************* CREATE_REVERSING_BUFFERS *******************************/
- int create_reversing_buffers(dataptr dz)
- {
- //TW BIG SIMPLIFICATION as buffer sector-alignment abolished
- size_t bigbufsize;
- bigbufsize = (size_t) Malloc(-1);
- dz->buflen = (int)(bigbufsize / sizeof(float));
- dz->buflen = (dz->buflen / dz->infile->channels) * dz->infile->channels;
- dz->iparam[REV_BUFCNT] = dz->insams[0]/dz->buflen;
- if(dz->iparam[REV_BUFCNT] > 0)
- dz->iparam[REV_RSAMPS] = dz->insams[0] - (dz->iparam[REV_BUFCNT] * dz->buflen);
- if((dz->bigbuf = (float *)malloc(dz->buflen * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for sound buffers.\n");
- return(MEMORY_ERROR);
- }
- dz->sampbuf[0] = dz->bigbuf;
- return FINISHED;
- }
- /******************************* DO_REVERSING *******************************/
- int do_reversing(dataptr dz)
- {
- //TW BIG SIMPLIFICATION as buffer sector-alignment abolished
- int exit_status;
- float *buf = dz->sampbuf[0];
- int chans = dz->infile->channels;
- int nbuffs = dz->iparam[REV_BUFCNT];
- int thisbufsamps;
- if(nbuffs <=0) {
- if((exit_status = read_samps(buf,dz)) < 0) {
- sprintf(errstr,"Failed (1) to read input file.\n");
- return(PROGRAM_ERROR);
- }
- if(dz->ssampsread != dz->insams[0]) {
- sprintf(errstr,"Bad accounting.\n");
- return(PROGRAM_ERROR);
- }
- reverse_the_buffer(buf,chans,dz->ssampsread);
- if(dz->ssampsread > 0) {
- if((exit_status = write_samps(buf,dz->ssampsread,dz)) < 0) {
- sprintf(errstr,"Failed (1) to write to output file.");
- return(PROGRAM_ERROR);
- }
- }
- } else {
- thisbufsamps = dz->insams[0] - dz->iparam[REV_RSAMPS];
- if((sndseekEx(dz->ifd[0], thisbufsamps, 0)) < 0) {
- sprintf(errstr,"Reverse: failed to seek to point in file\n");
- return(SYSTEM_ERROR);
- }
- if((thisbufsamps -= dz->buflen)<0) { /* ready for next iteration */
- sprintf(errstr,"Bad accounting 1.\n");
- return(PROGRAM_ERROR);
- }
- if((exit_status = read_samps(buf,dz)) < 0) {
- sprintf(errstr,"Failed (1a) to read input file\n");
- return(PROGRAM_ERROR);
- }
- if(dz->ssampsread != dz->iparam[REV_RSAMPS]) {
- sprintf(errstr,"Bad accounting 2.\n");
- return(PROGRAM_ERROR);
- }
- reverse_the_buffer(buf,chans,dz->ssampsread);
- if(dz->ssampsread > 0) {
- if((write_samps(buf, dz->ssampsread,dz)) < 0) { /* writes (truncated number of) whole sector */
- sprintf(errstr,"Failed (1a) to write to output file");
- return(SYSTEM_ERROR);
- }
- }
- while(nbuffs>0) {
- if((sndseekEx(dz->ifd[0], thisbufsamps, 0)) < 0) {
- sprintf(errstr,"Reverse: failed to seek to point in file.\n");
- return(SYSTEM_ERROR);
- }
- if((exit_status = read_samps(buf,dz)) < 0) {
- sprintf(errstr,"Failed (1b) to read input file\n");
- return(PROGRAM_ERROR);
- }
- if(dz->ssampsread != dz->buflen) {
- sprintf(errstr,"Bad accounting 3.\n");
- return(PROGRAM_ERROR);
- }
- nbuffs--;
- if(nbuffs>0 && (thisbufsamps -= dz->buflen)<0) { /* ready for next iteration */
- sprintf(errstr,"Bad accounting 4.\n");
- return(PROGRAM_ERROR);
- }
- reverse_the_buffer(buf,chans,dz->ssampsread);
- if(dz->ssampsread > 0) {
- if((exit_status = write_exact_samps(buf,dz->ssampsread,dz)) < 0) {
- sprintf(errstr,"Failed (1b) to write to output file");
- return(PROGRAM_ERROR);
- }
- }
- }
- }
- return(FINISHED);
- }
-
- /******************************* REVERSE_THE_BUFFER *******************************/
- void reverse_the_buffer(float *ibuf,int chans,long ssampsread)
- {
- int half_ssampsread = ((ssampsread/chans)/2) * chans;
- int n, m, k;
- float temp;
- for(n = 0,m = ssampsread-chans;n< half_ssampsread;n+=chans,m-=chans) {
- for(k=0;k<chans;k++) {
- temp = ibuf[n+k];
- ibuf[n+k] = ibuf[m+k];
- ibuf[m+k] = temp;
- }
- }
- }
- /***************************** LOBIT_PCONSISTENCY *************************/
- int lobit_pconsistency(dataptr dz)
- {
- int garf = 1;
- int m;
- SFPROPS props = {0};
- if(!snd_headread(dz->ifd[0],&props)) {
- fprintf(stdout,"Failure to read sample size\n");
- fflush(stdout);
- return(DATA_ERROR);
- }
-
- //TW ADDED
- dz->iparam[LOBIT_BRES_SHIFT] = 0;
- if(dz->iparam[LOBIT_BRES]!=MAX_BIT_DIV) {
- dz->iparam[LOBIT_BRES] = MAX_BIT_DIV - dz->iparam[LOBIT_BRES];
- //TW DISCOVERED ERROR
- // garf = 1;
- garf = 2;
- for(m=1;m<dz->iparam[LOBIT_BRES];m++)
- garf *= 2;
- dz->iparam[LOBIT_BRES] = garf;
- //TW SIMPLIFIED, removed shift arithmetic
- }
- //TW ADDED non-16-bit cases
- switch(props.samptype) {
- case(0): /* SHORT8 */
- case(7): /* INT_MASKED */
- sprintf(errstr,"Process does not work with 8-bit files.\n");
- return(DATA_ERROR);
- case(1): /* SHORT16 */ break;
- case(2): /* FLOAT32 */
- case(3): /* INT_32 */ dz->iparam[LOBIT_BRES] *= (256 * 256); break;
- case(4): /* INT2424 */
- case(5): /* INT2432 */ dz->iparam[LOBIT_BRES] *= 256; break;
- case(6): /* INT2024 */ dz->iparam[LOBIT_BRES] *= 16; break;
- default:
- sprintf(errstr,"Unknown sample type.\n");
- return(DATA_ERROR);
- }
- //TW SIMPLIFIED, removed shift arithmetic for the time averaging
- return(FINISHED);
- }
- /****************************** LOBIT_PROCESS *************************/
- int lobit_process(dataptr dz)
- {
- int exit_status;
- float *buffer = dz->sampbuf[0];
- float maxsamp = 0.0, postmaxsamp = 0.0;
- display_virtual_time(0L,dz);
- if(dz->mode == MOD_LOBIT)
- dz->buflen = (dz->buflen / (dz->iparam[LOBIT_TSCAN] * dz->infile->channels)) * dz->iparam[LOBIT_TSCAN] * dz->infile->channels;
- while(dz->samps_left != 0) {
- if((exit_status = read_samps(buffer,dz))<0)
- return(exit_status);
- switch(dz->mode) {
- case(MOD_LOBIT):
- if((exit_status = do_lowbit(&maxsamp,&postmaxsamp,dz))<0)
- return(exit_status);
- break;
- case(MOD_LOBIT2):
- if((exit_status = do_lowbit2(dz))<0)
- return(exit_status);
- break;
- }
- if(dz->ssampsread > 0) {
- if((exit_status = write_exact_samps(buffer,dz->ssampsread,dz))<0)
- return(exit_status);
- }
- }
- return(FINISHED);
- }
- /**************************** DO_LOWBIT ***************************/
- int do_lowbit(float *maxsamp,float *postmaxsamp,dataptr dz)
- {
- register int i, j;
- double x, maxsampval;
- int k, todo_samples;
- int n;
- //TW MODIFIED FOR floats and non-16-bit sndfile formats
- float *buffer = dz->sampbuf[0];
- int tscan = dz->iparam[LOBIT_TSCAN];
- int bres = dz->iparam[LOBIT_BRES];
- int chans = dz->infile->channels;
- SFPROPS props = {0};
-
- if(!snd_headread(dz->ifd[0],&props)) {
- fprintf(stdout,"Failure to read sample size\n");
- fflush(stdout);
- return(DATA_ERROR);
- }
- switch(props.samptype) {
- case(1): /* SHORT16 */ maxsampval = MAXSAMP; break;
- case(2): /* FLOAT32 */
- case(3): /* INT_32 */ maxsampval = 2147483647.0; break;
- case(4): /* INT2424 */
- case(5): /* INT2432 */ maxsampval = 8388607.0; break;
- case(6): /* INT2024 */ maxsampval = 524287.0; break;
- /*RWD April 2004: need a default case; may add new formats one day! */
- /* OR: make one of the above cases the default... */
- default:
- fprintf(stdout,"Unsupported sample type\n");
- fflush(stdout);
- return(DATA_ERROR);
- /* other cases rejected earlier */
- }
- if(tscan!=1) {
- if((todo_samples = (dz->ssampsread/(tscan * chans)) * tscan * chans) != dz->ssampsread) {
- for(i = todo_samples;i<dz->ssampsread;i++)
- buffer[i] = 0.0f;
- dz->ssampsread = todo_samples;
- }
- }
- //TW MODIFIED to include non-16-bit cases, & files that are not mono
- for(i = 0; i < dz->ssampsread; i += (tscan * chans)) {
- for(n=0;n < chans; n++) {
- x = 0.0;
- k = i + n + (tscan * chans);
- for(j = i+n;j < k; j+= chans) {
- *maxsamp = (float) max(*maxsamp,fabs(buffer[j]));
- x += buffer[j];
- }
- x /= tscan; /* Take a time average */
- x *= maxsampval; /* convert to 'integer' range */
- x /= bres;
- x = (double)round(x); /* do a rounding mod bres */
- x *= bres;
- x /= maxsampval;
- x = min(x,1.0);
- x = max(x,-1.0);
- k = min(k,dz->ssampsread);
- for(j = i+n;j < k; j+= chans) {
- buffer[j] = (float)x; /* reconvert to float range */
- *postmaxsamp = (float) max(*postmaxsamp,fabs(buffer[j]));
- }
- }
- }
- return(FINISHED);
- }
- /**************************** DO_LOWBIT2 ***************************/
- int do_lowbit2(dataptr dz)
- {
- int n;
- //TW MODIFIED FOR floats and non-16-bit sndfile formats
- float *buffer = dz->sampbuf[0];
- double samp;
- int srcbits = 16; // We assume src is quasi-16bit
- int nbits = dz->iparam[LOBIT_BRES];
- int rescalebits = srcbits - nbits;
- double rescalefac = pow(2.0,rescalebits);
- for(n = 0; n < dz->ssampsread; n++) {
- samp = buffer[n] * 32767.0; // prescale to 16-bit range
- if(samp <= -32767.0)
- samp = -32767.0; // keep within range
- // do mid-rise quantisation
- samp /= rescalefac;
- samp = round(samp+0.5) - 0.5; // round to a multiple of 0.5
- samp *= rescalefac;
- // rescale back to float 0-1 representation
- buffer[n] = (float)(samp/32768.0);
- }
- return FINISHED;
- }
- /***************************** SHRED_PCONSISTENCY *************************/
- int shred_pconsistency(dataptr dz)
- {
- int chans = dz->infile->channels;
- double duration = (double)(dz->insams[0]/chans)/(double)dz->infile->srate;
- initrand48();
- dz->iparam[SHR_CHCNT] = round(duration/dz->param[SHRED_CHLEN]);
- if(dz->param[SHRED_SCAT] > (double)dz->iparam[SHR_CHCNT]) {
- sprintf(errstr,"Scatter value cannot be greater than infileduration/chunklength.\n");
- return(DATA_ERROR);
- }
- if(dz->param[SHRED_SCAT] > 1.0)
- dz->iparam[SHRED_SCAT] = round(dz->param[SHRED_SCAT]);
- else
- dz->iparam[SHRED_SCAT] = 0;
- /* setup splice params */
- dz->iparam[SHRED_SPLEN] = SHRED_SPLICELEN * chans;
- if((dz->lparray[SHR_CHUNKPTR] = (int *)malloc(dz->iparam[SHR_CHCNT] * sizeof(long)))==NULL
- || (dz->lparray[SHR_CHUNKLEN] = (int *)malloc(dz->iparam[SHR_CHCNT] * sizeof(long)))==NULL
- || (dz->iparray[SHR_PERM] = (int *)malloc(dz->iparam[SHR_CHCNT] * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for shredding arrays.\n");
- return(MEMORY_ERROR);
- }
- dz->lparray[SHR_CHUNKPTR][0] = 0; /* first chunk is at start of buffer */
- return(FINISHED);
- }
- /***************************** SHRED_PREPROCESS *************************/
- int shred_preprocess(dataptr dz)
- {
- int sectorcnt;
- sectorcnt = dz->insams[0]/dz->buflen;
- if(sectorcnt * dz->buflen < dz->insams[0])
- sectorcnt++;
- if(sectorcnt > 1)
- fprintf(stdout,"INFO: File will be shredded in %d distinct sectors.\n",sectorcnt);
- fflush(stdout);
- return(FINISHED);
- }
- /***************************CREATE_SHRED_BUFFERS **************************/
- //TW replaced by global
- //#define SHRED_SECSIZE (256)
- /* RWD sigh..... */
- int create_shred_buffers(dataptr dz)
- {
- int exit_status;
- int bigfilesize, file_size_in_frames;
- double bufs_per_file, lchunkcnt;
- size_t basic_bufchunk, bufchunk = (size_t)Malloc(-1);
- int framesize = F_SECSIZE * dz->infile->channels;
- bigfilesize = dz->insams[0];
- if((dz->bigbuf = (float *)malloc((bigfilesize * dz->bufcnt) * sizeof(float)))==NULL) {
- bufchunk /= sizeof(float);
- basic_bufchunk = bufchunk;
- for(;;) {
- if((dz->buflen = (int) bufchunk) < 0) {
- sprintf(errstr,"INSUFFICIENT MEMORY to allocate sound buffer.\n");
- return(MEMORY_ERROR);
- }
- dz->buflen = (dz->buflen/(framesize * dz->bufcnt)) * framesize * dz->bufcnt;
- dz->buflen /= dz->bufcnt;
- /* NEW --> */
- if(dz->buflen <= 0)
- dz->buflen = framesize;
- /* <-- NEW */
- file_size_in_frames = dz->insams[0]/framesize;
- if(framesize * file_size_in_frames < dz->insams[0])
- file_size_in_frames++;
- bigfilesize = file_size_in_frames * framesize;
- if(bigfilesize <= dz->buflen)
- dz->buflen = bigfilesize;
- if((dz->bigbuf = (float *)malloc((dz->buflen * dz->bufcnt) * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to allocate sound buffer.\n");
- return(MEMORY_ERROR);
- }
- if((exit_status = check_for_too_small_buf(dz))>=0)
- break;
- bufchunk += basic_bufchunk;
- }
- dz->sampbuf[0] = dz->bigbuf;
- dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen;
- if(bigfilesize == dz->buflen) {
- dz->iparam[SHR_LAST_BUFLEN] = dz->insams[0]; /* i.e. buflen = true filelen */
- dz->iparam[SHR_LAST_CHCNT] = dz->iparam[SHR_CHCNT];
- dz->iparam[SHR_LAST_SCAT] = dz->iparam[SHRED_SCAT];
- } else {
- bufs_per_file = (double)dz->insams[0]/(double)dz->buflen;
- lchunkcnt = (double)dz->iparam[SHR_CHCNT]/bufs_per_file;
- dz->iparam[SHR_CHCNT] = round(lchunkcnt);
- dz->iparam[SHRED_SCAT] = min(dz->iparam[SHRED_SCAT],dz->iparam[SHR_CHCNT]);
- dz->iparam[SHR_LAST_BUFLEN] = (dz->insams[0]%dz->buflen);
- dz->iparam[SHR_LAST_CHCNT] = round(lchunkcnt*((double)dz->iparam[SHR_LAST_BUFLEN]/(double)dz->buflen));
- dz->iparam[SHR_LAST_SCAT] = min(dz->iparam[SHRED_SCAT],dz->iparam[SHR_LAST_CHCNT]);
- }
- if(dz->iparam[SHR_LAST_CHCNT] < 2) {
- fprintf(stdout, "WARNING: FINAL BUFFER WON'T BE SHREDDED (Too short for chunklen set).\n");
- fprintf(stdout, "WARNING: It will shred if you\n");
- fprintf(stdout, "WARNING: a) shorten infile by (>) chunklen, OR\n");
- fprintf(stdout, "WARNING: b) alter chunklen until last buffer has >1 chunk in it.\n");
- fflush(stdout);
- }
- } else {
- dz->buflen = bigfilesize;
- dz->sampbuf[0] = dz->bigbuf;
- dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen;
- dz->iparam[SHR_LAST_BUFLEN] = dz->insams[0]; /* i.e. buflen = true filelen */
- dz->iparam[SHR_LAST_CHCNT] = dz->iparam[SHR_CHCNT];
- dz->iparam[SHR_LAST_SCAT] = dz->iparam[SHRED_SCAT];
- if(dz->iparam[SHR_LAST_CHCNT] < 2) {
- fprintf(stdout, "WARNING: FINAL BUFFER WON'T BE SHREDDED (Too short for chunklen set).\n");
- fprintf(stdout, "WARNING: It will shred if you\n");
- fprintf(stdout, "WARNING: a) shorten infile by (>) chunklen, OR\n");
- fprintf(stdout, "WARNING: b) alter chunklen until last buffer has >1 chunk in it.\n");
- fflush(stdout);
- }
- }
- memset((char *) (dz->sampbuf[0]),0,(dz->buflen * dz->bufcnt) * sizeof(float));
- return(FINISHED);
- }
- /************************* SHRED_PROCESS ***************************/
- int shred_process(dataptr dz)
- {
- int exit_status;
- int n, cnt = 0, checker = 0, work_len;
- int current_buf;
- if(sloom && dz->iparam[SHRED_SCAT]) {
- fprintf(stdout,"WARNING: There is a finite possibility program will not terminate.\n");
- fprintf(stdout,"WARNING: If in doubt, press STOP\n");
- fflush(stdout);
- }
- do {
- if(!sloom && !sloombatch)
- fprintf(stdout,"\nBUFFER %d ",cnt++);
- else {
- fprintf(stdout,"INFO: BUFFER %d\n",cnt++);
- fflush(stdout);
- }
- if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
- return(exit_status);
- current_buf = 0;
- if(dz->samps_left <= 0 ) {
- dz->buflen = dz->iparam[SHR_LAST_BUFLEN];
- dz->iparam[SHRED_SCAT] = dz->iparam[SHR_LAST_SCAT];
- dz->iparam[SHR_CHCNT] = dz->iparam[SHR_LAST_CHCNT];
- }
- if((dz->iparam[SHR_CHCNT_LESS_ONE] = dz->iparam[SHR_CHCNT] - 1)<=0) {
- if(cnt==1) {
- sprintf(errstr,"SOUNDFILE TOO SMALL to shred.\n");
- return(DATA_ERROR);
- } else {
- n = dz->buflen;
- dz->buflen = dz->ssampsread;
- do_bufend_splices(current_buf,dz);
- if((exit_status = write_exact_samps(dz->sampbuf[current_buf],dz->buflen,dz))<0)
- return(exit_status);
- dz->buflen = n;
- }
- } else {
- if((exit_status = get_basis_lengths(&work_len,dz))<0)
- return(exit_status);
- if(!sloom && !sloombatch)
- checker = 0;
- else
- display_virtual_time(0L,dz);
- for(n=0;n<dz->iparam[SHRED_CNT];n++) {
- if((exit_status = shred(current_buf,work_len,dz))<0)
- return(exit_status);
- current_buf = !current_buf;
- if(!sloom && !sloombatch) {
- if(n==checker) {
- printf("*");
- checker += 16;
- }
- } else
- display_virtual_time((long)n,dz);
- }
- do_bufend_splices(current_buf,dz);
- if((exit_status = write_exact_samps(dz->sampbuf[current_buf],dz->buflen,dz))<0)
- return(exit_status);
- }
- } while(dz->samps_left > 0);
- return(FINISHED);
- }
- /******************************* SHRED **************************
- *
- * (1) If the random-scattering of chunk boundaries is <= 1.0, scatter
- * each chunk boundary separately (normal_scat).
- * Else, scatter chunk boundaries over groups of chunklens (heavy_scat).
- * (2) Calculate the lengths of the chunks, from difference of their positions.
- * (2A) NB the length of the is the difference between its start and
- * THE END OF THE work_len (NOT the ned of the buffer). Chunklens are
- * measured from start of startsplice to START of endsplice (see
- * diagram).
- * (3) Generate a permutation (permm[]) of the chunk numbers.
- *
- * (4) The chunk that is to be FIRST in the permuted set does not need
- * to be spliced at its beginning (as there's nothing prior to it,
- * to splice into) but only at its end.
- * (a) The address from which we copy is position in current buffer
- * where chunk associated with 0 (chunk[permm[0]) is.
- * (b) The address to copy TO is start of the OTHER buffer (buf[!this]).
- * (c) The unit_len of the chunk we're copying is chunklen[permm[0]].
- * (d) Copy all of this.
- * (f) Copy SPLICELEN extra (full_len is SPLICELEN bigger that unit_len..
- * .. see diagram), making an endsplice on it as we do.
- *
- * (5) For the rest of the chunks APART FROM THE LAST....
- * (a) as 4(a): n associated with perm[n]..
- * (b) advance in new buffer by chunklen of PREVIOUSLY written chunk..
- * This 'length' is length to START of its endsplice, which is where
- * new chunk is spliced in.
- * (c) as 4(c)
- * (d) Do a startsplice as we copy from old_address to new_address.
- * (e) Copy from END of this startsplice, a segment of length chnklen
- * (length of the total copied chunk) MINUS length of that startsplice
- * (SPLICELEN).
- * (f) as 4(f).
- *
- * (6) For the last chunk, we don't need an endsplice (nothing to splice to)
- * (a-d)as 5(a-d).
- * (e) Copy from end of STARTSPLICE to end of ENDSPLICE ... i.e.
- * a whole chunklen, because full_len - SPLICELEN = chunklen.
- *
- * ___full_len___
- * | |
- * _chunklen__ |
- * | S |
- * | T |E
- * | R ________|N
- * | T/| \D
- * | / | \
- * |/ | \|
- * | |
- * |_chunklen_|
- * |
- * |___full_len___|
- *
- * (7) Set memory in old buffer to 0 (because we ADD into it, with splices).
- */
- int shred(int current_buf,int work_len,dataptr dz)
- {
- int n;
- float *old_addr, *new_addr;
- int chnk_len;
- char *destination = NULL;
- int *chunkptr = dz->lparray[SHR_CHUNKPTR];
- int *chunklen = dz->lparray[SHR_CHUNKLEN];
- int *permm = dz->iparray[SHR_PERM];
- if(!dz->iparam[SHRED_SCAT])
- normal_scat(dz); /* 1 */
- else
- heavy_scat(dz);
- for(n=0;n<dz->iparam[SHR_CHCNT_LESS_ONE];n++) /* 2 */
- chunklen[n] = chunkptr[n+1] - chunkptr[n];
- chunklen[n] = work_len - chunkptr[n]; /* 2A */
- permute_chunks(dz); /* 3 */
- /* NEW FIRST-SEGMENT IN BUFFER */ /* 4 */
- old_addr = dz->sampbuf[current_buf] + chunkptr[permm[0]]; /* a */
- new_addr = dz->sampbuf[!current_buf]; /* b */
- chnk_len = chunklen[permm[0]]; /* c */
- if(dz->vflag[0]) {
- do_startsplice(old_addr,new_addr,dz);
- destination = (char *)(new_addr+dz->iparam[SHRED_SPLEN]);
- memcpy(destination,
- (char *)(old_addr+dz->iparam[SHRED_SPLEN]),(chnk_len-dz->iparam[SHRED_SPLEN]) * sizeof(float));
- } else {
- destination = (char *)new_addr;
- memcpy(destination,(char *)old_addr,chnk_len*sizeof(float));
- }
- do_endsplice(old_addr+chnk_len, new_addr+chnk_len,dz); /* f */
- /* MIDDLE-SEGMENTS IN BUFFER */ /* 5 */
- for(n=1;n<dz->iparam[SHR_CHCNT_LESS_ONE];n++) {
- old_addr = dz->sampbuf[current_buf] + chunkptr[permm[n]]; /* a */
- new_addr += chnk_len; /* b */
- chnk_len = chunklen[permm[n]]; /* c */
- do_startsplice(old_addr,new_addr,dz); /* d */
- destination = (char *)(new_addr+dz->iparam[SHRED_SPLEN]);
- memcpy(destination,
- (char *)(old_addr+dz->iparam[SHRED_SPLEN]),(chnk_len-dz->iparam[SHRED_SPLEN]) * sizeof(float));
- do_endsplice(old_addr+chnk_len,new_addr+chnk_len,dz);
- } /* f */
- /* NEW END-SEGMENT IN BUFFER */ /* 6 */
- old_addr = dz->sampbuf[current_buf] + chunkptr[permm[n]]; /* a */
- new_addr += chnk_len; /* b */
- chnk_len = chunklen[permm[n]]; /* c */
- do_startsplice(old_addr,new_addr,dz); /* d */
- if(dz->vflag[0])
- do_endsplice(old_addr+chnk_len,new_addr+chnk_len,dz);
- destination = (char *)(new_addr+dz->iparam[SHRED_SPLEN]);
- memcpy(destination,(char *)(old_addr+dz->iparam[SHRED_SPLEN]),chnk_len*sizeof(float));
- /* RESET BUFFERS */
- memset((char *)dz->sampbuf[current_buf],0,dz->buflen * sizeof(float)); /* 7 */
- return(FINISHED);
- }
- /*********************** GET_BASIS_LENGTHS **********************
- *
- *
- * ______________buflen_______________
- * |............worklen............. | buflen - SPLICELEN = worklen.
- * | unitlen unitlen | | unit_len * dz->iparam[SHR_CHCNT] = worklen.
- * | | | | |
- * |_full_len_ | _full_len__| full_len = worklen + SPLICELEN.
- * | | | | | | |
- * | _____| |_____| ____| _____| |
- * | /| \ / \ / \ / \ |
- * | / | |X| X X \ |
- * |/ | / \ / \ / \ \|
- * | | |
- * | | |
- * rawlen
- *
- *
- */
- int get_basis_lengths(int *work_len,dataptr dz)
- {
- int excess, full_len, endunit_len, endfull_len;
- *work_len = dz->buflen - dz->iparam[SHRED_SPLEN];
- dz->iparam[SHR_UNITLEN] = (int)round((*work_len)/dz->iparam[SHR_CHCNT]);
- excess = dz->iparam[SHR_UNITLEN] % dz->infile->channels;
- dz->iparam[SHR_UNITLEN] -= excess;
- excess = (*work_len) - (dz->iparam[SHR_UNITLEN] * dz->iparam[SHR_CHCNT]);
- if(excess % dz->infile->channels) {
- sprintf(errstr,"Problem in buffer accounting.\n");
- return(PROGRAM_ERROR);
- }
- dz->iparam[SHR_RAWLEN] = dz->iparam[SHR_UNITLEN] - dz->iparam[SHRED_SPLEN];
- full_len = dz->iparam[SHR_UNITLEN] + dz->iparam[SHRED_SPLEN];
- endunit_len = dz->iparam[SHR_UNITLEN] + excess;
- endfull_len = full_len + excess;
- dz->iparam[SHR_ENDRAWLEN] = dz->iparam[SHR_RAWLEN] + excess;
- if(full_len < (dz->iparam[SHRED_SPLEN] * 2) || endfull_len < (dz->iparam[SHRED_SPLEN] * 2)) {
- sprintf(errstr,"Chunksize too small for splices.\n");
- return(DATA_ERROR);
- }
- if(dz->iparam[SHRED_SCAT]) {
- dz->iparam[SHR_SCATGRPCNT] = (int)(dz->iparam[SHR_CHCNT]/dz->iparam[SHRED_SCAT]);
- dz->iparam[SHR_ENDSCAT] = (int)(dz->iparam[SHR_CHCNT] - (dz->iparam[SHR_SCATGRPCNT] * dz->iparam[SHRED_SCAT]));
- dz->iparam[SHR_RANGE] = dz->iparam[SHR_UNITLEN] * dz->iparam[SHRED_SCAT];
- dz->iparam[SHR_ENDRANGE] = ((dz->iparam[SHR_ENDSCAT]-1) * dz->iparam[SHR_UNITLEN]) + endunit_len;
- }
- return(FINISHED);
- }
- /************************** NORMAL_SCAT ******************************
- *
- * (1) TOTLA_LEN generates the unscattered positions of the chunks.
- * Each is UNIT_LEN long, so they are equally spaced at UNIT_LEN
- * intervals.
- We can't scatter the FIRST chunk as it MUST start at ZERO!!
- * (2) For all chunks except the first and last...
- * (3) Scatter position of chunk over +- 1/2 of value of scatter,
- * times the RAW-distance (not including splices) between chunks.
- * (4) Add (could be negative) this scattering to orig position.
- * (5) For the last chunk, do the same, scattering over RAW-len of previous
- * chunk, if scatter -ve, and over endraw_len of final chunk, if +ve.
- */
- void normal_scat(dataptr dz)
- {
- double this_scatter;
- int n, k;
- int chunkscat, total_len = dz->iparam[SHR_UNITLEN]; /* 1 */
- int *chunkptr = dz->lparray[SHR_CHUNKPTR];
- for(n=1;n<dz->iparam[SHR_CHCNT_LESS_ONE];n++) { /* 2 */
- this_scatter = (drand48() - 0.5) * dz->param[SHRED_SCAT];
- chunkscat = (int)(this_scatter * (double)dz->iparam[SHR_RAWLEN]);
- k = chunkscat % dz->infile->channels;
- chunkscat -= k;
- chunkptr[n] = total_len + chunkscat;
- total_len += dz->iparam[SHR_UNITLEN]; /* 4 */
- }
- this_scatter = (drand48() - 0.5) * dz->param[SHRED_SCAT];
- if(this_scatter<0.0) { /* 5 */
- chunkscat = (int)(this_scatter * (double)dz->iparam[SHR_RAWLEN]);
- k = chunkscat % dz->infile->channels;
- chunkscat -= k;
- chunkptr[n] = total_len - chunkscat;
- } else {
- chunkscat = (int)(this_scatter * (double)dz->iparam[SHR_ENDRAWLEN]);
- k = chunkscat % dz->infile->channels;
- chunkscat -= k;
- chunkptr[n] = total_len + chunkscat;
- }
- }
- /*********************** 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.
- */
- void heavy_scat(dataptr dz)
- {
- int thiss = 1, that, start, n, m, OK; /* 1 */
- int k;
- int startptr = 0; /* 2 */
- int endptr = 0;
- int first = 1; /* 3 */
- int *chunkptr = dz->lparray[SHR_CHUNKPTR];
- for(n=0;n<dz->iparam[SHR_SCATGRPCNT];n++) { /* 4 */
- start = thiss; /* 5 */
- endptr += dz->iparam[SHR_RANGE];
- for(m=first;m<dz->iparam[SHRED_SCAT];m++) { /* 6 */
- do{ /* 7 */
- OK = 1;
- chunkptr[thiss] = (long)(drand48()*dz->iparam[SHR_RANGE]); /* TRUNCATE (?)*/
- chunkptr[thiss] += startptr; /* 8 */
- k = chunkptr[thiss] % dz->infile->channels;
- chunkptr[thiss] -= k;
- for(that=start-1; that<thiss; that++) {
- if(abs(chunkptr[thiss] - chunkptr[that])<dz->iparam[SHRED_SPLEN]) {
- OK = 0; /* 9 */
- break;
- }
- if(abs(endptr - chunkptr[thiss])<dz->iparam[SHRED_SPLEN]) {
- OK = 0;
- break;
- }
- }
- } while(!OK); /* 10 */
- thiss++; /* 11 */
- }
- startptr += dz->iparam[SHR_RANGE]; /* 12 */
- first = 0; /* 13 */
- }
- endptr += dz->iparam[SHR_ENDRANGE];
- if(dz->iparam[SHR_ENDSCAT]) { /* 14 */
- start = thiss;
- for(m=0;m<dz->iparam[SHR_ENDSCAT];m++) {
- do {
- OK = 1;
- chunkptr[thiss] = (long)(drand48() * dz->iparam[SHR_ENDRANGE]); /* TRUNCATE (?) */
- chunkptr[thiss] += startptr;
- k = chunkptr[thiss] % dz->infile->channels;
- chunkptr[thiss] -= k;
- for(that=start-1; that<thiss; that++) {
- if(abs(chunkptr[thiss] - chunkptr[that])<dz->iparam[SHRED_SPLEN]) {
- OK = 0;
- break;
- }
- if(abs(endptr - chunkptr[thiss])<dz->iparam[SHRED_SPLEN]) {
- OK = 0;
- break;
- }
- }
- } while(!OK);
- thiss++;
- }
- }
- ptr_sort(thiss,dz);
- }
- /*************************** PERMUTE_CHUNKS ***************************/
- void permute_chunks(dataptr dz)
- {
- int n, t;
- for(n=0;n<dz->iparam[SHR_CHCNT];n++) {
- t = (int)(drand48() * (double)(n+1)); /* TRUNCATE */
- if(t==n)
- prefix(n,dz);
- else
- insert(n,t,dz);
- }
- }
- /****************************** INSERT ****************************/
- void insert(int n,int t,dataptr dz)
- {
- shuflup(t+1,dz);
- dz->iparray[SHR_PERM][t+1] = n;
- }
- /****************************** PREFIX ****************************/
- void prefix(int n,dataptr dz)
- {
- shuflup(0,dz);
- dz->iparray[SHR_PERM][0] = n;
- }
- /****************************** SHUFLUP ****************************/
- void shuflup(int k,dataptr dz)
- {
- int n;
- for(n = dz->iparam[SHR_CHCNT_LESS_ONE]; n > k; n--)
- dz->iparray[SHR_PERM][n] = dz->iparray[SHR_PERM][n-1];
- }
- /************************* DO_STARTSPLICE *************************
- *
- * (0) For each position in splice.
- * (1) Get the value from the source file & multiply it by position in splice.
- * We 'should' multiply it by position/SPLICELEN,
- * so new value is SPLICELEN too large.
- * (2) Add a rounding factor (if value were correct, this would be 1/2)
- * But everything is SPLICELEN times too big, so add SHRED_HSPLICELEN.
- * (3) Divide by SPLICELEN.
- * (4) ADD this value to existing value (this is a splice TO another chunk!!).
- */
- void do_startsplice(float *i,float *j,dataptr dz)
- {
- double z;
- int n;
- for(n = 0; n <dz->iparam[SHRED_SPLEN]; n ++) { /* 0 */
- z = (*i) * (double)n/dz->iparam[SHRED_SPLEN]; /* 1 */
- i++;
- *j = (float) /*round*/((*j) + z); /* 4 */
- j++;
- }
- }
- /************************* DO_ENDSPLICE *************************/
- void do_endsplice(float *i,float *j,dataptr dz)
- {
- double z;
- int n;
- for(n = dz->iparam[SHRED_SPLEN]-1; n>=0; n--) {
- z = *i++ * (double)n/dz->iparam[SHRED_SPLEN];
- *j++ += (float) /*round*/ (z);
- }
- }
- /********************* DO_BUFEND_SPLICES *************************/
- void do_bufend_splices(int current_buf,dataptr dz)
- {
- double z;
- int n;
- float *b = dz->sampbuf[current_buf];
- for(n = 0; n <dz->iparam[SHRED_SPLEN]; n ++) {
- z = (*b) * (double)n/dz->iparam[SHRED_SPLEN];
- *b++ = (float)z;
- }
- b = dz->sampbuf[current_buf] + dz->buflen - dz->iparam[SHRED_SPLEN];
- for(n = dz->iparam[SHRED_SPLEN]-1; n>=0; n--) {
- z = (*b) * (double)n/dz->iparam[SHRED_SPLEN];
- *b++ = (float) /*round*/(z);
- }
- }
- /**************************** CHECK_FOR_TOO_SMALL_BUF *********************/
- int check_for_too_small_buf(dataptr dz)
- {
- int chunksamps = round(dz->param[SHRED_CHLEN] * dz->infile->srate) * dz->infile->channels;
- if(dz->iparam[SHRED_SCAT]) {
- if(dz->buflen <= chunksamps * dz->iparam[SHRED_SCAT]) {
- sprintf(errstr,"Internal sound buffer too short (%lf secs) for chunksize and scatter.\n",
- (double)(dz->buflen/dz->infile->channels)/(double)dz->infile->srate);
- return(GOAL_FAILED);
- }
- } else {
- if(dz->buflen <= chunksamps * 2) {
- sprintf(errstr,"Sound buffer too short for chunksize.\n");
- return(GOAL_FAILED);
- }
- }
- return(FINISHED);
- }
- /************************** PTR_SORT ***************************/
- void ptr_sort(int end,dataptr dz)
- {
- int i,j;
- int a;
- int *chunkptr = dz->lparray[SHR_CHUNKPTR];
- for(j=1;j<end;j++) {
- a = chunkptr[j];
- i = j-1;
- while(i >= 0 && chunkptr[i] > a) {
- chunkptr[i+1]=chunkptr[i];
- i--;
- }
- chunkptr[i+1] = a;
- }
- }
- /*************************** SCRUB_PCONSISTENCY **************************/
- int scrub_pconsistency(dataptr dz)
- {
- if(dz->param[SCRUB_MINSPEED] > dz->param[SCRUB_MAXSPEED])
- swap(&(dz->param[SCRUB_MINSPEED]),&dz->param[SCRUB_MAXSPEED]);
- dz->iparam[SCRUB_TOTALDUR] = round(dz->param[SCRUB_TOTALDUR] * (double)(dz->infile->srate * dz->infile->channels));
- return(FINISHED);
- }
- /*************************** SCRUB_PREPROCESS **************************/
- int scrub_preprocess(dataptr dz)
- {
- int exit_status;
- double sr = (double)dz->infile->srate;
- int chans = dz->infile->channels;
- initrand48();
- if((exit_status = create_sintable(dz))<0)
- return(exit_status);
- dz->iparam[SCRUB_STARTRANGE] = round(dz->param[SCRUB_STARTRANGE] * sr);
- dz->iparam[SCRUB_ESTART] = round(dz->param[SCRUB_ESTART] * sr);
- dz->iparam[SCRUB_ENDRANGE] = (dz->insams[0]/chans) - dz->iparam[SCRUB_ESTART];
- dz->param[SCRUB_SPEEDRANGE] = dz->param[SCRUB_MAXSPEED] - dz->param[SCRUB_MINSPEED];
- return(FINISHED);
- }
- /*************************** CREATE_SINTABLE **************************/
- int create_sintable(dataptr dz)
- {
- int n;
- /* GENERATE A WARPED SINUS TABLE, Range 0 - 1 */
- if((dz->parray[SCRUB_SIN] = (double *)malloc((SCRUB_SINTABSIZE+1) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to create sintable for scrubbing.\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<SCRUB_SINTABSIZE;n++) {
- dz->parray[SCRUB_SIN][n] = sin(PI * (double)n/(double)SCRUB_SINTABSIZE);
- dz->parray[SCRUB_SIN][n] = pow(dz->parray[SCRUB_SIN][n],SCRUB_SINWARP);
- }
- dz->parray[SCRUB_SIN][n] = 0.0;
- if((dz->parray[SCRUB_READTAB] = (double *)malloc((SCRUB_SINTABSIZE+1) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to create skewtable for scrubbing.\n");
- return(MEMORY_ERROR);
- }
- return(FINISHED);
- }
- /***************************CREATE_BUFFERS **************************/
- int create_scrub_buffers(dataptr dz)
- {
- size_t bigbufsize;
- long shsecsize = F_SECSIZE, sum = 0L;
- long framesize = F_SECSIZE * dz->infile->channels;
- bigbufsize = (size_t)Malloc(-1);
- bigbufsize /= sizeof(float);
- bigbufsize = (bigbufsize/(framesize*dz->bufcnt)) * framesize * dz->bufcnt;
- bigbufsize = bigbufsize/dz->bufcnt;
- if(bigbufsize <= 0)
- bigbufsize = framesize;
- dz->buflen = (int) bigbufsize;
- if((dz->bigbuf = (float *)malloc(
- ((dz->buflen * dz->bufcnt) + (F_SECSIZE*2)) * sizeof(float))) == NULL) {
- sprintf(errstr, "INSUFFICIENT MEMORY for sound buffers.\n");
- return(MEMORY_ERROR);
- }
- dz->sampbuf[0] = dz->bigbuf;
- dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen + (shsecsize*2); /* inbuf has wraparound sectors */
- dz->iparam[SCRUB_DROPOUT] = FALSE;
- if(dz->iparam[SCRUB_TOTALDUR] <= dz->buflen + shsecsize) {
- dz->buflen = dz->iparam[SCRUB_TOTALDUR];
- dz->iparam[SCRUB_DROPOUT] = TRUE;
- }
- dz->iparam[SCRUB_BUFCNT] = 0;
- while(sum < dz->insams[0]) {
- dz->iparam[SCRUB_BUFCNT]++;
- sum += dz->buflen;
- }
- return(FINISHED);
- }
- /****************************** DO_SCRUBBING *************************/
- int do_scrubbing(dataptr dz)
- {
- int exit_status;
- /* float *ibuf = dz->sampbuf[0];*/
- float *obuf = dz->sampbuf[1];
- int chans = dz->infile->channels;
- int scrublen_in_src, effective_tablen;
- double skew, lospeed,speedrange;
- int direction = SCRUB_BACKWARDS, here, lasthere = 0, there = 0;
- display_virtual_time(0,dz); /* fraction of total_dur!! */
- get_end(&direction,&lasthere,dz); /* setup start position */
- do {
- here = lasthere;
- get_end(&direction,&here,dz);
- skew = get_skew();
- get_speed(&lospeed,&speedrange,dz);
- scrublen_in_src = abs(here - lasthere);
- effective_tablen = gen_readtab(skew,lospeed,speedrange,scrublen_in_src,dz);
- if((exit_status = scrub(&lasthere,&there,!direction,effective_tablen,dz))<0)
- return(exit_status);
- if(exit_status == FINISHED)
- break;
- if(dz->vflag[0]) // FORWARD SCRUB ONLY
- break;
- } while((there * chans) + dz->total_samps_written < dz->iparam[SCRUB_TOTALDUR]);
- if(there > 0)
- return write_samps(obuf,there * chans,dz);
- return(FINISHED);
- }
- /******************************* GET_SKEW ******************************/
- double get_skew(void)
- { double skew;
- skew = (drand48() * 2.0) - 1.0; /* -1 to +1 */
- skew *= SCRUB_SKEWRANGE;
- skew += 1.0; /* 1 +- SKEWRANGE */
- return(skew);
- }
- /******************************* GET_SPEED ******************************
- *
- * Generate a speed distribution which is pitch (not frq) distributed.
- */
- void get_speed(double *lospeed,double *speedrang,dataptr dz)
- {
- double hispeed;
- hispeed = drand48() * dz->param[SCRUB_SPEEDRANGE] * SCRUB_RANGE_REDUCE_FACTOR;
- hispeed = dz->param[SCRUB_MAXSPEED] - hispeed;
- *lospeed = drand48() * dz->param[SCRUB_SPEEDRANGE] * SCRUB_RANGE_REDUCE_FACTOR;
- *lospeed += dz->param[SCRUB_MINSPEED];
- *speedrang = hispeed - *lospeed;
- }
- /******************************* GET_END ******************************/
- void get_end(int *direction,int *here,dataptr dz)
- {
- int lasthere = *here;
- switch(*direction) {
- case(SCRUB_FORWARDS):
- *here = round(drand48() * dz->iparam[SCRUB_ENDRANGE]);
- *here += dz->iparam[SCRUB_ESTART];
- *direction = SCRUB_BACKWARDS;
- break;
- case(SCRUB_BACKWARDS):
- *here = round(drand48() * dz->iparam[SCRUB_STARTRANGE]);
- *direction = SCRUB_FORWARDS;
- break;
- }
- //TW COMMENT: this statement has no effect
- dz->param[SCRUB_LENGTH] = abs(lasthere - *here);
- }
- /***************************** GEN_READTAB *****************************/
- int gen_readtab(double skew,double lospeed,double speedrange,int scrublen_in_src,dataptr dz)
- {
- int n, here, next, tablen = -1;
- double step, sin_index, frac, dindex;
- double *sintab = dz->parray[SCRUB_SIN];
- double *readtab = dz->parray[SCRUB_READTAB];
- double readtab_integral = 0.0, last_readtab_integral, searchstep = 1.01;
- /* GENERATE A SKEWED WARPED-SINUS-TABLE, Range 0 - 1, from orig WARPED-SINUS-TABLE */
- if(flteq(skew,1.0)) {
- memcpy((char *)readtab,(char *)sintab,(SCRUB_SINTABSIZE + 1) * sizeof(double));
- tablen = SCRUB_SINTABSIZE;
- } else {
- sin_index = 0.0;
- step = (double)SCRUB_SINTABSIZE * (1.0-skew); /* initial step found using */
- step /= (1.0 - pow(skew,(double)SCRUB_SINTABSIZE)); /* geometric series sum */
- readtab[0] = 0.0;
- for(n=1;n<SCRUB_SINTABSIZE;n++) {
- sin_index += step;
- if((here = (int)sin_index) >= SCRUB_SINTABSIZE) { /* TRUNCATE */
- tablen = n;
- sprintf(errstr,"scrubbing table incomplete by %d items\n",SCRUB_SINTABSIZE - n);
- print_outwarning_flush(errstr);
- break;
- } else {
- frac = sin_index - (double)here;
- next = here + 1;
- readtab[n] = (sintab[next] - sintab[here]) * frac;
- readtab[n] += sintab[here];
- step *= skew;
- }
- }
- if(tablen < 0)
- tablen = SCRUB_SINTABSIZE;
- readtab[tablen] = readtab[tablen-1];
- }
- for(n=0;n<=tablen;n++) {
- /* range is initially 0 - 1 */
- readtab[n] *= speedrange; /* change scale to range of speedrange */
- readtab[n] += lospeed; /* shift values to be within range lospeed to hispeed */
- readtab[n] *= OCTAVES_PER_SEMITONE; /* convert values to octaves */
- readtab[n] = pow(2.0,readtab[n]); /* convert vals to transposition ratios = increments in infile */
- readtab_integral += readtab[n]; /* integrate func to get total length */
- }
- /* If the speedvary process causes sample-read to fall off end of file */
- /* move more quickly through the sample-read-incrs file */
- while(readtab_integral >= (double)scrublen_in_src) {
- last_readtab_integral = readtab_integral;
- dz->param[SCRUB_TABINC] = readtab_integral/(double)scrublen_in_src;
- dindex = 0.0;
- readtab_integral = 0.0;
- while(dindex <= (double)tablen) {
- here = (int)floor(dindex);
- next = here+1;
- frac = dindex - (double)here;
- readtab_integral += (readtab[n] * (1.0 - frac)) + (readtab[next] * frac);
- dindex += dz->param[SCRUB_TABINC];
- }
- if(last_readtab_integral == readtab_integral) {
- /* if the search process stalls, kick restart it */
- readtab_integral *= searchstep;
- searchstep *= searchstep;
- }
- }
- /* in effect: change area under function by expanding or contracting it along x-axis */
- dz->param[SCRUB_TABINC] = readtab_integral/(double)scrublen_in_src;
- return tablen;
- }
- /**************************** SCRUB *******************************/
- #define SCRUB_SPLICE (0.1)
- int scrub(int *hhere,int *tthere,int direction,int effective_tablen,dataptr dz)
- {
- int exit_status, scrub_exit_status;
- int index;
- double lfrac, inval;
- int n, m;
- int chans = dz->infile->channels;
- int effective_buflen = dz->buflen/chans;
- int abshere = *hhere, there = *tthere;
- int here = abshere % effective_buflen;
- int bufno = abshere/effective_buflen; /* TRUNCATE */
- int truehere, truethere;
- int cnt = 0, splicend, scrubend = 0;
- double splincr, splval;
- double dindex, dhere = here, frac, val;
- float *ibuf = dz->sampbuf[0];
- float *obuf = dz->sampbuf[1];
- double *readtab = dz->parray[SCRUB_READTAB];
- if((exit_status = read_samps_for_scrub(bufno,dz))<0) /* read wraparound buffer */
- return(exit_status);
- if(there >= effective_buflen) {
- if(dz->iparam[SCRUB_DROPOUT])
- return(FINISHED);
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
- return(exit_status);
- there = 0;
- truethere = there *chans;
- }
- for(m=0;m<chans;m++)
- obuf[(there*chans)+m] = 0.0f;
- splicend = (int)round((double)dz->infile->srate * SCRUB_SPLICE);
- dindex = dz->param[SCRUB_TABINC];
- while (dindex < (double)effective_tablen) {
- dindex += dz->param[SCRUB_TABINC];
- scrubend++;
- }
- scrubend -= splicend;
- if(scrubend < splicend) {
- scrubend += splicend;
- splicend = scrubend/2;
- scrubend -= splicend;
- }
- splincr = 1.0/(double)splicend;
- splval = splincr;
- dindex = dz->param[SCRUB_TABINC];
- there++;
- truethere = there *chans;
- do {
- if(there >= effective_buflen) {
- if(dz->iparam[SCRUB_DROPOUT])
- return(FINISHED);
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
- return(exit_status);
- there = 0;
- truethere = there *chans;
- }
- index = (long)dindex; /* TRUNCATE */ /* interpolate vals in readtable */
- frac = dindex - (double)index;
- val = (readtab[index+1] - readtab[index]) * frac;
- val += readtab[index];
- scrub_exit_status = CONTINUE;
- if(direction==SCRUB_FORWARDS) {
- dhere += val; /* use readtab val to interpolate in sndfile */
- here = (int)dhere; /* TRUNCATE */
- truehere = here * chans;
- if(truehere >= dz->ssampsread) {
- if(++bufno >= dz->iparam[SCRUB_BUFCNT]) {
- fprintf(stdout,"WARNING: overreached infile.\n");
- fflush(stdout);
- scrub_exit_status = FINISHED;
- break;
- }
- if((exit_status = read_samps_for_scrub(bufno,dz))<0) /* read wraparound buffer */
- return(exit_status);
- truehere -= dz->buflen;
- here -= effective_buflen;
- dhere -= (double)effective_buflen;
- }
- } else {
- dhere -= val;
- here = (int)dhere; /* TRUNCATE */
- truehere = here * chans;
- if(here < 0) {
- if(--bufno < 0) {
- fprintf(stdout,"WARNING: fell off start of infile.\n");
- fflush(stdout);
- scrub_exit_status = FINISHED;
- break;
- }
- if((exit_status = read_samps_for_scrub(bufno,dz))<0) /* read wraparound buffer */
- return(exit_status);
- truehere += dz->buflen;
- here += effective_buflen;
- dhere += (double)effective_buflen;
- }
- }
- lfrac = dhere - (double)here;
- if (cnt > scrubend) {
- for(m=0;m<chans;m++) {
- inval = ibuf[truehere+m] * (1.0 - lfrac);
- inval += ibuf[truehere+m+chans] * lfrac;
- obuf[truethere+m] = (float)(inval * splval);
- splval -= splincr;
- }
- } else if(cnt < splicend) {
- for(m=0;m<chans;m++) {
- inval = ibuf[truehere+m] * (1.0 - lfrac);
- inval += ibuf[truehere+m+chans] * lfrac;
- obuf[truethere+m] = (float)(inval * splval);
- splval += splincr;
- }
- } else {
- for(m=0;m<chans;m++) {
- inval = ibuf[truehere+m] * (1.0 - lfrac);
- inval += ibuf[truehere+m+chans] * lfrac;
- obuf[truethere+m] = (float) /*round*/(inval);
- }
- }
- there++;
- truethere = there *chans;
- cnt++;
- } while ((dindex += dz->param[SCRUB_TABINC]) < SCRUB_SINTABSIZE);
- for(n=0;n<SCRUB_SINTABSIZE;n++) { /* create silent gap to avoid clicks */
- if(there >= effective_buflen) {
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
- return(exit_status);
- there = 0;
- truethere = 0;
- }
- for(m=0;m<chans;m++)
- obuf[truethere+m] = 0.0f;
- truethere += chans;
- there++;
- }
- *hhere = (bufno * effective_buflen) + here;
- *tthere = there;
- return(scrub_exit_status);
- }
- /**************************** READ_SAMPS_FOR_SCRUB *******************************/
- int read_samps_for_scrub(int bufno,dataptr dz)
- {
- int exit_status;
- float *buf = dz->sampbuf[0];
- if(sndseekEx(dz->ifd[0],bufno * dz->buflen,0)<0) {
- sprintf(errstr,"sndseek() 1 failed in scrub.\n"); /* seek to start of buffer from which to read */
- return(SYSTEM_ERROR);
- }
- dz->buflen += F_SECSIZE; /* samps to read, with F_SECSIZE wraparound for interpd reading last sample in buf */
- /* zeroes buffer in case wraparound on last-samp-in-file !! */
- memset((char *)buf,0,(dz->buflen + F_SECSIZE) * sizeof(float));
- /* zeros FURTHER F_SECSIZE samps in case file exactly fills the F_SECSIZE-extended buffer */
- /* & there's wraparound on last-samp-in-file !! */
- if((exit_status = read_samps(buf,dz))<0) /* read wraparound buffer */
- return(exit_status);
- dz->buflen -= F_SECSIZE; /* reset to unwrapped buffer size */
- if(dz->ssampsread > dz->buflen) /* if read beyond effective bufsize, there are samps in file beyond this */
- dz->ssampsread = dz->buflen; /* reset samps_read to non-wrapped samps read */
- return(FINISHED);
- }
- /*************************** CROSSMOD_PCONSISTENCY **************************/
- int crossmod_pconsistency(dataptr dz)
- {
- if(dz->infile->srate != dz->otherfile->srate) {
- sprintf(errstr,"Cross modulation only works with files of same srate.\n");
- return(DATA_ERROR);
- }
- if((dz->otherfile->channels > 2 && dz->infile->channels != 1) || (dz->infile->channels > 2 && dz->otherfile->channels != 1)) {
- if(dz->infile->channels != dz->otherfile->channels) {
- sprintf(errstr,"With multichannel files, Cross modulation ONLY works if files have same number of channels OR if one file is mono.\n");
- return(DATA_ERROR);
- }
- }
- return(FINISHED);
- }
- /*************************** CREATE_CROSSMOD_BUFFERS **************************/
- //TW replaced by global
- //#define FSECSIZE (256)
- int create_crossmod_buffers(dataptr dz)
- {
- size_t bigbufsize;
- int framesize;
- int bufchunks;
- bufchunks = dz->infile->channels;
- bufchunks += dz->otherfile->channels;
- bufchunks += max(dz->otherfile->channels,dz->infile->channels);
- bigbufsize = (size_t)Malloc(-1);
- dz->buflen = (int)(bigbufsize / sizeof(float));
- //TW MODIFIED ....
- framesize = F_SECSIZE * bufchunks;
- if((dz->buflen = (dz->buflen/framesize) * framesize)<=0)
- dz->buflen = framesize;
- if((dz->bigbuf = (float *)malloc(dz->buflen * sizeof(float))) == NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
- return(PROGRAM_ERROR);
- }
- dz->buflen /= bufchunks;
- dz->sampbuf[0] = dz->bigbuf;
- dz->sampbuf[1] = dz->sampbuf[0] + (dz->buflen * dz->infile->channels);
- dz->sampbuf[2] = dz->sampbuf[1] + (dz->buflen * dz->otherfile->channels);
- return(FINISHED);
- }
- /**************************** RING_MODULATE *************************/
- int ring_modulate(dataptr dz)
- {
- int exit_status;
- double sr = (double)dz->infile->srate;
- int chans = dz->infile->channels;
- double thistime = 0.0;
- double this_pitch = 0.0, next_pitch, pitchstep = 0.0, thisfrq, tabstep, tabindex = 0.0, sinval;
- double tabconvertor = (double)RM_SINTABSIZE/sr;
- float *ibuf = dz->sampbuf[0];
- int blokcnt = 0;
- long m,k,j,r;
- long total_stereosamp_cnt = 0;
- if(dz->brksize[RM_FRQ]) {
- if((exit_status = read_value_from_brktable(thistime,RM_FRQ,dz))<0)
- return(exit_status);
- }
- next_pitch = log10(dz->param[RM_FRQ]);
- while(dz->samps_left > 0) {
- if((exit_status = read_samps(ibuf,dz))<0)
- return(exit_status);
- dz->ssampsread /= chans;
- for(m=0,k=0;m<dz->ssampsread;m++,k+=chans) {
- if(blokcnt<=0) {
- total_stereosamp_cnt += RING_MOD_BLOK;
- thistime = (double)total_stereosamp_cnt/sr; /* reading 1 block ahead */
- if(dz->brksize[RM_FRQ]) {
- if((exit_status = read_value_from_brktable(thistime,RM_FRQ,dz))<0)
- return(exit_status);
- }
- this_pitch = next_pitch;
- next_pitch = log10(dz->param[RM_FRQ]);
- pitchstep = (next_pitch - this_pitch)/(double)RING_MOD_BLOK;
- blokcnt = RING_MOD_BLOK;
- }
- blokcnt--;
- thisfrq = pow(10.0,this_pitch);
- tabstep = thisfrq * tabconvertor;
- sinval = read_rmod_tab(tabindex,dz);
- for(j=0;j<chans;j++) {
- r = k+j;
- ibuf[r] = (float)/*round*/((double)ibuf[r] * sinval);
- }
- tabindex += tabstep;
- while(tabindex >= (double)RM_SINTABSIZE)
- tabindex -= (double)RM_SINTABSIZE;
- this_pitch += pitchstep;
- }
- if(dz->ssampsread > 0) {
- if((exit_status = write_exact_samps(ibuf,dz->ssampsread * chans,dz))<0)
- return(exit_status);
- }
- }
- return(FINISHED);
- }
- /**************************** CROSS_MODULATE *************************/
- int cross_modulate(dataptr dz)
- {
- int exit_status;
- /*double sr = (double)dz->infile->srate;*/
- float *ibuf1 = dz->sampbuf[0];
- float *ibuf2 = dz->sampbuf[1];
- float *obuf = dz->sampbuf[2];
- int chans1 = dz->infile->channels;
- int chans2 = dz->otherfile->channels;
- int maxchans = max(chans1,chans2);
- int samps_read, samps_read1, samps_read2, samps_to_write;
- int m,k,j,r;
- dz->tempsize = max(dz->insams[0],dz->insams[1]);
- display_virtual_time(0L,dz);
- for(;;) {
- if((samps_read1 = fgetfbufEx(ibuf1,dz->buflen * chans1,dz->ifd[0],0))<0) {
- sprintf(errstr,"Failed to read sound from 1st file.\n");
- return(SYSTEM_ERROR);
- }
- if((samps_read2 = fgetfbufEx(ibuf2,dz->buflen * chans2,dz->ifd[1],0))<0) {
- sprintf(errstr,"Failed to read sound from 2nd file.\n");
- return(SYSTEM_ERROR);
- }
- if((samps_read = min(samps_read1/chans1,samps_read2/chans2))<=0)
- break;
- samps_to_write = samps_read * maxchans;
- dz->ssampsread = samps_read;
-
- for(m=0;m<dz->ssampsread;m++) {
- switch(chans1) {
- case(STEREO): // STEREO-STEREO
- switch(chans2) {
- case(STEREO):
- k = m * 2;
- for(j=0;j<STEREO;j++) {
- r = k+j;
- obuf[r] = (float)(ibuf1[r] * ibuf2[r]);
- }
- break;
- case(MONO): // STEREO-MONO
- k = m * 2;
- for(j=0;j<STEREO;j++) {
- r = k+j;
- obuf[r] = (float)(ibuf1[r] * ibuf2[m]);
- }
- break;
- }
- break;
- case(MONO): // MONO-MULTICHANNEL
- k = m * chans2;
- for(j=0;j<chans2;j++) {
- r = k+j;
- obuf[r] = (float)(ibuf1[m] * ibuf2[r]);
- }
- break;
- default:
- switch(chans2) { // MULTICHANNEL-MONO
- case(MONO):
- k = m * chans1;
- for(j=0;j<chans1;j++) {
- r = k+j;
- obuf[r] = (float)(ibuf1[r] * ibuf2[m]);
- }
- break;
- default: // MULTICHANNEL-MULTICHANNEL
- obuf[m] = (float)(ibuf1[m] * ibuf2[m]);
- break;
- } // OTHER POSSIBLE CHANNEL COMBOS ARE TRAPPED EARLIER
- }
- }
- if(samps_to_write==dz->buflen * maxchans) {
- if((exit_status = write_exact_samps(obuf,samps_to_write,dz))<0)
- return(exit_status);
- } else if(samps_to_write > 0) {
- if((exit_status = write_samps(obuf,samps_to_write,dz))<0)
- return(exit_status);
- }
- }
- dz->infile->channels = maxchans;
- return(FINISHED);
- }
- /**************************** READ_RMOD_TAB *************************/
- double read_rmod_tab(double dtabindex,dataptr dz)
- {
- double *sintab = dz->parray[RM_SINTAB];
- int tabindex = (int)dtabindex; /* TRUNCATE */
- double frac = dtabindex - (double)tabindex;
- double loval = sintab[tabindex];
- double hival = sintab[tabindex+1];
- double incr = (hival - loval) * frac;
- return(loval + incr);
- }
- /********************** CREATE_RM_SINTAB *************************/
- int create_rm_sintab(dataptr dz)
- {
- int n;
- double *sintab, sinsize = (double) RM_SINTABSIZE;
- #ifdef NOTDEF
- double scaling = (double)MAXSHORT/(double)(MAXSHORT+2); /* avoid clipping inverted max -ve sample */
- #endif
- if((dz->parray[RM_SINTAB] = (double *)malloc((RM_SINTABSIZE+1) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for sine rtable.\n");
- return(MEMORY_ERROR);
- }
- sintab = dz->parray[RM_SINTAB];
- for(n=0;n<RM_SINTABSIZE;n++)
- sintab[n] = sin(TWOPI * (double)n/sinsize) /* * scaling*/;
- sintab[n] = 0.0;
- return(FINISHED);
- }
- //TW UPDATE: NEW FUNCTIONS BELOW (converted to flotsams)
- /********************** STACK_PREPROCESS *************************/
- int stack_preprocess(dataptr dz)
- {
- int n, k;
- double step, sum, thisstep, mult;
- if(dz->itemcnt == 0) { /* value NOT in file */
- if((dz->parray[STACK_TRANS] =
- (double *)realloc((char *)(dz->parray[STACK_TRANS]),dz->iparam[STACK_CNT] * sizeof(double)))==NULL) {
- sprintf(errstr,"Insufficient memory for storing stack transpositions.\n");
- return(MEMORY_ERROR);
- }
- thisstep = 1.0;
- mult = dz->parray[STACK_TRANS][0];
- if(mult > 1.0) {
- for(n=0;n<dz->iparam[STACK_CNT];n++) {
- dz->parray[STACK_TRANS][n] = thisstep;
- thisstep *= mult;
- }
- } else {
- for(n=dz->iparam[STACK_CNT] - 1;n>=0;n--) { /* pitch highest track always at top */
- dz->parray[STACK_TRANS][n] = thisstep;
- thisstep *= mult;
- }
- }
- dz->itemcnt = dz->iparam[STACK_CNT];
- } else if(dz->itemcnt != dz->iparam[STACK_CNT]) {
- fprintf(stdout,"WARNING: Count of transposition values in file (%d)\n",dz->itemcnt);
- fprintf(stdout,"WARNING: does not correspond to number of stack components entered as parameter (%d),\n",dz->iparam[STACK_CNT]);
- fprintf(stdout,"WARNING: Using %d as number of transpositions\n",dz->itemcnt);
- fflush(stdout);
- dz->iparam[STACK_CNT] = dz->itemcnt;
- }
- if((dz->parray[STACK_AMP] = (double *)malloc(dz->iparam[STACK_CNT] * sizeof(double)))==NULL) {
- sprintf(errstr,"Insufficient memory for storing stack amplitudes.\n");
- return(MEMORY_ERROR);
- }
- dz->param[STACK_MINTRANS] = HUGE;
- for(n=0;n<dz->iparam[STACK_CNT];n++)
- dz->param[STACK_MINTRANS] = min(dz->param[STACK_MINTRANS],dz->parray[STACK_TRANS][n]);
- dz->param[STACK_DUR] = (double)round(dz->param[STACK_DUR] * 10)/10.0;
- if(flteq(dz->param[STACK_DUR],1.0))
- dz->iparam[STACK_DUR] = 0;
- else if(flteq(dz->param[STACK_DUR],0.0)) {
- sprintf(errstr,"You have asked to make NONE of the output!!");
- return(USER_ERROR);
- } else {
- dz->param[STACK_DUR] /= dz->param[STACK_MINTRANS];
- dz->iparam[STACK_DUR] = round(dz->param[STACK_DUR] * (dz->insams[0]/dz->infile->channels)) * dz->infile->channels;
- }
- /* attack distance from start, in input, in grouped-samples */
- dz->iparam[STACK_OFFSET] = (long)round(dz->param[STACK_OFFSET] * dz->infile->srate);
- /* attack distance from start, in output of slowest transposition, in grouped-samples */
- if(dz->param[STACK_MINTRANS] < 1.0)
- dz->iparam[STACK_OFFSET] = (long)round(dz->iparam[STACK_OFFSET] * (1.0/dz->param[STACK_MINTRANS]));
- k = dz->iparam[STACK_CNT] - 1;
- if(flteq(dz->param[STACK_LEAN],1.0)) {
- for(n=0;n<dz->iparam[STACK_CNT];n++)
- dz->parray[STACK_AMP][n] = dz->param[STACK_GAIN]/dz->iparam[STACK_CNT];
- } else {
- dz->parray[STACK_AMP][0] = dz->param[STACK_LEAN];
- dz->parray[STACK_AMP][k] = 1.0;
- step = dz->parray[STACK_AMP][k] - dz->parray[STACK_AMP][0];
- step /= (double)k;
- for(n = 1; n < k; n++)
- dz->parray[STACK_AMP][n] = dz->parray[STACK_AMP][n-1] + step;
- sum = 0.0;
- for(n = 0; n < dz->iparam[STACK_CNT]; n++)
- sum += dz->parray[STACK_AMP][n];
- for(n = 0; n < dz->iparam[STACK_CNT]; n++) {
- dz->parray[STACK_AMP][n] /= sum;
- dz->parray[STACK_AMP][n] *= dz->param[STACK_GAIN];
- if(dz->vflag[STACK_SEE]) {
- fprintf(stdout,"INFO: stackitem[%d] level %lf\n",n,dz->parray[STACK_AMP][n]);
- }
- }
- if(dz->vflag[STACK_SEE])
- fflush(stdout);
- }
- return(FINISHED);
- }
- /********************** DO_STACK *************************/
- int do_stack(dataptr dz)
- {
- int exit_status;
- //TW ADDED FOR MULTICHANNEL WORK
- int qq;
- float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1];
- int chans = dz->infile->channels;
- int bufsamplen = dz->buflen/chans; /* buffer length in grouped-samples */
- int all_transpositions_active, n, nn, lastpos, *obufpos, max_obufpos;
- double *inbufpos, maxoutsamp;
- int *active_transpos;
- float *lastibufval;
- int *obufskip, *seeklen, *origseeklen, *offset, *eof_in_ibuf;
- if(dz->iparam[STACK_DUR] <= 0)
- dz->tempsize = (int)round(dz->insams[0] * (1.0/dz->param[STACK_MINTRANS]));
- else
- dz->tempsize = dz->iparam[STACK_DUR];
- if((inbufpos = (double *)malloc(dz->iparam[STACK_CNT] * sizeof(double)))==NULL) {
- sprintf(errstr,"Insufficient memory for storing input buffer pointers.\n");
- return(MEMORY_ERROR);
- }
- if((obufpos = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
- sprintf(errstr,"Insufficient memory for storing output buffer pointers.\n");
- return(MEMORY_ERROR);
- }
- if((active_transpos = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
- sprintf(errstr,"Insufficient memory for storing transposition flags.\n");
- return(MEMORY_ERROR);
- }
- if((obufskip = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
- sprintf(errstr,"Insufficient memory for storing seek values.\n");
- return(MEMORY_ERROR);
- }
- if((lastibufval = (float *)malloc(dz->iparam[STACK_CNT] * sizeof(float) * dz->infile->channels))==NULL) {
- sprintf(errstr,"Insufficient memory for storing last values in input bufs values.\n");
- return(MEMORY_ERROR);
- }
- if((seeklen = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
- sprintf(errstr,"Insufficient memory for storing seek values.\n");
- return(MEMORY_ERROR);
- }
- if((origseeklen = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
- sprintf(errstr,"Insufficient memory for storing original seek values.\n");
- return(MEMORY_ERROR);
- }
- if((offset = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
- sprintf(errstr,"Insufficient memory for storing offset values.\n");
- return(MEMORY_ERROR);
- }
- if((eof_in_ibuf = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
- sprintf(errstr,"Insufficient memory for storing end-of-file markers.\n");
- return(MEMORY_ERROR);
- }
- all_transpositions_active = 0;
- for(n=0;n<dz->iparam[STACK_CNT];n++) {
- all_transpositions_active |= (int) pow(2.0,n); /* set all bitflags for active buffers */
- seeklen[n] = origseeklen[n] = 0;
- inbufpos[n] = 0.0;
- obufskip[n] = get_obuf_sampoffset(n,dz);
- eof_in_ibuf[n] = dz->insams[0];
- lastibufval[n] = 0.0f;
- active_transpos[n] = 1;
- }
- if(chans > 1) {
- while(n < dz->iparam[STACK_CNT] * chans)
- lastibufval[n++] = 0.0f;
- }
- if(dz->vflag[1]) {
- /* GET MAX OUTPUT LEVEL, THEN ADJUST LATER */
- if(sloom) {
- fprintf(stdout,"INFO: Assessing Output Level.\n");
- fflush(stdout);
- }
- maxoutsamp = 0.0;
- do {
- memset((char *)obuf,0,dz->buflen * sizeof(float)); /* clear the output buffer */
- max_obufpos = 0; /* clear count of outsamps written */
- for(n=0;n<dz->iparam[STACK_CNT];n++) { /* For each transposition */
- if(!active_transpos[n]) /* if this transposition inactive, go to next transpos */
- continue;
- if(obufskip[n] >= dz->buflen) { /* if more samps to skip than space in obuf */
- obufskip[n] -= dz->buflen; /* decrement skip-value, ready for next outbuf, & go to next transpos */
- continue;
- } /* get the current seek position for this transposition */
- sndseekEx(dz->ifd[0],seeklen[n],0); /* go to current buffer in infile, for this transposition */
- obufpos[n] = obufskip[n]; /* set pointer to start in outputbuf for this write */
- /* THIS LOOP READS INPUT AND WRITES OUTPUT UNTIL outbuf FULL OR inbuf OR infile EXHAUSTED */
- do {
- memset((char *)ibuf,0,dz->buflen * sizeof(float)); /* clear the input buffer */
- if((exit_status = read_samps(ibuf,dz)) < 0) {
- sprintf(errstr,"Failed to read from input file.\n");
- return(PROGRAM_ERROR);
- }
- /* THIS LOOP WRITES OUTPUT UNTIL outbuf FULL OR inbuf OR infile EXHAUSTED */
- do {
- if((exit_status = transpos_and_add_to_obuf(n,&(obufpos[n]),&(inbufpos[n]),lastibufval,chans,dz)) < 0)
- return(exit_status);
- if(inbufpos[n] > (double)eof_in_ibuf[n]) {
- active_transpos[n] = 0; /* break at end of input FILE */
- break;
- }
- if (inbufpos[n] > bufsamplen - 1) { /* break at end of input BUFFER */
- inbufpos[n] -= (double)bufsamplen; /* move ibufpointer to buf start */
- lastpos = dz->buflen - chans; /* get last position in current buffer */
- // MODIFY FOR MULTICHANNEL WORK
- for(qq=0;qq<chans;qq++)
- lastibufval[n+(dz->iparam[STACK_CNT] * qq)] = ibuf[lastpos++];
- seeklen[n] += dz->buflen; /* set seek position for next read, in case */
- /* we (later) break out during a WRITE-end */
-
- if((eof_in_ibuf[n] -= dz->buflen) <= dz->buflen) /* if EOF is in the next buffer */
- eof_in_ibuf[n] /= chans; /* convert to a grouped-sample count */
- break; /* break from here and READ MORE INFILE */
- }
- } while(obufpos[n] < dz->buflen); /* break at end of OUTPUT BUFFER */
- } while(active_transpos[n] && (obufpos[n] < dz->buflen)); /* if inFILE or outBUF finished, break from loop */
- max_obufpos = max(max_obufpos,obufpos[n]);
- obufskip[n] = 0; /* written outbuf we skipped into, so NO skip next time */
- if(!active_transpos[n]) /* if FILE finished, reset flag for outer loop */
- all_transpositions_active &= ~((int) pow(2.0,n));
- }
- if(max_obufpos > 0) {
- if(dz->iparam[STACK_DUR] > 0) {
- if(dz->total_samps_written + max_obufpos >= dz->iparam[STACK_DUR]) {
- max_obufpos = dz->iparam[STACK_DUR] - dz->total_samps_written;
- all_transpositions_active = 0;
- }
- }
- for(nn = 0; nn < max_obufpos; nn++) {
- if(fabs(obuf[nn]) > maxoutsamp)
- maxoutsamp = fabs(obuf[nn]);
- }
- }
- } while(all_transpositions_active);
-
-
- if(flteq(maxoutsamp,0.0)) {
- sprintf(errstr,"NO SIGNIFICANT SIGNAL LEVEL GENERATED\n");
- return(DATA_ERROR);
- }
- for(n = 0; n < dz->iparam[STACK_CNT]; n++)
- dz->parray[STACK_AMP][n] *= (0.95/maxoutsamp);
- all_transpositions_active = 0;
- for(n=0;n<dz->iparam[STACK_CNT];n++) {
- all_transpositions_active |= (int)pow(2.0,n); /* set all bitflags for active buffers */
- seeklen[n] = origseeklen[n] = 0;
- inbufpos[n] = 0.0;
- obufskip[n] = get_obuf_sampoffset(n,dz);
- eof_in_ibuf[n] = dz->insams[0];
- lastibufval[n] = 0.0f;
- active_transpos[n] = 1;
- }
- if(chans > 1) {
- while(n < dz->iparam[STACK_CNT] * chans)
- lastibufval[n++] = 0.0f;
- }
- if(sloom) {
- fprintf(stdout,"INFO: Generating Output.\n");
- fflush(stdout);
- }
- }
-
- /* THIS LOOP REPEATS UNTIL ALL INPUT TRANSPOSITION PROCESSES ARE COMPLETED */
- do {
- memset((char *)obuf,0,dz->buflen * sizeof(float)); /* clear the output buffer */
- max_obufpos = 0; /* clear count of outsamps written */
- for(n=0;n<dz->iparam[STACK_CNT];n++) { /* For each transposition */
- if(!active_transpos[n]) /* if this transposition inactive, go to next transpos */
- continue;
- if(obufskip[n] >= dz->buflen) { /* if more samps to skip than space in obuf */
- obufskip[n] -= dz->buflen; /* decrement skip-value, ready for next outbuf, & go to next transpos */
- continue;
- } /* get the current seek position for this transposition */
- sndseekEx(dz->ifd[0],seeklen[n],0); /* go to current buffer in infile, for this transposition */
- obufpos[n] = obufskip[n]; /* set pointer to start in outputbuf for this write */
- /* THIS LOOP READS INPUT AND WRITES OUTPUT UNTIL outbuf FULL OR inbuf OR infile EXHAUSTED */
- do {
- memset((char *)ibuf,0,dz->buflen * sizeof(float)); /* clear the input buffer */
- if((exit_status = read_samps(ibuf,dz)) < 0) {
- sprintf(errstr,"Failed to read from input file.\n");
- return(PROGRAM_ERROR);
- }
- /* THIS LOOP WRITES OUTPUT UNTIL outbuf FULL OR inbuf OR infile EXHAUSTED */
- do {
- if((exit_status = transpos_and_add_to_obuf(n,&(obufpos[n]),&(inbufpos[n]),lastibufval,chans,dz)) < 0)
- return(exit_status);
- if(inbufpos[n] > (double)eof_in_ibuf[n]) {
- active_transpos[n] = 0; /* break at end of input FILE */
- break;
- }
- if (inbufpos[n] > bufsamplen - 1) { /* break at end of input BUFFER */
- inbufpos[n] -= (double)bufsamplen; /* move ibufpointer to buf start */
- lastpos = dz->buflen - chans; /* get last position in current buffer */
- // MODIFY FOR MULTICHANNEL WORK
- for(qq=0;qq<chans;qq++)
- lastibufval[n+(dz->iparam[STACK_CNT] * qq)] = ibuf[lastpos++];
- seeklen[n] += dz->buflen; /* set seek position for next read, in case */
- /* we (later) break out during a WRITE-end */
-
- if((eof_in_ibuf[n] -= dz->buflen) <= dz->buflen) /* if EOF is in the next buffer */
- eof_in_ibuf[n] /= chans; /* convert to a grouped-sample count */
- break; /* break from here and READ MORE INFILE */
- }
- } while(obufpos[n] < dz->buflen); /* break at end of OUTPUT BUFFER */
- } while(active_transpos[n] && (obufpos[n] < dz->buflen)); /* if inFILE or outBUF finished, break from loop */
- max_obufpos = max(max_obufpos,obufpos[n]);
- obufskip[n] = 0; /* written outbuf we skipped into, so NO skip next time */
- if(!active_transpos[n]) /* if FILE finished, reset flag for outer loop */
- all_transpositions_active &= ~((int)pow(2.0,n));
- }
- if(max_obufpos > 0) {
- if(dz->iparam[STACK_DUR] > 0) {
- if(dz->total_samps_written + max_obufpos >= dz->iparam[STACK_DUR]) {
- max_obufpos = dz->iparam[STACK_DUR] - dz->total_samps_written;
- all_transpositions_active = 0;
- }
- }
- if((exit_status = write_samps(obuf,max_obufpos,dz))<0)
- return(exit_status);
- }
- } while(all_transpositions_active);
- return(FINISHED);
- }
- /********************** GET_OBUF_SAMPOFFSET *************************/
- int get_obuf_sampoffset(int n,dataptr dz)
- {
- double speed_ratio_vs_slowest, offset_frac;
- int skip;
- speed_ratio_vs_slowest = dz->parray[STACK_TRANS][n]/dz->param[STACK_MINTRANS];
- if(flteq(speed_ratio_vs_slowest,1.0))
- return 0;
- offset_frac = 1.0 - (1.0/speed_ratio_vs_slowest);
- skip = (int)round(dz->iparam[STACK_OFFSET] * offset_frac);
- return (skip * dz->infile->channels);
- }
- /********************** TRANSPOS_AND_ADD_TO_OBUF *************************/
- //TW new version for multichannel work !!
- int transpos_and_add_to_obuf(int n,int *obufpos,double *inbufpos,float *lastival,int chans,dataptr dz)
- {
- float lastval, nextval, *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1];
- int i_bufpos, o_bufpos = *obufpos, i_bufpos_base = 0;
- int k;
- double step, val;
- if(*inbufpos < -1.0) {
- sprintf(errstr,"Impossible input buffer position encountered\n");
- return(PROGRAM_ERROR);
- }
- if(*inbufpos < 0.0) /* ibuf pointer points between lastval in last buffer and 1st in this buffer */
- step = 1.0 + (*inbufpos); /* interp position between these */
- else {
- step = fmod(*inbufpos,1.0);
- i_bufpos_base = (int)floor(*inbufpos) * chans;
- }
- for(k=0;k<chans;k++) {
- if(*inbufpos < 0.0) { /* ibuf pointer points between lastval in last buffer and 1st in this buffer */
- i_bufpos = k; /* point to channel at start of this buffer */
- lastval = lastival[n + (k * dz->iparam[STACK_CNT])]; /* get channel-val from end of last bufer */
- nextval = ibuf[i_bufpos];
- } else {
- i_bufpos = i_bufpos_base + k;
- lastval = ibuf[i_bufpos];
- nextval = ibuf[i_bufpos+chans];
- } /* add interpd val to val already in outbuf */
- val = lastval + ((nextval - lastval) * step);
- val *= dz->parray[STACK_AMP][n]; /* scaling by amplitude scalers */
- obuf[o_bufpos] = (float)(obuf[o_bufpos] + val);
- o_bufpos++;
- }
- *obufpos = o_bufpos; /* advance normally in outbuf */
- *inbufpos += dz->parray[STACK_TRANS][n]; /* advance ibuf-pointer by transpos value */
- return(FINISHED);
- }
|