*------------- Telecommunications & Signal Processing Lab --------------
*                          McGill University
*
*
* Module:
*     SUBROUTINE IMPLRP (H, NCOF, FLTTYP, IST, Y, NPT)
*
*
* Purpose:
*     Find the impulse response of a filter
*
*
* Description:
*     This routine calculates the impulse response of an FIR or IIR
*     filter specified by its coefficients.
*
*     *** FIR or WIN:
*     For an FIR filter, the coefficients are the direct-form
*     coefficients, h(i)
*
*              N-1       -i
*       H(z) = SUM h(i) z    .
*              i=0
*
*     *** ALL:
*     For an all-pole IIR filter, the response is specified by the
*     direct-form feedback coefficients, h(i),
*
*               1                    N-1       -i
*       H(z) = ----  ,  where C(z) = SUM h(i) z    .
*              C(z)                  i=0
*
*     Normally, the first coefficient is unity, i.e. h(0)=1.  A
*     non-unity value will result in a gain scaling of the response.
*
*     *** IIR:
*     For a general IIR filter, the response is specified in terms of
*     the coefficients of cascaded second order sections,
*
*              NSECT
*       H(z) = PROD H(k,z) .
*              k=1
*
*     Each second order section has a response defined by five
*     coefficients,
*
*               h(1,k)*z**2 + h(2,k)*z + h(3,k)
*      H(k,z) = -------------------------------  .
*                  z**2 + h(4,k)*z + h(k,5)
*
*
* Parameters:
* R ->  H      - Array of filter coefficients.  For IIR filters, each
*                group of 5 coefficients describes a second order
*                section.
* I ->  NCOF   - Number of filter coefficients.
* C ->  FLTTYP - Character string,
*                 ALL - all-pole filters
*                 FIR - FIR filters
*                 IIR - IIR filters
*                 WIN - windows (same as FIR)
* I ->  IST    - Starting impulse response coefficient, with IST=0
*                corresponding to time zero
* R <-  Y      - Output array of impulse response values
* I ->  NPT    - Number of impulse response values
*
*
* Author / revision:
*     P. Kabal
*     $Revision: 1.6 $  $Date: 1995/03/08 15:46:09 $
*
*
*-----------------------------------------------------------------------

      SUBROUTINE IMPLRP (H, NCOF, FLTTYP, IST, Y, NPT)


      INTEGER NTMP
      PARAMETER (NTMP=2000)

      INTEGER NCOF,IST,NPT
      INTEGER I,K,NMEM,NSBLK,N,ISY,IFS,NSECT

      CHARACTER*(*) FLTTYP

      REAL H(0:NCOF-1),Y(0:NPT-1)
      REAL VAL
      REAL TMP(NTMP)


      IF (FLTTYP.EQ.'FIR' .OR.  FLTTYP.EQ.'WIN') THEN

* FIR filters:
*   Copy over the impulse response
        DO 100 I=0,NPT-1
          K=I+IST
          IF (K.GE.0 .AND. K.LT.NCOF) THEN
            Y(I)=H(K)
          ELSE
            Y(I)=0.0
          END IF
 100    CONTINUE

      ELSE IF (FLTTYP.EQ.'ALL') THEN


* All-pole filter:
        NMEM=NCOF-1
        NSBLK=NTMP-NMEM
        IF (NSBLK.LE.0)
     -      CALL HALT('IMPLRP - Too many filter coefficients')

*   Calculate the impulse response
*   IST - First impulse sample number H(IST) <=> Y(0)
*   IFS - Last impulse sample number H(IFS) <=> Y(NPT-1)

* Impulse response for I from -IST to -1 is zero.
        N=MIN(-IST,NPT)
        IF (N.LT.0) N=0
        CALL VZERO(Y,N)
        ISY=N

* Filter a unit pulse.  This is done in two parts: I from 0 to IST-1
* and then I from IST to IFN.  Depending on the value of IST, either
* or both of the two loops may not be executed.
        CALL VZERO(TMP,NMEM)
        VAL=1.0
        N=0
        DO 200 I=0,IST-1,NSBLK
          CALL VSHIFT(TMP,NMEM,N)
          N=MIN((IST-1)-I+1,NSBLK)
          CALL VZERO(TMP(NMEM+1),N)
          TMP(NMEM+1)=VAL
          CALL FLTALL(TMP,N,H,NCOF)
          VAL=0.0
 200    CONTINUE

        IFS=IST+NPT-1
        DO 220 I=MAX(0,IST),IFS,NSBLK
          CALL VSHIFT(TMP,NMEM,N)
          N=MIN(IFS-I+1,NSBLK)
          CALL VZERO(TMP(NMEM+1),N)
          TMP(NMEM+1)=VAL
          CALL FLTALL(TMP,N,H,NCOF)
          CALL VCOPY(TMP(NMEM+1),Y(ISY),N)
          ISY=ISY+N
          VAL=0.0
 220    CONTINUE


      ELSE IF (FLTTYP.EQ.'IIR') THEN

* General IIR filters
        IF (MOD(NCOF,5).NE.0)
     -      CALL HALT('IMPLRP - Invalid number of coefficients')
        NSECT=NCOF/5
        NMEM=2*(NSECT+1)
        NSBLK=NTMP-NMEM
        IF (NSBLK.LE.0)
     -      CALL HALT('IMPLRP - Too many filter coefficients')

*   Calculate the impulse response
*   IST - First impulse sample number H(IST) <=> Y(0)
*   IFS - Last impulse sample number H(IFS) <=> Y(NPT-1)

* Impulse response for I from -IST to -1 is zero.
        N=MIN(-IST,NPT)
        IF (N.LT.0) N=0
        CALL VZERO(Y,N)
        ISY=N

* Filter a unit pulse.  This is done in two parts: I from 0 to IST-1
* and then I from IST to IFN.  Depending on the value of IST, either
* or both of the two loops may not be executed.
        CALL VZERO(TMP,NMEM)
        VAL=1.0
        N=0
        DO 300 I=0,IST-1,NSBLK
          CALL VSHIFT(TMP,NMEM,N)
          N=MIN((IST-1)-I+1,NSBLK)
          CALL VZERO(TMP(NMEM+1),N)
          TMP(NMEM+1)=VAL
          CALL FLTIIR(TMP,N,H,NSECT)
          VAL=0.0
 300    CONTINUE

        IFS=IST+NPT-1
        DO 320 I=MAX(0,IST),IFS,NSBLK
          CALL VSHIFT(TMP,NMEM,N)
          N=MIN(IFS-I+1,NSBLK)
          CALL VZERO(TMP(NMEM+1),N)
          TMP(NMEM+1)=VAL
          CALL FLTIIR(TMP,N,H,NSECT)
          CALL VCOPY(TMP(3),Y(ISY),N)
          ISY=ISY+N
          VAL=0.0
 320    CONTINUE

      ELSE

        CALL HALT('IMPLRP - Invalid filter type')

      END IF


      RETURN

      END
