Daniel@0: function y=MakeVowel(len, pitch, sampleRate, f1, f2, f3) Daniel@0: % MakeVowel(len, pitch [, sampleRate, f1, f2, f3]) - Make a vowel with Daniel@0: % "len" samples and the given pitch. The sample rate defaults to Daniel@0: % be 22254.545454 Hz (the native Mactinosh Sampling Rate). The Daniel@0: % formant frequencies are f1, f2 & f3. Some common vowels are Daniel@0: % Vowel f1 f2 f3 Daniel@0: % /a/ 730 1090 2440 Daniel@0: % /i/ 270 2290 3010 Daniel@0: % /u/ 300 870 2240 Daniel@0: % Daniel@0: % The pitch variable can either be a scalar indicating the actual Daniel@0: % pitch frequency, or an array of impulse locations. Using an Daniel@0: % array of impulses allows this routine to compute vowels with Daniel@0: % varying pitch. Daniel@0: % Daniel@0: % Alternatively, f1 can be replaced with one of the following strings Daniel@0: % 'a', 'i', 'u' and the appropriate formant frequencies are Daniel@0: % automatically selected. Daniel@0: % Modified by R. Duda, 3/13/94 Daniel@0: Daniel@0: % (c) 1998 Interval Research Corporation Daniel@0: Daniel@0: if nargin < 2, Daniel@0: fprintf('Format: y = MakeVowel(len, pitch [, sampleRate, f1, f2, f3])\n'); Daniel@0: return; Daniel@0: end; Daniel@0: Daniel@0: if nargin < 6; f3 = 0; end; Daniel@0: if nargin < 5; f2 = 0; end; Daniel@0: if nargin < 4, Daniel@0: f1 = 0; Daniel@0: else Daniel@0: if isstr(f1) Daniel@0: if f1 == 'a' | f1 == '/a/' Daniel@0: f1=730; f2=1090; f3=2440; Daniel@0: elseif f1 == 'i' | f1 == '/i/' Daniel@0: f1=270; f2=2290; f3=3010; Daniel@0: elseif f1 == 'u' | f1 == '/u/' Daniel@0: f1=300; f2=870; f3=2240; Daniel@0: end Daniel@0: end; Daniel@0: end; Daniel@0: Daniel@0: if nargin < 3, Daniel@0: sampleRate = 22254.545454; Daniel@0: elseif sampleRate < 1000, % Apparently for test purposes Daniel@0: sampleRate = 22254.545454; Daniel@0: end; Daniel@0: Daniel@0: % GlottalPulses(pitch, fs, len) - Generate a stream of Daniel@0: % glottal pulses with the given pitch (in Hz) and sampling Daniel@0: % frequency (sampleRate). A vector of the requested length is returned. Daniel@0: y=zeros(1,len); Daniel@0: if length(pitch) > 1, % If true, use to determine points Daniel@0: points=pitch; % Check for valid sequence of points Daniel@0: if any(points~=sort(points)), Daniel@0: error('Values in pitch array must be in ascending order.') Daniel@0: end; Daniel@0: if points(1) < 1, Daniel@0: error('Values in pitch array cannot be less than 1.'); Daniel@0: end; Daniel@0: kmax=sum(points <= len); Daniel@0: if kmax == 0, Daniel@0: error('All values in pitch array exceed "len"; none should.'); Daniel@0: elseif kmax < length(points), Daniel@0: fprintf('Some values in pitch array exceed "len"; truncating.\n'); Daniel@0: points=points(1:kmax); Daniel@0: end; Daniel@0: else Daniel@0: points=1:sampleRate/pitch:len; Daniel@0: end; Daniel@0: indices=floor(points); Daniel@0: Daniel@0: % Use a triangular approximation to an impulse function. The important Daniel@0: % part is to keep the total amplitude the same. Daniel@0: y(indices) = (indices+1)-points; Daniel@0: y(indices+1) = points-indices; Daniel@0: Daniel@0: % GlottalFilter(x,fs) - Filter an impulse train and simulate the glottal Daniel@0: % transfer function. The sampling interval (sampleRate) is given in Hz. Daniel@0: % The filtering performed by this function is two first-order filters Daniel@0: % at 250Hz. Daniel@0: a = exp(-250*2*pi/sampleRate); Daniel@0: %y=filter([1,0,-1],[1,-2*a,a*a],y); % Not as good as one below.... Daniel@0: y=filter([1],[1,0,-a*a],y); Daniel@0: Daniel@0: % FormantFilter(input, f, fs) - Filter an input sequence to model one Daniel@0: % formant in a speech signal. The formant frequency (in Hz) is given Daniel@0: % by f and the bandwidth of the formant is a constant 50Hz. The Daniel@0: % sampling frequency in Hz is given by fs. Daniel@0: if f1 > 0 Daniel@0: cft = f1/sampleRate; Daniel@0: bw = 50; Daniel@0: q = f1/bw; Daniel@0: rho = exp(-pi * cft / q); Daniel@0: theta = 2 * pi * cft * sqrt(1-1/(4 * q*q)); Daniel@0: a2 = -2*rho*cos(theta); Daniel@0: a3 = rho*rho; Daniel@0: y=filter([1+a2+a3],[1,a2,a3],y); Daniel@0: end; Daniel@0: Daniel@0: % FormantFilter(input, f, fs) - Filter an input sequence to model one Daniel@0: % formant in a speech signal. The formant frequency (in Hz) is given Daniel@0: % by f and the bandwidth of the formant is a constant 50Hz. The Daniel@0: % sampling frequency in Hz is given by fs. Daniel@0: if f2 > 0 Daniel@0: cft = f2/sampleRate; Daniel@0: bw = 50; Daniel@0: q = f2/bw; Daniel@0: rho = exp(-pi * cft / q); Daniel@0: theta = 2 * pi * cft * sqrt(1-1/(4 * q*q)); Daniel@0: a2 = -2*rho*cos(theta); Daniel@0: a3 = rho*rho; Daniel@0: y=filter([1+a2+a3],[1,a2,a3],y); Daniel@0: end; Daniel@0: Daniel@0: % FormantFilter(input, f, fs) - Filter an input sequence to model one Daniel@0: % formant in a speech signal. The formant frequency (in Hz) is given Daniel@0: % by f and the bandwidth of the formant is a constant 50Hz. The Daniel@0: % sampling frequency in Hz is given by fs. Daniel@0: if f3 > 0 Daniel@0: cft = f3/sampleRate; Daniel@0: bw = 50; Daniel@0: q = f3/bw; Daniel@0: rho = exp(-pi * cft / q); Daniel@0: theta = 2 * pi * cft * sqrt(1-1/(4 * q*q)); Daniel@0: a2 = -2*rho*cos(theta); Daniel@0: a3 = rho*rho; Daniel@0: y=filter([1+a2+a3],[1,a2,a3],y); Daniel@0: end;