wolffd@0
|
1 function varargout = mircepstrum(orig,varargin)
|
wolffd@0
|
2 % s = mircepstrum(x) computes the cepstrum, which indicates
|
wolffd@0
|
3 % periodicities, and is used for instance for pitch detection.
|
wolffd@0
|
4 % x can be either a spectrum, an audio signal, or the name of an audio file.
|
wolffd@0
|
5 % Optional parameter:
|
wolffd@0
|
6 % mircepstrum(...,'Min',min) specifies the lowest delay taken into
|
wolffd@0
|
7 % consideration, in seconds.
|
wolffd@0
|
8 % Default value: 0.0002 s (corresponding to a maximum frequency of
|
wolffd@0
|
9 % 5 kHz).
|
wolffd@0
|
10 % mircepstrum(...,'Max',max) specifies the highest delay taken into
|
wolffd@0
|
11 % consideration, in seconds.
|
wolffd@0
|
12 % Default value: 0.05 s (corresponding to a minimum frequency of
|
wolffd@0
|
13 % 20 Hz).
|
wolffd@0
|
14 % mircepstrum(...,'Freq') represents the cepstrum in the frequency
|
wolffd@0
|
15 % domain.
|
wolffd@0
|
16
|
wolffd@0
|
17 mi.key = 'Min';
|
wolffd@0
|
18 mi.type = 'Integer';
|
wolffd@0
|
19 mi.default = 0.0002;
|
wolffd@0
|
20 mi.unit = {'s','Hz'};
|
wolffd@0
|
21 mi.defaultunit = 's';
|
wolffd@0
|
22 mi.opposite = 'ma';
|
wolffd@0
|
23 option.mi = mi;
|
wolffd@0
|
24
|
wolffd@0
|
25 ma.key = 'Max';
|
wolffd@0
|
26 ma.type = 'Integer';
|
wolffd@0
|
27 ma.default = .05;
|
wolffd@0
|
28 ma.unit = {'s','Hz'};
|
wolffd@0
|
29 ma.defaultunit = 's';
|
wolffd@0
|
30 ma.opposite = 'mi';
|
wolffd@0
|
31 option.ma = ma;
|
wolffd@0
|
32
|
wolffd@0
|
33 fr.key = 'Freq';
|
wolffd@0
|
34 fr.type = 'Boolean';
|
wolffd@0
|
35 fr.default = 0;
|
wolffd@0
|
36 option.fr = fr;
|
wolffd@0
|
37
|
wolffd@0
|
38 complex.key = 'Complex';
|
wolffd@0
|
39 complex.type = 'Boolean';
|
wolffd@0
|
40 complex.default = 0;
|
wolffd@0
|
41 option.complex = complex;
|
wolffd@0
|
42
|
wolffd@0
|
43 specif.option = option;
|
wolffd@0
|
44
|
wolffd@0
|
45 specif.defaultframelength = 0.05;
|
wolffd@0
|
46 specif.defaultframehop = 0.5;
|
wolffd@0
|
47
|
wolffd@0
|
48 varargout = mirfunction(@mircepstrum,orig,varargin,nargout,specif,@init,@main);
|
wolffd@0
|
49
|
wolffd@0
|
50
|
wolffd@0
|
51 function [x type] = init(x,option)
|
wolffd@0
|
52 if not(isamir(x,'mircepstrum'))
|
wolffd@0
|
53 x = mirspectrum(x);
|
wolffd@0
|
54 end
|
wolffd@0
|
55 type = 'mircepstrum';
|
wolffd@0
|
56
|
wolffd@0
|
57
|
wolffd@0
|
58 function c = main(orig,option,postoption)
|
wolffd@0
|
59 if iscell(orig)
|
wolffd@0
|
60 orig = orig{1};
|
wolffd@0
|
61 end
|
wolffd@0
|
62 c.phase = [];
|
wolffd@0
|
63 if isa(orig,'mircepstrum')
|
wolffd@0
|
64 c.freq = orig.freq;
|
wolffd@0
|
65 else
|
wolffd@0
|
66 c.freq = 0;
|
wolffd@0
|
67 end
|
wolffd@0
|
68 c = class(c,'mircepstrum',mirdata(orig));
|
wolffd@0
|
69 c = purgedata(c);
|
wolffd@0
|
70 c = set(c,'Title','Cepstrum','Abs','quefrency (s)','Ord','magnitude');
|
wolffd@0
|
71
|
wolffd@0
|
72 if isa(orig,'mircepstrum')
|
wolffd@0
|
73 if option.ma < Inf || option.mi > 0 || get(orig,'FreqDomain')
|
wolffd@0
|
74 mag = get(orig,'Magnitude');
|
wolffd@0
|
75 pha = get(orig,'Phase');
|
wolffd@0
|
76 que = get(orig,'Quefrency');
|
wolffd@0
|
77 for h = 1:length(mag)
|
wolffd@0
|
78 for k = 1:length(mag{h})
|
wolffd@0
|
79 if get(orig,'FreqDomain')
|
wolffd@0
|
80 mag{h}{k} = flipud(mag{h}{k});
|
wolffd@0
|
81 que{h}{k} = flipud(1./que{h}{k});
|
wolffd@0
|
82 pha{h}{k} = flipud(pha{h}{k});
|
wolffd@0
|
83 end
|
wolffd@0
|
84 range = find(que{h}{k}(:,1,1) <= option.ma & ...
|
wolffd@0
|
85 que{h}{k}(:,1,1) >= option.mi);
|
wolffd@0
|
86 mag{h}{k} = mag{h}{k}(range,:,:);
|
wolffd@0
|
87 pha{h}{k} = pha{h}{k}(range,:,:);
|
wolffd@0
|
88 que{h}{k} = que{h}{k}(range,:,:);
|
wolffd@0
|
89 end
|
wolffd@0
|
90 end
|
wolffd@0
|
91 c = set(c,'Magnitude',mag,'Phase',pha,'Quefrency',que,'FreqDomain',0);
|
wolffd@0
|
92 end
|
wolffd@0
|
93 c = modif(c,option);
|
wolffd@0
|
94 elseif isa(orig,'mirspectrum')
|
wolffd@0
|
95 mag = get(orig,'Magnitude');
|
wolffd@0
|
96 pha = get(orig,'Phase');
|
wolffd@0
|
97 f = get(orig,'Sampling');
|
wolffd@0
|
98 q = cell(1,length(mag));
|
wolffd@0
|
99 for h = 1:length(mag)
|
wolffd@0
|
100 len = ceil(option.ma*f{h});
|
wolffd@0
|
101 start = ceil(option.mi*f{h})+1;
|
wolffd@0
|
102 q{h} = cell(1,length(mag{h}));
|
wolffd@0
|
103 for k = 1:length(mag{h})
|
wolffd@0
|
104 m = mag{h}{k}.*exp(1i*pha{h}{k});
|
wolffd@0
|
105 m = [m(1:end-1,:) ; conj(flipud(m))]; % Reconstitution of the complete abs(FFT)
|
wolffd@0
|
106 if not(option.complex)
|
wolffd@0
|
107 m = abs(m);
|
wolffd@0
|
108 end
|
wolffd@0
|
109 m = log(m);
|
wolffd@0
|
110 c0=fft(m);
|
wolffd@0
|
111 q0=repmat((0:(size(c0,1)-1))'/f{k},[1,size(m,2),size(m,3)]);
|
wolffd@0
|
112 len = min(len,floor(size(c0,1)/2));
|
wolffd@0
|
113 mag{h}{k} = abs(c0(start:len,:,:));
|
wolffd@0
|
114 if option.complex
|
wolffd@0
|
115 pha{h}{k} = unwrap(angle(c0(start:len,:,:)));
|
wolffd@0
|
116 else
|
wolffd@0
|
117 pha{h}{k} = nan(size(c0(start:len,:,:)));
|
wolffd@0
|
118 end
|
wolffd@0
|
119 q{h}{k} = q0(start:len,:,:);
|
wolffd@0
|
120 end
|
wolffd@0
|
121 end
|
wolffd@0
|
122 c = set(c,'Magnitude',mag,'Phase',pha,'Quefrency',q);
|
wolffd@0
|
123 c = modif(c,option);
|
wolffd@0
|
124 end
|
wolffd@0
|
125
|
wolffd@0
|
126
|
wolffd@0
|
127 function c = modif(c,option)
|
wolffd@0
|
128 mag = get(c,'Magnitude');
|
wolffd@0
|
129 que = get(c,'Quefrency');
|
wolffd@0
|
130 if option.fr && not(get(c,'FreqDomain'))
|
wolffd@0
|
131 for k = 1:length(mag)
|
wolffd@0
|
132 for l = 1:length(mag{k})
|
wolffd@0
|
133 m = mag{k}{l};
|
wolffd@0
|
134 q = que{k}{l};
|
wolffd@0
|
135 if not(isempty(m))
|
wolffd@0
|
136 if q(1,1) == 0
|
wolffd@0
|
137 m = m(2:end,:,:);
|
wolffd@0
|
138 q = q(2:end,:,:);
|
wolffd@0
|
139 end
|
wolffd@0
|
140 m = flipud(m);
|
wolffd@0
|
141 q = flipud(1./q);
|
wolffd@0
|
142 end
|
wolffd@0
|
143 mag{k}{l} = m;
|
wolffd@0
|
144 que{k}{l} = q;
|
wolffd@0
|
145 end
|
wolffd@0
|
146 end
|
wolffd@0
|
147 c = set(c,'FreqDomain',1,'Abs','frequency (Hz)');
|
wolffd@0
|
148 end
|
wolffd@0
|
149 c = set(c,'Magnitude',mag,'Quefrency',que,'Freq'); |