tomwalters@0
|
1 % method of class @signal
|
tomwalters@0
|
2 % function sig=genharmonicstim(sig,varargin)
|
tomwalters@0
|
3 % INPUT VALUES:
|
tomwalters@0
|
4 % sig: @signal with length and samplerate
|
tomwalters@0
|
5 % varargin must have several parameters:
|
tomwalters@0
|
6 % fundamental (default 128) = periodicity
|
tomwalters@0
|
7 % min_fre (128) = lowest possible frequency
|
tomwalters@0
|
8 % max_fre (10000) = highest possible frequency
|
tomwalters@0
|
9 %
|
tomwalters@0
|
10 % envelope of amplitudes
|
tomwalters@0
|
11 % either
|
tomwalters@0
|
12 % filterprop ([256,256,1024,512]) = fc, df1, bandwidth, df2 (in Hz)
|
tomwalters@0
|
13 % default values: fc=3500;
|
tomwalters@0
|
14 % df1=256;
|
tomwalters@0
|
15 % bandwidth=1024;
|
tomwalters@0
|
16 % df2=512;
|
tomwalters@0
|
17 % the amplitdes can also be given by cf and two slopes for
|
tomwalters@0
|
18 % higher and lower frequencies:
|
tomwalters@0
|
19 % eg 'cf',1000,'lowslope',25,'highslope',38
|
tomwalters@0
|
20 % the highest and lowest possible allowed harmonic are given
|
tomwalters@0
|
21 % in either case by giving 'lowestharmonic' and
|
tomwalters@0
|
22 % 'highestharmonic' (default value: 1 and inf)
|
tomwalters@0
|
23 %
|
tomwalters@0
|
24 % type = which type (default none)
|
tomwalters@0
|
25 % filtered,
|
tomwalters@0
|
26 % decreaseoddamplitude,
|
tomwalters@0
|
27 % decreaseoddphase
|
tomwalters@0
|
28 % shiftallcomponents
|
tomwalters@0
|
29 % mistunedharmonic
|
tomwalters@0
|
30 % decrease_amplitude_linear
|
tomwalters@0
|
31 % changeby = value, that the odd harmonics shall vary (degree or dB or whatever)
|
tomwalters@0
|
32 % phases must be in degrees!
|
tomwalters@0
|
33 % RETURN VALUE:
|
tomwalters@0
|
34 % sig: @signal
|
tomwalters@0
|
35 %
|
tomwalters@0
|
36 % examples:
|
tomwalters@0
|
37 % create a stimulus with certain filtercharacteristic with random
|
tomwalters@0
|
38 % phase, and every second harmonic reduced by an amount
|
tomwalters@0
|
39 % tone(i)=genharmonics(sig,'fundamental',chroma,...
|
tomwalters@0
|
40 % 'filterprop',[toneheight,handles.df1,handles.bw,handles.df2],...
|
tomwalters@0
|
41 % 'phase','random',...
|
tomwalters@0
|
42 % 'type','decreaseoddamplitude',...
|
tomwalters@0
|
43 % 'changeby',octheight...
|
tomwalters@0
|
44 % );
|
tomwalters@0
|
45 %
|
tomwalters@0
|
46
|
tomwalters@0
|
47 % (c) 2003, University of Cambridge, Medical Research Council
|
tomwalters@0
|
48 % Stefan Bleeck (stefan@bleeck.de)
|
tomwalters@0
|
49 % http://www.mrc-cbu.cam.ac.uk/cnbh/aimmanual
|
tomwalters@0
|
50 % $Date: 2003/09/19 09:32:22 $
|
tomwalters@0
|
51 % $Revision: 1.12 $
|
tomwalters@0
|
52
|
tomwalters@0
|
53 function sig=genharmonics(sig,varargin)
|
tomwalters@0
|
54
|
tomwalters@0
|
55 if mod(nargin,2)==0
|
tomwalters@0
|
56 disp('odd number of parameters - please input a full set of parameters and arguments');
|
tomwalters@0
|
57 return;
|
tomwalters@0
|
58 end
|
tomwalters@0
|
59 str_fundamental=getargument(varargin,'fundamental');
|
tomwalters@0
|
60 str_type=getargument(varargin,'type');
|
tomwalters@0
|
61 str_harmnr=getargument(varargin,'harmonicnumber');
|
tomwalters@0
|
62 str_changeby=getargument(varargin,'changeby');
|
tomwalters@0
|
63 str_filterprop=getargument(varargin,'filterprop');
|
tomwalters@0
|
64 str_fc=getargument(varargin,'fc');
|
tomwalters@0
|
65 str_lowslope=getargument(varargin,'lowslope');
|
tomwalters@0
|
66 str_highslope=getargument(varargin,'highslope');
|
tomwalters@0
|
67 str_lowestharmonic=getargument(varargin,'lowestharmonic');
|
tomwalters@0
|
68 str_highestharmonic=getargument(varargin,'highestharmonic');
|
tomwalters@0
|
69 str_bw=getargument(varargin,'bw');
|
tomwalters@0
|
70 str_phase=getargument(varargin,'phase');
|
tomwalters@0
|
71 str_min_fre=getargument(varargin,'min_fre');
|
tomwalters@0
|
72 str_max_fre=getargument(varargin,'max_fre');
|
tomwalters@0
|
73
|
tomwalters@0
|
74 str_which_harmonics=getargument(varargin,'which harmonics');
|
tomwalters@0
|
75
|
tomwalters@0
|
76 % defaultvalues:
|
tomwalters@0
|
77 if strcmp(str_filterprop,'')
|
tomwalters@0
|
78 if strcmp(str_changeby,'')
|
tomwalters@0
|
79 str_filterprop{1}=[256,256,1024,512];
|
tomwalters@0
|
80 fc=256;
|
tomwalters@0
|
81 df1=256;
|
tomwalters@0
|
82 bandwidth=1024;
|
tomwalters@0
|
83 df2=512;
|
tomwalters@0
|
84 else
|
tomwalters@0
|
85 min_fre=str_min_fre{1};
|
tomwalters@0
|
86 max_fre=str_max_fre{1};
|
tomwalters@0
|
87 df1=1;
|
tomwalters@0
|
88 df2=1;
|
tomwalters@0
|
89 fc=min_fre;
|
tomwalters@0
|
90 bandwidth=max_fre-min_fre;
|
tomwalters@0
|
91 end
|
tomwalters@0
|
92 else
|
tomwalters@0
|
93 %eval(sprintf('filterprop=%s;',str_filterprop{1}));
|
tomwalters@0
|
94 fc=str_filterprop{1}(1);
|
tomwalters@0
|
95 df1=str_filterprop{1}(2);
|
tomwalters@0
|
96 bandwidth=str_filterprop{1}(3);
|
tomwalters@0
|
97 df2=str_filterprop{1}(4);
|
tomwalters@0
|
98 end
|
tomwalters@0
|
99 if strcmp(str_changeby,'')
|
tomwalters@0
|
100 else
|
tomwalters@0
|
101 if isnumeric(str_changeby{1})
|
tomwalters@0
|
102 changeby=str_changeby{1};
|
tomwalters@0
|
103 else
|
tomwalters@0
|
104 eval(sprintf('changeby=%f;',str_changeby{1}));
|
tomwalters@0
|
105 end
|
tomwalters@0
|
106 end
|
tomwalters@0
|
107
|
tomwalters@0
|
108 % different method of defining envelope: center frequency is the
|
tomwalters@0
|
109 % highest point, highslope and lowslope define the amplitude on both
|
tomwalters@0
|
110 % sides for each harmonic
|
tomwalters@0
|
111 if ~strcmp(str_lowslope,'') && ~strcmp(str_highslope,'')
|
tomwalters@0
|
112 lowslope=str_lowslope{1};
|
tomwalters@0
|
113 highslope=str_highslope{1};
|
tomwalters@0
|
114 calculate_amplitude_with_slopes=1;
|
tomwalters@0
|
115
|
tomwalters@0
|
116 % test with
|
tomwalters@0
|
117 % plot(powerspectrum(genharmonics(signal(0.1,16000),'fc',2000,'lowslope',30,'highslope',40,'fundamental',250)))
|
tomwalters@0
|
118 else
|
tomwalters@0
|
119 calculate_amplitude_with_slopes=0;
|
tomwalters@0
|
120 end
|
tomwalters@0
|
121
|
tomwalters@0
|
122 if strcmp(str_type,'')
|
tomwalters@0
|
123 str_type{1}='';
|
tomwalters@0
|
124 type='';
|
tomwalters@0
|
125 else
|
tomwalters@0
|
126 type=str_type{1};
|
tomwalters@0
|
127 end
|
tomwalters@0
|
128
|
tomwalters@0
|
129 if strcmp(str_phase,'')
|
tomwalters@0
|
130 setphase='cosine';
|
tomwalters@0
|
131 else
|
tomwalters@0
|
132 setphase=str_phase{1};
|
tomwalters@0
|
133 end
|
tomwalters@0
|
134
|
tomwalters@0
|
135 if strcmp(str_fundamental,'')
|
tomwalters@0
|
136 str_fundamental{1}='128';
|
tomwalters@0
|
137 fundamental=128;
|
tomwalters@0
|
138 else
|
tomwalters@0
|
139 if isnumeric(str_fundamental{1})
|
tomwalters@0
|
140 fundamental=str_fundamental{1};
|
tomwalters@0
|
141 else
|
tomwalters@0
|
142 eval(sprintf('fundamental=%s;',str_fundamental{1}));
|
tomwalters@0
|
143 end
|
tomwalters@0
|
144 end
|
tomwalters@0
|
145
|
tomwalters@0
|
146 if strcmp(str_lowestharmonic,'')
|
tomwalters@0
|
147 lowestharmonic=1;
|
tomwalters@0
|
148 else
|
tomwalters@0
|
149 if isnumeric(str_lowestharmonic{1})
|
tomwalters@0
|
150 lowestharmonic=str_lowestharmonic{1};
|
tomwalters@0
|
151 else
|
tomwalters@0
|
152 eval(sprintf('lowestharmonic=%s;',lowestharmonic{1}));
|
tomwalters@0
|
153 end
|
tomwalters@0
|
154 end
|
tomwalters@0
|
155 if strcmp(str_highestharmonic,'')
|
tomwalters@0
|
156 highestharmonic=inf;
|
tomwalters@0
|
157 else
|
tomwalters@0
|
158 if isnumeric(str_highestharmonic{1})
|
tomwalters@0
|
159 highestharmonic=str_highestharmonic{1};
|
tomwalters@0
|
160 else
|
tomwalters@0
|
161 eval(sprintf('highestharmonic=%s;',highestharmonic{1}));
|
tomwalters@0
|
162 end
|
tomwalters@0
|
163 end
|
tomwalters@0
|
164
|
tomwalters@0
|
165 if strcmp(str_fc,'')
|
tomwalters@0
|
166 else
|
tomwalters@0
|
167 if isnumeric(str_fc{1})
|
tomwalters@0
|
168 fc=str_fc{1};
|
tomwalters@0
|
169 else
|
tomwalters@0
|
170 eval(sprintf('fc=%s;',str_fc{1}));
|
tomwalters@0
|
171 end
|
tomwalters@0
|
172 end
|
tomwalters@0
|
173
|
tomwalters@0
|
174 if strcmp(str_bw,'')
|
tomwalters@0
|
175 else
|
tomwalters@0
|
176 if isnumeric(str_bw{1})
|
tomwalters@0
|
177 bandwidth=str_bw{1};
|
tomwalters@0
|
178 else
|
tomwalters@0
|
179 eval(sprintf('bandwidth=%s;',str_bw{1}));
|
tomwalters@0
|
180 end
|
tomwalters@0
|
181 end
|
tomwalters@0
|
182
|
tomwalters@0
|
183 if strcmp(str_which_harmonics,'')
|
tomwalters@0
|
184 str_which_harmonics{1}='all';
|
tomwalters@0
|
185 end
|
tomwalters@0
|
186
|
tomwalters@0
|
187 samplerate=sig.samplerate;
|
tomwalters@0
|
188 length=getlength(sig);
|
tomwalters@0
|
189
|
tomwalters@0
|
190
|
tomwalters@0
|
191 % begin!
|
tomwalters@0
|
192
|
tomwalters@0
|
193 max_fre=fc+bandwidth+df2;
|
tomwalters@0
|
194 min_fre=fc-df1;
|
tomwalters@0
|
195 if (min_fre<0) %squeese df1 to go from 0 to fc
|
tomwalters@0
|
196 df1=df1-abs(min_fre);
|
tomwalters@0
|
197 % disp('df1 was reduced')
|
tomwalters@0
|
198 end
|
tomwalters@0
|
199
|
tomwalters@0
|
200 if fundamental > max_fre
|
tomwalters@0
|
201 disp('error: genharmonics: fundamental must be smaller then highest frequency');
|
tomwalters@0
|
202 return;
|
tomwalters@0
|
203 end
|
tomwalters@0
|
204
|
tomwalters@0
|
205 s=signal(length,samplerate);
|
tomwalters@0
|
206 if max_fre>1000
|
tomwalters@0
|
207 s=setname(s,sprintf('Harmonic Signal - f0=%4.1f Hz, type: %s (from %2.2f kHz to %2.2f kHz)',fundamental,type,min_fre/1000,max_fre/1000));
|
tomwalters@0
|
208 else
|
tomwalters@0
|
209 s=setname(s,sprintf('Harmonic Signal - f0=%4.1f Hz, type: %s (from %3.0 Hz to %3.0f Hz)',fundamental,type,min_fre,max_fre));
|
tomwalters@0
|
210 end
|
tomwalters@0
|
211
|
tomwalters@0
|
212 if calculate_amplitude_with_slopes
|
tomwalters@0
|
213 s=setname(s,sprintf('Harmonic Signal - modfre=%4.1f Hz, type: %s (cf: %2.2f kHz, low slope: %3.0f dB/oct, high slope %3.0f dB/oct)',fundamental,type,fc/1000,lowslope,highslope));
|
tomwalters@0
|
214 end
|
tomwalters@0
|
215
|
tomwalters@0
|
216 % in case of sloped amplitudes, we dont want a limit on harmonics
|
tomwalters@0
|
217 if calculate_amplitude_with_slopes
|
tomwalters@0
|
218 max_fre=getsr(sig)/2;
|
tomwalters@0
|
219 min_fre=0;
|
tomwalters@0
|
220 end
|
tomwalters@0
|
221
|
tomwalters@0
|
222 % if limit of harmonics is explicitly given
|
tomwalters@0
|
223 if ~strcmp(str_highestharmonic,'')
|
tomwalters@0
|
224 max_fre=highestharmonic*fundamental;
|
tomwalters@0
|
225 end
|
tomwalters@0
|
226 if ~strcmp(str_lowestharmonic,'')
|
tomwalters@0
|
227 min_fre=lowestharmonic*fundamental;
|
tomwalters@0
|
228 end
|
tomwalters@0
|
229
|
tomwalters@0
|
230 fre=fundamental;
|
tomwalters@0
|
231 count_partials=1;
|
tomwalters@0
|
232 while fre <= max_fre
|
tomwalters@0
|
233 if fre >= min_fre
|
tomwalters@0
|
234 temp=signal(length,samplerate);
|
tomwalters@0
|
235 amplitude=1;
|
tomwalters@0
|
236 phase=0;
|
tomwalters@0
|
237 offset=0;
|
tomwalters@0
|
238 if strcmp(type,'mistunedharmonic') % in %
|
tomwalters@0
|
239 eval(sprintf('nr=%s;',str_harmnr{1}));
|
tomwalters@0
|
240 if count_partials==nr
|
tomwalters@0
|
241 offset=fundamental*changeby/100;
|
tomwalters@0
|
242 amplitude=1;
|
tomwalters@0
|
243 phase=0;
|
tomwalters@0
|
244 end
|
tomwalters@0
|
245 end
|
tomwalters@0
|
246 if strcmp(type,'shiftallcomponents') % in Hz
|
tomwalters@0
|
247 offset=changeby;
|
tomwalters@0
|
248 amplitude=1;
|
tomwalters@0
|
249 phase=0;
|
tomwalters@0
|
250 end
|
tomwalters@0
|
251 if strcmp(type,'decreaseoddphase')
|
tomwalters@0
|
252 % phase must be given in degree!
|
tomwalters@0
|
253 if mod(count_partials,2)==1
|
tomwalters@0
|
254 amplitude=1;
|
tomwalters@0
|
255 phase=changeby;
|
tomwalters@0
|
256 end
|
tomwalters@0
|
257 end
|
tomwalters@0
|
258
|
tomwalters@0
|
259 if strcmp(type,'decrease_amplitude_linear')
|
tomwalters@0
|
260 % the amount must be given in changeby!
|
tomwalters@0
|
261 amplitude=1*power(10,(-changeby*count_partials)/20);
|
tomwalters@0
|
262 ampscale=1;
|
tomwalters@0
|
263 else
|
tomwalters@0
|
264 ampscale=filterbandamp(fre+offset,amplitude,fc,df1,bandwidth,df2);
|
tomwalters@0
|
265 end
|
tomwalters@0
|
266 amplitude=amplitude*ampscale;
|
tomwalters@0
|
267
|
tomwalters@0
|
268
|
tomwalters@0
|
269 % stattdessen mit Slopes:
|
tomwalters@0
|
270 if calculate_amplitude_with_slopes
|
tomwalters@0
|
271 % calculate the distance from cf (in octaves)
|
tomwalters@0
|
272 % and from this the attenuation
|
tomwalters@0
|
273 distance=log2(fre/fc);
|
tomwalters@0
|
274 if distance >= 0
|
tomwalters@0
|
275 atten=distance*highslope;
|
tomwalters@0
|
276 else
|
tomwalters@0
|
277 atten=-distance*lowslope;
|
tomwalters@0
|
278 end
|
tomwalters@0
|
279 amplitude=1*power(10,-atten/20);
|
tomwalters@0
|
280 end
|
tomwalters@0
|
281
|
tomwalters@0
|
282 if strcmp(type,'decreaseoddamplitude')
|
tomwalters@0
|
283 if mod(count_partials,2)==1
|
tomwalters@0
|
284 amplitude=amplitude*power(10,changeby/20);
|
tomwalters@0
|
285 end
|
tomwalters@0
|
286 end
|
tomwalters@0
|
287 if strcmp(type,'decreaseevenamplitude')
|
tomwalters@0
|
288 if mod(count_partials,2)==0
|
tomwalters@0
|
289 amplitude=amplitude*power(10,changeby/20);
|
tomwalters@0
|
290 end
|
tomwalters@0
|
291 end
|
tomwalters@0
|
292
|
tomwalters@0
|
293
|
tomwalters@0
|
294 switch str_which_harmonics{1}
|
tomwalters@0
|
295 case 'all'
|
tomwalters@0
|
296 case 'only odd'
|
tomwalters@0
|
297 if mod(count_partials,2)==0
|
tomwalters@0
|
298 amplitude=0;
|
tomwalters@0
|
299 end
|
tomwalters@0
|
300 case 'only even'
|
tomwalters@0
|
301 if mod(count_partials,2)==1
|
tomwalters@0
|
302 amplitude=0;
|
tomwalters@0
|
303 end
|
tomwalters@0
|
304 end
|
tomwalters@0
|
305
|
tomwalters@0
|
306 % degree2rad
|
tomwalters@0
|
307 switch setphase
|
tomwalters@0
|
308 case 'random'
|
tomwalters@0
|
309 piphase=rand(1)*2*pi+pi;
|
tomwalters@0
|
310 case 'cos'
|
tomwalters@0
|
311 % piphase=phase*(pi/180)+pi/2;
|
tomwalters@0
|
312 piphase=phase*(pi/180);
|
tomwalters@0
|
313 end
|
tomwalters@0
|
314 % disp(sprintf('fre: %3.2f amp:%2.1f',fre,amplitude*100));
|
tomwalters@0
|
315 % amplitude
|
tomwalters@0
|
316 % fre
|
tomwalters@0
|
317 temp=generatesinus(temp,fre+offset,amplitude,piphase);
|
tomwalters@0
|
318
|
tomwalters@0
|
319 % add them up!
|
tomwalters@0
|
320 s=s+temp;
|
tomwalters@0
|
321 end
|
tomwalters@0
|
322 fre=fre+fundamental;
|
tomwalters@0
|
323 count_partials=count_partials+1;
|
tomwalters@0
|
324 end
|
tomwalters@0
|
325
|
tomwalters@0
|
326 sig=s;
|