| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- /*
- * 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 <limits.h>
- #include <structures.h>
- #include <tkglobals.h>
- #include <globcon.h>
- #include <filetype.h>
- #include <modeno.h>
- #include <mix.h>
- #include <sfsys.h>
- //#ifdef unix
- #define round(x) lround((x))
- //#endif
- static int do_refill_acts(dataptr dz);
- static void sort_actions(dataptr dz);
- static int init_inbufs(dataptr dz);
- static int gen_mcr_table(dataptr dz);
- /************************** MIX_PREPROCESS ******************/
- int mix_preprocess(dataptr dz)
- {
- int exit_status;
- if((exit_status = do_refill_acts(dz))<0)
- return(exit_status);
- sort_actions(dz);
- if(dz->iparam[MIX_STRTPOS] > 0) /* Allow for mix not starting at zero time */
- dz->iparam[MIX_STRTPOS_IN_ACTION] = (int)max(dz->iparam[MIX_STRTPOS] - dz->act[0]->position,0L);
- /* NEW 2000 */
- /* RWD now in samps */
- dz->tempsize = (dz->act[dz->iparam[MIX_TOTAL_ACTCNT]-1]->position - dz->iparam[MIX_STRTPOS_IN_ACTION]);
- /* NEW 2000 */
- return init_inbufs(dz);
- }
- /*************************** DO_REFILL_ACTS **************************/
- int do_refill_acts(dataptr dz)
- {
- int n;
- int samps_used, actcnt = dz->iparam[MIX_TOTAL_ACTCNT];
- int arraysize = actcnt + BIGARRAY; /* Generate more space for further actions. */
- if((dz->act=(actptr *)realloc(dz->act,arraysize * sizeof(actptr)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to construct buffer-fill action pointers.\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->iparam[MIX_TOTAL_ACTCNT];n+=2) { /* actions paired as ON/OFF, so we look only at ON bufs */
- if(dz->act[n]->val->samplen > dz->buflen) { /* If more data in (action's) file than fits in 1 buffer */
- samps_used = 0;
- while((samps_used += dz->buflen) < dz->act[n]->val->samplen) {
- if((dz->act[actcnt] = (actptr)malloc(sizeof(struct action)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to construct buffer-fill actions.\n");
- return(MEMORY_ERROR);
- }
- dz->act[actcnt]->val = dz->act[n]->val; /* Create a new action, using same vals as the original */
- dz->act[actcnt]->position = dz->act[n]->position + samps_used;/* Positioned 1 further buflen later, and */
- dz->act[actcnt]->role = MIX_ACTION_REFILL; /* with role REFILL */
- if(++actcnt >= arraysize) {
- arraysize += BIGARRAY;
- if((dz->act=(actptr *)realloc(dz->act,arraysize * sizeof(actptr)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to reallocate buffer-fill action pointers.\n");
- return(MEMORY_ERROR);
- }
- }
- }
- }
- }
- if((dz->act=(actptr *)realloc(dz->act,actcnt * sizeof(actptr)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to reallocate buffer-fill actions.\n");
- return(MEMORY_ERROR);
- }
- dz->iparam[MIX_TOTAL_ACTCNT] = (int)actcnt;
- return(FINISHED);
- }
- /************************* SORT_ACTIONS ****************************/
- void sort_actions(dataptr dz)
- {
- actptr temp;
- int n, m;
- for(n=0;n<dz->iparam[MIX_TOTAL_ACTCNT]-1;n++) {
- for(m=n+1;m<dz->iparam[MIX_TOTAL_ACTCNT];m++) {
- if(dz->act[m]->position < dz->act[n]->position) {
- temp = dz->act[n];
- dz->act[n] = dz->act[m];
- dz->act[m] = temp;
- }
- }
- }
- }
- /****************************** INIT_INBUFS *********************************
- *
- * (1) Create the space for buffers within each bufitem. NB enough space
- * for ALL these buffers must be allocated in the initial creation
- * of 'inbuf' in create_buffers.
- * (2) Create the pointers to point to start and current_position in ACTIVE bufs.
- */
- int init_inbufs(dataptr dz)
- {
- int n;
- float *thisbuf = dz->sampbuf[IBUFMIX];
- dz->buflist = (mixbufptr *)malloc(dz->bufcnt * sizeof(mixbufptr));
- for(n=0;n<dz->bufcnt;n++) {
- dz->buflist[n] = NULL;
- if((dz->buflist[n] = (mixbufptr)malloc(sizeof(struct bufitem)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for buffer list.\n");
- return(MEMORY_ERROR);
- }
- dz->buflist[n]->status = MIX_ACTION_OFF;
- dz->buflist[n]->buf = thisbuf;
- dz->buflist[n]->here = dz->buflist[n]->buf;
- thisbuf += dz->buflen;
- }
- if((dz->activebuf = (int *)malloc(dz->bufcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for active buffer list.\n");
- return(MEMORY_ERROR);
- }
- if((dz->activebuf_ptr = (float **)malloc(dz->bufcnt * sizeof(float *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for active buffer pointer list.\n");
- return(MEMORY_ERROR);
- }
- return(FINISHED);
- }
- /****************************** MIXTWO_PREPROCESS ************************************/
- int mixtwo_preprocess(dataptr dz)
- {
- int shsecsize = F_SECSIZE * dz->infile->channels;
- double k;
- dz->iparam[MIX_STAGGER] = round(dz->param[MIX_STAGGER] * (double)dz->infile->srate) * dz->infile->channels;
- dz->iparam[MIX_STAGGER] = (dz->iparam[MIX_STAGGER]/shsecsize) * shsecsize;
- dz->iparam[MIX_STAGGER] = min(dz->iparam[MIX_STAGGER],dz->insams[0] - dz->infile->channels);
- dz->iparam[MIX_SKIP] = round(dz->param[MIX_SKIP] * (double)dz->infile->srate) * dz->infile->channels;
- dz->iparam[MIX_SKIP] = (dz->iparam[MIX_SKIP]/shsecsize) * shsecsize;
- dz->iparam[MIX_SKIP] = min(dz->iparam[MIX_SKIP],dz->insams[1] - dz->infile->channels);
-
- if(((k = (dz->param[MIX_STTA] * (double)dz->infile->srate)) * (double)dz->infile->channels) >= (double)LONG_MAX)
- dz->iparam[MIX_STTA] = INT_MAX;
- else
- dz->iparam[MIX_STTA] = round(dz->param[MIX_STTA] * (double)dz->infile->srate) * dz->infile->channels;
- dz->iparam[MIX_STTA] = (dz->iparam[MIX_STTA]/shsecsize) * shsecsize;
- dz->param[MIX2_GAIN1] = dz->param[MIX_SKEW]/(dz->param[MIX_SKEW] + 1.0);
- dz->param[MIX2_GAIN2] = 1.0 - dz->param[MIX2_GAIN1];
- if(((k = (dz->param[MIX_DURA] * (double)dz->infile->srate)) * (double)dz->infile->channels) >= (double)LONG_MAX)
- dz->iparam[MIX_DURA] = dz->insams[0] + dz->insams[1];
- else
- dz->iparam[MIX_DURA] = round(k) * dz->infile->channels;
- if(dz->iparam[MIX_DURA] <= dz->iparam[MIX_STAGGER]) {
- sprintf(errstr,"Mix cuts off before 2nd file enters\n");
- return(DATA_ERROR);
- }
- if(dz->iparam[MIX_STTA] >= dz->insams[0]) {
- sprintf(errstr,"Mix does not start until first file has ended.\n");
- return(DATA_ERROR);
- }
- if(dz->iparam[MIX_DURA] <= dz->iparam[MIX_STTA]) {
- sprintf(errstr,"Mix end is before mix start.\n");
- return(DATA_ERROR);
- }
- /* RWD all now in samps */
- dz->tempsize = max((dz->insams[1]-dz->iparam[MIX_SKIP]+dz->iparam[MIX_STAGGER]),dz->insams[0]);
- dz->tempsize = min(dz->tempsize,dz->iparam[MIX_DURA]);
- dz->tempsize -= (dz->iparam[MIX_STTA]);
- return(FINISHED);
- }
- /********************** MIXCROSS_PREPROCESS **********************/
- int mixcross_preprocess(dataptr dz)
- {
- int exit_status;
- int crosfact, maxend;
- /* CONVERT TO SAMPLES */
- dz->iparam[MCR_BEGIN] = round(dz->param[MCR_BEGIN] * dz->infile->srate) * dz->infile->channels;
-
- /* CONVERT TO SAMPLES AND APPROXIMATE TO SECTOR BOUNDARY */
- dz->iparam[MCR_STAGGER] = round(dz->param[MCR_STAGGER] * dz->infile->srate) * dz->infile->channels;
- //TW SAFE ??
- //#ifdef NOTDEF
- // dz->iparam[MCR_STAGGER] = (dz->iparam[MCR_STAGGER]/SECSIZE) * SECSIZE;
- //#endif
- maxend = min(dz->insams[0],dz->iparam[MCR_STAGGER] + dz->insams[1]);
- if(dz->param[MCR_END] > 0.0) { /* i.e. HAS BEEN SET */
- dz->iparam[MCR_END] = round(dz->param[MCR_END] * dz->infile->srate) * dz->infile->channels;
- dz->iparam[MCR_END] = min(dz->iparam[MCR_END],maxend); /* END may be curtailed by stagger's rounding */
- } else
- dz->iparam[MCR_END] = maxend;
- /* TEST CROSSFADE PARAMS FOR CONSISTENCY */
- if(dz->iparam[MCR_BEGIN] < dz->iparam[MCR_STAGGER]) {
- sprintf(errstr,"Crossfade begins before end of stagger: Impossible.\n");
- return(USER_ERROR);
- }
- if(dz->iparam[MCR_BEGIN] >= dz->iparam[MCR_STAGGER] + dz->insams[1]) {
- sprintf(errstr,"Crossfade begins after end of 2nd file: Impossible.\n");
- return(USER_ERROR);
- }
- if((crosfact = dz->iparam[MCR_END] - dz->iparam[MCR_BEGIN])<=0) {
- sprintf(errstr,"Crossfade length is zero or negative: Impossible.\n");
- return(USER_ERROR);
- }
- /* SET UP LENGTH OF CROSSFADE, AND THE DIVIDE FACTOR FOR INDEXING THIS */
- dz->param[MCR_CROSFACT] = 1.0/(double)crosfact;
- /* SET CONTOUR TYPE */
- if(dz->mode==MCLIN)
- dz->iparam[MCR_CONTOUR] = MCR_LINEAR;
- else if(flteq(dz->param[MCR_POWFAC],1.0))
- dz->iparam[MCR_CONTOUR] = MCR_COSIN;
- else
- dz->iparam[MCR_CONTOUR] = MCR_SKEWED;
- /* FOR COSIN CONTOUR TYPE : MAKE COSTABLE */
- if(dz->iparam[MCR_CONTOUR]==MCR_SKEWED || dz->iparam[MCR_CONTOUR]==MCR_COSIN) {
- if((exit_status = gen_mcr_table(dz))<0)
- return(exit_status);
- }
- /* SET CROSS-FADE INDEX OT ZERO */
- dz->iparam[MCR_INDEX] = 0;
- return(FINISHED);
- }
- /*** GONE TO TK *********************** GEN_MCR_TABLE **********************/
- int gen_mcr_table(dataptr dz)
- {
- int n;
- double *costable;
- if((dz->parray[MCR_COSTABLE] = (double *)malloc((MCR_TABLEN+1)* sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for cosine table.\n");
- return(MEMORY_ERROR);
- }
- costable = dz->parray[MCR_COSTABLE];
- for(n=0;n<MCR_TABLEN;n++) {
- costable[n] = ((double)n/(double)(MCR_TABLEN)) * PI;
- costable[n] = cos(costable[n]);
- costable[n] += 1.0;
- costable[n] /= 2.0;
- costable[n] = 1.0 - costable[n];
- costable[n] = max(0.0,costable[n]);
- costable[n] = min(costable[n],1.0);
- }
- costable[n] = 1.0;
- return(FINISHED);
- }
- /******************************** GET_INBETWEEN_RATIOS ***************************/
- int get_inbetween_ratios(dataptr dz)
- {
- double *p, scaler;
- int n;
- switch(dz->mode) {
- case(INBI_RATIO): /* now read as special data */
- break;
- case(INBI_COUNT): /* GENERATE RATIOS AUTOMATICALLY IN A NEWLY MALLOCD brkpnt TABLE */
- dz->iparam[INBETW] = round(dz->param[INBETW]);
- if((dz->brk[INBETW] = (double *)malloc(dz->iparam[INBETW] * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for inbetween values store.\n");
- return(MEMORY_ERROR);
- }
- dz->no_brk[INBETW] = FALSE;
- p = dz->brk[INBETW];
- scaler = 1.0/(double)(dz->iparam[INBETW]+1);
- for(n=1;n<=dz->iparam[INBETW];n++)
- *p++ = (double)n * scaler;
- break;
- default:
- sprintf(errstr,"Unknown mode in get_inbetween_ratios()\n");
- return(PROGRAM_ERROR);
- }
- return(FINISHED);
- }
- /************** CHECK_NEW_FILENAME ***********/
- int check_new_filename(char *filename,dataptr dz)
- {
- int exit_status;
- double maxamp, maxloc;
- int maxrep;
- int getmax = 0, getmaxinfo = 0;
- infileptr ifp;
- if((ifp = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to store data on files.\n");
- return(MEMORY_ERROR);
- }
- if(dz->mode!=MSH_DUPL_AND_RENAME || dz->vflag[MSH_NOCHECK])
- return(FINISHED);
- if(dz->infile->srate==0) {
- sprintf(errstr,"srate not set: check_new_filename()\n");
- return(PROGRAM_ERROR);
- }
- if(dz->ifd!=NULL) /* set up by default in main() */
- free(dz->ifd);
- if((exit_status = establish_file_data_storage_for_mix((int)1,dz))<0)
- return(exit_status);
- if((dz->ifd[0] = sndopenEx(filename,0,CDP_OPEN_RDONLY)) < 0) {
- sprintf(errstr,"Failed to open sndfile %s: check_new_filename()\n",filename);
- return(DATA_ERROR);
- }
- if((exit_status = readhead(ifp,dz->ifd[0],filename,&maxamp,&maxloc,&maxrep,getmax,getmaxinfo))<0)
- return(exit_status);
- copy_to_fileptr(ifp,dz->otherfile);
- if(dz->otherfile->filetype!=SNDFILE) {
- sprintf(errstr,"%s is not a soundfile: check_new_filename()\n",filename);
- return(DATA_ERROR);
- }
- if(dz->otherfile->srate != dz->infile->srate) {
- sprintf(errstr,"Incompatible srate: check_new_filename()\n");
- return(DATA_ERROR);
- }
- return(FINISHED);
- }
|