| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546 |
- /*
- * Copyright (c) 1983-2013 Composers Desktop Project Ltd
- * 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
- *
- */
-
- /* delay.c
- * generalised delay line featuring
- * feedthrough, feedforward and feedback
- * A. Bentley, Composers' Desktop Project, Nov 1987.
- * Revised and extended to stereo and command-line mode
- * by Richard Dobson Oct 1993.
- */
- static char *rcsid = "$Id: delay.c%v 3.3 1994/10/31 22:30:12 martin Exp $";
- /*
- * $Log: delay.c%v $
- * Revision 3.3 1994/10/31 22:30:12 martin
- * first rcs version
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include "sfsys.h"
- #include "cdplib.h"
- static char *sfsys_h_rcsid = SFSYS_H_RCSID;
- static char *cdplib_h_rcsid = CDPLIB_H_RCSID;
- #define remainder my_remainder
- #define BUFLEN (4096)
- #define DELBUFSIZ (176400) /* allows 2sec delay in stereo */
- #define ONE_FLT (65536.0)
- void domono();
- void dostereo();
- void usage();
- void delinit(int cmndline,char *argv[]);
- void initfbuf();
- void initlbuf();
- int Funcflag = 0;
- int Quickflag = 1;
- long Nchans;
- long Delaysamps;
- long bufcnt;
- long remainder;
- float *Fdelbuf;
- long *Ldelbuf;
- double Sr;
- double Delay;
- float Feedforgain;
- float Feedbckgain;
- float Delaygain;
- float Prescale = 1.0F;
- double Invert =1.0;
- double Rescale;
- long Lfeedforgain;
- long Lfeedbckgain;
- long Ldelaygain;
- long Lprescale;
- double Trailtime = 0.;
- long Trailsamps = 0;
- int ifd; /* input file descriptor */
- int ofd; /* output file descriptor */
- long isr;
- long sampsize;
- short *inbuf;
- short *outbuf;
- static char version[] =
- "~CDPVER~GROUCHO: DELAY Portable version 3.0, REVISED BY R. DOBSON OCT 1993.";
-
- PROGRAM_NUMBER(0xf93c2705);
- void
- main(argc,argv)
- int argc;
- char *argv[];
- {
- int cmndline = 0;
- char *ptr;
-
- if(sflinit("delay")) {
- sfperror("Delay: initialisation");
- exit(1);
- }
- while(argv[1] != 0 && argv[1][0] == '-') {
- switch(argv[1][1]) {
- case 'f':
- Quickflag--;
- break;
- case 'p':
- ptr = (char *) &(argv[1][2]);
- if(*ptr==0)
- {
- usage();
- }
- Prescale = (float)atof(ptr);
- if(Prescale==0.0)
- {
- printf("\ndelay: -p error, prescale = 0.0!\n");
- usage();
- }
- break;
- case 'i':
- Invert = -1.0;
- break;
- default:
- usage();
- break;
- }
- argv++; argc--;
- }
- if(argc < 3) usage();
- if(argc>4)
- {
- if(argc<7)
- {
- fprintf(stderr,"\ndelay: incorrect no of parameters");
- usage();
- }
- else
- {
- cmndline=1;
- }
- }
- if((inbuf =
- (short *) malloc((BUFLEN) * sizeof(short))) == NULL) {
- fprintf(stderr,"\ndelay: not enough memory for input buffer");
- exit(1);
- }
- if((outbuf =
- (short *) malloc(BUFLEN * sizeof(short))) == NULL) {
- fprintf(stderr,"\ndelay: not enough memory for output buffer");
- exit(1);
- }
- if((ifd = sndopen(argv[1])) < 0) {
- fprintf(stderr,"\ndelay: unable to open input file\n");
- exit(1);
- }
- if(sndgetprop(ifd,"sample rate",(char *) &isr, sizeof(long)) < 0) {
- fprintf(stderr,"\ndelay: failed to get sample rate");
- exit(1);
- }
- if(sndgetprop(ifd,"channels",(char *) &Nchans, sizeof(long)) < 0) {
- fprintf(stderr,"\ndelay: failed to get channel data");
- exit(1);
- }
- if(sndgetprop(ifd,"sample type",(char *) &sampsize, sizeof(long)) < 0){
- fprintf(stderr,"\ndelay: failed to get sample type");
- exit(1);
- }
- if(Nchans > 2) {
- fprintf(stderr,"\ndelay: too many channels! Mono or stereo only.\n");
- exit(1);
- }
- Sr = (double) isr;
- delinit(cmndline,argv);
- if((ofd = sndcreat(argv[2],-1,sampsize)) < 0) {
- fprintf(stderr,"\ndelay: unable to open output file\n");
- exit(1);
- }
- if(!Quickflag)
- initfbuf();
- else
- initlbuf();
- stopwatch(1);
- if(Nchans==1) {domono();} else {dostereo();}
- stopwatch(0);
- sndclose(ifd);
- if(sndputprop(ofd,"sample rate",(char *) &isr, sizeof(long)) < 0){
- fprintf(stderr,"\ndelay: failed to write sample rate");
- }
- if(sndputprop(ofd,"channels", (char *) &Nchans, sizeof(long)) < 0){
- fprintf(stderr,"\ndelay: failed to write channel data");
- }
- free(inbuf);
- free(outbuf);
- if(!Quickflag) {free(Fdelbuf);} else {free(Ldelbuf);}
- sndclose(ofd);
- sffinish();
- }
- void
- domono()
- {
- int i;
- long rdsamps;
- float input,output;
- long linput,loutput;
- long ltemp1,ltemp2;
- long ipptr=0,opptr=0;
- do /* while rdsamps */
- {
- if((rdsamps = fgetsbuf(inbuf, BUFLEN, ifd)) < 0) {
- fprintf(stderr,"\ndelay: failure to read input file\n");
- exit(1);
- }
-
- for(i=0;i<rdsamps;i++)
- {
-
- /* delay line */
- input = inbuf[i] * Prescale;
- output = (input * Feedforgain) + //dry signal
- (Fdelbuf[opptr] * Delaygain);
- Fdelbuf[ipptr] = Fdelbuf[opptr++] * Feedbckgain;
- Fdelbuf[ipptr++] += input ;
- outbuf[i] = (short) output; //dry + wet
- if(ipptr >= Delaysamps) ipptr -= Delaysamps;
- if(opptr >= Delaysamps) opptr -= Delaysamps;
-
-
- if(ipptr < 0 || opptr < 0) {
- printf(
- "\ninternal error, ipptr=%d,opptr=%d\n",ipptr,opptr);
- }
- }
- if(fputsbuf(outbuf,rdsamps,ofd) < rdsamps) {
- fprintf(stderr,
- "\ndelay: failure in writing to output file\n");
- exit(1);
- }
- inform(rdsamps,Sr);
- } while(rdsamps > 0);
- /* now do trailer */
- rdsamps=BUFLEN;
- if (Trailsamps>0) {
- do { /* while bufcnt */
-
- if(!bufcnt)
- rdsamps = remainder;
-
- for(i=0;i<rdsamps;i++) {
- output=(Fdelbuf[opptr] * Delaygain);
- Fdelbuf[ipptr++] =
- Fdelbuf[opptr++] *Feedbckgain;
- outbuf[i] = (short) output;
- if(ipptr >= Delaysamps) ipptr -= Delaysamps;
- if(opptr >= Delaysamps) opptr -= Delaysamps;
- }
-
- if(fputsbuf(outbuf,rdsamps,ofd) < rdsamps){
- fprintf(stderr,
- "\ndelay: failure in writing to output file\n");
- exit(1);
- }
- inform(BUFLEN,Sr);
- bufcnt -=1;
- } while(bufcnt>=0);
- } /* end if Trailsamps */
- } /* end domono */
- void
- dostereo() /* do stereo delay */
- {
- int i;
- long rdsamps;
- float Linput,Rinput;
- float Loutput,Routput;
- long Llinput,Rlinput;
- long Lloutput,Rloutput;
- long Ltemp1,Ltemp2;
- long Rtemp1,Rtemp2;
- long Lipptr = 0,Ripptr = 1;
- long Lopptr = 0,Ropptr = 1;
- do /* while rdsamps */
- {
- if((rdsamps = fgetsbuf(inbuf,BUFLEN,ifd)) < 0)
- {
- fprintf(stderr,"\ndelay: failure to read input file\n");
- exit(1);
- }
- for(i=0;i<(rdsamps-1);i+=2)
- {
- if(!Quickflag)
- {
- Linput=inbuf[i]*Prescale;
- Rinput=inbuf[i+1]*Prescale;
- Loutput=(Linput*Feedforgain) +
- (Fdelbuf[Lopptr]*Delaygain);
- Routput=(Rinput*Feedforgain) +
- (Fdelbuf[Ropptr]*Delaygain);
- Fdelbuf[Lipptr] = Fdelbuf[Lopptr]*Feedbckgain;
- Lopptr+=2;
- Fdelbuf[Ripptr] = Fdelbuf[Ropptr]*Feedbckgain;
- Ropptr+=2;
- Fdelbuf[Lipptr]+=Linput;
- Fdelbuf[Ripptr]+=Rinput;
- Lipptr+=2;
- Ripptr+=2;
- outbuf[i] = (short) Loutput;
- outbuf[i+1] = (short) Routput;
- if(Lipptr >= Delaysamps) Lipptr -= Delaysamps;
- if(Ripptr >= Delaysamps) Ripptr -= Delaysamps;
- if(Lopptr >= Delaysamps) Lopptr -= Delaysamps;
- if(Ropptr >= Delaysamps) Ropptr -= Delaysamps;
- }
- else
- {
- Llinput = inbuf[i] * Lprescale;
- Rlinput = inbuf[i+1] * Lprescale;
- Ltemp1 = Llinput >> 16;
- Rtemp1 = Rlinput >> 16;
- Ltemp2 = Ldelbuf[Lopptr] >> 16;
- Rtemp2 = Ldelbuf[Ropptr] >> 16;
- Lopptr += 2;
- Ropptr += 2;
- Lloutput = (Ltemp1 * Lfeedforgain) +
- (Ltemp2 * Ldelaygain);
- Rloutput = (Rtemp1 * Lfeedforgain) +
- (Rtemp2 * Ldelaygain);
- Ldelbuf[Lipptr] = Ltemp2 * Lfeedbckgain;
- Ldelbuf[Ripptr] = Rtemp2 * Lfeedbckgain;
- Ldelbuf[Lipptr] += Llinput;
- Ldelbuf[Ripptr] += Rlinput;
- Lipptr += 2;
- Ripptr += 2;
- outbuf[i] = (short)(Lloutput>>16);
- outbuf[i+1] = (short)(Rloutput>>16);
- if(Lipptr >= Delaysamps) Lipptr -= Delaysamps;
- if(Ripptr >= Delaysamps) Ripptr -= Delaysamps;
- if(Lopptr >= Delaysamps) Lopptr -= Delaysamps;
- if(Ropptr >= Delaysamps) Ropptr -= Delaysamps;
- }
- }
- if(fputsbuf(outbuf,rdsamps,ofd) < rdsamps) {
- fprintf(stderr,"\ndelay: failure in writing to output file\n");
- exit(1);
- }
- inform(rdsamps/2,Sr);
- }while(rdsamps > 0); /* end do */
- /* now do trailer */
- rdsamps=BUFLEN;
- if(Trailsamps>0)
- {
- do
- {
- if(!bufcnt) rdsamps = remainder;
- if(!Quickflag)
- {
- for(i=0;i<(rdsamps-1);i+=2)
- {
- Loutput = Fdelbuf[Lopptr]*Delaygain;
- Routput = Fdelbuf[Ropptr]*Delaygain;
- Fdelbuf[Lipptr] = Fdelbuf[Lopptr]*Feedbckgain;
- Fdelbuf[Ripptr] = Fdelbuf[Ropptr]*Feedbckgain;
- Lopptr+=2;
- Ropptr+=2;
- Lipptr+=2;
- Ripptr+=2;
- outbuf[i] = (short) Loutput;
- outbuf[i+1] = (short) Routput;
- if(Lipptr >= Delaysamps) Lipptr -= Delaysamps;
- if(Ripptr >= Delaysamps) Ripptr -= Delaysamps;
- if(Lopptr >= Delaysamps) Lopptr -= Delaysamps;
- if(Ropptr >= Delaysamps) Ropptr -= Delaysamps;
- }
- }
- else
- {
- for(i=0;i<(rdsamps-1);i+=2)
- {
- Ltemp2 = Ldelbuf[Lopptr] >> 16;
- Lopptr+=2;
- Rtemp2 = Ldelbuf[Ropptr] >> 16;
- Ropptr+=2;
- Lloutput = Ltemp2 * Ldelaygain;
- Rloutput = Rtemp2 * Ldelaygain;
- Ldelbuf[Lipptr] = Ltemp2*Lfeedbckgain;
- Ldelbuf[Ripptr] = Rtemp2*Lfeedbckgain;
- Lipptr +=2;
- Ripptr +=2;
- outbuf[i] = (short)(Lloutput>>16);
- outbuf[i+1] = (short)(Rloutput>>16);
- if(Lipptr >= Delaysamps) Lipptr -= Delaysamps;
- if(Ripptr >= Delaysamps) Ripptr -= Delaysamps;
- if(Lopptr >= Delaysamps) Lopptr -= Delaysamps;
- if(Ropptr >= Delaysamps) Ropptr -= Delaysamps;
- }
- }
- if(fputsbuf(outbuf,rdsamps,ofd) < rdsamps) {
- fprintf(stderr,"\ndelay: failure in writing to output file\n");
- exit(1);
- }
- inform(rdsamps/2,Sr);
- bufcnt -=1;
- } while (bufcnt>=0);
- } /* end if */
- } /* end dostereo */
-
- void
- usage()
- {
- fprintf(stderr,"delay - A Groucho Program: $Revision: 3.3 $\n");
- fprintf(stderr,
- "usage: delay [-f][-pN][-i] infile outfile [4 cmndline parameters]\n");
- fprintf(stderr,
- " where -f sets output in floatsams, -p sets prescale = N for infile,\n");
- fprintf(stderr,
- " and -i inverts dry signal (for allpass filters).\n");
- fprintf(stderr,"\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
- "Cmndline option: after [flags] filenames, enter all parameters in this order:",
- " delaytime mix feedbackgain trailertime",
- " 0.0 < delaytime (msecs) <= maxdelay",
- " 0.0 <= mix <= 1.0",
- " -1.0 <= feedbackgain <= 1.0",
- " 0.0 <= trailertime (secs) <= 30.0",
- "where maxdelay = 8000ms @22050 mono",
- " = 4000ms @22050 stereo, and 44100 mono",
- " = 2000ms @44100 stereo");
- exit(0);
- }
- void
- delinit(int cmndlin, char *argv[])
- {
- double temp,maxdelay,mix;
- char msg[80];
- /* Some jiggery pokery is needed in setting the
- * fixed point variables to avoid overloading
- * the input to the delay line. The input is
- * divided by two in conjunction with prescaling
- * and the feedthrough and delay outputs are
- * raised by two to compensate.
- */
- maxdelay = ((double) (DELBUFSIZ) / Sr) * 1000.0; /* milliseconds */
- if(Nchans==2) {maxdelay /= 2;}
- if(cmndlin)
- {
- temp = atof(argv[3]);
- if (temp > maxdelay)
- {
- printf("delay: delay time too long\n");
- exit(1);
- }
- Delaysamps = (long) ((Sr *temp) / 1000.0);
- mix = atof(argv[4]);
- if((mix < 0.0) || (mix > 1.0))
- {
- printf("delay: mix value out of range\n");
- exit(1);
- }
- Feedbckgain = (float)atof(argv[5]);
- if((Feedbckgain < -1.0) || (Feedbckgain > 1.0))
- {
- printf("delay: feedbackgain out of range\n");
- exit(1);
- }
- Trailtime = atof(argv[6]);
- if((Trailtime < 0.0) || (Trailtime > 1000.0))
- {
- printf("delay: trailtime out of range\n");
- exit(1);
- }
-
- }
- else /* ask for params from terminal */
- {
- printf("max delay in msec = %f\n",maxdelay);
- sprintf(msg,
- "Give delay time in milliseconds :");
- temp = accexpr(msg,0.0,maxdelay,0.0,0,Sr);
- if(temp==0.0)
- {
- printf("\nzero delay time!!! No point in running program. Bye!\n");
- exit(1);
- }
- Delaysamps = (long) ((Sr * temp) / 1000.0);
- printf("\ndelay length in samples = %ld \n",Delaysamps);
- sprintf(msg,
- "Give mix proportion (0.0 <= level <= 1.0) :");
- mix = accexpr(msg,0.0,1.0,0.0,0,Sr);
- sprintf(msg,
- "Give feedback gain (-1.0 <= level <= 1.0) :");
- Feedbckgain = (float)accexpr(msg,-1.0,1.0,0.0,0,Sr);
- sprintf(msg,
- "Give trailer time (default = 0 <= trailtime <= 30.0) :");
- Trailtime = accexpr(msg, 0.0,30.0,0.0,1,Sr);
- }
- /* now massage parameters */
- /* nb delaysamps is per channel here */
-
- Feedforgain = (float)((1.0 - mix)*Invert);
- Lfeedbckgain = (long) (Feedbckgain * ONE_FLT);
- Delaygain = (float)mix;
- Ldelaygain = (long) (Delaygain * ONE_FLT * 2.0);
- Rescale = (1.0 / (Feedbckgain + 1.0)); /* i/p compensation */
- Prescale *= (float)Rescale;
- Lprescale= (long) (Prescale * ONE_FLT * .5);
- Feedforgain /= (float)Rescale;
- Lfeedforgain = (long) (Feedforgain * ONE_FLT * 2.0);
- Trailsamps = (long) (Trailtime * Sr);
- if(Nchans==2) Trailsamps *= 2;
- bufcnt = Trailsamps/BUFLEN;
- remainder = Trailsamps % BUFLEN;
- }
- void
- initfbuf()
- {
- Delaysamps*=Nchans;
- if((Fdelbuf = (float *) calloc(Delaysamps+2, sizeof(float))) == NULL){
- fprintf(stderr,"\ndelay: not enough memory for main delay buffer");
- exit(1);
- }
- }
- void
- initlbuf()
- {
- Delaysamps*=Nchans;
- if((Ldelbuf = (long *) calloc(Delaysamps+4, sizeof(long))) == NULL){
- fprintf(stderr,"\ndelay: not enough memory for main delay buffer");
- exit(1);
- }
- }
|