annotate toolboxes/MIRtoolbox1.3.2/MIRToolbox/@miraudio/miraudio.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
rev   line source
wolffd@0 1 function varargout = miraudio(orig,varargin)
wolffd@0 2 % a = miraudio('filename') loads the sound file 'filename' (in WAV or AU
wolffd@0 3 % format) into a miraudio object.
wolffd@0 4 % a = miraudio('Folder') loads all the sound files in the CURRENT folder
wolffd@0 5 % into a miraudio object.
wolffd@0 6 % a = miraudio(v,sr), where v is a column vector, translates the vector v
wolffd@0 7 % into a miraudio object. The sampling frequency is set to sr Hertz.
wolffd@0 8 % Default value for sr: 44100 Hz.
wolffd@0 9 % a = miraudio(b, ...), where b is already a miraudio object, performs
wolffd@0 10 % operations on b specified by the optional arguments (see below).
wolffd@0 11 %
wolffd@0 12 % Transformation options:
wolffd@0 13 % miraudio(...,'Mono',0) does not perform the default summing of
wolffd@0 14 % channels into one single mono track, but instead stores each
wolffd@0 15 % channel of the initial soundfile separately.
wolffd@0 16 % miraudio(...,'Center') centers the signals.
wolffd@0 17 % miraudio(...,'Sampling',r) resamples at sampling rate r (in Hz).
wolffd@0 18 % (Requires the Signal Processing Toolbox.)
wolffd@0 19 % miraudio(...,'Normal') normalizes with respect to RMS energy.
wolffd@0 20 % Extraction options:
wolffd@0 21 % miraudio(...,'Extract',t1,t2,u,f) extracts the signal between dates
wolffd@0 22 % t1 and t2, expressed in the unit u.
wolffd@0 23 % Possible values for u:
wolffd@0 24 % 's' (seconds, by default),
wolffd@0 25 % 'sp' (sample index, starting from 1).
wolffd@0 26 % The additional optional argument f indicates the referential
wolffd@0 27 % origin of the temporal positions. Possible values for f:
wolffd@0 28 % 'Start' (by default)
wolffd@0 29 % 'Middle' (of the sequence)
wolffd@0 30 % 'End' of the sequence
wolffd@0 31 % When using 'Middle' or 'End', negative values for t1 or t2
wolffd@0 32 % indicate values before the middle or the end of the audio
wolffd@0 33 % sequence.
wolffd@0 34 % miraudio(...,'Trim') trims the pseudo-silence beginning and end off
wolffd@0 35 % the audio file. Silent frames are frames with RMS below t times
wolffd@0 36 % the medium RMS of the whole audio file.
wolffd@0 37 % Default value: t = 0.06
wolffd@0 38 % instead of 'Trim':
wolffd@0 39 % 'TrimStart' only trims the beginning of the audio file,
wolffd@0 40 % 'TrimEnd' only trims the end.
wolffd@0 41 % miraudio(...,'TrimThreshold',t) specifies the trimming threshold t.
wolffd@0 42 % miraudio(...,'Channel',c) or miraudio(...,'Channels',c) selects the
wolffd@0 43 % channels indicated by the (array of) integer(s) c.
wolffd@0 44 % Labeling option:
wolffd@0 45 % miraudio(...,'Label',l) labels the audio signal(s) following the
wolffd@0 46 % label(s) l.
wolffd@0 47 % If l is a (series of) number(s), the audio signal(s) are
wolffd@0 48 % labelled using the substring of their respective file name of
wolffd@0 49 % index l. If l=0, the audio signal(s) are labelled using the
wolffd@0 50 % whole file name.
wolffd@0 51
wolffd@0 52
wolffd@0 53 if isnumeric(orig)
wolffd@0 54 if size(orig,2) > 1 || size(orig,3) > 1
wolffd@0 55 mirerror('MIRAUDIO','Only column vectors can be imported into mirtoolbox.');
wolffd@0 56 end
wolffd@0 57 if nargin == 1
wolffd@0 58 f = 44100;
wolffd@0 59 else
wolffd@0 60 f = varargin{1};
wolffd@0 61 end
wolffd@0 62 b = 32;
wolffd@0 63 if size(orig,1) == 1
wolffd@0 64 orig = orig';
wolffd@0 65 end
wolffd@0 66 tp = (0:size(orig,1)-1)'/f;
wolffd@0 67 t = mirtemporal([],'Time',{{tp}},'Data',{{orig}},...
wolffd@0 68 'FramePos',{{tp([1 end])}},'Sampling',{f},...
wolffd@0 69 'Name',{inputname(1)},'Label',{{}},'Clusters',{{}},...
wolffd@0 70 'Channels',[],'Centered',0,'NBits',{b},...
wolffd@0 71 'Title','Audio signal',...
wolffd@0 72 'PeakPos',{{{}}},'PeakVal',{{{}}},'PeakMode',{{{}}});
wolffd@0 73 aa.fresh = 1;
wolffd@0 74 varargout = {class(aa,'miraudio',t)};
wolffd@0 75 return
wolffd@0 76 end
wolffd@0 77
wolffd@0 78
wolffd@0 79 center.key = 'Center';
wolffd@0 80 center.type = 'Boolean';
wolffd@0 81 center.default = 0;
wolffd@0 82 center.when = 'After';
wolffd@0 83 option.center = center;
wolffd@0 84
wolffd@0 85 normal.key = 'Normal';
wolffd@0 86 normal.type = 'Boolean';
wolffd@0 87 normal.default = 0;
wolffd@0 88 normal.when = 'After';
wolffd@0 89 option.normal = normal;
wolffd@0 90
wolffd@0 91 extract.key = {'Extract','Excerpt'};
wolffd@0 92 extract.type = 'Integer';
wolffd@0 93 extract.number = 2;
wolffd@0 94 extract.default = [];
wolffd@0 95 extract.unit = {'s','sp'};
wolffd@0 96 extract.defaultunit = 's';
wolffd@0 97 extract.from = {'Start','Middle','End'};
wolffd@0 98 extract.defaultfrom = 'Start';
wolffd@0 99 option.extract = extract;
wolffd@0 100
wolffd@0 101 trim.type = 'String';
wolffd@0 102 trim.choice = {'NoTrim','Trim','TrimBegin','TrimStart','TrimEnd'};
wolffd@0 103 trim.default = 'NoTrim';
wolffd@0 104 trim.when = 'After';
wolffd@0 105 option.trim = trim;
wolffd@0 106
wolffd@0 107 trimthreshold.key = 'TrimThreshold';
wolffd@0 108 trimthreshold.type = 'Integer';
wolffd@0 109 trimthreshold.default = .06;
wolffd@0 110 trimthreshold.when = 'After';
wolffd@0 111 option.trimthreshold = trimthreshold;
wolffd@0 112
wolffd@0 113 label.key = 'Label';
wolffd@0 114 label.default = '';
wolffd@0 115 label.when = 'After';
wolffd@0 116 option.label = label;
wolffd@0 117
wolffd@0 118 sampling.key = 'Sampling';
wolffd@0 119 sampling.type = 'Integer';
wolffd@0 120 sampling.default = 0;
wolffd@0 121 sampling.when = 'Both';
wolffd@0 122 option.sampling = sampling;
wolffd@0 123
wolffd@0 124 % segment.key = 'Segment';
wolffd@0 125 % segment.type = 'Integer';
wolffd@0 126 % segment.default = [];
wolffd@0 127 % segment.when = 'After';
wolffd@0 128 % option.segment = segment;
wolffd@0 129
wolffd@0 130 reverse.key = 'Reverse';
wolffd@0 131 reverse.type = 'Boolean';
wolffd@0 132 reverse.default = 0;
wolffd@0 133 reverse.when = 'After';
wolffd@0 134 option.reverse = reverse;
wolffd@0 135
wolffd@0 136 mono.key = 'Mono';
wolffd@0 137 mono.type = 'Boolean';
wolffd@0 138 mono.default = NaN;
wolffd@0 139 mono.when = 'After';
wolffd@0 140 option.mono = mono;
wolffd@0 141
wolffd@0 142 separate.key = 'SeparateChannels';
wolffd@0 143 separate.type = 'Boolean';
wolffd@0 144 separate.default = 0;
wolffd@0 145 option.separate = separate;
wolffd@0 146
wolffd@0 147 Ch.key = {'Channel','Channels'};
wolffd@0 148 Ch.type = 'Integer';
wolffd@0 149 Ch.default = [];
wolffd@0 150 Ch.when = 'After';
wolffd@0 151 option.Ch = Ch;
wolffd@0 152
wolffd@0 153 specif.option = option;
wolffd@0 154
wolffd@0 155 specif.beforechunk = {@beforechunk,'normal'};
wolffd@0 156 specif.eachchunk = @eachchunk;
wolffd@0 157 specif.combinechunk = @combinechunk;
wolffd@0 158
wolffd@0 159 if nargin > 1 && ischar(varargin{1}) && strcmp(varargin{1},'Now')
wolffd@0 160 if nargin > 2
wolffd@0 161 extract = varargin{2};
wolffd@0 162 else
wolffd@0 163 extract = [];
wolffd@0 164 end
wolffd@0 165 para = [];
wolffd@0 166 varargout = {main(orig,[],para,[],extract)};
wolffd@0 167 else
wolffd@0 168 varargout = mirfunction(@miraudio,orig,varargin,nargout,specif,@init,@main);
wolffd@0 169 end
wolffd@0 170 if isempty(varargout)
wolffd@0 171 varargout = {{}};
wolffd@0 172 end
wolffd@0 173
wolffd@0 174
wolffd@0 175 function [x type] = init(x,option)
wolffd@0 176 if isa(x,'mirdesign')
wolffd@0 177 if option.sampling
wolffd@0 178 x = setresampling(x,option.sampling);
wolffd@0 179 end
wolffd@0 180 end
wolffd@0 181 type = 'miraudio';
wolffd@0 182
wolffd@0 183
wolffd@0 184 function a = main(orig,option,after,index,extract)
wolffd@0 185 if iscell(orig)
wolffd@0 186 orig = orig{1};
wolffd@0 187 end
wolffd@0 188 if ischar(orig)
wolffd@0 189 if nargin < 5
wolffd@0 190 extract = [];
wolffd@0 191 end
wolffd@0 192 [d{1},tp{1},fp{1},f{1},b{1},n{1},ch{1}] = mirread(extract,orig,1,0);
wolffd@0 193 t = mirtemporal([],'Time',tp,'Data',d,'FramePos',fp,'Sampling',f,...
wolffd@0 194 'Name',n,'Label',cell(1,length(d)),...
wolffd@0 195 'Clusters',cell(1,length(d)),...
wolffd@0 196 'Channels',ch,'Centered',0,'NBits',b);
wolffd@0 197 t = set(t,'Title','Audio waveform');
wolffd@0 198 a.fresh = 1;
wolffd@0 199 a = class(a,'miraudio',t);
wolffd@0 200 else
wolffd@0 201 if not(isempty(option)) && not(isempty(option.extract))
wolffd@0 202 if not(isstruct(after))
wolffd@0 203 after = struct;
wolffd@0 204 end
wolffd@0 205 after.extract = option.extract;
wolffd@0 206 end
wolffd@0 207 if isa(orig,'miraudio')
wolffd@0 208 a = orig;
wolffd@0 209 else
wolffd@0 210 a.fresh = 1;
wolffd@0 211 a = class(a,'miraudio',orig);
wolffd@0 212 end
wolffd@0 213 end
wolffd@0 214 if not(isempty(after))
wolffd@0 215 a = post(a,after);
wolffd@0 216 end
wolffd@0 217
wolffd@0 218
wolffd@0 219 function a = post(a,para)
wolffd@0 220 if a.fresh && isfield(para,'mono')
wolffd@0 221 a.fresh = 0;
wolffd@0 222 if isnan(para.mono)
wolffd@0 223 para.mono = 1;
wolffd@0 224 end
wolffd@0 225 end
wolffd@0 226 if isfield(para,'mono') && para.mono == 1
wolffd@0 227 a = mirsum(a,'Mean');
wolffd@0 228 end
wolffd@0 229 d = get(a,'Data');
wolffd@0 230 t = get(a,'Time');
wolffd@0 231 ac = get(a,'AcrossChunks');
wolffd@0 232 f = get(a,'Sampling');
wolffd@0 233 cl = get(a,'Clusters');
wolffd@0 234 for h = 1:length(d)
wolffd@0 235 for k = 1:length(d{h})
wolffd@0 236 tk = t{h}{k};
wolffd@0 237 dk = d{h}{k};
wolffd@0 238 if isfield(para,'extract') && not(isempty(para.extract))
wolffd@0 239 t1 = para.extract(1);
wolffd@0 240 t2 = para.extract(2);
wolffd@0 241 if para.extract(4)
wolffd@0 242 if para.extract(4) == 1
wolffd@0 243 shift = round(size(tk,1)/2);
wolffd@0 244 elseif para.extract(4) == 2
wolffd@0 245 shift = size(tk,1);
wolffd@0 246 end
wolffd@0 247 if para.extract(3)
wolffd@0 248 shift = tk(shift,1,1);
wolffd@0 249 end
wolffd@0 250 t1 = t1+shift;
wolffd@0 251 t2 = t2+shift;
wolffd@0 252 end
wolffd@0 253 if para.extract(3) % in seconds
wolffd@0 254 ft = find(tk>=t1 & tk<=t2);
wolffd@0 255 else % in samples
wolffd@0 256 if not(t1)
wolffd@0 257 warning('WARNING IN MIRAUDIO: Extract sample positions should be real positive integers.')
wolffd@0 258 display('Positions incremented by one.');
wolffd@0 259 t1 = t1+1;
wolffd@0 260 t2 = t2+1;
wolffd@0 261 end
wolffd@0 262 ft = t1:t2;
wolffd@0 263 end
wolffd@0 264 tk = tk(ft,:,:);
wolffd@0 265 dk = dk(ft,:,:);
wolffd@0 266 end
wolffd@0 267 if isfield(para,'Ch') && not(isempty(para.Ch))
wolffd@0 268 dk = dk(:,:,para.Ch);
wolffd@0 269 end
wolffd@0 270 if isfield(para,'center') && para.center
wolffd@0 271 dk = center(dk);
wolffd@0 272 a = set(a,'Centered',1);
wolffd@0 273 end
wolffd@0 274 if isfield(para,'normal') && para.normal
wolffd@0 275 nl = size(dk,1);
wolffd@0 276 nc = size(dk,3);
wolffd@0 277 if isempty(ac)
wolffd@0 278 ee = 0;
wolffd@0 279 for j = 1:nc
wolffd@0 280 ee = ee+sum(dk(:,:,j).^2);
wolffd@0 281 end
wolffd@0 282 ee = sqrt(ee/nl/nc);
wolffd@0 283 else
wolffd@0 284 ee = sqrt(sum(ac.sqrsum.^2)/ac.samples);
wolffd@0 285 end
wolffd@0 286 dk = dk./repmat(ee,[nl,1,nc]);
wolffd@0 287 end
wolffd@0 288 if isfield(para,'trim') && not(isequal(para.trim,0)) ...
wolffd@0 289 && not(strcmpi(para.trim,'NoTrim'))
wolffd@0 290 if not(para.trimthreshold)
wolffd@0 291 para.trimthreshold = 0.06;
wolffd@0 292 end
wolffd@0 293 trimframe = 100;
wolffd@0 294 trimhop = 10;
wolffd@0 295 nframes = floor((length(tk)-trimframe)/trimhop)+1;
wolffd@0 296 rms = zeros(1,nframes);
wolffd@0 297 for j = 1:nframes
wolffd@0 298 st = floor((j-1)*trimhop)+1;
wolffd@0 299 for z = 1:size(dk,3)
wolffd@0 300 rms(1,j,z) = norm(dk(st:st+trimframe-1,1,z))/sqrt(trimframe);
wolffd@0 301 end
wolffd@0 302 end
wolffd@0 303 rms = (rms-repmat(min(rms),[1,size(rms,2),1]))...
wolffd@0 304 ./repmat(max(rms)-min(rms),[1,size(rms,2),1]);
wolffd@0 305 nosil = find(rms>para.trimthreshold);
wolffd@0 306 if strcmpi(para.trim,'Trim') || strcmpi(para.trim,'TrimStart') ...
wolffd@0 307 || strcmpi(para.trim,'TrimBegin')
wolffd@0 308 nosil1 = min(nosil);
wolffd@0 309 if nosil1 > 1
wolffd@0 310 nosil1 = nosil1-1;
wolffd@0 311 end
wolffd@0 312 n1 = floor((nosil1-1)*trimhop)+1;
wolffd@0 313 else
wolffd@0 314 n1 = 1;
wolffd@0 315 end
wolffd@0 316 if strcmpi(para.trim,'Trim') || strcmpi(para.trim,'TrimEnd')
wolffd@0 317 nosil2 = max(nosil);
wolffd@0 318 if nosil2 < length(rms)
wolffd@0 319 nosil2 = nosil2+1;
wolffd@0 320 end
wolffd@0 321 n2 = floor((nosil2-1)*trimhop)+1;
wolffd@0 322 else
wolffd@0 323 n2 = length(tk);
wolffd@0 324 end
wolffd@0 325 wh = ones(n2-n1+1,1);
wolffd@0 326 dt = round(.02*f{h});
wolffd@0 327 ha = hann(dt*2);
wolffd@0 328 wh(1:dt) = ha(1:dt);
wolffd@0 329 wh(end-dt+1:end) = ha(dt+1:end);
wolffd@0 330 tk = tk(n1:n2);
wolffd@0 331 dk = dk(n1:n2,1,:);%.*repmat(wh,[1 1 size(dk,3)]);
wolffd@0 332 end
wolffd@0 333 if isfield(para,'sampling') && para.sampling
wolffd@0 334 if and(f{k}, not(f{k} == para.sampling))
wolffd@0 335 for j = 1:size(dk,3)
wolffd@0 336 rk(:,:,j) = resample(dk(:,:,j),para.sampling,f{k});
wolffd@0 337 end
wolffd@0 338 dk = rk;
wolffd@0 339 tk = repmat((0:size(dk,1)-1)',[1 1 size(tk,3)])...
wolffd@0 340 /para.sampling + tk(1,:,:);
wolffd@0 341 end
wolffd@0 342 f{k} = para.sampling;
wolffd@0 343 end
wolffd@0 344 d{h}{k} = dk;
wolffd@0 345 t{h}{k} = tk;
wolffd@0 346 %if isfield(para,'reverse') && para.reverse
wolffd@0 347 % d{h}{k} = flipdim(d{h}{k},1);
wolffd@0 348 %end
wolffd@0 349 end
wolffd@0 350 end
wolffd@0 351 a = set(a,'Data',d,'Time',t,'Sampling',f,'Clusters',cl);
wolffd@0 352 if isfield(para,'label')
wolffd@0 353 if isnumeric(para.label)
wolffd@0 354 n = get(a,'Name');
wolffd@0 355 l = cell(1,length(d));
wolffd@0 356 for k = 1:length(d)
wolffd@0 357 if para.label
wolffd@0 358 l{k} = n{k}(para.label);
wolffd@0 359 else
wolffd@0 360 l{k} = n{k};
wolffd@0 361 end
wolffd@0 362 end
wolffd@0 363 a = set(a,'Label',l);
wolffd@0 364 elseif iscell(para.label)
wolffd@0 365 idx = mod(get(a,'Index'),length(para.label));
wolffd@0 366 if not(idx)
wolffd@0 367 idx = length(para.label);
wolffd@0 368 end
wolffd@0 369 a = set(a,'Label',para.label{idx});
wolffd@0 370 elseif ischar(para.label)
wolffd@0 371 l = cell(1,length(d));
wolffd@0 372 for k = 1:length(d)
wolffd@0 373 l{k} = para.label;
wolffd@0 374 end
wolffd@0 375 a = set(a,'Label',l);
wolffd@0 376 end
wolffd@0 377 end
wolffd@0 378
wolffd@0 379
wolffd@0 380 function [new orig] = beforechunk(orig,option,missing)
wolffd@0 381 option.normal = 0;
wolffd@0 382 a = miraudio(orig,option);
wolffd@0 383 d = get(a,'Data');
wolffd@0 384 old = get(orig,'AcrossChunks');
wolffd@0 385 if isempty(old)
wolffd@0 386 old.sqrsum = 0;
wolffd@0 387 old.samples = 0;
wolffd@0 388 end
wolffd@0 389 new = mircompute(@crossum,d);
wolffd@0 390 new = new{1}{1};
wolffd@0 391 new.sqrsum = old.sqrsum + new.sqrsum;
wolffd@0 392 new.samples = old.samples + new.samples;
wolffd@0 393
wolffd@0 394
wolffd@0 395 function s = crossum(d)
wolffd@0 396 s.sqrsum = sum(d.^2);
wolffd@0 397 s.samples = length(d);
wolffd@0 398
wolffd@0 399
wolffd@0 400 function [y orig] = eachchunk(orig,option,missing)
wolffd@0 401 y = miraudio(orig,option);
wolffd@0 402
wolffd@0 403
wolffd@0 404 function y = combinechunk(old,new)
wolffd@0 405 do = get(old,'Data');
wolffd@0 406 to = get(old,'Time');
wolffd@0 407 dn = get(new,'Data');
wolffd@0 408 tn = get(new,'Time');
wolffd@0 409 y = set(old,'Data',{{[do{1}{1};dn{1}{1}]}},...
wolffd@0 410 'Time',{{[to{1}{1};tn{1}{1}]}});