annotate aim-mat/tools/@signal/genharmonics.asv @ 4:537f939baef0 tip

various bug fixes and changed copyright message
author Stefan Bleeck <bleeck@gmail.com>
date Tue, 16 Aug 2011 14:37:17 +0100
parents 74dedb26614d
children
rev   line source
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;