www.pudn.com > lpc10-15.zip > bsynz.f
******************************************************************
*
* BSYNZ Version 54
*
* $Log: bsynz.f,v $
* Revision 1.5 1996/08/20 21:13:00 jaf
* In the previous version, I mistakenly SAVE'd and initialized LPI0 and
* HPI0 instead of LPI1 and HPI1. LPI0 and HPI0 do not need to be saved,
* nor do they need to be initialized.
*
* Revision 1.4 1996/03/27 18:11:22 jaf
* Changed the range of NOISE printed out in the debugging statements,
* even though they are commented out. I didn't discover this until I
* tried comparing two different versions of the LPC-10 coder, each with
* full tracing enabled.
*
* Revision 1.3 1996/03/26 19:33:23 jaf
* Commented out trace statements.
*
* Revision 1.2 1996/03/20 17:12:54 jaf
* Added comments about which indices of array arguments are read or
* written.
*
* Rearranged local variable declarations to indicate which need to be
* saved from one invocation to the next. Added entry INITBSYNZ to
* reinitialize the local state variables, if desired.
*
* Revision 1.1 1996/02/07 14:43:15 jaf
* Initial revision
*
*
******************************************************************
*
* Synthesize One Pitch Epoch
*
* Input:
* COEF - Predictor coefficients
* Indices 1 through ORDER read.
* IP - Pitch period (number of samples to synthesize)
* IV - Voicing for the current epoch
* RMS - Energy for the current epoch
* RATIO - Energy slope for plosives
* G2PASS- Sharpening factor for 2 pass synthesis
* Output:
* SOUT - Synthesized speech
* Indices 1 through IP written.
*
* 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
* INITBSYNZ.
*
SUBROUTINE BSYNZ(COEF, IP, IV, SOUT, RMS, RATIO, G2PASS)
INCLUDE 'config.fh'
INCLUDE 'contrl.fh'
* Arguments
REAL COEF(ORDER)
INTEGER IP, IV
REAL SOUT(IP), RMS, RATIO, G2PASS
* Function return value definitions
INTEGER RANDOM
* Parameters/constants
* KEXC is not a Fortran PARAMETER, but it is an array initialized
* with a DATA statement that is never modified.
INTEGER KEXC(25)
REAL A0, A1, A2, A3, B0, B1, B2, B3
REAL MESCL, PESCL
PARAMETER (A0= .125, A1=.75, A2= .125, A3=0)
PARAMETER (B0=-.125, B1=.25, B2=-.125, B3=0)
PARAMETER (MESCL=1.0, PESCL=1.0)
* Local variables that need not be saved
* NOISE is declared with range (1:MAXPIT+MAXORD), but only indices
* ORDER+1 through ORDER+IP are ever used, and I think that IP
* .LE. MAXPIT. Why not declare it to be in the range (1:MAXPIT)
* and use that range?
INTEGER I, J, K
INTEGER PX
REAL NOISE(MAXPIT+MAXORD)
REAL LPI0, HPI0
REAL PULSE, SSCALE, XSSQ, SUM, SSQ, GAIN
REAL XY
* Local state
* I believe that only indices 1 through ORDER of EXC need to be
* saved from one invocation to the next, but we may as well save
* the whole array.
* None of these local variables were given initial values in the
* original code. I'm guessing that 0 is a reasonable initial
* value for all of them.
INTEGER IPO
REAL EXC(MAXPIT+MAXORD), EXC2(MAXPIT+MAXORD)
REAL LPI1, LPI2, LPI3, HPI1, HPI2, HPI3
REAL RMSO
SAVE IPO
SAVE EXC, EXC2
SAVE LPI1, LPI2, LPI3, HPI1, HPI2, HPI3
SAVE RMSO
DATA IPO /0/
* MAXPIT+MAXORD=166
DATA EXC /166*0./, EXC2 /166*0./
DATA LPI1 /0./, LPI2 /0./, LPI3 /0./
DATA HPI1 /0./, HPI2 /0./, HPI3 /0./
DATA RMSO /0./
DATA KEXC /8,-16,26,-48,86,-162,294,-502,718,-728,
1 184,672,-610,-672,184,728,718,502,294,162,
1 86,48,26,16,8/
* Calculate history scale factor XY and scale filter state
XY = MIN( RMSO/(RMS+1E-6), 8. )
RMSO = RMS
DO I = 1,ORDER
EXC2(I) = EXC2(IPO+I)*XY
END DO
IPO = IP
IF(IV.EQ.0) THEN
* Generate white noise for unvoiced
DO I = 1,IP
EXC(ORDER+I) = RANDOM() / 2**6
END DO
* Impulse doublet excitation for plosives
* (RANDOM()+32768) is in the range 0 to 2**16-1. Therefore the
* following expression should be evaluated using integers with at
* least 32 bits (16 isn't enough), and PX should be in the range
* ORDER+1+0 through ORDER+1+(IP-2) .EQ. ORDER+IP-1.
PX = ((RANDOM()+32768)*(IP-1)/2**16) + ORDER + 1
PULSE = PESCL*(RATIO/4)*342
IF(PULSE.GT.2000) PULSE = 2000
EXC(PX) = EXC(PX) + PULSE
EXC(PX+1) = EXC(PX+1) - PULSE
* Load voiced excitation
ELSE
SSCALE = SQRT(FLOAT(IP))/6.928
DO I = 1,IP
EXC(ORDER+I) = 0.
IF(I.LE.25) EXC(ORDER+I) = SSCALE*KEXC(I)
LPI0 = EXC(ORDER+I)
EXC(ORDER+I) = A0*EXC(ORDER+I) + A1*LPI1 + A2*LPI2 + A3*LPI3
LPI3 = LPI2
LPI2 = LPI1
LPI1 = LPI0
END DO
DO I = 1,IP
NOISE(ORDER+I) = MESCL * RANDOM() / 2**6
HPI0 = NOISE(ORDER+I)
NOISE(ORDER+I) = B0*NOISE(ORDER+I)
1 + B1*HPI1 + B2*HPI2 + B3*HPI3
HPI3 = HPI2
HPI2 = HPI1
HPI1 = HPI0
END DO
DO I = 1,IP
EXC(ORDER+I) = EXC(ORDER+I) + NOISE(ORDER+I)
END DO
END IF
* Synthesis filters:
* Modify the excitation with all-zero filter 1 + G*SUM
XSSQ = 0
DO I = 1,IP
K = ORDER + I
SUM = 0.
DO J = 1,ORDER
SUM = SUM + COEF(J)*EXC(K-J)
END DO
SUM = SUM*G2PASS
EXC2(K) = SUM + EXC(K)
END DO
* Synthesize using the all pole filter 1 / (1 - SUM)
DO I = 1,IP
K = ORDER + I
SUM = 0.
DO J = 1,ORDER
SUM = SUM + COEF(J)*EXC2(K-J)
END DO
EXC2(K) = SUM + EXC2(K)
XSSQ = XSSQ + EXC2(K)*EXC2(K)
END DO
* Save filter history for next epoch
DO I = 1,ORDER
EXC(I) = EXC(IP+I)
EXC2(I) = EXC2(IP+I)
END DO
* Apply gain to match RMS
SSQ = RMS*RMS*IP
GAIN = SQRT(SSQ/XSSQ)
DO I = 1,IP
SOUT(I) = GAIN*EXC2(ORDER+I)
END DO
* Print test data
* IF(LISTL.GE.5) THEN
*
* I changed the range of indices to print within NOISE from
* 1,IP+ORDER to 1+ORDER,IP+ORDER since indices 1 through ORDER
* of NOISE are never used. This avoids printing out their
* "garbage" values.
*
* IF(IV.NE.0)
* 1 WRITE(FDEBUG,980) 'NOISE:',(NOISE(I),I=1+ORDER,IP+ORDER)
* WRITE(FDEBUG,980) 'EXC:', (EXC(I), I=1,IP+ORDER)
* WRITE(FDEBUG,980) 'EXC2:', (EXC2(I), I=1,IP+ORDER)
* WRITE(FDEBUG,980) 'SOUT:', (SOUT(I), I=1,IP)
*980 FORMAT(1X,A,100(/1X,10F10.1))
* END IF
RETURN
ENTRY INITBSYNZ ()
IPO = 0
DO I = 1,(MAXPIT+MAXORD)
EXC(I) = 0.
EXC2(I) = 0.
END DO
LPI1 = 0.
LPI2 = 0.
LPI3 = 0.
HPI1 = 0.
HPI2 = 0.
HPI3 = 0.
RMSO = 0.
RETURN
END