/* * Copyright (c) 1983-2023 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 * */ /* RWD 22/02/2018 replaced hamming with vonhann window for smooth frame transition. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int outfloats(float *nextOut, float *maxsampl,float *minsample,int *num_overflows,int todo, dataptr dz); static int pvoc_float_array(int nnn,float **ptr); static int sndwrite_header(float R,dataptr dz); #if 0 static void hamming(float *win,int winLen,int even); #endif static void vonhann(float *win,int winLen,int even); static int pvoc_time_display(int nI,unsigned int samps_so_far,int srate,int *samptime,dataptr dz); static void reset_file_params_for_analout(int orig_proctype,int orig_srate, int orig_chans,int orig_stype,dataptr dz); /****************************** PVOC_OUT ************************* * * 1) This code assumes there is an output analysis file from a previous process. * 2) It assumes that the NAME of that file (orig_outfilename) is NOT the name of the new file being created. * In fact its name have a HIGHER numeric index, so when it is deleted there are no gaps * in the numbering of VALID outfiles (which run from 0 upwards). * 3) root_outfname is the base outfilename, without its numeric add-on * 'jj' is the humeric extension which will be added to that root name. * 4) any INPUT file(s) to previous process MUST BE CLOSED before calling this function * 5) floats_out = number of float samples in analysis file * 6) samps_so_far is counter of TOTAL floats written out to any output files so far, * and is accumulated to the write-count sent to the timer-display bar by PVOC. * It does not affect counters in writing of file data. * Time-display for the process containing this function should be calculated as fraction of dz->tempsize, * which itself must hold the total of ALL the samps written out to ALL the files over the whole process. * 7) the original analysis file (input to this function) is closed AND DELETED by this process. * 8) mxfft() must be included in compilation, for this to work. */ int pvoc_out (int floats_out,unsigned int *samps_so_far,char *orig_outfilename, char *root_outname, int jj, dataptr dz) { int exit_status; int orig_proctype, orig_chans, orig_stype; int orig_srate; int orig_infilecnt = dz->infilecnt; int len = strlen(orig_outfilename); char filename[256]; int stype; /*RWD 2004 */ char pfname[_MAX_PATH]; //Create enough space to remember filename if(dz->wordstor == NULL) { if((dz->wordstor = (char **)malloc(sizeof(char *)))==NULL) return(MEMORY_ERROR); dz->wordstor[0] = NULL; if((dz->wordstor[0] = (char *)malloc((len + 1) * sizeof(char *)))==NULL) return(MEMORY_ERROR); } else { if(strlen(dz->wordstor[0]) < (unsigned int)len) { if((dz->wordstor[0] = (char *)realloc((char *)dz->wordstor[0],(len + 1) * sizeof(char *)))==NULL) return(MEMORY_ERROR); } } strcpy(dz->wordstor[0],orig_outfilename); /* save name of file in dz->wordstor[0]: in this case, no malloc reqd */ strcpy(filename,root_outname); /* create new outfilename, for sound output */ //TW REVISION new protocol : always pass outfile extension to cmdline insert_new_number_at_filename_end(filename,jj,0); dz->infilecnt = 2; /* tell system we have 1 inputfile */ /*RWD Feb 2004 write full anal props so we can inspect etc */ #ifdef _DEBUG if(sndputprop(dz->ofd,"original sampsize", (char *)&(dz->outfile->origstype), sizeof(int)) < 0){ sprintf(errstr,"Failure to write original sample size. headwrite()\n"); return(PROGRAM_ERROR); } if(sndputprop(dz->ofd,"original sample rate", (char *)&(dz->outfile->origrate), sizeof(int)) < 0){ sprintf(errstr,"Failure to write original sample rate. headwrite()\n"); return(PROGRAM_ERROR); } if(sndputprop(dz->ofd,"arate",(char *)&(dz->outfile->arate),sizeof(float)) < 0){ sprintf(errstr,"Failed to write analysis sample rate. headwrite()\n"); return(PROGRAM_ERROR); } if(sndputprop(dz->ofd,"analwinlen",(char *)&(dz->outfile->Mlen),sizeof(int)) < 0){ sprintf(errstr,"Failure to write analysis window length. headwrite()\n"); return(PROGRAM_ERROR); } if(sndputprop(dz->ofd,"decfactor",(char *)&(dz->outfile->Dfac),sizeof(int)) < 0){ sprintf(errstr,"Failure to write decimation factor. headwrite()\n"); return(PROGRAM_ERROR); } #endif /* set output file as input file */ sndcloseEx(dz->ofd); dz->ofd = -1; if(dz->ifd == NULL) allocate_filespace(dz); if((dz->ifd[0] = sndopenEx(orig_outfilename,0,CDP_OPEN_RDONLY)) < 0) { sprintf(errstr,"Cannot reopen temporary analysis file '%s' to generate sound data:%s\n", orig_outfilename,sferrstr()); return(SYSTEM_ERROR); } *samps_so_far += dz->total_samps_written; reset_file_params_for_sndout(&orig_proctype,&orig_srate,&orig_chans,&orig_stype,dz); if(dz->floatsam_output==1) stype = SAMP_FLOAT; else stype = SAMP_SHORT; dz->true_outfile_stype = stype; if((dz->ofd = sndcreat_formatted(filename,-1,stype, 1,(int)round(dz->param[SS_SRATE]),CDP_CREATE_NORMAL)) < 0) { sprintf(errstr,"Cannot open output intermediate soundfile %s\n", filename); return(DATA_ERROR); } dz->total_samps_written = 0L; dz->insams[0] = floats_out; /*RWD need retval - may run out of memory! */ if((exit_status = pvoc_process_addon(*samps_so_far,dz)) < 0) //TW Bare messages break sound Loom messaging system return exit_status; samps_so_far += dz->total_samps_written; /*RWD Feb 2004 */ if(dz->ifd[0] >= 0){ strcpy(pfname,snd_getfilename(dz->ifd[0])); if(sndcloseEx(dz->ifd[0]) < 0) { sprintf(errstr,"Can't close intermediate analfile %s\n",orig_outfilename); return(SYSTEM_ERROR); } } dz->ifd[0] = -1; if(remove(/*orig_outfilename*/pfname)<0) { fprintf(stdout,"WARNING: Can't remove temporary analysis file %s\n",/*orig_outfilename*/pfname); fflush(stdout); } sndcloseEx(dz->ofd); reset_file_params_for_analout(orig_proctype,orig_srate,orig_chans,orig_stype,dz); dz->infilecnt = orig_infilecnt; return(FINISHED); } /****************************** HAMMING ******************************/ #if 0 void hamming(float *win,int winLen,int even) { float Pi,ftmp; int i; /*********************************************************** Pi = (float)((double)4.*atan((double)1.)); ***********************************************************/ Pi = (float)PI; ftmp = Pi/winLen; if (even) { for (i=0; iinfile->channels - 2, analWinLen, /* half-length of analysis window */ synWinLen; /* half-length of synthesis window */ int outCount, /* number of samples written to output */ ibuflen, /* length of input buffer */ obuflen, /* length of output buffer */ nI = 0, /* current input (analysis) sample */ nO, /* current output (synthesis) sample */ nMaxOut; /* last output (synthesis) sample */ int isr, /* sampling rate */ endsamp = VERY_BIG_INT; float mag, /* magnitude of analysis data */ phase, /* phase of analysis data */ //RoverTwoPi, /* R/D divided by 2*Pi */ TwoPioverR, /* 2*Pi divided by R/I */ sum, /* scale factor for renormalizing windows */ //rIn, /* decimated sampling rate */ rOut, /* pre-interpolated sampling rate */ R; /* input sampling rate */ int i,j,k, /* index variables */ Dd, /* number of new inputs to read (Dd <= D) */ Ii, /* number of new outputs to write (Ii <= I) */ N2, /* pvoc_chans/2 */ NO, /* synthesis NO = pvoc_chans / P */ NO2, /* NO/2 */ IO, /* synthesis IO = I / P */ IOi, /* synthesis IOi = Ii / P */ Mf = 0, /* flag for even M */ #ifdef SINGLE_SAMP rv, /* return value from fgetfloat */ #endif flag = 0; /* end-of-input flag */ float arate; /* sample rate for header on stdout if -A */ /*RWD*/ float F = 0.0f; #if defined(__SC__) && defined(SOFT_FP) extern int _8087; _8087 = 0; #endif { char *mem; if((mem = malloc(64*SECSIZE)) == 0 //TW dz->snd_ifd no longer exists /* RWD Nov 2011 not allowed to call sndsetbuf these days! */ /* ||sndsetbuf(dz->ifd[0], mem, 64) < 0 */ ) { /*RWD*/ sprintf(errstr, "pvoc: Can't set big input buffer\n"); return(MEMORY_ERROR); } } isr = dz->infile->origrate; arate = dz->infile->arate; M = dz->infile->Mlen; D = dz->infile->Dfac; R = ((float) D * arate); if(flteq(R,0.0)) { sprintf(errstr,"Problem: zero sampling rate\n"); return(DATA_ERROR); } N2 = pvoc_chans / 2; F = /*(int)*/(R /(float)pvoc_chans); Mf = 1 - M%2; if (M < 7) { fprintf(stdout,"WARNING: analWindow impulse response is too small\n"); fflush(stdout); } ibuflen = 4 * M; obuflen = 4 * M; I = D; NO = pvoc_chans; /* synthesis transform will be NO points */ NO2 = NO/2; IO = I; if((exit_status = sndwrite_header(R,dz))<0) return(exit_status); /* set up analysis window: The window is assumed to be symmetric with M total points. After the initial memory allocation, analWindow always points to the midpoint of the window (or one half sample to the right, if M is even); analWinLen is half the true window length (rounded down). Any low pass window will work; a Hamming window is generally fine, but a Kaiser is also available. If the window duration is longer than the transform (M > N), then the window is multiplied by a sin(x)/x function to meet the condition: analWindow[Ni] = 0 for i != 0. In either case, the window is renormalized so that the phase vocoder amplitude estimates are properly scaled. The maximum allowable window duration is ibuflen/2. */ if((exit_status = pvoc_float_array(M+Mf,&analWindow))<0) return(exit_status); analWindow += (analWinLen = M/2); //hamming(analWindow,analWinLen,Mf); vonhann(analWindow,analWinLen,Mf); for (i = 1; i <= analWinLen; i++) *(analWindow - i) = *(analWindow + i - Mf); if (M > pvoc_chans) { if (Mf) *analWindow *=(float) ((double)pvoc_chans*sin((double)PI*.5/pvoc_chans)/(double)(PI*.5)); for (i = 1; i <= analWinLen; i++) *(analWindow + i) *=(float) ((double)pvoc_chans * sin((double) (PI*(i+.5*Mf)/pvoc_chans)) / (PI*(i+.5*Mf))); /*RWD*/ for (i = 1; i <= analWinLen; i++) *(analWindow - i) = *(analWindow + i - Mf); } sum = 0.0f; for (i = -analWinLen; i <= analWinLen; i++) sum += *(analWindow + i); sum = (float)(2.0/sum); /*factor of 2 comes in later in trig identity*/ for (i = -analWinLen; i <= analWinLen; i++) *(analWindow + i) *= sum; /* set up synthesis window: For the minimal mean-square-error formulation (valid for N >= M), the synthesis window is identical to the analysis window (except for a scale factor), and both are even in length. If N < M, then an interpolating synthesis window is used. */ if((exit_status = pvoc_float_array(M+Mf,&synWindow))<0) return(exit_status); synWindow += (synWinLen = M/2); if (M <= pvoc_chans){ //hamming(synWindow,synWinLen,Mf); vonhann(synWindow,synWinLen,Mf); for (i = 1; i <= synWinLen; i++) *(synWindow - i) = *(synWindow + i - Mf); for (i = -synWinLen; i <= synWinLen; i++) *(synWindow + i) *= sum; sum = 0.0f; for (i = -synWinLen; i <= synWinLen; i+=I) sum += *(synWindow + i) * *(synWindow + i); sum = (float)(1.0/ sum); for (i = -synWinLen; i <= synWinLen; i++) *(synWindow + i) *= sum; } else { //hamming(synWindow,synWinLen,Mf); vonhann(synWindow,synWinLen,Mf); for (i = 1; i <= synWinLen; i++) *(synWindow - i) = *(synWindow + i - Mf); if (Mf) *synWindow *= (float)((double)IO * sin((double) (PI*.5/IO)) / (double)(PI*.5)); for (i = 1; i <= synWinLen; i++) *(synWindow + i) *=(float) ((double)IO * sin((double) (PI*(i+.5*Mf)/IO)) /(double) (PI*(i+.5*Mf))); for (i = 1; i <= synWinLen; i++) *(synWindow - i) = *(synWindow + i - Mf); sum = (float)(1.0/sum); for (i = -synWinLen; i <= synWinLen; i++) *(synWindow + i) *= sum; } /* set up input buffer: nextIn always points to the next empty word in the input buffer (i.e., the sample following sample number (n + analWinLen)). If the buffer is full, then nextIn jumps back to the beginning, and the old values are written over. */ if((exit_status = pvoc_float_array(ibuflen,&input))<0) return(exit_status); // nextIn = input; /* set up output buffer: nextOut always points to the next word to be shifted out. The shift is simulated by writing the value to the standard output and then setting that word of the buffer to zero. When nextOut reaches the end of the buffer, it jumps back to the beginning. */ if((exit_status = pvoc_float_array(obuflen,&output))<0) return(exit_status); nextOut = output; /* set up analysis buffer for (N/2 + 1) channels: The input is real, so the other channels are redundant. oldInPhase is used in the conversion to remember the previous phase when calculating phase difference between successive samples. */ if((exit_status = pvoc_float_array(pvoc_chans+2,&anal))<0) return(exit_status); if((exit_status = pvoc_float_array(N2+1,&oldInPhase))<0) return(exit_status); if((exit_status = pvoc_float_array(N2+1,&maxAmp))<0) return(exit_status); if((exit_status = pvoc_float_array(N2+1,&avgAmp))<0) return(exit_status); if((exit_status = pvoc_float_array(N2+1,&avgFrq))<0) return(exit_status); if((exit_status = pvoc_float_array(N2+1,&env))<0) return(exit_status); /* set up synthesis buffer for (pvoc_chans/2 + 1) channels: (This is included only for clarity.) oldOutPhase is used in the re- conversion to accumulate angle differences (actually angle difference per second). */ if((exit_status = pvoc_float_array(NO+2,&syn))<0) return(exit_status); bsyn = syn + 1; if((exit_status = pvoc_float_array(NO2+1,&oldOutPhase))<0) return(exit_status); /* initialization: input time starts negative so that the rightmost edge of the analysis filter just catches the first non-zero input samples; output time is always T times input time. */ outCount = 0; //rIn = (float)(R/(float)D); rOut = (float)(R/(float)I); //RoverTwoPi = (float)(rIn/TWOPI); TwoPioverR = (float)(TWOPI/rOut); nI = -(analWinLen / D) * D; /* input time (in samples) */ nO = nI; /* output time (in samples) */ Dd = analWinLen + nI + 1; /* number of new inputs to read */ Ii = 0; /* number of new outputs to write */ IOi = 0; flag = 1; /* main loop: If endsamp is not specified it is assumed to be very large and then readjusted when fgetfloat detects the end of input. */ while(nI < (endsamp + analWinLen)){ #ifdef SINGLE_SAMP for (i = 0; i < pvoc_chans+2; i++){ /* synthesis only */ if ((rv = fgetfloat((anal+i),dz->ifd[0])) <= 0){ goto epilog; } } #else //TW snd_ibuf no longer exists if((i = fgetfbufEx(anal, pvoc_chans+2, dz->ifd[0],0)) < 0) { /*RWD*/ sfperror("pvoc: read error: "); return(PROGRAM_ERROR); } if(i < pvoc_chans+2) goto epilog; #endif /* reconversion: The magnitude and angle-difference-per-second in syn (assuming an intermediate sampling rate of rOut) are converted to real and imaginary values and are returned in syn. This automatically incorporates the proper phase scaling for time modifications. */ if (NO <= pvoc_chans){ for (i = 0; i < NO+2; i++) *(syn+i) = *(anal+i); } else { for (i = 0; i <= pvoc_chans+1; i++) *(syn+i) = *(anal+i); for (i = pvoc_chans+2; i < NO+2; i++) *(syn+i) = 0.0f; } for(i=0, i0=syn, i1=syn+1; i<= NO2; i++,i0+=2,i1+=2) { mag = *i0; *(oldOutPhase + i) += *i1 - ((float) i * F); phase = *(oldOutPhase + i) * TwoPioverR; *i0 = (float)((double)mag * cos((double)phase)); *i1 = (float)((double)mag * sin((double)phase)); } /* synthesis: The synthesis subroutine uses the Weighted Overlap-Add technique to reconstruct the time-domain signal. The (pvoc_chans/2 + 1) phase vocoder channel outputs at time n are inverse Fourier transformed, windowed, and added into the output array. The subroutine thinks of output as a shift register in which locations are referenced modulo obuflen. Therefore, the main program must take care to zero each location which it "shifts" out (to standard output). The subroutines reals and fft together perform an efficient inverse FFT. */ if((exit_status = reals_(syn,bsyn,NO2,2))<0) return(exit_status); if((exit_status = fft_(syn,bsyn,1,NO2,1,2))<0) return(exit_status); j = nO - synWinLen - 1; while (j < 0) j += obuflen; j = j % obuflen; k = nO - synWinLen - 1; while (k < 0) k += NO; k = k % NO; for (i = -synWinLen; i <= synWinLen; i++) { /*overlap-add*/ if (++j >= obuflen) j -= obuflen; if (++k >= NO) k -= NO; *(output + j) += *(syn + k) * *(synWindow + i); } #ifdef SINGLE_SAMP for (i = 0; i < IOi; i++) { /* shift out next IOi values */ fputfloat(nextOut,dz->ofd); *(nextOut++) = 0.; if (nextOut >= (output + obuflen)) nextOut -= obuflen; outCount++; } #else for (i = 0; i < IOi;) { /* shift out next IOi values */ int j; int todo = min(IOi-i, output+obuflen-nextOut); if((exit_status = outfloats(nextOut,&maxsample,&minsample,&num_overflows,todo, dz))<0) return(exit_status); i += todo; outCount += todo; for(j = 0; j < todo; j++) *nextOut++ = 0.0f; if (nextOut >= (output + obuflen)) nextOut -= obuflen; } #endif if(flag /* flag means do this operation only once */ && (nI > 0) && (Dd < D)) { /* EOF detected */ flag = 0; endsamp = nI + analWinLen - (D - Dd); } nI += D; /* increment time */ nO += IO; /* Dd = D except when the end of the sample stream intervenes */ Dd = min(D, max(0, D+endsamp-nI-analWinLen)); if (nO > (synWinLen + I)) Ii = I; else if (nO > synWinLen) Ii = nO - synWinLen; else { Ii = 0; for (i=nO+synWinLen; i 0) *(output+i) = 0.0f; } } IOi = Ii; if(nI > samptime && (exit_status = pvoc_time_display(nI,samps_so_far,isr,&samptime,dz))<0) return(exit_status); } /* End of main while loop */ nMaxOut = endsamp; while (outCount <= nMaxOut){ #ifdef SINGLE_SAMP outCount++; fputfloat(nextOut++,dz->ofd); if (nextOut >= (output + obuflen)) nextOut -= obuflen; #else int todo = min(nMaxOut-outCount, output+obuflen-nextOut); if(todo == 0) break; if((exit_status = outfloats(nextOut,&maxsample,&minsample,&num_overflows,todo, dz))<0) return(exit_status); outCount += todo; nextOut += todo; if (nextOut >= (output + obuflen)) nextOut -= obuflen; #endif } if((exit_status = pvoc_time_display((int)endsamp,samps_so_far,isr,&samptime,dz))<0) return(exit_status); epilog: #ifndef NOOVERCHK if(num_overflows > 0) { biggest = maxsample; if(-minsample > maxsample) biggest = -minsample; fprintf(stdout, "WARNING: %d samples overflowed, and were clipped\n",num_overflows); fprintf(stdout, "WARNING: maximum sample was %f : minimum sample was %f\n",maxsample,minsample); fprintf(stdout, "WARNING: You should reduce source level to avoid clipping: use gain of <= %lf\n",1.0/biggest); fflush(stdout); } #endif return(FINISHED); } /*MCA * Convert floats -> shorts explicitly, since we are compiled with * hardware FP(probably), and the sound filing system is not! * (even without this, it should be more efficient!) */ //TW NO CONVERSION TO FLOATS NEEDED 2002 int outfloats(float *nextOut,float *maxsample,float *minsample,int *num_overflows,int todo, dataptr dz) { static float *sbuf = 0; static int sblen = 0; float *sp; int cnt; float val; if(sblen < todo) { if(sbuf != 0) free(sbuf); if((sbuf = (float *)malloc(todo*sizeof(float))) == 0) { sprintf(errstr, "pvoc: can't allocate output buffer\n"); return(MEMORY_ERROR); } sblen = todo; } sp = sbuf; #ifdef NOOVERCHK for(cnt = 0; cnt < todo; cnt++) *sp++ = *nextOut++; #else for(cnt = 0; cnt < todo; cnt++) { val = *nextOut++; if(val >= 1.0 || val <= -1.0) { (*num_overflows)++; if(val > 0.0f) { if(val > *maxsample) *maxsample = val; val = 1.0f; } if(val < 0.0f) { if(val < *minsample) *minsample = val; val = -1.0f; } } *sp++ = val; } #endif // if(fputfbufEx(sbuf, todo, ofd) < todo) { if(todo > 0) { if(write_samps(sbuf, todo, dz) < 0) { sfperror("pvoc: write error"); return(SYSTEM_ERROR);; } } //TW UPDATE return FINISHED; } /************************************ SNDWRITE_HEADER ************************************/ /*RWD changed dz->ofd to to dz->ofd */ int sndwrite_header(float R,dataptr dz) { int Nchans = 1; int isr = (int)R; if(sndputprop(dz->ofd,"sample rate",(char *)&isr,sizeof(int)) < 0 ) fprintf(stdout,"WARNING: failed to write sample rate\n"); if(sndputprop(dz->ofd,"channels",(char *)&Nchans,sizeof(int)) < 0 ) fprintf(stdout,"WARNING: failed to write channel data\n"); fflush(stdout); return(FINISHED); } /*********************************** PVOC_TIME_DISPLAY ***********************************/ int pvoc_time_display(int nI,unsigned int samps_so_far,int srate,int *samptime,dataptr dz) { int true_chans, true_srate; true_chans = dz->infile->channels; true_srate = dz->infile->srate; dz->infile->channels = 1; dz->infile->srate = srate; display_virtual_time(nI + samps_so_far,dz); dz->infile->channels = true_chans; dz->infile->srate = true_srate; *samptime += SAMP_TIME_STEP; return(FINISHED); } /*void get_name_of_intermediate_file(char *filename,char *nufilename) { char temp[256]; char *p; strcpy(nufilename,filename); p = nufilename + strlen(nufilename) - 1; while(p > nufilename) { if(*p == '/' || *p == '\\' || *p == ':') { p = nufilename; break; } if(*p == '.') { p--; c = *p; c += 2; *p = c; return; } p--; } if(p == nufilename) { p = nufilename + strlen(nufilename) - 1; c = *p; c += 2; *p = c; } } */ void reset_file_params_for_sndout (int *orig_proctype,int *orig_srate,int *orig_chans,int *orig_stype,dataptr dz) { int stype; if(dz->floatsam_output==1 ) stype= SAMP_FLOAT; else stype = SAMP_SHORT; dz->true_outfile_stype = stype; *orig_proctype = dz->process_type; *orig_srate = dz->outfile->srate; *orig_chans = dz->outfile->channels; *orig_stype = dz->outfile->stype; dz->process_type = UNEQUAL_SNDFILE; dz->outfile->srate = dz->infile->srate = dz->iparam[SS_SRATE]; dz->outfile->channels = MONO; dz->outfile->stype = /* dz->outfile->stype = */ stype; /* RWD: should that be infile->stype? */ } void reset_file_params_for_analout (int orig_proctype,int orig_srate,int orig_chans,int orig_stype,dataptr dz) { dz->process_type = orig_proctype; dz->outfile->srate = dz->infile->srate = orig_srate; dz->outfile->channels = orig_chans; dz->outfile->stype = /* dz->outfile->stype = */ orig_stype; }