/* ugen developed by matt ingalls, ... */ /* */ /* diskin - a new soundin that shifts pitch */ /* based on the old soundin code */ #include "cs.h" #include "soundio.h" #include "diskin.h" extern char *retfilnam; extern HEADATA *readheader(int, char *, SOUNDIN*); extern void bytrev2(char*, int); extern void bytrev4(char*, int); extern char *getstrformat(int); extern int getsizformat(int); extern int bytrevhost(void); extern void sndwrterr(unsigned, unsigned); static int sreadinew( /* special handling of sound input */ int infd, /* to accomodate reads thru pipes & net */ char *inbuf, /* where nbytes rcvd can be < n requested*/ int nbytes, /* */ SOUNDINEW *p) /* extra arg passed for filetyp testing */ { /* on POST-HEADER reads of audio samples */ int n, ntot=0; do if ((n = read(infd, inbuf+ntot, nbytes-ntot)) < 0) die("soundfile read error"); while (n > 0 && (ntot += n) < nbytes); if (p->filetyp) { /* for AIFF and WAV samples */ if (p->filetyp == TYP_AIFF) { if (p->audrem > 0) { /* AIFF: */ if (ntot > p->audrem) /* chk haven't exceeded */ ntot = p->audrem; /* limit of audio data */ p->audrem -= ntot; } else ntot = 0; } if (ntot && p->bytrev != NULL) /* for post-header of both */ p->bytrev(inbuf, ntot); /* bytrev 2 or 4 as reqd */ } return(ntot); } void newsndinset(SOUNDINEW *p) /* init routine for soundinew */ { /* this is just like sndinset() with sndgetset() inside of it except it takes the SOUNDINEW struct, and has to form a fake SOUNDIN struct to call readheader() */ int n; HEADATA *hdr; long hdrsize = 0, readlong = 0; /*, framesinbuf, skipframes; -matt */ char *sfname, soundiname[128]; int sinfd; SOUNDIN forReadHeader; /*????*/ if (p->fdch.fd != 0) return; /* if file already open, rtn */ p->channel = ALLCHNLS; /* reading all channels */ p->analonly = 0; /************** now the sndgetset() code..... **********/ if ((n = p->OUTOCOUNT) && n != 1 && n != 2 && n != 4) { /* if appl,chkchnls */ sprintf(errmsg,"diskin: illegal no of receiving channels"); goto errtn; } if (*p->ifilno == sstrcod) /* if char string name given */ strcpy(soundiname,unquote(p->STRARG)); /* unquote it, else use */ else sprintf(soundiname,"soundin.%ld",(long)*p->ifilno); /* soundin.filno */ sfname = soundiname; if ((sinfd = openin(sfname)) < 0) { /* open with full dir paths */ if (isfullpath(sfname)) sprintf(errmsg,"diskin cannot open %s", sfname); else sprintf(errmsg,"diskin can't find \"%s\" in its search paths", sfname); goto errtn; } sfname = retfilnam; /* & record fullpath filnam */ if ((p->format = (short)*p->iformat) > 0) /* convert spec'd format code */ p->format |= 0x100; p->endfile = 0; p->begfile = 0; p->filetyp = 0; /* initially non-typed for readheader */ /******* construct the SOUNDIN struct to use old readheader ***********/ forReadHeader.filetyp = p->filetyp; forReadHeader.bytrev = p->bytrev; forReadHeader.audrem = p->audrem; if ((hdr=readheader(sinfd,sfname,&forReadHeader)) != NULL /* if headerblk returned */ && !(readlong = hdr->readlong)) { /* & hadn't readin audio */ if (hdr->filetyp == TYP_AIFF /* chk the hdr codes */ && hdr->aiffdata != NULL && hdr->aiffdata->loopmode1 != 0 /* looping aiff: */ && (p->analonly || p->OUTOCOUNT)) /* ok for gen01 only */ warning("aiff looping file, once through only"); if (p->analonly) { /* anal: if sr param val */ if (p->sr != 0 && p->sr != hdr->sr) { /* use it */ sprintf(errmsg,"-s %ld overriding soundfile sr %ld", p->sr, hdr->sr); warning(errmsg); hdr->sr = p->sr; } } else if (hdr->sr != esr) { /* non-anal: cmp w. esr */ sprintf(errmsg,"%s sr = %ld, orch sr = %7.1f", sfname, hdr->sr, esr); warning(errmsg); } if (p->OUTOCOUNT) { /* for orch SOUNDIN: */ if (hdr->nchnls != p->OUTOCOUNT) { /* chk nchnls */ sprintf(errmsg,"%s nchnls = %d, soundin reading as if nchnls = %d", sfname, (int) hdr->nchnls, (int) p->OUTOCOUNT); warning(errmsg); hdr->nchnls = p->OUTOCOUNT; } } /* else chk sufficient */ else if (p->channel != ALLCHNLS && p->channel > hdr->nchnls) { sprintf(errmsg,"req chan %d, file %s has only %ld", p->channel, sfname, hdr->nchnls); die(errmsg); } if (p->format && hdr->format != p->format) { sprintf(errmsg,"diskin %s superceded by %s header format %s", getstrformat((int)p->format), sfname, getstrformat((int)hdr->format)); warning(errmsg); } switch ((p->format = (short)hdr->format)) { /* & copy header data */ case AE_CHAR: break; case AE_UNCH: break; case AE_SHORT: break; case AE_LONG: break; case AE_FLOAT: break; default: sprintf(errmsg,"%s format %s not yet supported", sfname, getstrformat((int)p->format)); goto errcls; } p->sampframsiz = (short)(hdr->sampsize * hdr->nchnls); hdrsize = hdr->hdrsize; p->filetyp = hdr->filetyp; /* copy type from headata */ p->aiffdata = hdr->aiffdata; p->sr = (short)hdr->sr; p->nchnls = (short)hdr->nchnls; } else { /* no hdr: find info elsewhere */ if (p->analonly) { if (!p->sr) { p->sr = (long)DFLT_SR; sprintf(errmsg, "no -s and no soundheader, using sr default %ld",p->sr); warning(errmsg); } } else { warning("no soundin header, presuming orchestra sr"); p->sr = (long) esr; } if (!p->OUTOCOUNT && p->channel == ALLCHNLS) p->channel = 1; if (!p->format) { /* no format: */ if (p->analonly) /* analonly defaults to short */ p->format = AE_SHORT; else p->format = O.outformat; /* orch defaults to outformat */ } sprintf(errmsg,"%s has no soundfile header, reading as %s, %d chnl%s", sfname, getstrformat((int)p->format), (int)p->channel, p->channel == 1 ? "" : "s"); warning(errmsg); p->sampframsiz = getsizformat((int)p->format) * p->channel; p->filetyp = 0; /* in_type can't be AIFF or WAV */ p->aiffdata = NULL; p->nchnls = p->channel; } printf("audio sr = %ld, ", p->sr); if (p->nchnls == 1) printf("monaural\n"); else { printf("%s, reading ", p->nchnls == 2 ? "stereo" : "quad"); if (p->channel == ALLCHNLS) printf("%s channels\n", p->nchnls == 2 ? "both" : "all"); else printf("channel %d\n", p->channel); } if (p->filetyp == TYP_AIFF && bytrevhost() || p->filetyp == TYP_AIFC && bytrevhost() || p->filetyp == TYP_WAV && !bytrevhost()) { if (p->format == AE_SHORT) /* if audio_in needs byte rev */ p->bytrev = bytrev2; /* set on sample size */ else if (p->format == AE_LONG) p->bytrev = bytrev4; else p->bytrev = NULL; printf("opening %s infile %s, with%s bytrev\n", p->filetyp == TYP_AIFF ? "AIFF" : TYP_AIFC ? "AIFC" : "WAV", sfname, p->bytrev == NULL ? " no" : ""); } else p->bytrev = NULL; if (p->sampframsiz <= 0) /* must know framsiz */ die("illegal sampframsiz"); if (hdr->audsize > 0 ) /* given audiosize */ p->audrem = p->audsize = hdr->audsize; else p->audrem = -1; /* else mark unknown */ /***** this next section looked kinda iffy, so rewrote it*********-matt*/ { long nbytes = (long)(*p->iskptim * p->sr) * p->sampframsiz; p->firstsampinfile = tell(sinfd); /* this might not work for all header types??? */ if ((p->audrem > 0) && (nbytes > p->audrem)) { warning("skip time larger than audio data,substituting zero."); nbytes = 0; } if (nbytes > 0) { if (hdr->audsize > 0 ) /* change audsize */ p->audrem = p->audsize = p->audsize-nbytes+p->firstsampinfile; if ((p->filepos = lseek(sinfd, nbytes+p->firstsampinfile, 0)) < 0) /* seek to bndry */ die("diskin seek error: invalid skip time"); } else { p->begfile = TRUE; if (*p->ktransp < 0) p->endfile = TRUE; } if ((n = sreadinew(sinfd,p->inbuf,SNDINEWBUFSIZ,p)) == 0) /* now rd fulbuf */ p->endfile = 1; p->inbufp = p->inbuf; p->bufend = p->inbuf + n; } /***********************************************************************/ if (sinfd > 0) { /* if soundinset successful */ p->fdch.fd = sinfd; /* store & log the fd */ fdrecord(&p->fdch); /* instr will close later */ p->guardpt = p->bufend - p->sampframsiz; p->phs = 0.; return; } else initerror(errmsg); return; errcls: close(sinfd); /* init error: close any open file */ errtn: return; /* return empty handed */ } void soundinew(SOUNDINEW *p) /* a-rate routine for soundinew */ { float *r1, *r2, *r3, *r4, ktransp,looping; int chnsout, n, ntogo, bytesLeft; double phs,phsFract,phsTrunc; char *inbufp = p->inbufp; if ((!p->bufend) || (!p->inbufp) || (!p->sampframsiz)) { initerror("diskin: not initialised"); return; } r1 = p->r1; r2 = p->r2; r3 = p->r3; r4 = p->r4; ktransp = *p->ktransp; looping = *p->ilooping; chnsout = p->OUTOCOUNT; phs = p->phs; ntogo = ksmps; if (ktransp > 0 ) { /* forwards... */ if (phs < 0) phs = 0; /* we have just switched directions, forget (negative) old phase */ if (p->endfile) { if (p->begfile) p->endfile = FALSE; else goto filend; } while (ntogo) { switch (chnsout) { /* a lot of the following code has been "written out" for speed */ case 1: phsFract = modf(phs,&phsTrunc); switch (p->format) { case AE_CHAR: do { *r1++ = (float) (*(char *)inbufp + (*(char *)(inbufp + 1) - *(char *)inbufp) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_UNCH: do { *r1++ = (float) (*(unsigned char *)inbufp + (*(unsigned char *)(inbufp + 1) - *(unsigned char *)inbufp) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_SHORT: do { *r1++ = (float) (*(short *)inbufp + (*(short *)(inbufp + 2) - *(short *)inbufp) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 2); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_LONG: do { *r1++ = (float) (*(long *)inbufp + (*(long *)(inbufp + 4) - *(long *)inbufp) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 4); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_FLOAT: do { *r1++ = (float) (*(float *)inbufp + (*(float *)(inbufp + 4) - *(float *)inbufp) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 4); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; } break; case 2: phsFract = modf(phs,&phsTrunc); switch (p->format) { case AE_CHAR: do { *r1++ = (float) (*(char *)inbufp + (*(char *)(inbufp + 2) - *(char *)inbufp) * phsFract); *r2++ = (float) (*(char *)(inbufp + 1) + (*(char *)(inbufp + 3) - *(char *)(inbufp + 1)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 2); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_UNCH: do { *r1++ = (float) (*(unsigned char *)inbufp + (*(unsigned char *)(inbufp + 2) - *(unsigned char *)inbufp) * phsFract); *r2++ = (float) (*(unsigned char *)(inbufp + 1) + (*(unsigned char *)(inbufp + 3) - *(unsigned char *)(inbufp + 1)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 2); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_SHORT: do { *r1++ = (float) (*(short *)inbufp + (*(short *)(inbufp + 4) - *(short *)inbufp) * phsFract); *r2++ = (float) (*(short *)(inbufp + 2) + (*(short *)(inbufp + 6) - *(short *)(inbufp + 2)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 4); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_LONG: do { *r1++ = (float) (*(long *)inbufp + (*(long *)(inbufp + 8) - *(long *)inbufp) * phsFract); *r2++ = (float) (*(long *)(inbufp + 4) + (*(long *)(inbufp + 12) - *(long *)(inbufp + 4)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 8); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_FLOAT: do { *r1++ = (float) (*(float *)inbufp + (*(float *)(inbufp + 8) - *(float *)inbufp) * phsFract); *r2++ = (float) (*(float *)(inbufp + 4) + (*(float *)(inbufp + 12) - *(float *)(inbufp + 4)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 8); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; } break; case 4: phsFract = modf(phs,&phsTrunc); switch (p->format) { case AE_CHAR: do { *r1++ = (float) (*(char *)inbufp + (*(char *)(inbufp + 4) - *(char *)inbufp) * phsFract); *r2++ = (float) (*(char *)(inbufp + 1) + (*(char *)(inbufp + 5) - *(char *)(inbufp + 1)) * phsFract); *r3++ = (float) (*(char *)(inbufp + 2) + (*(char *)(inbufp + 6) - *(char *)(inbufp + 2)) * phsFract); *r4++ = (float) (*(char *)(inbufp + 3) + (*(char *)(inbufp + 7) - *(char *)(inbufp + 3)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 4); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_UNCH: do { *r1++ = (float) (*(unsigned char *)inbufp + (*(unsigned char *)(inbufp + 4) - *(unsigned char *)inbufp) * phsFract); *r2++ = (float) (*(unsigned char *)(inbufp + 1) + (*(unsigned char *)(inbufp + 5) - *(unsigned char *)(inbufp + 1)) * phsFract); *r3++ = (float) (*(unsigned char *)(inbufp + 2) + (*(unsigned char *)(inbufp + 6) - *(unsigned char *)(inbufp + 2)) * phsFract); *r4++ = (float) (*(unsigned char *)(inbufp + 3) + (*(unsigned char *)(inbufp + 7) - *(unsigned char *)(inbufp + 3)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 4); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_SHORT: do { *r1++ = (float) (*(short *)inbufp + (*(short *)(inbufp + 8) - *(short *)inbufp) * phsFract); *r2++ = (float) (*(short *)(inbufp + 2) + (*(short *)(inbufp + 10) - *(short *)(inbufp + 2)) * phsFract); *r3++ = (float) (*(short *)(inbufp + 4) + (*(short *)(inbufp + 12) - *(short *)(inbufp + 4)) * phsFract); *r4++ = (float) (*(short *)(inbufp + 6) + (*(short *)(inbufp + 14) - *(short *)(inbufp + 6)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 8); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_LONG: do { *r1++ = (float) (*(long *)inbufp + (*(long *)(inbufp + 16) - *(long *)inbufp) * phsFract); *r2++ = (float) (*(long *)(inbufp + 4) + (*(long *)(inbufp + 20) - *(long *)(inbufp + 4)) * phsFract); *r3++ = (float) (*(long *)(inbufp + 8) + (*(long *)(inbufp + 24) - *(long *)(inbufp + 8)) * phsFract); *r4++ = (float) (*(long *)(inbufp + 12) + (*(long *)(inbufp + 28) - *(long *)(inbufp + 12)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 16); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; case AE_FLOAT: do { *r1++ = (float) (*(float *)inbufp + (*(float *)(inbufp + 16) - *(float *)inbufp) * phsFract); *r2++ = (float) (*(float *)(inbufp + 4) + (*(float *)(inbufp + 20) - *(float *)(inbufp + 4)) * phsFract); *r3++ = (float) (*(float *)(inbufp + 8) + (*(float *)(inbufp + 24) - *(float *)(inbufp + 8)) * phsFract); *r4++ = (float) (*(float *)(inbufp + 12) + (*(float *)(inbufp + 28) - *(float *)(inbufp + 12)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 16); --ntogo; } while ((inbufp < p->guardpt) && (ntogo)); break; } break; } bytesLeft = (int)(p->bufend - inbufp); if (bytesLeft <= p->sampframsiz) { /* first set file position to where inbuf p "thinks" its pointing to */ p->filepos = lseek(p->fdch.fd,-bytesLeft,1); if ((n = sreadinew(p->fdch.fd,p->inbuf,SNDINEWBUFSIZ,p)) == 0) { if (looping) { /* go to beginning of file. depending on the pitch and phase, we might drop a few "guardpoint" samples, but this ugen is intended for large files anyway -- if a few end samples are critical for looping, use oscil or table!!!! */ p->audrem = p->audsize; p->filepos = lseek(p->fdch.fd,p->firstsampinfile,0); if ((n = sreadinew(p->fdch.fd,p->inbuf,SNDINEWBUFSIZ,p)) == 0) die("error trying to loop back to the beginning of the sound file!?!??"); p->begfile = 1; phs = 0; inbufp = p->inbufp = p->inbuf; p->bufend = p->inbuf + n; p->guardpt = p->bufend - p->sampframsiz; } else { p->endfile = TRUE; goto filend; } } else { inbufp = p->inbufp = p->inbuf; p->bufend = p->inbuf + n; p->guardpt = p->bufend - p->sampframsiz; phs = modf(phs,&phsTrunc); p->begfile = FALSE; } } } } else { /* backwards... same thing but different */ if (phs > 0) phs = 0; /* we have just switched directions, forget (positive) old phase */ if (p->endfile) { /* firewall-flag signaling when we are at either end of the file */ if (p->begfile) goto filend; /* make sure we are at beginning, not end */ else p->endfile = FALSE; /* at end, must have just switched directions, start making sound again */ } while (ntogo) { switch(chnsout) { case 1: phsFract = modf(phs,&phsTrunc); /* phsFract and phsTrunc will be non-positive */ switch (p->format) { case AE_CHAR: do { *r1++ = (float) (*(char *)inbufp + (*(char *)inbufp - *(char *)(inbufp - 1)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); /* make sure it points to the second sample or greater in the buffer, because we need at least two to interpolate */ break; case AE_UNCH: do { *r1++ = (float) (*(unsigned char *)inbufp + (*(unsigned char *)inbufp - *(unsigned char *)(inbufp - 1)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; case AE_SHORT: do { *r1++ = (float) (*(short *)inbufp + (*(short *)inbufp - *(short *)(inbufp - 2)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 2); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; case AE_LONG: do { *r1++ = (float) (*(long *)inbufp + (*(long *)inbufp - *(long *)(inbufp - 4)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 4); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; case AE_FLOAT: do { *r1++ = (float) (*(float *)inbufp + (*(float *)inbufp - *(float *)(inbufp - 4)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 4); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; } break; case 2: phsFract = modf(phs,&phsTrunc); /* phsFract will be negative */ switch (p->format) { case AE_CHAR: do { *r1++ = (float) (*(char *)inbufp + (*(char *)inbufp - *(char *)(inbufp - 2)) * phsFract); *r2++ = (float) (*(char *)(inbufp + 1) + (*(char *)(inbufp + 1) - *(char *)(inbufp - 1)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 2); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; case AE_UNCH: do { *r1++ = (float) (*(unsigned char *)inbufp + (*(unsigned char *)inbufp - *(unsigned char *)(inbufp - 2)) * phsFract); *r2++ = (float) (*(unsigned char *)(inbufp + 1) + (*(unsigned char *)(inbufp + 1) - *(unsigned char *)(inbufp - 1)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 2); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; case AE_SHORT: do { *r1++ = (float) (*(short *)inbufp + (*(short *)inbufp - *(short *)(inbufp - 4)) * phsFract); *r2++ = (float) (*(short *)(inbufp + 2) + (*(short *)(inbufp + 2) - *(short *)(inbufp - 2)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 4); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; case AE_LONG: do { *r1++ = (float) (*(long *)inbufp + (*(long *)inbufp - *(long *)(inbufp - 8)) * phsFract); *r2++ = (float) (*(long *)(inbufp + 4) + (*(long *)(inbufp + 4) - *(long *)(inbufp - 4)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 8); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; case AE_FLOAT: do { *r1++ = (float) (*(float *)inbufp + (*(float *)inbufp - *(float *)(inbufp - 8)) * phsFract); *r2++ = (float) (*(float *)(inbufp + 4) + (*(float *)(inbufp + 4) - *(float *)(inbufp - 4)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 8); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; } break; case 4: phsFract = modf(phs,&phsTrunc); /* phsFract will be negative */ switch (p->format) { case AE_CHAR: do { *r1++ = (float) (*(char *)inbufp + (*(char *)inbufp - *(char *)(inbufp - 4)) * phsFract); *r2++ = (float) (*(char *)(inbufp + 1) + (*(char *)(inbufp + 1) - *(char *)(inbufp - 3)) * phsFract); *r3++ = (float) (*(char *)(inbufp + 2) + (*(char *)(inbufp + 2) - *(char *)(inbufp - 2)) * phsFract); *r4++ = (float) (*(char *)(inbufp + 3) + (*(char *)(inbufp + 3) - *(char *)(inbufp - 1)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 4); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; case AE_UNCH: do { *r1++ = (float) (*(unsigned char *)inbufp + (*(unsigned char *)inbufp - *(unsigned char *)(inbufp - 4)) * phsFract); *r2++ = (float) (*(unsigned char *)(inbufp + 1) + (*(unsigned char *)(inbufp + 1) - *(unsigned char *)(inbufp - 3)) * phsFract); *r3++ = (float) (*(unsigned char *)(inbufp + 2) + (*(unsigned char *)(inbufp + 2) - *(unsigned char *)(inbufp - 2)) * phsFract); *r4++ = (float) (*(unsigned char *)(inbufp + 3) + (*(unsigned char *)(inbufp + 3) - *(unsigned char *)(inbufp - 1)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 4); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; case AE_SHORT: do { *r1++ = (float) (*(short *)inbufp + (*(short *)inbufp - *(short *)(inbufp - 8)) * phsFract); *r2++ = (float) (*(short *)(inbufp + 2) + (*(short *)(inbufp + 2) - *(short *)(inbufp - 6)) * phsFract); *r3++ = (float) (*(short *)(inbufp + 4) + (*(short *)(inbufp + 4) - *(short *)(inbufp - 4)) * phsFract); *r4++ = (float) (*(short *)(inbufp + 6) + (*(short *)(inbufp + 6) - *(short *)(inbufp - 2)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 8); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; case AE_LONG: do { *r1++ = (float) (*(long *)inbufp + (*(long *)inbufp - *(long *)(inbufp - 16)) * phsFract); *r2++ = (float) (*(long *)(inbufp + 4) + (*(long *)(inbufp + 4) - *(long *)(inbufp - 12)) * phsFract); *r3++ = (float) (*(long *)(inbufp + 8) + (*(long *)(inbufp + 8) - *(long *)(inbufp - 8)) * phsFract); *r4++ = (float) (*(long *)(inbufp + 12) + (*(long *)(inbufp + 12) - *(long *)(inbufp - 4)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 16); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; case AE_FLOAT: do { *r1++ = (float) (*(float *)inbufp + (*(float *)inbufp - *(float *)(inbufp - 16)) * phsFract); *r2++ = (float) (*(float *)(inbufp + 4) + (*(float *)(inbufp + 4) - *(float *)(inbufp - 12)) * phsFract); *r3++ = (float) (*(float *)(inbufp + 8) + (*(float *)(inbufp + 8) - *(float *)(inbufp - 8)) * phsFract); *r4++ = (float) (*(float *)(inbufp + 12) + (*(float *)(inbufp + 12) - *(float *)(inbufp - 4)) * phsFract); phs += ktransp; phsFract = modf(phs,&phsTrunc); inbufp = p->inbufp + (long)(phsTrunc * 16); --ntogo; } while ((inbufp > p->inbuf) && (ntogo)); break; } break; } if (inbufp <= p->inbuf) { /* we need to get some more samples!! */ if (p->begfile) { if (looping) { /* hopes this works -- set 1 buffer lenght at end of sound file */ p->filepos = lseek(p->fdch.fd, p->firstsampinfile+p->audsize-SNDINEWBUFSIZ, 0); phs = -0.; p->begfile = 0; } else { p->endfile = 1; goto filend; } } else { bytesLeft = (int)(inbufp - p->inbuf + p->sampframsiz); /* we're going backwards, so bytesLeft should be * non-positive because inpufp should be pointing * to the first sample in the buffer or "in front" * the buffer. But we must add a sample frame * (p->ampframsiz) to make sure the sample we are * pointing at right now becomes the last sample * in the next buffer*/ if ((p->filepos = lseek(p->fdch.fd, (bytesLeft-SNDINEWBUFSIZ-SNDINEWBUFSIZ), 1)) <= p->firstsampinfile) { p->filepos = lseek(p->fdch.fd,p->firstsampinfile,0); p->begfile = 1; } } p->audrem = p->audsize; /* a hack to prevent errors (returning 'ntot')in the sread for AIFF */ if ((n = sreadinew(p->fdch.fd,p->inbuf,SNDINEWBUFSIZ,p)) != SNDINEWBUFSIZ) { /* we should never get here. if we do, we're fucked because didn't get a full buffer and our present sample is the last sample of the buffer!!! */ die("diskin read error - during backwards playback"); return; } /* now get the correct remaining size */ p->audrem = p->audsize - p->firstsampinfile - p->filepos; p->bufend = p->inbuf + n; /* point to the last sample in buffer */ inbufp = p->inbufp = p->guardpt = p->bufend - p->sampframsiz; phs = modf(phs,&phsTrunc); } } } p->inbufp = inbufp; p->phs = modf(phs,&phsTrunc); return; filend: switch(chnsout) { /* if past end of file, */ case 1: do *r1++ = 0.0f; /* move in zeros */ while (--ntogo); break; case 2: do { *r1++ = 0.0f; *r2++ = 0.0f; } while (--ntogo); break; case 4: do { *r1++ = 0.0f; *r2++ = 0.0f; *r3++ = 0.0f; *r4++ = 0.0f; } while (--ntogo); } } /* Empty buffer to file */ static void sndwrt1(int fd, float *buf, int nsamps) /* diskfile write */ { int n; char buffer[SNDOUTSMPS]; for (n=0; n 32767) x = 32767; else if (x < -32768) x = 32768; buffer[n] = (char)(x >> 8); } if ((n = write(fd, (char*)buffer, nsamps)) < nsamps) sndwrterr(n, nsamps); } static void sndwrtu(int fd, float *buf, int nsamps) /* diskfile write */ { int n; unsigned char buffer[SNDOUTSMPS]; for (n=0; n 32767) x = 32767; else if (x < -32768) x = 32768; buffer[n] = (unsigned char)(x >> 8)^0x80; } if ((n = write(fd, buffer, nsamps)) < nsamps) sndwrterr(n, nsamps); } static void sndwrt2rev(int fd, float *buf, int nsamps) /* diskfile write */ { int n, nbytes; short buffer[SNDOUTSMPS]; for (n=0; n 32767) x = 32767; else if (x < -32768) x = 32768; buffer[n] = (short)x; } bytrev2((char *)buffer, nbytes = (nsamps<<1)); /* rev bytes in shorts */ if ((n = write(fd, (char*)buffer, nbytes)) < nbytes) sndwrterr(n, nbytes); } static void sndwrt2(int fd, float *buf, int nsamps) /* diskfile write */ { int n, nbytes; short buffer[SNDOUTSMPS]; for (n=0; n 32767) x = 32767; else if (x < -32768) x = 32768; buffer[n] = (short)x; } nbytes = nsamps << 1; if ((n = write(fd, buffer, nbytes)) < nbytes) sndwrterr(n, nbytes); } static void sndwrt4rev(int fd, float *buf, int nsamps) /* diskfile write */ { int n, nbytes; long buffer[SNDOUTSMPS]; for (n=0; nc.fdch.fd != 0) return; /* if file already open, rtn */ if (*p->c.ifilcod == sstrcod) strcpy(sndoutname, unquote(p->STRARG)); else if ((filno = (int)*p->c.ifilcod) >= 0) /* Positive or negative? */ sprintf(sndoutname,"soundout.%d", filno); /* else { */ /* char *setname; */ /* if (strsets != NULL && filno <= STRSMAX */ /* && (setname = strsets[filno]) != NULL) */ /* strcpy(sndoutname, setname); */ /* else { */ /* sprintf(errmsg,"soundout: no strset %d in orch", filno); */ /* goto errtn; */ /* } */ /* } */ sfname = sndoutname; if ((soutfd = openout(sfname, 1)) < 0) { /* if openout successful */ if (isfullpath(sfname)) sprintf(errmsg,"soundout cannot open %s", sfname); else sprintf(errmsg,"soundout can't find %s in search paths", sfname); goto errtn; } sfname = retfilnam; if ((p->c.format = (short)*p->c.iformat) > 0) p->c.format |= 0x100; if (p->c.filetyp == TYP_AIFF && bytrevhost() || p->c.filetyp == TYP_AIFC && bytrevhost() || p->c.filetyp == TYP_WAV && !bytrevhost()) { int rev; switch(p->c.format) { case AE_UNCH: p->c.swrtmethod = sndwrtu; rev = 0; break; case AE_CHAR: case AE_ALAW: case AE_ULAW: p->c.swrtmethod = sndwrt1; rev = 0; break; case AE_SHORT: p->c.swrtmethod = sndwrt2rev; rev = 1; break; case AE_LONG: p->c.swrtmethod = sndwrt4rev; rev = 1; break; case AE_FLOAT: p->c.swrtmethod = sndwrtf; rev = 0; break; } printf("opening %s outfile %s, with%s bytrev\n", p->c.filetyp==TYP_AIFF ? "AIFF": p->c.filetyp==TYP_AIFC ? "AIFC":"WAV", sfname, rev ? "":" no"); } else switch(p->c.format) { case AE_UNCH: p->c.swrtmethod = sndwrt1; break; case AE_CHAR: case AE_ALAW: case AE_ULAW: p->c.swrtmethod = sndwrt1; break; case AE_SHORT: p->c.swrtmethod = sndwrt2; break; case AE_LONG: p->c.swrtmethod = sndwrt4; break; case AE_FLOAT: p->c.swrtmethod = sndwrtf; break; } p->c.outbufp = p->c.outbuf; /* fix - isro 20-11-96 */ p->c.bufend = p->c.outbuf + SNDOUTSMPS; /* fix - isro 20-11-96 */ p->c.fdch.fd = soutfd; /* store & log the fd */ fdrecord(&p->c.fdch); /* instr will close later */ return; errtn: initerror(errmsg); /* else just print the errmsg */ } void soundout(SNDOUT *p) { float *outbufp, *asig; int nn, nsamps, ospace; asig = p->asig; outbufp = p->c.outbufp; nsamps = ksmps; ospace = (p->c.bufend - outbufp); nchk: if ((nn = nsamps) > ospace) nn = ospace; nsamps -= nn; ospace -= nn; do *outbufp++ = *asig++; while (--nn); if (!ospace) { /* when buf is full */ p->c.swrtmethod(p->c.fdch.fd, (void *)p->c.outbuf, p->c.bufend - p->c.outbuf); outbufp = p->c.outbuf; ospace = SNDOUTSMPS; if (nsamps) goto nchk; /* chk rem samples */ } p->c.outbufp = outbufp; } void sndo2set(SNDOUTS *p) {} void soundouts(SNDOUTS *p) {}