#!/bin/sh # This is resample, a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 01/05/1992 02:19 UTC by thinman@netcom.com # Source directory /usr2/sound/resample # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 459 -rw-r--r-- Readme # 9614 -rw-r--r-- Notes # 954 -rw-r--r-- Makefile # 380 -rw-r--r-- filterkit.h # 3396 -rw-r--r-- protos.h # 2942 -rw-r--r-- resample.h # 699 -rw-r--r-- stdefs.h # 12170 -rw-r--r-- kaiser.c # 16885 -rw-r--r-- filterkit.c # 4633 -rw-r--r-- makefilter.c # 13378 -rw-r--r-- resample.c # 10961 -rw-r--r-- warp.c # # ============= Readme ============== if test -f 'Readme' -a X"$1" != X"-c"; then echo 'x - skipping Readme (File already exists)' else echo 'x - extracting Readme (Text)' sed 's/^X//' << 'SHAR_EOF' > 'Readme' && X X XFilterkit is a C translation of an old SAIL program (SAIL = XStanford AI Lab) which does FIR filtering with sample rate Xchanging on the fly. X XChristopher Fraley @CMU did the translation and split it up Xinto a toolkit. Being ignorant, I've glommed some of the pieces Xtogether into a program that performs straight filtering on Xa sound sample file of signed words. X XThe warp program in particular looks very promising; I haven't Xused it yet. X X Lance Norskog SHAR_EOF chmod 0644 Readme || echo 'restore of Readme failed' Wc_c="`wc -c < 'Readme'`" test 459 -eq "$Wc_c" || echo 'Readme: original size 459, current size' "$Wc_c" fi # ============= Notes ============== if test -f 'Notes' -a X"$1" != X"-c"; then echo 'x - skipping Notes (File already exists)' else echo 'x - extracting Notes (Text)' sed 's/^X//' << 'SHAR_EOF' > 'Notes' && X X NOTES X X XPROGRAM ORGANIZATION: X X The original SAIL resampling program is now located among four files: X"filterkit.c", "makefilter.c", "resample.c", and "resample.h". These files Xcontain: X X filterkit.c - The source code for the library. Contains routines X to calculate filter coeff's, convert these to a 16-bit X integer format, write a filter file, read a filter file, X apply the filter when up-sampling, apply the filter when X up-/down-sampling, and apply the filter to find a zero- X crossing. X X makefilter.c - Routines to design and write a filter to a file. X Creates a Kaiser-windowed lowpass filter based upon routines X found in the filterkit library. X X resample.c - The original resampling program stripped down to the X part that does the actual resampling. Designing a filter X was moved to "makefilter.c", the conversion constants X were moved into "resample.c", and various general filter X routines were moved into the filterkit library. X X resample.h - Contains the resampling conversion constants. These X constants govern such things as the number of bits in the X input sample & filter coeff's, the number of bits to the X right of the binary-point for fixed-point math, etc. X X Other programs included in this package are the Makefiles for each of Xthe programs (and the filterkit library), the needed headerfiles, and a Xhuman-readable copy of the lint version of the filterkit library: X X warp.c - Very similar to "resample.c", except is modified to allow X the conversion factor to change on a sample-by-sample basis, X currently using sinusiods. This program can be used to add X vibrato or other pitch-shifting effects to a sample. X X stdefs.h - Contains the definitions for words and halfwords, which X can change from machine to machine. Also, useful constants X are defined, as well as a few useful macros. X X filterkit.h - Contains the declarations of each of the functions in X the filterkit library. Must be included by any program using X any of the filterkit routines. X X llib-lfilterkit - A human-readble version of the lint-library for X filterkit. Simply defines the type of each function and X the routine's formal parameters, so lint can check programs X which use the filterkit library. The compact version of this X file is created via the -C option of lint. See the filterkit X Makefile for details. X X X XNOTES ON COMPILATION: X X All of the modules should compile without any problems, although search Xpaths will have to be set up correctly so "cc" can find all of the proper Xinclude and library files. Alternatively, one could also explicly cite an Xabsolute file path for each of the files. X X A few minor changes have been made to some of these files since they were Xlast compiled: X 1. All absolute paths were removed from the Makefiles to make X adaption to your site less confusing. X 2. The source for the filterkit library was concatinated into one X file. The Query(), GetUShort(), GetDouble(), and GetString() X routines were originally in a separate file "query.c". X 3. "llib-lfilterkit" was modified to reflect the latest change to X the zerox() routine. This has not been tested yet. X X The routines originally in "query.c" may have to be modified slightly Xto get them to compile. Apparently, the getstr() routine (which is used in Xeach of these routines) is not a part of the standard C library on all Unix Xsystems. Its specification is: X getstr(prompt, defalt, answer) X char *prompt, *defalt, *answer; X Getstr() will print the passed "prompt" as a message to the user, and X wait for the user to type an input string. The string is X then copied into "answer". If the user types just a carriage X return, then the string "defalt" is copied into "answer". X "Answer" and "defalt" may be the same string, in which case, X the default value will be the original contents of "answer". X X Also note that the constants in "resample.h" and the typedefs in X"stdefs.h" may need to be changed to reflect the word-size of the machine Xthe program will be running on. These files currently reflect a word-size Xof 32-bits. X X X XSTRUCTURE OF FILES: X X There are two types of files used to pass information from one program Xthe the next: the filter file and a sound-sample file. The filter file Xhas the following format: X X File Name: "F" Nmult "T" Nhc ".filter" X example: "F13T8.filter" and "F27T8.filter" X X Structure of File: X "ScaleFactor" LpScl X "Length" Nwing X "Coeffs:" X Imp[0] X Imp[1] X : X Imp[Nwing-1] X "Differences:" X ImpD[0] X ImpD[1] X : X ImpD[Nwing-1] X EOF X X where: Something enclosed in "" inicates specific characters found X in the file. X Nmult, Nwing, Imp[], and ImpD[] are variables (HWORD) X Npc is a conversion constant. X EOF is the end of the file. X See writeFilter() and readFilter() in "filterkit.c" for more details. X X XThe sound-sample file has the following format: X X File Name: unspecified. X example: "horn.in", "Cello.adc", etc. X X Structure of File: X Data[0] X Data[1] X : X Data[n] X EOF X X where: Data[i] is a 16-bit integer in ascii format. (Example: X "32767", "-232") X EOF is the end of the file. X Note that there is no indication of the length of the X sample; the EOF is the only indication that the X last sample has been reached. X X X XSUGGESTIONS, CORRECTIONS, IMPROVEMENTS: X X The following were assumed to be mistakes in the original SAIL program, Xand have been changed in "resample.c" and other related programs: X X 1. LpScl was scaled by Factor (when Factor<1.0) only when the filter X was loaded from a file, but not when the filter was created X at run-time. X 2. ImpD[Nwing-1] was originally set to Imp[Nwing-1], but in general X ImpD[i] = ImpD[i+1] - ImpD[i], indicating ImpD[Nwing-1] X should be set to NEGATIVE Imp[Nwing-1]. X 3. To keep the # of multiplies consistant (and odd), I added a check X near the begining of the Filter() routines to skip the last X coeff in the right wing when the phase was 180 degrees. X (The "if (Inc == 1) End--;" clause). X 4. When the phase was zero, and the right-wing Filter() is performed, X the pointers to the filter coeffs must be incremented to X keep the pointing to the correct coeff. (The "if (Ph == 0) X { Hp += Npc; Hdp += Npc; }" clause). X X X The following were changes made to the basic implementation of the Xalgorithm: X X 1. ImpD[] is now created from the integer Imp[] instead of the X double ImpR[], in order to avoid problems with rounding. X 2. In SrcUp() and SrcUD(), the order of making guard bits (v>>Nhg) X and normalizing was switched. This was done to prevent X overflow problems. X 3. Rounding was removed from SrcUp() and SrcUD() to get more accurate X response to a DC input. X X X The following are improvements that I recommend be made to various Xroutines: X X 1. Change file format of sound files (and possibly filter files) to X a binary format. If you are in a Unix environment, you can X use the functions read() and write() to perform low-level X i/o, instead of fprintf() and fscanf(). This would be MUCH X faster, but I have not made the changes yet because the X current code is much clearer, and probably easier to port X to your system and your sound-file format. X 2. I believe the restriction that Nmult must be odd may be removed. X 3. When Filter() is currently called for the right-wing, Xp+1 must X be passed to it. This should probably be changed so that X Filter() adds one to Xp if it is doing the right-wing, X instead of the user. This way, that increment would be X transparent to the user, and provide a more consistent X interface to these functions. X X X XNOTES ON SPECIFIC FILES: X X "resample.c" - should be a faithful reproduction of the original SAIL X program in C. X X "warp.c" - I modified SrcUD() to get the current value for Factor from X the function warpFunction(). WarpFunction() should be changed to X some form desirable. X X "filterkit.c" - Contains the following useful routines: X LpFilter() - Calculates the filter coeffs for a Kaiser-windowed X low-pass filter with a given roll-off frequency. These X coeffs are stored into a array of doubles. X writeFilter() - Writes a filter to a file. X makeFilter() - A section of the original SAIL program. Calls X LpFilter() to create a filter, then scales the double X coeffs into a array of half words. X readFilter() - Reads a filter from a file. X FilterUp() - Applies a filter to a given sample when up-converting. X FilterUD() - Applies a filter to a given sample when up- or down- X converting. Both are repoductions of the original SAIL X program. X initZerox() - Initialization routine for the zerox() function. Must X be called before zerox() is called. This routine loads X the correct filter so zerox() can use it. X zerox() - Given a pointer into a sample, finds a zero-crossing on the X interval [pointer-1:pointer+2] by iteration. X Query() - Ask the user for a yes/no question with prompt, default, X and optional help. X GetUShort() - Ask the user for a unsigned short with prompt, default, X and optional help. X GetDouble() - Ask the user for a double with prompt, default, and X optional help. X GetString() - Ask the user for a string with prompt, default, and X optional help. X X X XFURTHER INFORMATION: X X Any printf()'s that start with a "|" as the first character in the Xcontrol string are used for debugging to to alert the user of an error Xcondition. X For further information on any of the files, look in the comments and Xhelp strings contained within that file. Also I can be contacted at: X cf0v@spice.cs.cmu.edu, or X cf0v@andrew.cmu.edu. X X --Christopher Lee Fraley X SHAR_EOF chmod 0644 Notes || echo 'restore of Notes failed' Wc_c="`wc -c < 'Notes'`" test 9614 -eq "$Wc_c" || echo 'Notes: original size 9614, current size' "$Wc_c" fi # ============= Makefile ============== if test -f 'Makefile' -a X"$1" != X"-c"; then echo 'x - skipping Makefile (File already exists)' else echo 'x - extracting Makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'Makefile' && XSRC = kaiser.c filterkit.c makefilter.c resample.c warp.c XOBJ = kaiser.o filterkit.o makefilter.o resample.o warp.o XBIN = kaiser makefilter resample warp X XFILES = Readme Notes Makefile filterkit.h protos.h resample.h stdefs.h $(SRC) X XINSTALLDIR = /usr/local/bin X Xall: $(BIN) X Xinstall: $(BIN) X cp $(BIN) "$(INSTALLDIR)" X Xkaiser: kaiser.c filterkit.c X rm -f kaiser X $(CC) $(CFLAGS) kaiser.c filterkit.c -o kaiser -lm X Xmakefilter: makefilter.c filterkit.c X rm -f makefilter X $(CC) $(CFLAGS) makefilter.c filterkit.c -o makefilter -lm X Xresample: resample.c filterkit.c X rm -f resample X $(CC) $(CFLAGS) resample.c filterkit.c -o resample -lm X Xwarp: warp.c filterkit.c X rm -f warp X $(CC) $(CFLAGS) warp.c filterkit.c -o warp -lm X X$(SRC): filterkit.h stdefs.h Xresample.c: resample.h X X# Shar: -F (prefix all lines with X), X# -s addr (set return addr of poster) Xshar: $(FILES) X /usr2/tools/shar/shar -F -l 50 -o shar -n resample -s thinman@netcom.com $(FILES) SHAR_EOF chmod 0644 Makefile || echo 'restore of Makefile failed' Wc_c="`wc -c < 'Makefile'`" test 954 -eq "$Wc_c" || echo 'Makefile: original size 954, current size' "$Wc_c" fi # ============= filterkit.h ============== if test -f 'filterkit.h' -a X"$1" != X"-c"; then echo 'x - skipping filterkit.h (File already exists)' else echo 'x - extracting filterkit.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'filterkit.h' && X X/* X * FILE:filterkit.h X * BY: Christopher Lee Fraley (cf0v@andrew.cmu.edu) X * DATE: 17-JUN-88 X * VERS: 1.0 (20-JUN-88, 3:10pm) X */ X Xvoid LpFilter(); Xint writeFilter(), readFilter(), makeFilter(); XWORD FilterUp(), FilterUD(); Xdouble GetDouble(); Xunsigned short GetUShort(); Xchar *GetString(); XBOOL Query(); Xdouble cubic(), zerox(); X X#define GetUHWORD(x,y,z) GetUShort(x,y,z) X SHAR_EOF chmod 0644 filterkit.h || echo 'restore of filterkit.h failed' Wc_c="`wc -c < 'filterkit.h'`" test 380 -eq "$Wc_c" || echo 'filterkit.h: original size 380, current size' "$Wc_c" fi # ============= protos.h ============== if test -f 'protos.h' -a X"$1" != X"-c"; then echo 'x - skipping protos.h (File already exists)' else echo 'x - extracting protos.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'protos.h' && X#if defined(__STDC__) || defined(__cplusplus) X# define P_(s) s X#else X# define P_(s) () X#endif X X X/* filterkit.c */ Xdouble Izero P_((double x)); Xvoid LpFilter P_((double c[], int N, double frq, double Beta, int Num)); Xint writeFilter P_((HWORD Imp[], HWORD ImpD[], UHWORD LpScl, UHWORD Nmult, UHWORD Nwing)); Xint makeFilter P_((HWORD Imp[], HWORD ImpD[], UHWORD *LpScl, UHWORD Nwing, double Froll, double Beta)); Xint readFilter P_((HWORD Imp[], HWORD ImpD[], UHWORD *LpScl, UHWORD Nmult, UHWORD *Nwing)); XWORD FilterUp P_((HWORD Imp[], HWORD ImpD[], UHWORD Nwing, BOOL Interp, HWORD *Xp, HWORD Ph, HWORD Inc)); XWORD FilterUD P_((HWORD Imp[], HWORD ImpD[], UHWORD Nwing, BOOL Interp, HWORD *Xp, HWORD Ph, HWORD Inc, UHWORD dhb)); Xint initZerox P_((UHWORD tempNmult)); Xdouble zerox P_((HWORD *Data, double Factor)); XBOOL Query P_((char *prompt, BOOL deflt, char *help)); Xchar *GetString P_((char *prompt, char *deflt, char *help)); Xint getstr P_((char *s1, char *deflt, char *s2)); Xdouble GetDouble P_((char *title, double deflt, char *help)); Xunsigned short GetUShort P_((char *title, unsigned int deflt, char *help)); X X/* makefilter.c */ Xint main P_((void)); X X/* nres.c */ Xint fail P_((char *s)); Xint fails P_((char *s, char *s2)); Xint closeData P_((void)); Xint readData P_((HWORD Data[], int DataArraySize, int Xoff)); Xint writeData P_((int Nout, HWORD Data[])); Xint getparams P_((int argc, char **argv, double *Factor, double *Froll)); Xint SrcUp P_((HWORD X[], HWORD Y[], double Factor, UWORD *Time, UHWORD Nx, UHWORD Nwing, UHWORD LpScl, HWORD Imp[], HWORD ImpD[], BOOL Interp)); Xint SrcUD P_((HWORD X[], HWORD Y[], double Factor, UWORD *Time, UHWORD Nx, UHWORD Nwing, UHWORD LpScl, HWORD Imp[], HWORD ImpD[], BOOL Interp)); Xint resample P_((HWORD Imp[], HWORD ImpD[], UHWORD LpScl, UHWORD Nmult, UHWORD Nwing, double Factor, BOOL InterpFilt)); Xint main P_((int argc, char *argv[])); Xint genFilter P_((HWORD Imp[MAXNWING ], HWORD ImpD[MAXNWING ], UHWORD *LpScl, UHWORD Nmult, UHWORD *Nwing, double Froll)); X X/* resample.c */ Xint fail P_((char *s)); Xint fails P_((char *s, char *s2)); Xint openData P_((int argc, char *argv[])); Xint closeData P_((void)); Xint readData P_((HWORD Data[], int DataArraySize, int Xoff)); Xint writeData P_((int Nout, HWORD Data[])); Xint getparams P_((double *Factor, BOOL *InterpFilt, UHWORD *Nmult)); Xint SrcUp P_((HWORD X[], HWORD Y[], double Factor, UWORD *Time, UHWORD Nx, UHWORD Nwing, UHWORD LpScl, HWORD Imp[], HWORD ImpD[], BOOL Interp)); Xint SrcUD P_((HWORD X[], HWORD Y[], double Factor, UWORD *Time, UHWORD Nx, UHWORD Nwing, UHWORD LpScl, HWORD Imp[], HWORD ImpD[], BOOL Interp)); Xint resample P_((HWORD Imp[], HWORD ImpD[], UHWORD LpScl, UHWORD Nmult, UHWORD Nwing, double Factor, BOOL InterpFilt)); Xint main P_((int argc, char *argv[])); X X/* warp.c */ Xint fail P_((char *s)); Xint fails P_((char *s, char *s2)); Xint openData P_((int argc, char *argv[])); Xint closeData P_((void)); Xint readData P_((HWORD Data[], int DataArraySize, int Xoff)); Xint writeData P_((int Nout, HWORD Data[])); Xint check P_((void)); Xint initWarp P_((void)); Xdouble warpFunction P_((UWORD Time)); Xint SrcUD P_((HWORD X[], HWORD Y[], UWORD *Time, UHWORD Nx, UHWORD Nwing, UHWORD LpScl, HWORD Imp[], HWORD ImpD[], BOOL Interp)); Xint resample P_((HWORD Imp[], HWORD ImpD[], UHWORD LpScl, UHWORD Nmult, UHWORD Nwing, BOOL InterpFilt)); Xint main P_((int argc, char *argv[])); X X#undef P_ SHAR_EOF chmod 0644 protos.h || echo 'restore of protos.h failed' Wc_c="`wc -c < 'protos.h'`" test 3396 -eq "$Wc_c" || echo 'protos.h: original size 3396, current size' "$Wc_c" fi # ============= resample.h ============== if test -f 'resample.h' -a X"$1" != X"-c"; then echo 'x - skipping resample.h (File already exists)' else echo 'x - extracting resample.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'resample.h' && X X/* X * FILE: resample.h X * BY: Julius Smith (at CCRMA, Stanford U) X * C BY: translated from SAIL to C by Christopher Lee Fraley X * (cf0v@andrew.cmu.edu) X * DATE: 7-JUN-88 X * VERS: 2.0 (17-JUN-88, 3:00pm) X */ X X#define MAXNWING 5122 X#define MAXFACTOR 4 /* Maximum Factor without output buff overflow */ X X X X/* Conversion constants */ X#define Nhc 8 X#define Na 7 X#define Np (Nhc+Na) X#define Npc (1< 'stdefs.h' && X X/* X * FILE: stdefs.h X * BY: Christopher Lee Fraley X * DESC: Defines standard stuff for inclusion in C programs. X * DATE: 6-JUN-88 X * VERS: 1.0 (6-JUN-88, 2:00pm) X */ X X X#define TRUE 1 X#define FALSE 0 X X#define PI (3.14159265358979232846) X#define PI2 (6.28318530717958465692) X#define D2R (0.01745329348) /* (2*pi)/360 */ X#define R2D (57.29577951) /* 360/(2*pi) */ X X#define MAX(x,y) ((x)>(y) ?(x):(y)) X#define MIN(x,y) ((x)<(y) ?(x):(y)) X#define ABS(x) ((x)<0 ?(-(x)):(x)) X#define SGN(x) ((x)<0 ?(-1):((x)==0?(0):(1))) X Xtypedef char BOOL; Xtypedef short HWORD; Xtypedef unsigned short UHWORD; Xtypedef int WORD; Xtypedef unsigned int UWORD; X SHAR_EOF chmod 0644 stdefs.h || echo 'restore of stdefs.h failed' Wc_c="`wc -c < 'stdefs.h'`" test 699 -eq "$Wc_c" || echo 'stdefs.h: original size 699, current size' "$Wc_c" fi # ============= kaiser.c ============== if test -f 'kaiser.c' -a X"$1" != X"-c"; then echo 'x - skipping kaiser.c (File already exists)' else echo 'x - extracting kaiser.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'kaiser.c' && X X X/* X * FILE: resample.c X * BY: Julius Smith (at CCRMA, Stanford U) X * C BY: translated from SAIL to C by Christopher Lee Fraley X * (cf0v@spice.cs.cmu.edu or @andrew.cmu.edu) X * DATE: 7-JUN-88 X * X * HACKED: Lance Norskog, Dec. 28, 1991, to make sealed resampler for SoundKit X */ X Xchar resampleVERSION[] = "1.3 (24-JUN-88, 3:00pm)"; X X/* X * The original version of this program in SAIL may be found in: X * /../s/usr/mhs/resample or /../x/usr/rbd/src/resample X * X * Implement sampling rate conversions by (almost) arbitrary factors. X * Based on SRCONV.SAI[SYS,MUS] with new algorithm by JOS&PG. X * The program internally uses 16-bit data and 16-bit filter X * coefficients. X * X * Reference: "A Flexible Sampling-Rate Conversion Method," X * J. O. Smith and P. Gossett, ICASSP, San Diego, 1984, Pgs 19.4. X * X * * Need overflow detection in Filter() routines. Also, we want X * to saturate instead of wrap-around and report number of clipped X * samples. X */ X X/* CHANGES from original SAIL program: X * X * 1. LpScl is scaled by Factor (when Factor<1) in resample() so this is X * done whether the filter was loaded or created. X * 2. makeFilter() - ImpD[] is created from Imp[] instead of ImpR[], to avoid X * problems with round-off errors. X * 3. makeFilter() - ImpD[Nwing-1] gets NEGATIVE Imp[Nwing-1]. X * 4. SrcU/D() - Switched order of making guard bits (v>>Nhg) and X * normalizing. This was done to prevent overflow. X */ X X/* LIBRARIES needed: X * X * 1. filterkit X * readFilter() - reads standard filter file X * FilterUp() - applies filter to sample when Factor >= 1 X * FilterUD() - applies filter to sample for any Factor X * Query() - prompt user for y/n answer with help. X * GetDouble() - prompt user for a double with help. X * GetUShort() - prompt user for a UHWORD with help. X * X * 2. math X */ X X X X X#include X#include X#include X#include "stdefs.h" X#include "filterkit.h" X#include "resample.h" X#include "protos.h" X X#define IBUFFSIZE 1024 /* Input buffer size */ X#define OBUFFSIZE (IBUFFSIZE*MAXFACTOR+2) /* Calc'd out buffer size */ X Xfail(s) Xchar *s; X{ X fprintf(stderr, "kaiser: %s\n\n", s); /* Display error message */ X exit(1); /* Exit, indicating error */ X} X Xfails(s,s2) Xchar *s, *s2; X{ X fprintf(stderr, "kaiser: "); /* Display error message */ X fprintf(stderr, s,s2); X fprintf(stderr, "\n\n"); X exit(1); /* Exit, indicating error */ X} X X X X X/* Help Declarations */ X X/* Global file pointers: */ XFILE *fin, *fout; X XcloseData() X{ X (void) fclose(fin); X (void) fclose(fout); X} X X Xint readData(Data, DataArraySize, Xoff) /* return: 0 - notDone */ XHWORD Data[]; /* >0 - index of last sample */ Xint DataArraySize, Xoff; X{ X int Nsamps, Scan; X short val; X HWORD *DataStart; X X DataStart = Data; X Nsamps = DataArraySize - Xoff; /* Calculate number of samples to get */ X Data += Xoff; /* Start at designated sample number */ X for (; Nsamps>0; Nsamps--) X { X Scan = fread(&val, 1, 2, fin); /* Read in Nsamps samples */ X if (Scan==EOF || Scan==0) /* unless read error or EOF */ X break; /* in which case we exit and */ X *Data++ = val; X } X if (Nsamps > 0) X { X val = Data - DataStart; /* (Calc return value) */ X while (--Nsamps >= 0) /* fill unread spaces with 0's */ X *Data++ = 0; /* and return FALSE */ X return(val); X } X return(0); X} X X X XwriteData(Nout, Data) Xint Nout; XHWORD Data[]; X{ X short s; X /* Write Nout samples to ascii file */ X while (--Nout >= 0) { X s = *Data++; X fwrite(&s, 1, 2, fout); X } X} X X X X Xgetparams(argc, argv, Factor, Froll) Xint argc; Xchar **argv; Xdouble *Factor, *Froll; X{ X if ((argc != 2) && (argc != 3)) X fail("format is 'resample factor [ rolloff ]'"); X if ((*Factor = atof(argv[1])) < 0.01) X fail("conversion factor no good"); X if (argc == 2) X *Froll = 0.5; X else if ((*Froll = atof(argv[2])) < 0.01) X fail("rolloff factor no good"); X fin = stdin; X fout = stdout; X X /* Check for illegal constants */ X if (Np >= 16) X fail("Error: Np>=16"); X if (Nb+Nhg+NLpScl >= 32) X fail("Error: Nb+Nhg+NLpScl>=32"); X if (Nh+Nb > 32) X fail("Error: Nh+Nb>32"); X} X X X X/* Sampling rate up-conversion only subroutine; X * Slightly faster than down-conversion; X */ XSrcUp(X, Y, Factor, Time, Nx, Nwing, LpScl, Imp, ImpD, Interp) XHWORD X[], Y[], Imp[], ImpD[]; XUHWORD Nx, Nwing, LpScl; XUWORD *Time; Xdouble Factor; XBOOL Interp; X{ X HWORD *Xp, *Ystart; X WORD v; X X double dt; /* Step through input signal */ X UWORD dtb; /* Fixed-point version of Dt */ X UWORD endTime; /* When Time reaches EndTime, return to user */ X X dt = 1.0/Factor; /* Output sampling period */ X dtb = dt*(1<>Np]; /* Ptr to current input sample */ X v = FilterUp(Imp, ImpD, Nwing, Interp, Xp, (HWORD)(*Time&Pmask), X -1); /* Perform left-wing inner product */ X v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1, (HWORD)((-*Time)&Pmask), X 1); /* Perform right-wing inner product */ X v >>= Nhg; /* Make guard bits */ X v *= LpScl; /* Normalize for unity filter gain */ X *Y++ = v>>NLpScl; /* Deposit output */ X *Time += dtb; /* Move to next sample by time increment */ X } X return (Y - Ystart); /* Return the number of output samples */ X} X X X X/* Sampling rate conversion subroutine */ X XSrcUD(X, Y, Factor, Time, Nx, Nwing, LpScl, Imp, ImpD, Interp) XHWORD X[], Y[], Imp[], ImpD[]; XUHWORD Nx, Nwing, LpScl; XUWORD *Time; Xdouble Factor; XBOOL Interp; X{ X HWORD *Xp, *Ystart; X WORD v; X X double dh; /* Step through filter impulse response */ X double dt; /* Step through input signal */ X UWORD endTime; /* When Time reaches EndTime, return to user */ X UWORD dhb, dtb; /* Fixed-point versions of Dh,Dt */ X X dt = 1.0/Factor; /* Output sampling period */ X dtb = dt*(1<>Np]; /* Ptr to current input sample */ X v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, (HWORD)(*Time&Pmask), X -1, dhb); /* Perform left-wing inner product */ X v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, (HWORD)((-*Time)&Pmask), X 1, dhb); /* Perform right-wing inner product */ X v >>= Nhg; /* Make guard bits */ X v *= LpScl; /* Normalize for unity filter gain */ X *Y++ = v>>NLpScl; /* Deposit output */ X *Time += dtb; /* Move to next sample by time increment */ X } X return (Y - Ystart); /* Return the number of output samples */ X} X X X Xint resample(Imp, ImpD, LpScl, Nmult, Nwing, Factor, InterpFilt) XHWORD Imp[], ImpD[]; XUHWORD LpScl, Nmult, Nwing; Xdouble Factor; XBOOL InterpFilt; X{ X UWORD Time; /* Current time/pos in input sample */ X UHWORD Xp, Ncreep, Xoff, Xread; X HWORD X[IBUFFSIZE], Y[OBUFFSIZE]; /* I/O buffers */ X UHWORD Nout, Nx; X int i, Ycount, last; X X /* Account for increased filter gain when using Factors less than 1 */ X if (Factor < 1) X LpScl = LpScl*Factor + 0.5; X /* Calc reach of LP filter wing & give some creeping room */ X Xoff = ((Nmult+1)/2.0) * MAX(1.0,1.0/Factor) + 10; X if (IBUFFSIZE < 2*Xoff) /* Check input buffer size */ X fail("IBUFFSIZE (or Factor) is too small"); X Nx = IBUFFSIZE - 2*Xoff; /* # of samples to proccess each iteration */ X X last = FALSE; /* Have not read last input sample yet */ X Ycount = 0; /* Current sample and length of output file */ X Xp = Xoff; /* Current "now"-sample pointer for input */ X Xread = Xoff; /* Position in input array to read into */ X Time = (Xoff<= 1) /* Resample stuff in input buffer */ X Ycount += Nout = SrcUp(X,Y,Factor,&Time,Nx,Nwing,LpScl,Imp,ImpD, X InterpFilt); /* SrcUp() is faster if we can use it */ X else X Ycount += Nout = SrcUD(X,Y,Factor,&Time,Nx,Nwing,LpScl,Imp,ImpD, X InterpFilt); X Time -= (Nx<>Np) - Xoff; /* Calc time accumulation in Time */ X if (Ncreep) X { X Time -= (Ncreep< OBUFFSIZE) /* Check to see if output buff overflowed */ X fail("Output array overflow"); X X writeData((int)Nout ,Y); /* Write data in output buff to file */ X } while (last >= 0); /* Continue until done processing samples */ X return(Ycount); /* Return # of samples in output file */ X} X X X X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X double Factor; /* Factor = Fout/Fin */ X double Froll; /* roll-off frequency */ X BOOL InterpFilt = TRUE; /* TRUE means interpolate filter coeffs */ X UHWORD LpScl, Nmult, Nwing; X HWORD Imp[MAXNWING]; /* Filter coefficients */ X HWORD ImpD[MAXNWING]; /* ImpD[n] = Imp[n+1]-Imp[n] */ X int outCount; X X Nmult = 37; X getparams(argc, argv, &Factor, &Froll); X genFilter(Imp, ImpD, &LpScl, Nmult, &Nwing, Froll); X resample(Imp, ImpD, LpScl, Nmult, Nwing, Factor, InterpFilt); X closeData(); X} X Xchar *cantmake[5] = { X"0 - no error", X"1 - Nwing too large (Nwing is > MAXNWING)", X"2 - Froll is not in interval [0:1)", X"3 - Beta is < 1.0", X"4 - LpScl will not fit in 16-bits" X}; X XgenFilter(Imp, ImpD, LpScl, Nmult, Nwing, Froll) XHWORD Imp[MAXNWING]; /* Filter coefficients */ XHWORD ImpD[MAXNWING]; /* ImpD[i] = ImpD[i+1] - ImpD[i] */ XUHWORD Nmult, *LpScl, *Nwing; Xdouble Froll; X{ X double Beta = 2.120; X int err; X X *Nwing = Npc*(Nmult+1)/2; /* # of filter coeffs in right wing */ X *Nwing += Npc/2 + 1; /* This prevents just missing last coeff */ X /* for integer conversion factors */ X if ((Froll<=0) || (Froll>1)) X fail("Error: Roll-off freq must be 0