wolffd@0
|
1 function y=MakeVowel(len, pitch, sampleRate, f1, f2, f3)
|
wolffd@0
|
2 % MakeVowel(len, pitch [, sampleRate, f1, f2, f3]) - Make a vowel with
|
wolffd@0
|
3 % "len" samples and the given pitch. The sample rate defaults to
|
wolffd@0
|
4 % be 22254.545454 Hz (the native Mactinosh Sampling Rate). The
|
wolffd@0
|
5 % formant frequencies are f1, f2 & f3. Some common vowels are
|
wolffd@0
|
6 % Vowel f1 f2 f3
|
wolffd@0
|
7 % /a/ 730 1090 2440
|
wolffd@0
|
8 % /i/ 270 2290 3010
|
wolffd@0
|
9 % /u/ 300 870 2240
|
wolffd@0
|
10 %
|
wolffd@0
|
11 % The pitch variable can either be a scalar indicating the actual
|
wolffd@0
|
12 % pitch frequency, or an array of impulse locations. Using an
|
wolffd@0
|
13 % array of impulses allows this routine to compute vowels with
|
wolffd@0
|
14 % varying pitch.
|
wolffd@0
|
15 %
|
wolffd@0
|
16 % Alternatively, f1 can be replaced with one of the following strings
|
wolffd@0
|
17 % 'a', 'i', 'u' and the appropriate formant frequencies are
|
wolffd@0
|
18 % automatically selected.
|
wolffd@0
|
19 % Modified by R. Duda, 3/13/94
|
wolffd@0
|
20
|
wolffd@0
|
21 % (c) 1998 Interval Research Corporation
|
wolffd@0
|
22
|
wolffd@0
|
23 if nargin < 2,
|
wolffd@0
|
24 fprintf('Format: y = MakeVowel(len, pitch [, sampleRate, f1, f2, f3])\n');
|
wolffd@0
|
25 return;
|
wolffd@0
|
26 end;
|
wolffd@0
|
27
|
wolffd@0
|
28 if nargin < 6; f3 = 0; end;
|
wolffd@0
|
29 if nargin < 5; f2 = 0; end;
|
wolffd@0
|
30 if nargin < 4,
|
wolffd@0
|
31 f1 = 0;
|
wolffd@0
|
32 else
|
wolffd@0
|
33 if isstr(f1)
|
wolffd@0
|
34 if f1 == 'a' | f1 == '/a/'
|
wolffd@0
|
35 f1=730; f2=1090; f3=2440;
|
wolffd@0
|
36 elseif f1 == 'i' | f1 == '/i/'
|
wolffd@0
|
37 f1=270; f2=2290; f3=3010;
|
wolffd@0
|
38 elseif f1 == 'u' | f1 == '/u/'
|
wolffd@0
|
39 f1=300; f2=870; f3=2240;
|
wolffd@0
|
40 end
|
wolffd@0
|
41 end;
|
wolffd@0
|
42 end;
|
wolffd@0
|
43
|
wolffd@0
|
44 if nargin < 3,
|
wolffd@0
|
45 sampleRate = 22254.545454;
|
wolffd@0
|
46 elseif sampleRate < 1000, % Apparently for test purposes
|
wolffd@0
|
47 sampleRate = 22254.545454;
|
wolffd@0
|
48 end;
|
wolffd@0
|
49
|
wolffd@0
|
50 % GlottalPulses(pitch, fs, len) - Generate a stream of
|
wolffd@0
|
51 % glottal pulses with the given pitch (in Hz) and sampling
|
wolffd@0
|
52 % frequency (sampleRate). A vector of the requested length is returned.
|
wolffd@0
|
53 y=zeros(1,len);
|
wolffd@0
|
54 if length(pitch) > 1, % If true, use to determine points
|
wolffd@0
|
55 points=pitch; % Check for valid sequence of points
|
wolffd@0
|
56 if any(points~=sort(points)),
|
wolffd@0
|
57 error('Values in pitch array must be in ascending order.')
|
wolffd@0
|
58 end;
|
wolffd@0
|
59 if points(1) < 1,
|
wolffd@0
|
60 error('Values in pitch array cannot be less than 1.');
|
wolffd@0
|
61 end;
|
wolffd@0
|
62 kmax=sum(points <= len);
|
wolffd@0
|
63 if kmax == 0,
|
wolffd@0
|
64 error('All values in pitch array exceed "len"; none should.');
|
wolffd@0
|
65 elseif kmax < length(points),
|
wolffd@0
|
66 fprintf('Some values in pitch array exceed "len"; truncating.\n');
|
wolffd@0
|
67 points=points(1:kmax);
|
wolffd@0
|
68 end;
|
wolffd@0
|
69 else
|
wolffd@0
|
70 points=1:sampleRate/pitch:len;
|
wolffd@0
|
71 end;
|
wolffd@0
|
72 indices=floor(points);
|
wolffd@0
|
73
|
wolffd@0
|
74 % Use a triangular approximation to an impulse function. The important
|
wolffd@0
|
75 % part is to keep the total amplitude the same.
|
wolffd@0
|
76 y(indices) = (indices+1)-points;
|
wolffd@0
|
77 y(indices+1) = points-indices;
|
wolffd@0
|
78
|
wolffd@0
|
79 % GlottalFilter(x,fs) - Filter an impulse train and simulate the glottal
|
wolffd@0
|
80 % transfer function. The sampling interval (sampleRate) is given in Hz.
|
wolffd@0
|
81 % The filtering performed by this function is two first-order filters
|
wolffd@0
|
82 % at 250Hz.
|
wolffd@0
|
83 a = exp(-250*2*pi/sampleRate);
|
wolffd@0
|
84 %y=filter([1,0,-1],[1,-2*a,a*a],y); % Not as good as one below....
|
wolffd@0
|
85 y=filter([1],[1,0,-a*a],y);
|
wolffd@0
|
86
|
wolffd@0
|
87 % FormantFilter(input, f, fs) - Filter an input sequence to model one
|
wolffd@0
|
88 % formant in a speech signal. The formant frequency (in Hz) is given
|
wolffd@0
|
89 % by f and the bandwidth of the formant is a constant 50Hz. The
|
wolffd@0
|
90 % sampling frequency in Hz is given by fs.
|
wolffd@0
|
91 if f1 > 0
|
wolffd@0
|
92 cft = f1/sampleRate;
|
wolffd@0
|
93 bw = 50;
|
wolffd@0
|
94 q = f1/bw;
|
wolffd@0
|
95 rho = exp(-pi * cft / q);
|
wolffd@0
|
96 theta = 2 * pi * cft * sqrt(1-1/(4 * q*q));
|
wolffd@0
|
97 a2 = -2*rho*cos(theta);
|
wolffd@0
|
98 a3 = rho*rho;
|
wolffd@0
|
99 y=filter([1+a2+a3],[1,a2,a3],y);
|
wolffd@0
|
100 end;
|
wolffd@0
|
101
|
wolffd@0
|
102 % FormantFilter(input, f, fs) - Filter an input sequence to model one
|
wolffd@0
|
103 % formant in a speech signal. The formant frequency (in Hz) is given
|
wolffd@0
|
104 % by f and the bandwidth of the formant is a constant 50Hz. The
|
wolffd@0
|
105 % sampling frequency in Hz is given by fs.
|
wolffd@0
|
106 if f2 > 0
|
wolffd@0
|
107 cft = f2/sampleRate;
|
wolffd@0
|
108 bw = 50;
|
wolffd@0
|
109 q = f2/bw;
|
wolffd@0
|
110 rho = exp(-pi * cft / q);
|
wolffd@0
|
111 theta = 2 * pi * cft * sqrt(1-1/(4 * q*q));
|
wolffd@0
|
112 a2 = -2*rho*cos(theta);
|
wolffd@0
|
113 a3 = rho*rho;
|
wolffd@0
|
114 y=filter([1+a2+a3],[1,a2,a3],y);
|
wolffd@0
|
115 end;
|
wolffd@0
|
116
|
wolffd@0
|
117 % FormantFilter(input, f, fs) - Filter an input sequence to model one
|
wolffd@0
|
118 % formant in a speech signal. The formant frequency (in Hz) is given
|
wolffd@0
|
119 % by f and the bandwidth of the formant is a constant 50Hz. The
|
wolffd@0
|
120 % sampling frequency in Hz is given by fs.
|
wolffd@0
|
121 if f3 > 0
|
wolffd@0
|
122 cft = f3/sampleRate;
|
wolffd@0
|
123 bw = 50;
|
wolffd@0
|
124 q = f3/bw;
|
wolffd@0
|
125 rho = exp(-pi * cft / q);
|
wolffd@0
|
126 theta = 2 * pi * cft * sqrt(1-1/(4 * q*q));
|
wolffd@0
|
127 a2 = -2*rho*cos(theta);
|
wolffd@0
|
128 a3 = rho*rho;
|
wolffd@0
|
129 y=filter([1+a2+a3],[1,a2,a3],y);
|
wolffd@0
|
130 end;
|