www.pudn.com > lpc10-15.zip > analys.f
*******************************************************************
*
* ANALYS Version 55
*
* $Log: analys.f,v $
* Revision 1.9 1996/05/23 19:41:07 jaf
* Commented out some unnecessary lines that were reading uninitialized
* values.
*
* Revision 1.8 1996/03/27 23:57:55 jaf
* Added some comments about which indices of the local buffers INBUF,
* LPBUF, etc., get read or modified by some of the subroutine calls. I
* just did this while trying to figure out the discrepancy between the
* embedded code compiled with all local variables implicitly saved, and
* without.
*
* I added some debugging write statements in hopes of finding a problem.
* None of them ever printed anything while running with the long input
* speech file dam9.spd provided in the distribution.
*
* Revision 1.7 1996/03/27 18:06:20 jaf
* Commented out access to MAXOSP, which is just a debugging variable
* that was defined in the COMMON block CONTRL in contrl.fh.
*
* Revision 1.6 1996/03/26 19:31:33 jaf
* Commented out trace statements.
*
* Revision 1.5 1996/03/21 15:19:35 jaf
* Added comments for ENTRY PITDEC.
*
* Revision 1.4 1996/03/19 20:54:27 jaf
* Added a line to INITANALYS. See comments there.
*
* Revision 1.3 1996/03/19 20:52:49 jaf
* Rearranged the order of the local variables quite a bit, to separate
* them into groups of "constants", "locals that don't need to be saved
* from one call to the next", and "local that do need to be saved from
* one call to the next".
*
* Several locals in the last set should have been given initial values,
* but weren't. I gave them all initial values of 0.
*
* Added a separate ENTRY INITANALYS that initializes all local state
* that should be, and also calls the corresponding entries of the
* subroutines called by ANALYS that also have local state.
*
* There used to be DATA statements in ANALYS. I got rid of most of
* them, and added a local logical variable FIRST that calls the entry
* INITANALYS on the first call to ANALYS. This is just so that one need
* not remember to call INITANALYS first in order for the state to be
* initialized.
*
* Revision 1.2 1996/03/11 23:29:32 jaf
* Added several comments with my own personal questions about the
* Fortran 77 meaning of the parameters passed to the subroutine PREEMP.
*
* Revision 1.1 1996/02/07 14:42:29 jaf
* Initial revision
*
*
*******************************************************************
*
* SUBROUTINE ANALYS
*
* Input:
* SPEECH
* Indices 1 through LFRAME read.
* Output:
* VOICE
* Indices 1 through 2 written.
* PITCH
* Written in subroutine DYPTRK, and then perhaps read and written
* some more.
* RMS
* Written.
* RC
* Indices 1 through ORDER written (ORDER defined in contrl.fh).
*
* This subroutine maintains local state from one call to the next. If
* you want to switch to using a new audio stream for this filter, or
* reinitialize its state for any other reason, call the ENTRY
* INITANALYS.
*
*
* ENTRY PITDEC
*
* Input:
* PITCH - Encoded pitch index
* Output:
* PTAU - Decoded pitch period
*
* This entry has no local state. It accesses a "constant" array
* declared in ANALYS.
*
SUBROUTINE ANALYS(SPEECH, VOICE, PITCH, RMS, RC)
INCLUDE 'config.fh'
INCLUDE 'contrl.fh'
* Arguments to ANALYS
REAL SPEECH(LFRAME)
INTEGER VOICE(2), PITCH
REAL RMS, RC(ORDER)
* Arguments to entry PITDEC (below)
INTEGER PTAU
* Parameters/constants
* Constants
* NF = Number of frames
* AF = Frame in which analysis is done
* OSLEN = Length of the onset buffer
* LTAU = Number of pitch lags
* SBUFL, SBUFH = Start and end index of speech buffers
* LBUFL, LBUFH = Start and end index of LPF speech buffer
* MINWIN, MAXWIN = Min and Max length of voicing (and analysis) windows
* PWLEN, PWINH, PWINL = Length, upper and lower limits of pitch window
* DVWINL, DVWINH = Default lower and upper limits of voicing window
INTEGER NF, AF, OSLEN, LTAU, SBUFL, SBUFH, LBUFL, LBUFH
INTEGER MINWIN, MAXWIN, PWLEN, PWINL, PWINH, DVWINL, DVWINH
PARAMETER (NF=4, AF=3, OSLEN=10, LTAU=60)
PARAMETER (SBUFL=(AF-2)*MAXFRM+1, SBUFH=NF*MAXFRM)
PARAMETER (LBUFL=(AF-2)*MAXFRM-MAXPIT+1, LBUFH=NF*MAXFRM)
PARAMETER (MINWIN=90, MAXWIN=156)
PARAMETER (PWLEN=MAXPIT+MAXWIN)
PARAMETER (PWINH=AF*MAXFRM, PWINL=PWINH-PWLEN+1)
PARAMETER (DVWINL=PWINH-PWLEN/2-MAXWIN/2+1)
PARAMETER (DVWINH=DVWINL+MAXWIN-1)
* The tables TAU and BUFLIM, and the variable PRECOEF, are not
* Fortran PARAMETER's, but they are initialized with DATA
* statements, and never modified. Thus, they need not have SAVE
* statements for them to keep their values from one invocation to
* the next.
INTEGER TAU(LTAU)
INTEGER BUFLIM(4)
REAL PRECOEF
* Local variables that need not be saved
INTEGER I, J, LANAL, HALF
INTEGER IPITCH, MINPTR, MAXPTR, MINTAU, MIDX
REAL IVRC(2), PHI(MAXORD,MAXORD), PSI(MAXORD)
REAL AMDF(LTAU), TEMP
INTEGER EWIN(2,AF)
REAL ABUF(MAXWIN)
* Local state
* Data Buffers
* INBUF Raw speech (with DC bias removed each frame)
* PEBUF Preemphasized speech
* LPBUF Low pass speech buffer
* IVBUF Inverse filtered speech
* OSBUF Indexes of onsets in speech buffers
* VWIN Voicing window indices
* AWIN Analysis window indices
* EWIN Energy window indices
* VOIBUF Voicing decisions on windows in VWIN
* RMSBUF RMS energy
* RCBUF Reflection Coefficients
*
* Pitch is handled separately from the above parameters.
* The following variables deal with pitch:
* MIDX Encoded initial pitch estimate for analysis frame
* IPITCH Initial pitch computed for frame AF (decoded from MIDX)
* PITCH The encoded pitch value (index into TAU) for the present
* frame (delayed and smoothed by Dyptrack)
LOGICAL FIRST
REAL INBUF(SBUFL:SBUFH), PEBUF(SBUFL:SBUFH)
REAL LPBUF(LBUFL:LBUFH), IVBUF(PWINL:PWINH)
REAL BIAS
INTEGER OSBUF(OSLEN), OSPTR, OBOUND(AF)
INTEGER VWIN(2,AF), AWIN(2,AF), VOIBUF(2,0:AF)
REAL RMSBUF(AF), RCBUF(MAXORD, AF)
REAL ZPRE
SAVE FIRST
SAVE INBUF, PEBUF
SAVE LPBUF, IVBUF
SAVE BIAS
SAVE OSBUF, OSPTR, OBOUND
SAVE VWIN, AWIN, VOIBUF
SAVE RMSBUF, RCBUF
SAVE ZPRE
DATA TAU/20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
1 35,36,37,38,39,40,42,44,46,48,50,52,54,56,58,60,62,64,66,
1 68,70,72,74,76,78,80,84,88,92,96,100,104,108,112,116,120,
1 124,128,132,136,140,144,148,152,156/
DATA BUFLIM / SBUFL, SBUFH, LBUFL, LBUFH /
DATA PRECOEF /.9375/
DATA FIRST /.TRUE./
* IF(LISTL.GE.3) THEN
* WRITE(FDEBUG,900) NFRAME
*900 FORMAT(1X,//,65(2H- ),//,' ANALYSIS DATA -- FRAME',I6/)
* END IF
* Calculations are done on future frame due to requirements
* of the pitch tracker. Delay RMS and RC's 2 frames to give
* current frame parameters on return.
* Update all buffers
IF (FIRST) THEN
CALL INITANALYS ()
FIRST = .FALSE.
END IF
DO I = SBUFL, SBUFH-LFRAME
INBUF(I) = INBUF(LFRAME+I)
PEBUF(I) = PEBUF(LFRAME+I)
END DO
DO I = PWINL,PWINH-LFRAME
IVBUF(I) = IVBUF(LFRAME+I)
END DO
DO I = LBUFL,LBUFH-LFRAME
LPBUF(I) = LPBUF(LFRAME+I)
END DO
J=1
DO I = 1, OSPTR-1
IF (OSBUF(I) .GT. LFRAME) THEN
OSBUF(J)=OSBUF(I)-LFRAME
J=J+1
END IF
END DO
OSPTR=J
VOIBUF(1,0) = VOIBUF(1,1)
VOIBUF(2,0) = VOIBUF(2,1)
DO I = 1, AF-1
VWIN(1,I) = VWIN(1,I+1) - LFRAME
VWIN(2,I) = VWIN(2,I+1) - LFRAME
AWIN(1,I) = AWIN(1,I+1) - LFRAME
AWIN(2,I) = AWIN(2,I+1) - LFRAME
* EWIN(*,J) is unused for J .NE. AF, so the following shift is
* unnecessary. It also causes error messages when the C version
* of the code created from this by f2c is run with Purify. It
* correctly complains that uninitialized memory is being read.
* EWIN(1,I) = EWIN(1,I+1) - LFRAME
* EWIN(2,I) = EWIN(2,I+1) - LFRAME
OBOUND(I) = OBOUND(I+1)
VOIBUF(1,I) = VOIBUF(1,I+1)
VOIBUF(2,I) = VOIBUF(2,I+1)
RMSBUF(I) = RMSBUF(I+1)
DO J = 1, ORDER
RCBUF(J,I) = RCBUF(J,I+1)
END DO
END DO
* Copy input speech, scale to sign+12 bit integers
* Remove long term DC bias.
* If the average value in the frame was over 1/4096 (after current
* BIAS correction), then subtract that much more from samples in
* next frame. If the average value in the frame was under
* -1/4096, add 1/4096 more to samples in next frame. In all other
* cases, keep BIAS the same.
TEMP = 0
DO I = 1,LFRAME
INBUF(SBUFH-LFRAME+I) = SPEECH(I)*4096. - BIAS
TEMP = TEMP + INBUF(SBUFH-LFRAME+I)
END DO
IF( TEMP.GT. LFRAME ) BIAS = BIAS + 1
IF( TEMP.LT.-LFRAME ) BIAS = BIAS - 1
* Place Voicing Window
I = SBUFH + 1 - LFRAME
CALL PREEMP(INBUF(I), PEBUF(I), LFRAME, PRECOEF, ZPRE)
CALL ONSET( PEBUF, OSBUF, OSPTR, OSLEN,
1 SBUFL, SBUFH, LFRAME )
*
* MAXOSP is just a debugging variable.
*
* MAXOSP = MAX( MAXOSP, OSPTR )
*
CALL PLACEV( OSBUF, OSPTR, OSLEN, OBOUND(AF), VWIN, AF,
1 LFRAME, MINWIN, MAXWIN, DVWINL, DVWINH )
* The Pitch Extraction algorithm estimates the pitch for a frame
* of speech by locating the minimum of the average magnitude difference
* function (AMDF). The AMDF operates on low-pass, inverse filtered
* speech. (The low-pass filter is an 800 Hz, 19 tap, equiripple, FIR
* filter and the inverse filter is a 2nd-order LPC filter.) The pitch
* estimate is later refined by dynamic programming (DYPTRK). However,
* since some of DYPTRK's parameters are a function of the voicing
* decisions, a voicing decision must precede the final pitch estimation.
* See subroutines LPFILT, IVFILT, and TBDM.
* LPFILT reads indices LBUFH-LFRAME-29 = 511 through LBUFH = 720
* of INBUF, and writes indices LBUFH+1-LFRAME = 541 through LBUFH
* = 720 of LPBUF.
CALL LPFILT( INBUF(LBUFH+1-PWLEN), LPBUF(LBUFH+1-PWLEN),
1 PWLEN, LFRAME )
* IVFILT reads indices (PWINH-LFRAME-7) = 353 through PWINH = 540
* of LPBUF, and writes indices (PWINH-LFRAME+1) = 361 through
* PWINH = 540 of IVBUF.
CALL IVFILT( LPBUF(PWINL), IVBUF(PWINL), PWLEN, LFRAME, IVRC )
* TBDM reads indices PWINL = 229 through
* (PWINL-1)+MAXWIN+(TAU(LTAU)-TAU(1))/2 = 452 of IVBUF, and writes
* indices 1 through LTAU = 60 of AMDF.
CALL TBDM( IVBUF(PWINL), MAXWIN, TAU, LTAU, AMDF,
1 MINPTR, MAXPTR, MINTAU )
* Voicing decisions are made for each half frame of input speech.
* An initial voicing classification is made for each half of the
* analysis frame, and the voicing decisions for the present frame
* are finalized. See subroutine VOICIN.
* The voicing detector (VOICIN) classifies the input signal as
* unvoiced (including silence) or voiced using the AMDF windowed
* maximum-to-minimum ratio, the zero crossing rate, energy measures,
* reflection coefficients, and prediction gains.
* The pitch and voicing rules apply smoothing and isolated
* corrections to the pitch and voicing estimates and, in the process,
* introduce two frames of delay into the corrected pitch estimates and
* voicing decisions.
DO HALF = 1,2
CALL VOICIN( VWIN(1,AF), INBUF, LPBUF, BUFLIM, HALF,
1 AMDF(MINPTR), AMDF(MAXPTR), MINTAU, IVRC, OBOUND, VOIBUF, AF )
END DO
* Find the minimum cost pitch decision over several frames
* given the current voicing decision and the AMDF array
CALL DYPTRK( AMDF, LTAU, MINPTR, VOIBUF(2,AF), PITCH, MIDX )
IPITCH = TAU(MIDX)
* Place spectrum analysis and energy windows
CALL PLACEA( IPITCH, VOIBUF, OBOUND(AF), AF,
1 VWIN, AWIN, EWIN, LFRAME, MAXWIN )
* Remove short term DC bias over the analysis window, Put result in ABUF
LANAL = AWIN(2,AF) + 1 - AWIN(1,AF)
CALL DCBIAS( LANAL, PEBUF(AWIN(1,AF)), ABUF )
* ABUF(1:LANAL) is now defined. It is equal to
* PEBUF(AWIN(1,AF):AWIN(2,AF)) corrected for short term DC bias.
* IF ((AWIN(1,AF) .LT. SBUFL) .OR. (SBUFH .LT. AWIN(2,AF))) THEN
* WRITE (2,999) AWIN(1,AF), AWIN(2,AF), SBUFL, SBUFH
* 999 FORMAT(1X,'AWIN (',I4,':',I4,
* 1 ') goes outside of PEBUFs range (',I4,':',I4,')')
* STOP
* END IF
* IF (MAXWIN .LT. LANAL) THEN
* WRITE (2,998) LANAL, MAXWIN
* 998 FORMAT(1X,'LANAL (',I4,
* 1 ') goes outside of ABUFs range (1:',I4,')')
* STOP
* END IF
* Compute RMS over integer number of pitch periods within the
* analysis window.
* Note that in a hardware implementation this computation may be
* simplified by using diagonal elements of PHI computed by MLOAD.
* IF ( (EWIN(1,AF) .LT. AWIN(1,AF))
* 1 .OR. (AWIN(2,AF) .LT. EWIN(2,AF))) THEN
* WRITE (2,997) EWIN(1,AF), EWIN(2,AF), AWIN(1,AF), AWIN(2,AF)
* 997 FORMAT(1X,'EWIN (',I4,':',I4,
* 1 ') goes outside of AWINs range (',I4,':',I4,')')
* STOP
* END IF
CALL ENERGY( EWIN(2,AF)-EWIN(1,AF)+1,
1 ABUF(EWIN(1,AF)-AWIN(1,AF)+1), RMSBUF(AF) )
* Matrix load and invert, check RC's for stability
* IF (LANAL .LT. ORDER) THEN
* WRITE (2,996) LANAL, ORDER
* 996 FORMAT(1X,'MLOAD will read outside of ABUFs defined range ',
* 1 'of (1:LANAL=',I4,') because LANAL is less than',
* 1 ' ORDER=',I4)
* STOP
* END IF
CALL MLOAD( ORDER, 1, LANAL, ABUF, PHI, PSI )
CALL INVERT( ORDER, PHI, PSI, RCBUF(1,AF) )
CALL RCCHK( ORDER, RCBUF(1,AF-1), RCBUF(1,AF) )
* Set return parameters
VOICE(1) = VOIBUF(1,AF-2)
VOICE(2) = VOIBUF(2,AF-2)
RMS = RMSBUF(AF-2)
DO I = 1,ORDER
RC(I) = RCBUF(I,AF-2)
END DO
* Print out test data
* IF(LISTL.GE.3) THEN
* IF(LISTL.GE.4) THEN
* IF(LISTL.GE.6) THEN
* WRITE(FDEBUG,980) 'INBUF:',INBUF
* WRITE(FDEBUG,980) 'LPBUF:',LPBUF
* WRITE(FDEBUG,980) 'IVBUF:',IVBUF
* WRITE(FDEBUG,980) 'PEBUF:',PEBUF
* END IF
* WRITE(FDEBUG,980) 'AMDF:',AMDF
* END IF
* IF(OSPTR.GT.1) WRITE(FDEBUG,970)
* 1 'OSBUF Onset Locations:', (OSBUF(I),I=1,OSPTR-1)
* IF(LISTL.GE.4) THEN
* WRITE(FDEBUG,980) 'PHI Matrix Values:',
* 1 ((PHI(I,J),J=1,ORDER),I=1,ORDER)
* WRITE(FDEBUG,980) 'PSI Vector Values:',PSI
*970 FORMAT(1X,A,100(/1X,20I6))
*980 FORMAT(1X,A,100(/1X,10F12.1))
* END IF
* WRITE(FDEBUG,990)
*990 FORMAT(' FRAME AWIN EWIN BIAS',T34,
* 1 'V/UV Pitch RMS',T54,
* 1 'RC1 RC2 RC3 RC4 RC5 ',
* 1 'RC6 RC7 RC8 RC9 RC10')
* WRITE(FDEBUG,992) NFRAME, AWIN(1,AF), AWIN(2,AF),
* 1 EWIN(1,AF), EWIN(2,AF), BIAS,
* 1 VOIBUF(2,AF), IPITCH, RMSBUF(AF), (RCBUF(I,AF),I=1,ORDER)
*992 FORMAT(1X,I6,2I4,1X,2I4,F6.1,T34,I2,I8,F6.0,T50,10F8.3)
* END IF
RETURN
********************************************************************
* Decode pitch index (PITCH) to pitch period (PTAU)
********************************************************************
ENTRY PITDEC( PITCH, PTAU )
IF (PITCH .GE. 1 .AND. PITCH .LE. LTAU) THEN
PTAU = TAU(PITCH)
ELSE
PTAU = 0
END IF
RETURN
ENTRY INITANALYS ()
* Set FIRST to .FALSE., so that just in case someone calls
* INITANALYS before calling ANALYS for the first time, then this
* entry will not be called by ANALYS itself.
FIRST = .FALSE.
* Initialize local state in all subroutines that have local state.
CALL INITONSET ()
CALL INITVOICIN ()
CALL INITDYPTRK ()
* INBUF, PEBUF, LPBUF, and IVBUF were not initialized in the
* original code. Initial values of 0 appear to be safe.
DO I = SBUFL,SBUFH
INBUF(I) = 0.
PEBUF(I) = 0.
END DO
DO I = LBUFL,LBUFH
LPBUF(I) = 0.
END DO
DO I = PWINL,PWINH
IVBUF(I) = 0.
END DO
BIAS = 0
* Although OSBUF is saved from one invocation to the next, it need
* not have an initial defined value, because OSPTR is initialized
* to 1, and only entries 1 through OSPTR-1 may be read without
* writing them first.
OSPTR = 1
DO I = 1,AF
OBOUND(I) = 0
END DO
* Should other indices of VWIN and AWIN be initialized, or is this
* unnecessary? If unnecessary, why?
VWIN(1,AF) = DVWINL
VWIN(2,AF) = DVWINH
AWIN(1,AF) = DVWINL
AWIN(2,AF) = DVWINH
* VOIBUF was not initialized in the original code. I believe
* initializing it to all 0's is a safe decision, given that its
* contents are always 0/1 truth values representing the decision
* of whether a half-frame was voiced or not.
DO I = 1,2
DO J = 0,AF
VOIBUF(I,J) = 0
END DO
END DO
* RMSBUF and RCBUF were also not initialized in the original code.
* Again, initial values of 0 appear to be safe.
DO I = 1,AF
RMSBUF(I) = 0.
DO J = 1,ORDER
RCBUF(J,I) = 0.
END DO
END DO
ZPRE = 0.
RETURN
END