| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- /*
- * 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 <string.h>
- #include <structures.h>
- #include <tkglobals.h>
- #include <globcon.h>
- #include <processno.h>
- #include <modeno.h>
- #include <arrays.h>
- #include <filetype.h>
- #include <envel.h>
- #include <cdpmain.h>
- #include <sfsys.h>
- #include <osbind.h>
- //#ifdef unix
- #define round(x) lround((x))
- //#endif
- static int do_wrap(int samps_to_wrap,dataptr dz);
- static int read_rest_of_file(int initial_bufsize,dataptr dz);
- static int pluck(dataptr dz);
- static int envsyn_env(int *phase,int cyclestart,int *cycle_end,double one_less_trof,dataptr dz);
- static int envsyn_troffed(int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz);
- static int envsyn_userdef(int cyclestart,int *cyclend,int *phase,dataptr dz);
- static int envsyn_rising( int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz);
- static int envsyn_falling(int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz);
- static double do_firsthalf_trof(int k,int cyclehlf,double one_less_trof,dataptr dz);
- static double do_lasthalf_trof(int k,int cyclehlf,double one_less_trof,dataptr dz);
- static double do_rising(int k,int cyclelen,double one_less_trof,dataptr dz);
- static double do_falling(int k,int cyclelen,double one_less_trof,dataptr dz);
- static int read_from_user_envelope(double *env_val,double table_index,int init,dataptr dz);
- /****************************** ENVELOPE_PLUCK *************************/
- int envelope_pluck(dataptr dz)
- {
-
- int exit_status;
- int initial_bufsize;
- int first_read_offset = dz->sampbuf[PLK_INITBUF] - dz->bigbuf;
- dz->buflen -= first_read_offset; /* size of buffer from where first read takes place */
- if((exit_status = read_samps(dz->sampbuf[PLK_INITBUF],dz))<0)
- return(exit_status);
- initial_bufsize = dz->buflen;
- if((exit_status = pluck(dz))<0)
- return(exit_status);
- dz->buflen = dz->iparam[ENV_PLK_OBUFLEN]; /* size of buffer for subsequent reads */
- return read_rest_of_file(initial_bufsize,dz);
- }
- /**************************** PLUCK ******************************
- *
- * (1) goalbufend is the last sample of the cycle in the input file buffer from which we will
- * derive the pluck attack. We read it backwards, from this LAST sample.
- * (2) The outplukptr points to the position in the output buffer where we
- * are WRITING pluck-form wavecycles. We write these BKWDS
- * from here to start of dz->sampbuf[PLK_OUTBUF].
- * (3) Set goalbufptr to start(i.e. end!!) of goalbuf.
- * (4) Inverse_index is a BACKWARDS count of the samples in the pluck.
- * (5) For each wavecycle of Pluck attack..
- * (6) For each sample in wavecycle....
- * (7) Noiselevel is directly proportional to distance (bkwds) into pluck.
- * (8) Then reduced via exponential curve.
- * (9) Becoming this fraction of the maximum amplitude.
- * (10) Noise input itself is a random value in range +- this noiselevel value.
- * (11) Reinitialise goalbufptr for eack wavecycle.
- * (13a)By the time we reach the start of the pluck, signal will cause#
- * spurious foldover when added to orig signal: but this will simply make
- * it more like noise!!
- * (12) Calculate sample length of initial risetime.
- * (13) Finally, envelope start of pluck!!
- */
- int pluck(dataptr dz)
- {
- int n, m, inverse_index;
- float *goalbufend, *goalbufptr, *outplukptr;
- double noise_level;
- /*int*/double thisnoise;
- int startup;
- int pluklen = dz->iparam[ENV_PLK_CYCLEN] * dz->iparam[ENV_PLK_WAVELEN];
- if((goalbufend = dz->sampbuf[PLK_PLUKEND] + dz->iparam[ENV_PLK_WAVELEN] - 1) >=dz->sampbuf[PLK_BUFEND]) {
- sprintf(errstr,"End of goal pluck_cycle falls outside buffer: Insufficient memory to proceed.\n");
- return(GOAL_FAILED); /* 1 */
- }
- if((outplukptr = dz->sampbuf[PLK_PLUKEND] - 1) < dz->bigbuf) { /* 2 */
- sprintf(errstr,"Buffer accounting problem.\n");
- return(PROGRAM_ERROR);
- }
- goalbufptr = goalbufend; /* 3 */
- inverse_index = 0; /* 4 */
- for(n=0;n<dz->iparam[ENV_PLK_CYCLEN];n++) { /* 5 */
- for(m=0;m<dz->iparam[ENV_PLK_WAVELEN];m++) { /* 6 */
- noise_level = (double)inverse_index/(double)pluklen; /* 7 */
- noise_level = pow(noise_level,dz->param[ENV_PLK_DECAY]); /* 8 */
- noise_level = noise_level * (double)F_MAXSAMP; /* 9 */
- thisnoise = /*round*/ (((drand48() * 2.0) - 1.0) * noise_level); /* 10 */
- *outplukptr = (float)((*goalbufptr) + thisnoise);
- outplukptr--;
- goalbufptr--;
- inverse_index++;
- }
- goalbufptr = goalbufend; /* 11 */
- }
- startup = round(ENV_PLK_ONSET_TIME * MS_TO_SECS * (double)dz->infile->srate); /* 12 */
- startup = min(startup,dz->iparam[ENV_PLK_CYCLEN] * dz->iparam[ENV_PLK_WAVELEN]);
- for(n=0;n<startup;n++) {
- outplukptr++; /* 13 */
- *outplukptr = (float) /*round */(*outplukptr * (double)n/(double)startup);
- }
- return(FINISHED);
- }
- /*********************** READ_REST_OF_FILE ************************
- *
- * (1) If the input buffer was NOT filled, then we must be at end of file: so write data and return.
- * (2) Samples to write is those read,
- * MINUS the length of initial replaced segment (dz->iparam[ENV_PLK-STSAMP])
- * PLUS the added initial segment (dz->iparam[ENV_PLK_OWRAPLEN]).
- * ELSE
- * (3) Write a standard buffer_full, from start of obuf_preflow (where pluck has been constructed).
- * (4) This leaves, [ENV_PLK_OWRAPLEN] samples in end of dz->sampbuf[PLK_OUTBUF],
- * SO samps_to_wrap = [ENV_PLK_OWRAPLEN];
- * (6) Do the wrap-around.
- * (8) Whilst ever there is something in wrap-around part of buffer...
- * (10) Try to read more samples (may get full-buff, part-buf
- * or zero if file already exhausted).
- * (11) Total samps to write is the wrapped samps plus those just read.
- * (12) If this leaves no samps to wrap (i.e. buffer is NOT full, therefore FILE must be exhausted),
- * write all these samps to out and quit.
- * (13) ELSE, write a bufferfull and do another wrap-around.
- */
- int read_rest_of_file(int initial_bufsize,dataptr dz)
- {
- int exit_status;
- int samps_to_write, samps_to_wrap;
- int pluklen = dz->iparam[ENV_PLK_CYCLEN] * dz->iparam[ENV_PLK_WAVELEN];
- if(dz->ssampsread < (int)(initial_bufsize)) { /* 1 */
- if((samps_to_write = dz->ssampsread - dz->iparam[ENV_PLK_ENDSAMP] + pluklen)>0) { /* 2 */
- if((exit_status = write_samps(dz->sampbuf[PLK_OUTBUF],samps_to_write,dz))<0)
- return(exit_status);
- }
- } else {
- if((exit_status = write_samps(dz->sampbuf[PLK_OUTBUF],dz->buflen,dz))<0) /* 3 */
- return(exit_status);
- samps_to_wrap = dz->iparam[ENV_PLK_OWRAPLEN]; /* 4 */
- if((exit_status = do_wrap(samps_to_wrap,dz))<0) /* 6 */
- return(exit_status);
- while(samps_to_wrap > 0) { /* 8 */
- if((exit_status = read_samps(dz->sampbuf[PLK_INBUF],dz))<0) /* 10 */
- return(exit_status);
- samps_to_write = samps_to_wrap + dz->ssampsread; /* 11 */
- if((samps_to_wrap = samps_to_write - dz->buflen) <= 0) { /* 12 */
- if(samps_to_write > 0) {
- if((exit_status = write_samps(dz->sampbuf[PLK_OUTBUF],samps_to_write,dz))<0)
- return(exit_status);
- }
- } else {
- if((exit_status = write_samps(dz->sampbuf[PLK_OUTBUF],dz->buflen,dz))<0) /* 13 */
- return(exit_status);
- if((exit_status = do_wrap(samps_to_wrap,dz))<0)
- return(exit_status);
- }
- }
- }
- return(FINISHED);
- }
- /*********************** DO_WRAP ************************/
- int do_wrap(int samps_to_wrap,dataptr dz)
- {
- memmove((char *)dz->sampbuf[PLK_OUTBUF],(char *)dz->sampbuf[PLK_OBUFWRAP],(samps_to_wrap)*sizeof(float));
- return(FINISHED);
- }
- /************************** ENVSYN **************************/
- int envsyn(dataptr dz)
- {
- int exit_status;
- int current_pos = 0, cyclelen, cycle_end, done = 0;
- int phase, initial_phase;
- double thistime = 0.0, one_less_trof;
- int samps_needed;
- dz->param[ENVSYN_WSIZE] *= MS_TO_SECS;
- samps_needed = (int)floor((dz->param[ENVSYN_DUR]/ dz->param[ENVSYN_WSIZE]) + 1);
- dz->tempsize = samps_needed * sizeof(float);
- if((exit_status = read_values_from_all_existing_brktables(thistime,dz)) < 0)
- return(exit_status);
- one_less_trof = 1.0 - dz->param[ENVSYN_TROF];
- cyclelen = (int)round(dz->param[ENVSYN_CYCLEN]/dz->param[ENVSYN_WSIZE]);
- cycle_end = cyclelen;
- phase = (int)round((double)cyclelen * dz->param[ENVSYN_STARTPHASE]);
- initial_phase = phase;
- for (;;) {
- if(cyclelen < 2) {
- sprintf(errstr,"ENVELOPE DURATION TOO SHORT FOR WINDOWSIZE at time %lf\n",
- (dz->total_samps_written + current_pos) * dz->param[ENV_WSIZE]);
- return(DATA_ERROR);
- }
- if((exit_status = envsyn_env(&phase,current_pos,&cycle_end,one_less_trof,dz))< 0)
- return(exit_status);
- if((done += cyclelen) >= samps_needed + initial_phase)
- break;
- thistime += dz->param[ENVSYN_CYCLEN];
- if((exit_status = read_values_from_all_existing_brktables(thistime,dz)) < 0)
- return(exit_status);
- one_less_trof = 1.0 - dz->param[ENVSYN_TROF];
- cyclelen = (int)round(dz->param[ENVSYN_CYCLEN]/dz->param[ENVSYN_WSIZE]);
- current_pos = cycle_end;
- cycle_end = current_pos + cyclelen;
- }
- if(cycle_end > 0) {
- if((exit_status = write_samps(dz->flbufptr[0],cycle_end,dz))<0)
- return(exit_status);
- }
- return(FINISHED);
- }
- /************************** ENVSYN_ENV **************************/
- int envsyn_env(int *phase,int cyclestart,int *cycle_end,double one_less_trof,dataptr dz)
- {
- switch(dz->mode) {
- case(ENVSYN_TROFFED): return envsyn_troffed(cyclestart,cycle_end,one_less_trof,phase,dz);
- case(ENVSYN_USERDEF): return envsyn_userdef(cyclestart,cycle_end,phase,dz);
- case(ENVSYN_RISING): return envsyn_rising(cyclestart,cycle_end,one_less_trof,phase,dz);
- case(ENVSYN_FALLING): return envsyn_falling(cyclestart,cycle_end,one_less_trof,phase,dz);
- default:
- sprintf(errstr,"Unknown case: envsyn_env()\n");
- return(PROGRAM_ERROR);
- }
- return(CONTINUE);
- }
- /************************** ENVSYN_TROFFED *******************************/
- int envsyn_troffed(int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz)
- {
- int exit_status;
- register int k = 0, j = cyclestart;
- int cyclelen = *cyclend - cyclestart;
- int cyclehlf = cyclelen/2;
- int cyclemid = cyclestart + cyclehlf;
- float *b = dz->flbufptr[0];
- if(*phase > 0) {
- if(*phase >= cyclehlf) {
- cyclemid = -1;
- k = (*phase - cyclehlf);
- } else {
- cyclemid -= *phase;
- k = *phase;
- }
- (*cyclend) -= *phase;
- *phase = 0;
- }
- while(j<cyclemid) {
- b[j] = (float)do_firsthalf_trof(k,cyclehlf,one_less_trof,dz);
- k++;
- j++;
- if(j >= dz->buflen) {
- if((exit_status = write_samps(b,dz->buflen,dz))<0)
- return(exit_status);
- j = 0;
- *cyclend -= dz->buflen;
- }
- }
- if(cyclemid >= 0)
- k = 0;
- cyclehlf = cyclelen - cyclehlf;
- while(j < *cyclend) {
- b[j] = (float)do_lasthalf_trof(k,cyclehlf,one_less_trof,dz);
- k++;
- j++;
- if(j >= dz->buflen) {
- if((exit_status = write_samps(b,dz->buflen,dz))<0)
- return(exit_status);
- j = 0;
- *cyclend -= dz->buflen;
- }
- }
- return(FINISHED);
- }
- /*************************** ENVSYN_USERDEF ***************************/
- int envsyn_userdef(int cyclestart,int *cyclend,int *phase,dataptr dz)
- {
- int exit_status;
- register int k = 0, j = cyclestart;
- int cyclelen = *cyclend - cyclestart;
- double index;
- double z;
- int init = 1;
- float *b = dz->flbufptr[0];
- if(*phase > 0) {
- k = *phase;
- (*cyclend) -= *phase;
- *phase = 0;
- }
- while(j<*cyclend) {
- index = (double)k/(double)cyclelen;
- if((exit_status = read_from_user_envelope(&z,index,init,dz))<0)
- return(exit_status);
- b[j] = (float)z;
- k++;
- j++;
- if(j >= dz->buflen) {
- if((exit_status = write_samps(b,dz->buflen,dz))<0)
- return(exit_status);
- j = 0;
- *cyclend -= dz->buflen;
- }
- init = 0;
- }
- return(FINISHED);
- }
- /*************************** ENVSYN_RISING ***********************/
- int envsyn_rising(int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz)
- {
- int exit_status;
- register int k = 0, j = cyclestart;
- int cyclelen = *cyclend - cyclestart;
- float *b = dz->flbufptr[0];
-
- if(*phase > 0) {
- k = *phase;
- (*cyclend) -= *phase;
- *phase = 0;
- }
- while(j<*cyclend) {
- b[j] = (float)do_rising(k,cyclelen - 1,one_less_trof,dz);
- k++;
- j++;
- if(j >= dz->buflen) {
- if((exit_status = write_samps(b,dz->buflen,dz))<0)
- return(exit_status);
- j = 0;
- *cyclend -= dz->buflen;
- }
- }
- return(FINISHED);
- }
- /********************** ENVSYN_FALLING *************************/
- int envsyn_falling(int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz)
- {
- int exit_status;
- register int k = 0, j = cyclestart;
- int cyclelen = *cyclend - cyclestart;
- float *b = dz->flbufptr[0];
- if(*phase > 0) {
- k = *phase;
- (*cyclend) -= *phase;
- *phase = 0;
- }
- while(j<*cyclend) {
- b[j] = (float)do_falling(k,cyclelen - 1,one_less_trof,dz);
- k++;
- j++;
- if(j >= dz->buflen) {
- if((exit_status = write_samps(b,dz->buflen,dz))<0)
- return(exit_status);
- j = 0;
- *cyclend -= dz->buflen;
- }
- }
- return(FINISHED);
- }
- /******************* DO_FIRSTHALF_TROF **************************/
- double do_firsthalf_trof(int k,int cyclehlf,double one_less_trof,dataptr dz)
- {
- double z = 1.0 - ((double)k/(double)cyclehlf);
- z = (pow(z,dz->param[ENVSYN_EXPON]) * one_less_trof) + dz->param[ENVSYN_TROF];
- return (z);
- }
- /******************* DO_LASTHALF_TROF **************************/
- double do_lasthalf_trof(int k,int cyclehlf,double one_less_trof,dataptr dz)
- {
- double z = (double)k/(double)cyclehlf;
- z = (pow(z,dz->param[ENVSYN_EXPON]) * one_less_trof) + dz->param[ENVSYN_TROF];
- return(z);
- }
- /************************ DO_RISING_TROFFED *******************************/
- double do_rising(int k,int cyclelen,double one_less_trof,dataptr dz)
- {
- double z = (double)k/(double)cyclelen;
- z = pow(z,dz->param[ENVSYN_EXPON]);
- z *= one_less_trof;
- z += dz->param[ENVSYN_TROF];
- return(z);
- }
- /************************ DO_FALLING_TROFFED *******************************/
- double do_falling(int k,int cyclelen,double one_less_trof,dataptr dz)
- {
- double z;
- z = 1.0 - ((double)k/(double)cyclelen);
- z = (pow(z,dz->param[ENVSYN_EXPON]) * one_less_trof) + dz->param[ENVSYN_TROF];
- return z;
- }
- /************************ READ_FROM_USER_ENVELOPE *******************************/
- int read_from_user_envelope(double *env_val,double table_index,int init,dataptr dz)
- {
- double *p;
- double hi_env, lo_env, hi_index, lo_index;
- double env;
- if(init)
- dz->ptr[ENVSYN_ENV] = dz->parray[ENVSYN_ENV];
- p = dz->ptr[ENVSYN_ENV];
- while(table_index > *p) {
- if((p += 2) >= dz->ptr[ENVSYN_ENVEND]) {
- sprintf(errstr,"Problem reading user envelope data: read_from_user_envelope()\n");
- return(PROGRAM_ERROR);
- }
- }
- if(p != dz->parray[ENVSYN_ENV]) {
- hi_env = *(p+1);
- hi_index = *p;
- lo_env = *(p-1);
- lo_index = *(p-2);
- env = (double)((table_index - lo_index)/(hi_index - lo_index));
- env *= (double)(hi_env - lo_env);
- env += (double)lo_env;
- } else
- env = *(p+1);
- dz->ptr[ENVSYN_ENV] = p;
- *env_val = env;
- return(FINISHED);
- }
|