wolffd@0
|
1 function synWave = synlpc(aCoeff,source,sr,G,fr,fs,preemp)
|
wolffd@0
|
2 % USAGE: synWave = synlpc(aCoeff,source,sr,G,fr,fs,preemp);
|
wolffd@0
|
3 %
|
wolffd@0
|
4 % This function synthesizes a (speech) signal based on a LPC (linear-
|
wolffd@0
|
5 % predictive coding) model of the signal. The LPC coefficients are a
|
wolffd@0
|
6 % short-time measure of the speech signal which describe the signal as the
|
wolffd@0
|
7 % output of an all-pole filter. This all-pole filter provides a good
|
wolffd@0
|
8 % description of the speech articulators; thus LPC analysis is often used in
|
wolffd@0
|
9 % speech recognition and speech coding systems. The LPC analysis is done
|
wolffd@0
|
10 % using the proclpc routine. This routine can be used to verify that the
|
wolffd@0
|
11 % LPC analysis produces the correct answer, or as a synthesis stage after
|
wolffd@0
|
12 % first modifying the LPC model.
|
wolffd@0
|
13 %
|
wolffd@0
|
14 % The results of LPC analysis are a new representation of the signal
|
wolffd@0
|
15 % s(n) = G e(n) - sum from 1 to L a(i)s(n-i)
|
wolffd@0
|
16 % where s(n) is the original data. a(i) and e(n) are the outputs of the LPC
|
wolffd@0
|
17 % analysis with a(i) representing the LPC model. The e(n) term represents
|
wolffd@0
|
18 % either the speech source's excitation, or the residual: the details of the
|
wolffd@0
|
19 % signal that are not captured by the LPC coefficients. The G factor is a
|
wolffd@0
|
20 % gain term.
|
wolffd@0
|
21 %
|
wolffd@0
|
22 % LPC synthesis produces a monaural sound vector (synWave) which is
|
wolffd@0
|
23 % sampled at a sampling rate of "sr". The following parameters are mandatory
|
wolffd@0
|
24 % aCoeff - The LPC analysis results, a(i). One column of L+1 numbers for each
|
wolffd@0
|
25 % frame of data. The number of rows of aCoeff determines L.
|
wolffd@0
|
26 % source - The LPC residual, e(n). One column of sr*fs samples representing
|
wolffd@0
|
27 % the excitation or residual of the LPC filter.
|
wolffd@0
|
28 % G - The LPC gain for each frame.
|
wolffd@0
|
29 %
|
wolffd@0
|
30 % The following parameters are optional and default to the indicated values.
|
wolffd@0
|
31 % fr - Frame time increment, in ms. The LPC analysis is done starting every
|
wolffd@0
|
32 % fr ms in time. Defaults to 20ms (50 LPC vectors a second)
|
wolffd@0
|
33 % fs - Frame size in ms. The LPC analysis is done by windowing the speech
|
wolffd@0
|
34 % data with a rectangular window that is fs ms long. Defaults to 30ms
|
wolffd@0
|
35 % preemp - This variable is the epsilon in a digital one-zero filter which
|
wolffd@0
|
36 % serves to preemphasize the speech signal and compensate for the 6dB
|
wolffd@0
|
37 % per octave rolloff in the radiation function. Defaults to .9378.
|
wolffd@0
|
38 %
|
wolffd@0
|
39 % This code was graciously provided by:
|
wolffd@0
|
40 % Delores Etter (University of Colorado, Boulder) and
|
wolffd@0
|
41 % Professor Geoffrey Orsak (Southern Methodist University)
|
wolffd@0
|
42 % It was first published in
|
wolffd@0
|
43 % Orsak, G.C. et al. "Collaborative SP education using the Internet and
|
wolffd@0
|
44 % MATLAB" IEEE SIGNAL PROCESSING MAGAZINE Nov. 1995. vol.12, no.6, pp.
|
wolffd@0
|
45 % 23-32.
|
wolffd@0
|
46 % Modified and debugging plots added by Kate Nguyen and Malcolm Slaney
|
wolffd@0
|
47
|
wolffd@0
|
48 % (c) 1998 Interval Research Corporation
|
wolffd@0
|
49 % A more complete set of routines for LPC analysis can be found at
|
wolffd@0
|
50 % http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
|
wolffd@0
|
51
|
wolffd@0
|
52
|
wolffd@0
|
53
|
wolffd@0
|
54 if (nargin < 5), fr = 20; end;
|
wolffd@0
|
55 if (nargin < 6), fs = 30; end;
|
wolffd@0
|
56 if (nargin < 7), preemp = .9378; end;
|
wolffd@0
|
57
|
wolffd@0
|
58 msfs = round(sr*fs/1000);
|
wolffd@0
|
59 msfr = round(sr*fr/1000);
|
wolffd@0
|
60 msoverlap = msfs - msfr;
|
wolffd@0
|
61 ramp = [0:1/(msoverlap-1):1]';
|
wolffd@0
|
62 [L1 nframe] = size(aCoeff); % L1 = 1+number of LPC coeffs
|
wolffd@0
|
63
|
wolffd@0
|
64 [row col] = size(source);
|
wolffd@0
|
65 if(row==1 | col==1) % continous stream; must be
|
wolffd@0
|
66 % windowed
|
wolffd@0
|
67 postFilter = 0; duration = length(source); frameIndex = 1;
|
wolffd@0
|
68 for sampleIndex=1:msfr:duration-msfs+1
|
wolffd@0
|
69 resid(:,frameIndex) = source(sampleIndex:(sampleIndex+msfs-1))';
|
wolffd@0
|
70 frameIndex = frameIndex+1;
|
wolffd@0
|
71 end
|
wolffd@0
|
72 else
|
wolffd@0
|
73 postFilter = 1; resid = source;
|
wolffd@0
|
74 end
|
wolffd@0
|
75
|
wolffd@0
|
76 [row col] = size(resid);
|
wolffd@0
|
77 %if ~(col==nframe)
|
wolffd@0
|
78 % error('synLPC: numbers of LPC frames and source frames do not match');
|
wolffd@0
|
79 if col<nframe
|
wolffd@0
|
80 nframe=col;
|
wolffd@0
|
81 end
|
wolffd@0
|
82
|
wolffd@0
|
83 for frameIndex=1:nframe
|
wolffd@0
|
84 % Calculate the filter response
|
wolffd@0
|
85 % by evaluating the z-transform
|
wolffd@0
|
86 % if 1
|
wolffd@0
|
87 % gain=0;
|
wolffd@0
|
88 % cft=0:(1/255):1;
|
wolffd@0
|
89 % for index=1:L1-1
|
wolffd@0
|
90 % gain = gain + aCoeff(index,frameIndex)*exp(-i*2*pi*cft).^index;
|
wolffd@0
|
91 % end
|
wolffd@0
|
92 % gain = abs(1./gain);
|
wolffd@0
|
93 % spec(:,frameIndex) = 20*log10(gain(1:128))';
|
wolffd@0
|
94 % plot(20*log10(gain));
|
wolffd@0
|
95 % title(frameIndex);
|
wolffd@0
|
96 % drawnow;
|
wolffd@0
|
97 % end
|
wolffd@0
|
98
|
wolffd@0
|
99 % Calculate the filter response
|
wolffd@0
|
100 % from the filter's impulse
|
wolffd@0
|
101 % response (to check above).
|
wolffd@0
|
102 % if 0
|
wolffd@0
|
103 % impulseResponse = filter(1, aCoeff(:,frameIndex), [1 zeros(1,255)]);
|
wolffd@0
|
104 % freqResp = 20*log10(abs(fft(impulseResponse)));
|
wolffd@0
|
105 % plot(freqResp);
|
wolffd@0
|
106 % end
|
wolffd@0
|
107
|
wolffd@0
|
108
|
wolffd@0
|
109 A = aCoeff(:,frameIndex);
|
wolffd@0
|
110 residFrame = resid(:,frameIndex)*G(frameIndex);
|
wolffd@0
|
111 synFrame = filter(1, A', residFrame); % synthesize speech from LPC
|
wolffd@0
|
112 % coeffs
|
wolffd@0
|
113 if(frameIndex==1) % add synthesize frames using a
|
wolffd@0
|
114 synWave = synFrame(1:msfr); % trapezoidal window
|
wolffd@0
|
115 else
|
wolffd@0
|
116 synWave = [synWave; overlap+synFrame(1:msoverlap).*ramp; ...
|
wolffd@0
|
117 synFrame(msoverlap+1:msfr)];
|
wolffd@0
|
118 end
|
wolffd@0
|
119 if(frameIndex==nframe)
|
wolffd@0
|
120 synWave = [synWave; synFrame(msfr+1:msfs)];
|
wolffd@0
|
121 else
|
wolffd@0
|
122 overlap = synFrame(msfr+1:msfs).*flipud(ramp);
|
wolffd@0
|
123 end
|
wolffd@0
|
124 %length(synWave)
|
wolffd@0
|
125 end;
|
wolffd@0
|
126
|
wolffd@0
|
127 if(postFilter)
|
wolffd@0
|
128 synWave = filter(1, [1 -preemp], synWave);
|
wolffd@0
|
129 end
|
wolffd@0
|
130
|