 A General Program to Perform Sampling Rate Conversion of Data by Rational Ratios

```C
C-----------------------------------------------------------------------
C MAIN PROGRAM: TEST PROGRAM TO PERFORM SAMPLING RATE CONVERSION
C               BY A RATIONAL RATIO
C AUTHOR:       R E CROCHIERE
C               BELL LABORATORIES, MURRAY HILL, NEW JERSEY 07974
C INPUT:        COEF=ARRAY OF COEFFICIENTS FOR FIR INTERPOLATING FILTER
C-----------------------------------------------------------------------
C
COMMON /SRCOM/ IQ, JQ, IL
DIMENSION COEF(60), COFS(120), QBUF(30), ICTR(16), BUFL(24),
*    BUFM(15)
IQ = 0
JQ = 0
IL = 0
C
C THIS PROGRAM CONVERTS THE SAMPLING RATE OF A SIGNAL BY A RATIO OF L/M
C THE PROGRAM CALLS SRINIT TO INITIALIZE AND THEN CALLS SRCONV SUPPLYING
C INPUT DATA THROUGH BUFM AND TAKING OUTPUT DATA FROM BUFL
C
C INPUT: COEFFICIENTS ARE READ FROM THE STANDARD INPUT UNIT (IND)
C
C OUTPUT: ALL OUTPUT IS WRITTEN ON THE STANDARD OUTPUT UNIT (LPT)
C
IND = I1MACH(1)
LPT = I1MACH(2)
NN = 60
WRITE (LPT,9998)
WRITE (LPT,9997) (COEF(K),K=1,NN)
WRITE (LPT,9996)
C
C INITIALIZE CONVERSION ROUTINE
C
N = 119
NC = 120
NI = 16
L = 8
M = 5
NQ = 30
CALL SRINIT(M, L, QBUF, NQ, COEF, N, COFS, NC, ICTR, NI, IERR)
WRITE (LPT,9995) IERR
WRITE (LPT,9996)
C
C GENERATE UNIT SAMPLE
C
DO 10 I=1,15
BUFM(I) = 0.
10  CONTINUE
BUFM(1) = 1.
C
C PROCESS DATA
C
ND = 3
CALL SRCONV(BUFM, BUFL, ND, QBUF, COFS, ICTR)
WRITE (LPT,9994)
NN = 24
WRITE (LPT,9997) (BUFL(K),K=1,NN)
9999  FORMAT (7F11.0)
9998  FORMAT (13H COEFFICIENTS)
9997  FORMAT (1X, 5F10.6)
9996  FORMAT (1H )
9995  FORMAT (6H IERR=, I3)
9994  FORMAT (21H UNIT SAMPLE RESPONSE)
STOP
END
C
C-----------------------------------------------------------------------
C SUBROUTINE: SRINIT
C INITIALIZATION FOR SRCONV WHICH CONVERTS THE SAMPLING RATE
C OF A SIGNAL BY THE RATIO OF L/M
C-----------------------------------------------------------------------
C
SUBROUTINE SRINIT(M, L, QBUF, NQ, COEF, N, COFS, NC, ICTR, NI,
*    IERR)
COMMON /SRCOM/ IQ, JQ, IL
DIMENSION QBUF(1), COEF(1), COFS(1), ICTR(1)
C
C    M = DECIMATION RATIO
C    L = INTERPOLATION RATIO
C QBUF = STATE VARIABLE BUFFER
C   NQ = SIZE OF QBUF, GREATER OR EQUAL TO 2*(THE NEXT
C        GREATEST INTEGER OF N/L)
C COEF = ARRAY OF COEFFICIENTS FOR FIR INTERPOLATING FILTER
C    N = NO. OF TAPS IN THE FIR INTERPOLATING FILTER
C COFS = SCRAMBLED COEFFICIENT VECTOR GENERATED BY SRINIT
C   NC = SIZE OF COFS VECTOR, EQUAL TO OR GREATER THAN
C        L*(THE NEXT GREATEST INTEGER OF N/L)
C ICTR = CONTROL ARRAY GENERATED BY SRINIT AND USED BY SRCONV
C   NI = SIZE OF ICTR VECTOR EQUAL OR GREATER THAN 2*L
C IERR = ERROR CODE FOR DEBUGGING
C      = 0  NO ERRORS FOUND IN INITIALIZATION
C      = 1  QBUF (NQ) TOO SMALL
C      = 2  COFS (NC) TOO SMALL
C      = 3  ICTR (NI) TOO SMALL
C
IERR = 0
IL = L
C
C COMPUTE IQ
C
IQ = N/L
IF (N.NE.(IQ*L)) IQ = IQ + 1
NP = IQ*L
IF (NQ.LT.(2*IQ)) IERR = 1
IF (NC.LT.NP) IERR = 2
NCF = (N+1)/2
FL = L
C
C ZERO OUT QBUF
C
DO 10 I=1,NQ
QBUF(I) = 0
10  CONTINUE
C
C SCRAMBLE COEFFICIENTS
C
I = 1
DO 30 ML=1,L
DO 20 MQ=1,IQ
MX = (ML-1) + (MQ-1)*L
IF (MX.LT.NCF) MM = NCF - MX
IF (MX.GE.NCF) MM = MX - (N-NCF-1)
IF (MM.LE.NCF) COFS(I) = COEF(MM)*FL
IF (MM.GT.NCF) COFS(I) = 0.
I = I + 1
20    CONTINUE
30  CONTINUE
C
C SETUP OF MOVING ADDRESS POINTER
C
JQ = IQ
C
C GENERATE CONTROL ARRAY ICTR
C
LM = L*M
IF (NI.LT.(2*L)) IERR = 3
LC = 0
MC = 0
INCR = 0
K = 1
DO 50 I=1,LM
IF (LC.EQ.0) INCR = INCR + 1
IF (MC.LT.(M-1)) GO TO 40
C
C NO OF SAMPLES TO UPDATE QBUF
C
ICTR(K) = INCR
INCR = 0
K = K + 1
C
C STARTING LOCATION IN COFS VECTOR
C
ICTR(K) = LC*IQ
INCR = 0
MC = -1
K = K + 1
40    LC = LC + 1
IF (LC.GE.L) LC = 0
MC = MC + 1
50  CONTINUE
RETURN
END
C
C-----------------------------------------------------------------------
C SUBROUTINE: SRCONV
C CONVERTS THE SAMPLING RATE OF A SIGNAL BY THE RATIO L/M.
C SRINIT MUST BE CALLED PRIOR TO CALLING THIS ROUTINE.
C-----------------------------------------------------------------------
C
SUBROUTINE SRCONV(BUFM, BUFL, ND, QBUF, COFS, ICTR)
COMMON /SRCOM/ IQ, JQ, IL
DIMENSION BUFM(1), BUFL(1), QBUF(1), COFS(1), ICTR(1)
C
C BUFM = INPUT DATA BUFFER OF SIZE ND*M
C BUFL = OUTPUT DATA BUFFER OF SIZE ND*L
C   ND = ANY POSITIVE INTEGER
C QBUF = STATE VARIABLE BUFFER
C COFS = SCRAMBLED COEFFICIENT VECTOR GENERATED BY SRINIT
C ICTR = CONTROL ARRAY GENERATED BY SRINIT AND USED BY SRCONV
C
MB = 1
LB = 1
L = IL
DO 50 I=1,ND
C
C MB = INDEX ON BUFM
C COMPUTE L OUTPUT SAMPLES
C
K = 1
DO 40 J=1,L
JD = ICTR(K)
IC = ICTR(K+1)
K = K + 2
C
C UPDATE QBUF
C
10      IF (JD.EQ.0) GO TO 20
QBUF(JQ) = BUFM(MB)
JQ1 = JQ + IQ
QBUF(JQ1) = BUFM(MB)
MB = MB + 1
JQ = JQ - 1
IF (JQ.EQ.0) JQ = IQ
JD = JD - 1
GO TO 10
C
C COMPUTE 1 SAMPLE OF OUTPUT DATA AND STORE IN BUFL
C
20      SUM = 0.
DO 30 KQ=1,IQ
ICOF = KQ + IC
IQB = KQ + JQ
SUM = SUM + QBUF(IQB)*COFS(ICOF)
30      CONTINUE
BUFL(LB) = SUM
LB = LB + 1
40    CONTINUE
50  CONTINUE
RETURN
END
```