| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043 |
- /*
- * 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 <filetype.h>
- #include <arrays.h>
- #include <mix.h>
- #include <cdpmain.h>
- #include <sfsys.h>
- #include <mix.h>
- #include <limits.h>
- #ifdef unix
- #define round(x) lround((x))
- #endif
- static int do_mix2(float *inbuf1,float *inbuf2,double *dblbuf,float *obuf,dataptr dz);
- static int do_mix2_stagger(float *inbuf1,float *obuf,dataptr dz);
- static int do_mix2_skip(dataptr dz);
- static int cross_stagger(int *total_samps_read,int *end_of_samps_to_process,float *obuf,dataptr dz);
- static int pre_crossmix(int *samps_read2,int *cross_end,int *total_samps_read,
- int *end_of_samps_to_process,float *inbuf1,float *inbuf2,float *obuf,dataptr dz);
- static int crossmix(int *samps_read2,int *cross_end,int *total_samps_read,int *end_of_samps_to_process,
- float *inbuf1,float *inbuf2,float *obuf,dataptr dz);
- static int cross(int startcross,int endcross,float *inbuf1,float *inbuf2,float *obuf,dataptr dz);
- static double read_cos(double d,dataptr dz);
- static int advance_in_files(int *samps_read2,int *total_samps_read,int *end_of_samps_to_process,
- int *cross_end,float *inbuf1,float *inbuf2,dataptr dz);
- static void copy_to_channel(float *inbuf,float *obuf,int sampcnt,int outchans);
- static int renew_bufs(int typ,float *buf0,float *buf1,dataptr dz);
- static int do_stitch(int typ,int *mbf,int *sbf,float *buf0,float *buf1,double atten,int bflen,dataptr dz);
- static int flush_bufs(int typ,int *mbf,int *sbf,float *buf0,float *buf1,dataptr dz);
- //TW JAN 2010: FOR MULTICHANNEL
- //static int read_automix_sound(int *activebuf,int *chans,int chantype,dataptr dz);
- static int read_automix_sound(int *activebuf,dataptr dz);
- /************************************ MIXTWO ************************************/
- int mixtwo(dataptr dz)
- {
- int exit_status;
- char tempfnam[200];
- double *dblbuf = (double *) dz->sampbuf[3]; /* RWD I suppose we can keep this...*/
- float *inbuf1 = dz->sampbuf[0];
- float *inbuf2 = dz->sampbuf[1];
- float *obuf = dz->sampbuf[2];
- int extra_skip;
- if(dz->iparam[MIX_STTA] > 0) {
- if((sndseekEx(dz->ifd[0],dz->iparam[MIX_STTA],0))<0) {
- sprintf(errstr,"sndseek() failed in first file.\n");
- return(SYSTEM_ERROR);
- }
- }
- if((extra_skip = dz->iparam[MIX_STTA] - dz->iparam[MIX_STAGGER]) > 0) {
- if((dz->iparam[MIX_SKIP] += extra_skip) > dz->insams[1]) {
- sprintf(errstr,"Mix skips the 2nd file entirely.\n");
- return(DATA_ERROR);
- }
- }
- if(dz->iparam[MIX_SKIP] > 0) {
- if((exit_status = do_mix2_skip(dz))<0)
- return(exit_status);
- }
- if((dz->iparam[MIX_STAGGER] -= dz->iparam[MIX_STTA]) > 0) {
- if((exit_status = do_mix2_stagger(inbuf1,obuf,dz))<0)
- return(exit_status);
- } else {
- dz->iparam[MIX_STAGGER] = 0;
- }
- if((exit_status = do_mix2(inbuf1,inbuf2,dblbuf,obuf,dz))<0)
- return(exit_status);
- if(is_converted_to_stereo >= 0) {
- strcpy(tempfnam,snd_getfilename(dz->ifd[is_converted_to_stereo]));
- sndcloseEx(dz->ifd[is_converted_to_stereo]);
- if(remove(tempfnam)<0)
- fprintf(stdout, "ERROR: %s: Can't remove temporary stereo soundfile %s.\n",sferrstr(),tempfnam);
- dz->ifd[is_converted_to_stereo] = -1;
- }
- return(FINISHED);
- }
- /************************************ DO_MIX2_SKIP ************************************/
- int do_mix2_skip(dataptr dz)
- {
- if((sndseekEx(dz->ifd[1],dz->iparam[MIX_SKIP],0))<0) {
- sprintf(errstr,"sndseek() failed: do_mix2_skip()\n");
- return(SYSTEM_ERROR);
- }
- return(FINISHED);
- }
- /************************************ DO_MIX2_STAGGER ************************************/
- int do_mix2_stagger(float *inbuf1,float *obuf,dataptr dz)
- {
- int exit_status;
- int stagbufs,stagsamps, n;
- //TW
- int shsecsize = F_SECSIZE; /* RWD I suppose we can keep this...*/
- int samps_read;
- stagbufs = dz->iparam[MIX_STAGGER]/dz->buflen;
- stagsamps = dz->iparam[MIX_STAGGER] % dz->buflen;
- /*RWD do we still need this test? Is it still kosher ? */
- if(((stagsamps/shsecsize)*shsecsize) != stagsamps) {
- sprintf(errstr,"Error in sector arithmetic: do_mix2_stagger()\n");
- return(PROGRAM_ERROR);
- }
- while(stagbufs > 0) {
- if((samps_read = fgetfbufEx(inbuf1,dz->buflen,dz->ifd[0],0)) < dz->buflen) {
- if(samps_read < 0) {
- sprintf(errstr,"Sound read error.\n");
- return(SYSTEM_ERROR);
- } else {
- sprintf(errstr,"Problem 1 reading from file1 during stagger\n");
- return(PROGRAM_ERROR);
- }
- }
- for(n=0;n<dz->buflen;n++)
- obuf[n] = (float)(inbuf1[n] * dz->param[MIX2_GAIN1]);
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
- return(exit_status);
- stagbufs--;
- }
- if(stagsamps) {
- if((samps_read = fgetfbufEx(inbuf1,stagsamps,dz->ifd[0],0)) < stagsamps) {
- if(samps_read < 0) {
- sprintf(errstr,"Sound read error.\n");
- return(SYSTEM_ERROR);
- } else {
- sprintf(errstr,"Problem 2 reading from file1 during stagger\n");
- return(PROGRAM_ERROR);
- }
- }
- for(n=0;n<stagsamps;n++)
- obuf[n] = (float)(inbuf1[n] * dz->param[MIX2_GAIN1]);
- if((exit_status = write_samps(obuf,stagsamps,dz))<0)
- return(exit_status);
- }
- return(FINISHED);
- }
- /************************************ DO_MIX2 ************************************/
- int do_mix2(float *inbuf1,float *inbuf2,double *dblbuf,float *obuf,dataptr dz)
- {
- int exit_status;
- int gross_samps_read = 1, gross_total_samps_read = 0, cutoff_in_buf;
- int samps_read1, samps_read2, ssampsread, ssampsread1, ssampsread2, n;
- unsigned int cutoff_samps;
- cutoff_samps = (dz->iparam[MIX_DURA] - dz->iparam[MIX_STTA]) - dz->iparam[MIX_STAGGER];
- if((cutoff_samps) <= 0)
- cutoff_samps = UINT_MAX;
-
- while(gross_samps_read > 0) {
- memset((char *)inbuf1,0,(size_t)(dz->buflen * sizeof(float)));
- memset((char *)inbuf2,0,(size_t)(dz->buflen * sizeof(float)));
- memset((char *)dblbuf,0,(size_t)(dz->buflen * sizeof(double)));
- if((samps_read1 = fgetfbufEx(inbuf1,dz->buflen,dz->ifd[0],0))<0) {
- sprintf(errstr,"Problem reading from file1 during mix.\n");
- return(SYSTEM_ERROR);
- }
- if((samps_read2 = fgetfbufEx(inbuf2,dz->buflen,dz->ifd[1],0))<0) {
- sprintf(errstr,"Problem reading from file1 during mix.\n");
- return(SYSTEM_ERROR);
- }
- if((gross_samps_read = max(samps_read1,samps_read2))<=0)
- break;
- gross_total_samps_read += gross_samps_read;
- if(cutoff_samps > (unsigned int) gross_total_samps_read)
- cutoff_in_buf = gross_samps_read;
- else
- cutoff_in_buf = (cutoff_samps % dz->buflen);
- ssampsread1 = samps_read1;
- ssampsread1 = min(ssampsread1,cutoff_in_buf);
- if(ssampsread1) {
- for(n=0;n<ssampsread1;n++)
- dblbuf[n] = inbuf1[n] * dz->param[MIX2_GAIN1];
- if((ssampsread2 = samps_read2)>0) {
- ssampsread2 = min(ssampsread2,cutoff_in_buf);
- for(n=0;n<ssampsread2;n++)
- dblbuf[n] += inbuf2[n] * dz->param[MIX2_GAIN2];
- }
- } else {
- ssampsread2 = samps_read2;
- ssampsread2 = min(ssampsread2,cutoff_in_buf);
- for(n=0;n<ssampsread2;n++)
- dblbuf[n] = inbuf2[n] * dz->param[MIX2_GAIN2];
- }
- ssampsread = gross_samps_read;
- ssampsread = min(ssampsread,cutoff_in_buf);
- for(n=0;n<ssampsread;n++)
- obuf[n] = (float)dblbuf[n];
- if(ssampsread > 0) {
- if((exit_status = write_samps(obuf,ssampsread,dz))<0)
- return(exit_status);
- }
- if((unsigned int)gross_total_samps_read >= cutoff_samps)
- break;
- }
- return(FINISHED);
- }
- /******************************** MIX_CROSS **********************************/
- int mix_cross(dataptr dz)
- {
- int exit_status;
- float *inbuf1 = dz->sampbuf[0];
- float *inbuf2 = dz->sampbuf[1];
- float *obuf = dz->sampbuf[0];
- int samps_read2 = 0;
- int end_of_samps_to_process = dz->iparam[MCR_END];
- int cross_end = 0;
- int total_samps_read = 0;
- int remain;
- if(end_of_samps_to_process <= 0) {
- sprintf(errstr,"Accounting problem: mix_cross()\n");
- return(PROGRAM_ERROR);
- }
- display_virtual_time(0,dz);
- if(dz->iparam[MCR_STAGGER]>0 && (exit_status = cross_stagger(&total_samps_read,&end_of_samps_to_process,obuf,dz))<0)
- return(exit_status);
- if(end_of_samps_to_process <=0) {
- sprintf(errstr,"Accounting problem 1: mix_cross()\n");
- return(PROGRAM_ERROR);
- }
- while(total_samps_read <= dz->iparam[MCR_BEGIN]) {
- if((exit_status = pre_crossmix
- (&samps_read2,&cross_end,&total_samps_read,&end_of_samps_to_process,inbuf1,inbuf2,obuf,dz))<0)
- return(exit_status);
- if(exit_status == FINISHED)
- break;
- }
- if(end_of_samps_to_process <=0) {
- sprintf(errstr,"Accounting problem 2: mix_cross()\n");
- return(PROGRAM_ERROR);
- }
- remain = samps_read2 - end_of_samps_to_process;
- if(remain < 0) {
- do {
- if((exit_status = crossmix
- (&samps_read2,&cross_end,&total_samps_read,&end_of_samps_to_process,inbuf1,inbuf2,obuf,dz))<0)
- return(exit_status);
- } while((remain = samps_read2 - end_of_samps_to_process) < 0);
- }
- if(remain)
- memmove((char *)(obuf + cross_end),(char *)(inbuf2 + cross_end),(size_t)(remain * sizeof(float)));
- if(samps_read2 > 0) {
- if((exit_status = write_samps(obuf,samps_read2,dz))<0)
- return(exit_status);
- }
- while((samps_read2 = fgetfbufEx(obuf, dz->buflen,dz->ifd[1],0))>0) {
- if((exit_status = write_samps(obuf,samps_read2,dz))<0)
- return(exit_status);
- }
- if(samps_read2<0) {
- sprintf(errstr,"Sound read error.\n");
- return(SYSTEM_ERROR);
- }
- return(FINISHED);
- }
- /******************************** CROSS **********************************/
- int cross(int startcross,int endcross,float *inbuf1,float *inbuf2,float *obuf,dataptr dz)
- {
- double xxx, yyy;
- register int i;
- int crosindex = dz->iparam[MCR_INDEX];
- double crosfact = dz->param[MCR_CROSFACT];
- double powfac;
- switch(dz->iparam[MCR_CONTOUR]) {
- case(MCR_LINEAR): /* LINEAR */
- for(i=startcross;i<endcross;i++) {
- xxx = (double)crosindex * crosfact;
- yyy = 1.0 - xxx;
- obuf[i] = (float)((inbuf1[i] * yyy) + (inbuf2[i] * xxx));
- crosindex++;
- }
- break;
- case(MCR_COSIN): /* COSIN */
- for(i=startcross;i<endcross;i++) {
- xxx = (double)crosindex * crosfact;
- xxx = read_cos(xxx,dz);
- yyy = 1.0 - xxx;
- obuf[i] = (float)((inbuf1[i] * yyy) + (inbuf2[i] * xxx));
- crosindex++;
- }
- break;
- case(MCR_SKEWED): /* SKEWED COSIN */
- powfac = dz->param[MCR_POWFAC];
- for(i=startcross;i<endcross;i++) {
- xxx = (double)crosindex * crosfact;
- xxx = pow(xxx,powfac);
- xxx = read_cos(xxx,dz);
- yyy = 1.0 - xxx;
- obuf[i] = (float)((inbuf1[i] * yyy) + (inbuf2[i] * xxx));
- crosindex++;
- }
- break;
- }
- dz->iparam[MCR_INDEX] = crosindex;
- return(FINISHED);
- }
- /************************** READ_COS **********************/
- double read_cos(double d,dataptr dz)
- {
- int j, k;
- double frac, diff;
- double *costable = dz->parray[MCR_COSTABLE];
- d *= (double)MCR_TABLEN;
- j = (int)d; /* TRUNCATE */
- if((k=j+1)>MCR_TABLEN)
- return(1.0);
- frac = d - (double)j;
- diff = costable[k] - costable[j];
- frac *= diff;
- return(costable[j] + frac);
- }
- /************************** CROSSMIX **********************/
- int crossmix(int *samps_read2,int *cross_end,int *total_samps_read,int *end_of_samps_to_process,
- float *inbuf1,float *inbuf2,float *obuf,dataptr dz)
- {
- int exit_status;
- if((exit_status = advance_in_files
- (samps_read2,total_samps_read,end_of_samps_to_process,cross_end,inbuf1,inbuf2,dz))<0)
- return(exit_status);
- *cross_end = min(*cross_end,dz->buflen);
- if((exit_status = cross(0L,*cross_end,inbuf1,inbuf2,obuf,dz))<0)
- return(exit_status);
- if(*cross_end==dz->buflen) {
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
- return(exit_status);
- }
- return(FINISHED);
- }
- /************************** PRE_CROSSMIX **********************/
- int pre_crossmix(int *samps_read2,int *cross_end,int *total_samps_read,
- int *end_of_samps_to_process,float *inbuf1,float *inbuf2,float *obuf,dataptr dz)
- {
- int exit_status;
- int ssampstart, cross_start;
- int last_total_samps_read = *total_samps_read;
- if((exit_status = advance_in_files
- (samps_read2,total_samps_read,end_of_samps_to_process,cross_end,inbuf1,inbuf2,dz))<0)
- return(exit_status);
- if(*total_samps_read > dz->iparam[MCR_BEGIN]) {
- if((cross_start = dz->iparam[MCR_BEGIN] - last_total_samps_read)>=dz->buflen) {
- sprintf(errstr,"Accounting problem: pre_crossmix()\n");
- return(PROGRAM_ERROR);
- }
- ssampstart = cross_start;
- *cross_end = min(*cross_end,dz->buflen);
- if((exit_status = cross(ssampstart,*cross_end,inbuf1,inbuf2,obuf,dz))<0)
- return(exit_status);
- if(*cross_end < dz->buflen)
- return(FINISHED);
- }
- if((exit_status= write_samps(obuf,dz->buflen,dz))<0)
- return(exit_status);
- return(CONTINUE);
- }
- /************************** CROSS_STAGGER **********************/
- int cross_stagger(int *total_samps_read,int *end_of_samps_to_process,float *obuf,dataptr dz)
- {
- int exit_status;
- int samps_read1, samps_written;
- int stagger = dz->iparam[MCR_STAGGER];
- int stagbufs = stagger/dz->buflen;
- int stagsamps = stagger%dz->buflen;
- //TW SAFE??
- // if(((stagsamps/F_SECSIZE)*F_SECSIZE)!=stagsamps) {
- // sprintf(errstr,"Sector accounting problem: cross_stagger()\n");
- // return(PROGRAM_ERROR);
- // }
- while(stagbufs>0) {
- if((samps_read1 = fgetfbufEx(obuf, dz->buflen,dz->ifd[0],0))!=dz->buflen) {
- if(samps_read1<0) {
- sprintf(errstr,"Sound read error.\n");
- return(SYSTEM_ERROR);
- } else {
- sprintf(errstr,"First file read failed:1: cross_stagger()\n");
- return(PROGRAM_ERROR);
- }
- }
- // if((samps_written = fputfbufEx(obuf,dz->buflen,dz->ofd))!=dz->buflen) {
- if((exit_status = write_samps_no_report(obuf,dz->buflen,&samps_written,dz))<0)
- return(exit_status);
- if(samps_written!=dz->buflen) {
- sprintf(errstr,"Problem writing samps:1: cross_stagger()\n");
- return(PROGRAM_ERROR);
- }
- dz->total_samps_written += samps_written;
- *total_samps_read += dz->buflen;
- *end_of_samps_to_process -= dz->buflen;
- stagbufs--;
- }
- if(stagsamps > 0) {
- if((samps_read1 = fgetfbufEx(obuf, stagsamps,dz->ifd[0],0))!=stagsamps) {
- if(samps_read1<0) {
- sprintf(errstr,"Sound read error.\n");
- return(SYSTEM_ERROR);
- } else {
- sprintf(errstr,"First file read failed:2: cross_stagger()\n");
- return(PROGRAM_ERROR);
- }
- }
- // if((samps_written = fputfbufEx(obuf,stagsamps,dz->ofd))!=stagsamps) {
- if((exit_status = write_samps_no_report(obuf,stagsamps,&samps_written,dz) )< 0)
- return(exit_status);
- if(samps_written != stagsamps) {
- sprintf(errstr,"Problem writing samps:2: cross_stagger()\n");
- return(PROGRAM_ERROR);
- }
- dz->total_samps_written += stagsamps;
- *total_samps_read += stagsamps;
- *end_of_samps_to_process -= stagsamps;
- }
- return(FINISHED);
- }
- /************************** ADVANCE_IN_FILES **********************/
- int advance_in_files(int *samps_read2,int *total_samps_read,int *end_of_samps_to_process,
- int *cross_end,float *inbuf1,float *inbuf2,dataptr dz)
- {
- int samps_read1;
- *end_of_samps_to_process = dz->iparam[MCR_END] - *total_samps_read;
- if((samps_read1 = fgetfbufEx(inbuf1, dz->buflen,dz->ifd[0],0))<0) {
- sprintf(errstr,"First file read failed: advance_in_files()\n");
- return(SYSTEM_ERROR);
- }
- if((*samps_read2 = fgetfbufEx(inbuf2, dz->buflen,dz->ifd[1],0))<0) {
- sprintf(errstr,"Second file read failed: advance_in_files()\n");
- return(SYSTEM_ERROR);
- }
- *total_samps_read += *samps_read2; /* BECAUSE FADE IS TOWARDS FILE 2: and fade must END before then */
- *cross_end = *end_of_samps_to_process;
- return(FINISHED);
- }
- /************************************ MIX_INTERL ************************************/
- int mix_interl(dataptr dz)
- {
- int exit_status;
- float *inbuf = dz->sampbuf[0];
- float *outbuf = dz->sampbuf[1]; /* NB this buffer is large enough to take output */
-
- int samps_read, samps_left[MAX_MI_OUTCHANS];
- int n, gross_samps_read, gross_samps_left = 0, last_total_samps_written, samps_to_write;
- for(n=0;n<dz->infilecnt;n++) {
- samps_left[n] = dz->insams[n];
- gross_samps_left = max(gross_samps_left,samps_left[n]);
- }
- while(gross_samps_left) {
- memset((char *)outbuf,0,(size_t)(dz->buflen * dz->infilecnt * sizeof(float)));
- gross_samps_read = 0;
- gross_samps_left = 0;
- for(n=0;n<dz->infilecnt;n++) {
- if(samps_left[n]>0) {
- if((samps_read = fgetfbufEx(inbuf,dz->buflen,dz->ifd[n],0))<0) {
- sprintf(errstr,"Failed to read data from file %d: mix_interl()\n",n+1);
- return(SYSTEM_ERROR);
- }
- samps_left[n] -= samps_read;
- copy_to_channel(inbuf,outbuf+n,samps_read,dz->infilecnt);
- gross_samps_read = max(gross_samps_read,samps_read);
- gross_samps_left = max(gross_samps_left,samps_left[n]);
- }
- }
- samps_to_write = gross_samps_read*dz->infilecnt;
- last_total_samps_written = dz->total_samps_written;
- if(samps_to_write) {
- if((exit_status = write_samps(outbuf,samps_to_write,dz))<0)
- return(exit_status);
- }
- if(dz->total_samps_written - last_total_samps_written != samps_to_write) {
- sprintf(errstr,"Problem writing data: mix_interl()\n");
- return(PROGRAM_ERROR);
- }
- }
- // TW
- // /*RWD too late here! */
- // dz->infile->channels = dz->infilecnt; /* Force output to final channel-count */
- return(FINISHED);
- }
- /************************************ COPY_TO_CHANNEL ************************************/
- void copy_to_channel(float *inbuf,float *outbuf,int sampcnt,int outchans)
- {
- int n, m;
- for(n=0,m=0;n<sampcnt;n++,m+=outchans)
- outbuf[m] = inbuf[n];
- }
- /******************************** CROSS_STITCH *****************************/
- int cross_stitch(dataptr dz) {
- double srate = (double)dz->infile->srate;
- int n = 0, mbf, sbf, procend, input_procend;
- int exit_status, t = 0,v=0,m=0,done = 0;
- double *brrk = NULL, thisval, nextval = 0.0, valincr, atten = 0.0, val_here;
- double time_here, lastrtime,nextrtime, lastval, tratio;
- int nexttime = 0, thistime;
- float *buf0 = dz->sampbuf[0];
- float *buf1 = dz->sampbuf[1];
- int typ;
- int input_procskip, samps_to_skip = 0;
- if(dz->param[MIX_SKEW] <= dz->param[MIX_SKIP]) {
- sprintf(errstr,"Start and end times of mix are reversed, or equal.\n");
- return(DATA_ERROR);
- }
- /* RWD make this samps */
- dz->tempsize =
- (int)round((dz->param[MIX_SKEW] - dz->param[MIX_SKIP]) * (double)(srate *
- max(dz->infile->channels,dz->otherfile->channels)));
- display_virtual_time(0,dz);
- if(dz->infile->channels > 2) {
- typ = 4; /* multichan multichan */
- } else if(dz->infile->channels==1) {
- if(dz->otherfile->channels==1) {
- typ = 0; /* mono mono */
- } else {
- typ = 1; /* mono stereo */
- }
- } else {
- if(dz->otherfile->channels==1) {
- typ = 2; /* stereo mono */
- } else {
- typ = 3; /* stereo stereo */
- }
- }
- procend = dz->insams[0]/dz->infile->channels;
- input_procend = (int)round(dz->param[MIX_SKEW] * srate);
- procend = min(procend,input_procend);
- if((input_procskip = (int)round(dz->param[MIX_SKIP] * srate)) > 0) {
- samps_to_skip = input_procskip * dz->infile->channels;
- //TW SAFE??
- // samps_to_skip /= (F_SECSIZE * dz->infile->channels);
- // samps_to_skip *= (F_SECSIZE * dz->infile->channels); /* skip to nearest sector */
- if((sndseekEx(dz->ifd[0],samps_to_skip,0))<0) {
- sprintf(errstr,"seek() failed searching for startpoint of mix in first file.\n");
- return(SYSTEM_ERROR);
- }
- samps_to_skip = input_procskip * dz->otherfile->channels;
- //TW SAFE??
- // samps_to_skip /= (F_SECSIZE * dz->otherfile->channels);
- // samps_to_skip *= (F_SECSIZE * dz->otherfile->channels); /* skip to nearest sector */
- if((sndseekEx(dz->ifd[1],samps_to_skip,0))<0) {
- sprintf(errstr,"sndseek() failed searching for startpoint of mix in second file.\n");
- return(SYSTEM_ERROR);
- }
- }
- if(dz->brksize[MIX_STAGGER]) {
- brrk = dz->brk[MIX_STAGGER];
- if(input_procskip > 0) {
- thistime = samps_to_skip/dz->otherfile->channels;
- time_here = (double)thistime/srate;
- m = 0;
- while(brrk[m] <= time_here) {
- m += 2;
- if(m >= dz->brksize[MIX_STAGGER]) { /* IF beyond end of brk */
- dz->param[MIX_STAGGER] = brrk[m-1]; /* set atten to last brkval */
- dz->brksize[MIX_STAGGER] = 0; /* set brkfile as not existing */
- break;
- }
- }
- if(dz->brksize[MIX_STAGGER]) { /* If still in brkfile */
- lastrtime = brrk[m-2]; /* Note previous brkpnt-time+val */
- lastval = brrk[m-1];
- n = thistime; /* set the internal sample counter to here */
- t = m; /* set pointer for (following) brkpnt times */
- v = m+1; /* set pointer for (following) brkpnt vals */
- m /= 2; /* set position in brk-pairs */
- nextrtime = brrk[t];
- nexttime = round(nextrtime * srate);
- nextval = brrk[v];
- /* calc value at start-time */
- tratio = (double)(time_here - lastrtime)/(double)(nextrtime - lastrtime);
- val_here = ((nextval - lastval) * tratio) + lastval;
- nexttime = thistime; /* set up starting time & val */
- nextval = val_here;
- }
- } else {
- nexttime = round(brrk[0] * srate);
- nextval = brrk[1]; /* set up starting time & val */
- n = 0; /* set the internal sample counter to start */
- t = 2; /* set pointer for (following) brkpnt times */
- v = 3; /* set pointer for (following) brkpnt vals */
- m = 1; /* set position in brk-pairs */
- }
- } else {
- n = input_procskip;
- }
- memset((char *)buf0,0,dz->buflen * dz->infile->channels* sizeof(float));
- memset((char *)buf1,0,dz->buflen * dz->otherfile->channels * sizeof(float));
- if((fgetfbufEx(buf0,dz->buflen * dz->infile->channels,dz->ifd[0],0)) < 0) {
- sprintf(errstr,"Can't read samps from 1st soundfile.\n");
- return(SYSTEM_ERROR);
- }
- if((fgetfbufEx(buf1,dz->buflen * dz->otherfile->channels,dz->ifd[1],0)) < 0) {
- sprintf(errstr,"Can't read samps from 2nd soundfile.\n");
- return(SYSTEM_ERROR);
- }
- mbf = 0;
- sbf = 0;
- if(dz->brksize[MIX_STAGGER] == 0)
- atten = dz->param[MIX_STAGGER];
- else {
- for(; m < dz->brksize[MIX_STAGGER]; m++,t+=2,v+=2) {
- thistime = nexttime;
- thisval = nextval;
- nexttime = round(brrk[t] * srate);
- nextval = brrk[v];
- valincr = (nextval - thisval)/(double)(nexttime - thistime);
- if(nexttime >= procend) { /* IF brktable extends beyond end of sound */
- nexttime = procend;
- done = 1;
- }
- atten = thisval;
- while(n < nexttime) {
- if(do_stitch(typ,&mbf,&sbf,buf0,buf1,atten,dz->buflen,dz)) {
- if((exit_status = renew_bufs(typ,buf0,buf1,dz))<0)
- return(exit_status);
- mbf = 0;
- sbf = 0;
- }
- atten += valincr;
- n++;
- }
- if(done) /* IF brktable extends beyond end of sound: break */
- break;
- }
- }
- while(n < procend) { /* IF brktable stops short of end of sound, or no brktable */
- if(do_stitch(typ,&mbf,&sbf,buf0,buf1,atten,dz->buflen,dz)) {
- if((exit_status = renew_bufs(typ,buf0,buf1,dz))<0)
- return(exit_status);
- mbf = 0;
- sbf = 0;
- }
- n++;
- }
- return flush_bufs(typ,&mbf,&sbf,buf0,buf1,dz);
- }
- /******************************** DO_STITCH *****************************/
- int do_stitch(int typ,int *mbf,int *sbf,float *buf0,float *buf1,double atten,int bflen,dataptr dz)
- {
- int bufdone = 0, k;
- switch(typ) {
- case(0):
- buf0[*mbf] = (float)((buf0[*mbf] * atten) + (buf1[*mbf] * (1.0 - atten)));
- if(++(*mbf) >= bflen)
- bufdone = 1;
- break;
- case(1):
- buf1[*sbf] = (float)((buf0[*mbf] * atten) + (buf1[*sbf] * (1.0 - atten)));
- (*sbf)++;
- buf1[*sbf] = (float)((buf0[*mbf] * atten) + (buf1[*sbf] * (1.0 - atten)));
- (*sbf)++;
- if(++(*mbf) >= bflen)
- bufdone = 1;
- break;
- case(2):
- buf0[*sbf] = (float)((buf0[*sbf] * atten) + (buf1[*mbf] * (1.0 - atten)));
- (*sbf)++;
- buf0[*sbf] = (float)((buf0[*sbf] * atten) + (buf1[*mbf] * (1.0 - atten)));
- (*sbf)++;
- if(++(*mbf) >= bflen)
- bufdone = 1;
- break;
- case(3):
- buf0[*sbf] = (float)((buf0[*sbf] * atten) + (buf1[*sbf] * (1.0 - atten)));
- (*sbf)++;
- buf0[*sbf] = (float)((buf0[*sbf] * atten) + (buf1[*sbf] * (1.0 - atten)));
- if(++(*sbf) >= bflen * 2)
- bufdone = 1;
- break;
- case(4):
- for(k=0; k < dz->infile->channels; k++) {
- buf0[*sbf] = (float)((buf0[*sbf] * atten) + (buf1[*sbf] * (1.0 - atten)));
- (*sbf)++;
- }
- if(*sbf >= bflen * dz->infile->channels)
- bufdone = 1;
- break;
- }
- return(bufdone);
- }
- /******************************** RENEW_BUFS *****************************/
- int renew_bufs(int typ,float *buf0,float *buf1,dataptr dz)
- {
- int exit_status;
- switch(typ) {
- case(0):
- if((exit_status = write_samps(buf0,dz->buflen,dz))<0)
- return(exit_status);
- memset((char *)buf0,0,dz->buflen * sizeof(float));
- memset((char *)buf1,0,dz->buflen * sizeof(float));
- break;
- case(1):
- if((exit_status = write_samps(buf1,dz->buflen * 2,dz))<0)
- return(exit_status);
- memset((char *)buf0,0,dz->buflen * sizeof(float));
- memset((char *)buf1,0,dz->buflen * 2 * sizeof(float));
- break;
- case(2):
- if((exit_status = write_samps(buf0,dz->buflen * 2,dz))<0)
- return(exit_status);
- memset((char *)buf0,0,dz->buflen * 2 * sizeof(float));
- memset((char *)buf1,0,dz->buflen * sizeof(float));
- break;
- case(3):
- if((exit_status = write_samps(buf0,dz->buflen * 2,dz))<0)
- return(exit_status);
- memset((char *)buf0,0,dz->buflen * 2 * sizeof(float));
- memset((char *)buf1,0,dz->buflen * 2 * sizeof(float));
- break;
- case(4):
- if((exit_status = write_samps(buf0,dz->buflen * dz->infile->channels,dz))<0)
- return(exit_status);
- memset((char *)buf0,0,dz->buflen * dz->infile->channels * sizeof(float));
- memset((char *)buf1,0,dz->buflen * dz->otherfile->channels * sizeof(float));
- break;
- }
- if((fgetfbufEx(buf0,dz->buflen * dz->infile->channels,dz->ifd[0],0)) < 0) {
- sprintf(errstr,"Can't read samps from 1st soundfile.\n");
- return(SYSTEM_ERROR);
- }
- if((fgetfbufEx(buf1,dz->buflen * dz->otherfile->channels,dz->ifd[1],0)) < 0) {
- sprintf(errstr,"Can't read samps from 2nd soundfile.\n");
- return(SYSTEM_ERROR);
- }
- return(FINISHED);
- }
- /******************************** FLUSH_BUFS *****************************/
- int flush_bufs(int typ,int *mbf,int *sbf,float *buf0,float *buf1,dataptr dz)
- {
- int exit_status;
- switch(typ) {
- case(0): /* Output file takes its channel cnt from 1st input file : HENCE.... */
- if(*mbf > 0) {
- if((exit_status = write_samps(buf0,*mbf,dz))<0)
- return(exit_status);
- } /* 1st input file MONO : output file MONO */
- break;
- case(1):
- if(*sbf > 0) {
- if((exit_status = write_samps(buf1,*sbf,dz))<0)
- return(exit_status);
- } /* 1st input file MONO : output file STEREO */
- dz->infile->channels = 2; /* Force output file to have stereo header */
- break;
- case(2): /* 1st input file STEREO : output file STEREO */
- case(3):
- case(4):
- if(*sbf > 0) {
- if((exit_status = write_samps(buf0,*sbf,dz))<0)
- return(exit_status);
- }
- break;
- }
- return(FINISHED);
- }
- //TW JANUARY 2010: MODIFIED FOR MULTICHANNEL
- /*************************** DO_AUTOMIX *******************************/
- int do_automix(dataptr dz)
- {
- double srate = (double)dz->infile->srate;
- unsigned int nexttime, thistime, outcnt = 0, bufcnt = 0;
- int outchans = 1, exit_status;
- double *p = dz->parray[0], *arrayend = dz->parray[0] + dz->itemcnt;
- double *thislevel, *nextlevel, *incr, sum, convertor_to_time, convertor_to_smps;
- int *activebuf, overflows = 0;
- unsigned int max_insams = 0;
- int *chans, n;
- // RWD 2025 now use calloc to pacify gcc
- if((chans = (int *) calloc(dz->infilecnt, sizeof(int)))==NULL) {
- sprintf(errstr,"Insufficient memory for level stores\n");
- return(MEMORY_ERROR);
- }
- if((thislevel = (double *)malloc(dz->infilecnt * sizeof(double)))==NULL) {
- sprintf(errstr,"Insufficient memory for level stores\n");
- return(MEMORY_ERROR);
- }
- if((nextlevel = (double *)malloc(dz->infilecnt * sizeof(double)))==NULL) {
- sprintf(errstr,"Insufficient memory for level stores\n");
- return(MEMORY_ERROR);
- }
- if((incr = (double *)malloc(dz->infilecnt * sizeof(double)))==NULL) {
- sprintf(errstr,"Insufficient memory for level stores\n");
- return(MEMORY_ERROR);
- }
- if((activebuf = (int *)malloc(dz->infilecnt * sizeof(int)))==NULL) {
- sprintf(errstr,"Insufficient memory for level stores\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->infilecnt;n++) {
- activebuf[n] = 1;
- if(sndgetprop(dz->ifd[n],"channels", (char *)&(chans[n]), sizeof(int)) < 0) {
- sprintf(errstr,"Failure to read channel data, for input file %d\n",n+1);
- return(DATA_ERROR);
- }
- if(n>0 && chans[n] != chans[0]) {
- sprintf(errstr,"Process only works with files having the same number of channels: file %d will not work\n",n+1);
- return(DATA_ERROR);
- }
- }
- outchans = chans[0];
- convertor_to_smps = srate * outchans;
- convertor_to_time = 1.0/convertor_to_smps;
- for(n=0;n<dz->infilecnt;n++)
- max_insams = max(max_insams,(unsigned int)dz->insams[n]);
- dz->tempsize = max_insams; /* for scrollbar display */
- if((exit_status = create_sized_outfile(dz->outfilename,dz))<0)
- return(exit_status);
- if((exit_status = read_automix_sound(activebuf,dz))<0)
- return(exit_status);
- nexttime = (unsigned int)round(*p++ * convertor_to_smps);
- for(n = 0;n<dz->infilecnt; n++)
- nextlevel[n] = *p++;
- while(outcnt < max_insams) {
- thistime = nexttime; /* establish amplitude ramps */
- for(n = 0; n<dz->infilecnt; n++)
- thislevel[n] = nextlevel[n];
- if(p < arrayend) {
- nexttime = (unsigned int)round(*p++ * convertor_to_smps);
- for(n = 0;n<dz->infilecnt; n++) {
- nextlevel[n] = *p++;
- incr[n] = (nextlevel[n] - thislevel[n])/(double)(nexttime - thistime);
- }
- } else { /* if amp-data runs out */
- for(n = 0;n<dz->infilecnt; n++) /* set amp increments to zero */
- incr[n] = 0.0;
- nexttime = max_insams; /* and proceed to end of file */
- }
- nexttime = min(nexttime, max_insams); /* if snd-data runs out, curtail loop to snd-data end */
- while(outcnt < nexttime) {
- sum = 0.0;
- for(n=0;n<dz->infilecnt;n++) {
- if(activebuf[n]) {
- sum += dz->sampbuf[n][bufcnt] * thislevel[n];
- thislevel[n] += incr[n];
- if(outcnt >= (unsigned int)dz->insams[n])
- activebuf[n] = 0;
- }
- }
- if(fabs(sum) > F_MAXSAMP)
- overflows++;
- dz->sampbuf[dz->infilecnt][bufcnt] = (float)(sum * dz->param[0]);
- if(++bufcnt >= (unsigned int)dz->buflen) {
- if((exit_status = write_samps(dz->sampbuf[dz->infilecnt],dz->buflen,dz))<0)
- return(exit_status);
- if((exit_status = read_automix_sound(activebuf,dz))<0)
- return(exit_status);
- bufcnt = 0;
- }
- outcnt++;
- if(dz->brksize[0]) {
- if((exit_status = read_value_from_brktable((double)outcnt * convertor_to_time,0,dz))<0)
- return(exit_status);
- }
- }
- }
- if(bufcnt) {
- if((exit_status = write_samps(dz->sampbuf[dz->infilecnt],bufcnt,dz))<0)
- return(exit_status);
- }
- if(overflows) {
- fprintf(stdout,"WARNING: %d samples were clipped.\n",overflows);
- fflush(stdout);
- }
- return(FINISHED);
- }
- /*************************** READ_AUTOMIX_SOUND *******************************/
- int read_automix_sound(int *activebuf,dataptr dz)
- {
- int n;
- for(n=0;n<dz->infilecnt;n++) {
- if(!activebuf[n]) /* only read from files with data remaining */
- continue;
- if((dz->ssampsread = fgetfbufEx(dz->sampbuf[n],dz->buflen,dz->ifd[n],0)) < 0) {
- sprintf(errstr,"Can't read samps from input soundfile %d.\n",n+1);
- return(SYSTEM_ERROR);
- }
- }
- return(FINISHED);
- }
- /************************************ MIXMANY ************************************/
- int mixmany(dataptr dz)
- {
- int exit_status;
- int gross_samps_read, n, m;
- int ssampsread;
- double *dblbuf = (double *)dz->sampbuf[2], maxdsamp = 0.0;
- float *ibuf = dz->sampbuf[0];
- float *obuf = dz->sampbuf[1];
- dz->tempsize = 0;
- for(n=0;n<=dz->infilecnt;n++)
- dz->tempsize = max(dz->tempsize,dz->insams[n]);
- display_virtual_time(0L,dz);
- fprintf(stdout,"INFO: Finding maximum level\n");
- fflush(stdout);
- do {
- memset((char *)ibuf,0,(size_t)dz->buflen * sizeof(float));
- memset((char *)dblbuf,0,(size_t)dz->buflen * sizeof(double));
- gross_samps_read = 0;
- for(n=0;n<dz->infilecnt;n++) {
- if((ssampsread = fgetfbufEx(ibuf,dz->buflen,dz->ifd[n],0))<0) {
- sprintf(errstr,"Problem reading from file %d\n",n+1);
- return(SYSTEM_ERROR);
- }
- gross_samps_read = max(gross_samps_read,ssampsread);
- if(ssampsread > 0) {
- for(m=0;m<ssampsread;m++)
- dblbuf[m] += (double)ibuf[m];
- }
- }
- if(gross_samps_read<=0)
- break;
- for(m=0;m<gross_samps_read;m++)
- maxdsamp = max(maxdsamp,fabs(dblbuf[m]));
- } while(gross_samps_read > 0);
- maxdsamp = F_MAXSAMP/maxdsamp;
- for(n=0;n<dz->infilecnt;n++) {
- if(sndseekEx(dz->ifd[n],0,0)<0) {
- sprintf(errstr,"seek failed for file %d\n",n+1);
- return(SYSTEM_ERROR);
- }
- }
- dz->total_samps_written = 0;
- display_virtual_time(0,dz);
- fprintf(stdout,"INFO: Doing the mix.\n");
- fflush(stdout);
- do {
- memset((char *)ibuf,0,(size_t)dz->buflen * sizeof(float));
- memset((char *)dblbuf,0,(size_t)dz->buflen * sizeof(double));
- gross_samps_read = 0;
- for(n=0;n<dz->infilecnt;n++) {
- if((ssampsread = fgetfbufEx(ibuf,dz->buflen,dz->ifd[n],0))<0) {
- sprintf(errstr,"Problem reading from file %d during mix.\n",n+1);
- return(SYSTEM_ERROR);
- }
- gross_samps_read = max(gross_samps_read,ssampsread);
- if(ssampsread > 0) {
- for(m=0;m<ssampsread;m++)
- dblbuf[m] += (double)ibuf[m];
- }
- }
- if(gross_samps_read<=0)
- break;
- for(m=0;m<gross_samps_read;m++)
- obuf[m] = (float)(dblbuf[m] * maxdsamp);
- if((exit_status = write_samps(obuf,gross_samps_read,dz))<0)
- return(exit_status);
- } while(gross_samps_read > 0);
- return(FINISHED);
- }
|