Mercurial > hg > camir-aes2014
view 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 |
line wrap: on
line source
function varargout = miraudio(orig,varargin) % a = miraudio('filename') loads the sound file 'filename' (in WAV or AU % format) into a miraudio object. % a = miraudio('Folder') loads all the sound files in the CURRENT folder % into a miraudio object. % a = miraudio(v,sr), where v is a column vector, translates the vector v % into a miraudio object. The sampling frequency is set to sr Hertz. % Default value for sr: 44100 Hz. % a = miraudio(b, ...), where b is already a miraudio object, performs % operations on b specified by the optional arguments (see below). % % Transformation options: % miraudio(...,'Mono',0) does not perform the default summing of % channels into one single mono track, but instead stores each % channel of the initial soundfile separately. % miraudio(...,'Center') centers the signals. % miraudio(...,'Sampling',r) resamples at sampling rate r (in Hz). % (Requires the Signal Processing Toolbox.) % miraudio(...,'Normal') normalizes with respect to RMS energy. % Extraction options: % miraudio(...,'Extract',t1,t2,u,f) extracts the signal between dates % t1 and t2, expressed in the unit u. % Possible values for u: % 's' (seconds, by default), % 'sp' (sample index, starting from 1). % The additional optional argument f indicates the referential % origin of the temporal positions. Possible values for f: % 'Start' (by default) % 'Middle' (of the sequence) % 'End' of the sequence % When using 'Middle' or 'End', negative values for t1 or t2 % indicate values before the middle or the end of the audio % sequence. % miraudio(...,'Trim') trims the pseudo-silence beginning and end off % the audio file. Silent frames are frames with RMS below t times % the medium RMS of the whole audio file. % Default value: t = 0.06 % instead of 'Trim': % 'TrimStart' only trims the beginning of the audio file, % 'TrimEnd' only trims the end. % miraudio(...,'TrimThreshold',t) specifies the trimming threshold t. % miraudio(...,'Channel',c) or miraudio(...,'Channels',c) selects the % channels indicated by the (array of) integer(s) c. % Labeling option: % miraudio(...,'Label',l) labels the audio signal(s) following the % label(s) l. % If l is a (series of) number(s), the audio signal(s) are % labelled using the substring of their respective file name of % index l. If l=0, the audio signal(s) are labelled using the % whole file name. if isnumeric(orig) if size(orig,2) > 1 || size(orig,3) > 1 mirerror('MIRAUDIO','Only column vectors can be imported into mirtoolbox.'); end if nargin == 1 f = 44100; else f = varargin{1}; end b = 32; if size(orig,1) == 1 orig = orig'; end tp = (0:size(orig,1)-1)'/f; t = mirtemporal([],'Time',{{tp}},'Data',{{orig}},... 'FramePos',{{tp([1 end])}},'Sampling',{f},... 'Name',{inputname(1)},'Label',{{}},'Clusters',{{}},... 'Channels',[],'Centered',0,'NBits',{b},... 'Title','Audio signal',... 'PeakPos',{{{}}},'PeakVal',{{{}}},'PeakMode',{{{}}}); aa.fresh = 1; varargout = {class(aa,'miraudio',t)}; return end center.key = 'Center'; center.type = 'Boolean'; center.default = 0; center.when = 'After'; option.center = center; normal.key = 'Normal'; normal.type = 'Boolean'; normal.default = 0; normal.when = 'After'; option.normal = normal; extract.key = {'Extract','Excerpt'}; extract.type = 'Integer'; extract.number = 2; extract.default = []; extract.unit = {'s','sp'}; extract.defaultunit = 's'; extract.from = {'Start','Middle','End'}; extract.defaultfrom = 'Start'; option.extract = extract; trim.type = 'String'; trim.choice = {'NoTrim','Trim','TrimBegin','TrimStart','TrimEnd'}; trim.default = 'NoTrim'; trim.when = 'After'; option.trim = trim; trimthreshold.key = 'TrimThreshold'; trimthreshold.type = 'Integer'; trimthreshold.default = .06; trimthreshold.when = 'After'; option.trimthreshold = trimthreshold; label.key = 'Label'; label.default = ''; label.when = 'After'; option.label = label; sampling.key = 'Sampling'; sampling.type = 'Integer'; sampling.default = 0; sampling.when = 'Both'; option.sampling = sampling; % segment.key = 'Segment'; % segment.type = 'Integer'; % segment.default = []; % segment.when = 'After'; % option.segment = segment; reverse.key = 'Reverse'; reverse.type = 'Boolean'; reverse.default = 0; reverse.when = 'After'; option.reverse = reverse; mono.key = 'Mono'; mono.type = 'Boolean'; mono.default = NaN; mono.when = 'After'; option.mono = mono; separate.key = 'SeparateChannels'; separate.type = 'Boolean'; separate.default = 0; option.separate = separate; Ch.key = {'Channel','Channels'}; Ch.type = 'Integer'; Ch.default = []; Ch.when = 'After'; option.Ch = Ch; specif.option = option; specif.beforechunk = {@beforechunk,'normal'}; specif.eachchunk = @eachchunk; specif.combinechunk = @combinechunk; if nargin > 1 && ischar(varargin{1}) && strcmp(varargin{1},'Now') if nargin > 2 extract = varargin{2}; else extract = []; end para = []; varargout = {main(orig,[],para,[],extract)}; else varargout = mirfunction(@miraudio,orig,varargin,nargout,specif,@init,@main); end if isempty(varargout) varargout = {{}}; end function [x type] = init(x,option) if isa(x,'mirdesign') if option.sampling x = setresampling(x,option.sampling); end end type = 'miraudio'; function a = main(orig,option,after,index,extract) if iscell(orig) orig = orig{1}; end if ischar(orig) if nargin < 5 extract = []; end [d{1},tp{1},fp{1},f{1},b{1},n{1},ch{1}] = mirread(extract,orig,1,0); t = mirtemporal([],'Time',tp,'Data',d,'FramePos',fp,'Sampling',f,... 'Name',n,'Label',cell(1,length(d)),... 'Clusters',cell(1,length(d)),... 'Channels',ch,'Centered',0,'NBits',b); t = set(t,'Title','Audio waveform'); a.fresh = 1; a = class(a,'miraudio',t); else if not(isempty(option)) && not(isempty(option.extract)) if not(isstruct(after)) after = struct; end after.extract = option.extract; end if isa(orig,'miraudio') a = orig; else a.fresh = 1; a = class(a,'miraudio',orig); end end if not(isempty(after)) a = post(a,after); end function a = post(a,para) if a.fresh && isfield(para,'mono') a.fresh = 0; if isnan(para.mono) para.mono = 1; end end if isfield(para,'mono') && para.mono == 1 a = mirsum(a,'Mean'); end d = get(a,'Data'); t = get(a,'Time'); ac = get(a,'AcrossChunks'); f = get(a,'Sampling'); cl = get(a,'Clusters'); for h = 1:length(d) for k = 1:length(d{h}) tk = t{h}{k}; dk = d{h}{k}; if isfield(para,'extract') && not(isempty(para.extract)) t1 = para.extract(1); t2 = para.extract(2); if para.extract(4) if para.extract(4) == 1 shift = round(size(tk,1)/2); elseif para.extract(4) == 2 shift = size(tk,1); end if para.extract(3) shift = tk(shift,1,1); end t1 = t1+shift; t2 = t2+shift; end if para.extract(3) % in seconds ft = find(tk>=t1 & tk<=t2); else % in samples if not(t1) warning('WARNING IN MIRAUDIO: Extract sample positions should be real positive integers.') display('Positions incremented by one.'); t1 = t1+1; t2 = t2+1; end ft = t1:t2; end tk = tk(ft,:,:); dk = dk(ft,:,:); end if isfield(para,'Ch') && not(isempty(para.Ch)) dk = dk(:,:,para.Ch); end if isfield(para,'center') && para.center dk = center(dk); a = set(a,'Centered',1); end if isfield(para,'normal') && para.normal nl = size(dk,1); nc = size(dk,3); if isempty(ac) ee = 0; for j = 1:nc ee = ee+sum(dk(:,:,j).^2); end ee = sqrt(ee/nl/nc); else ee = sqrt(sum(ac.sqrsum.^2)/ac.samples); end dk = dk./repmat(ee,[nl,1,nc]); end if isfield(para,'trim') && not(isequal(para.trim,0)) ... && not(strcmpi(para.trim,'NoTrim')) if not(para.trimthreshold) para.trimthreshold = 0.06; end trimframe = 100; trimhop = 10; nframes = floor((length(tk)-trimframe)/trimhop)+1; rms = zeros(1,nframes); for j = 1:nframes st = floor((j-1)*trimhop)+1; for z = 1:size(dk,3) rms(1,j,z) = norm(dk(st:st+trimframe-1,1,z))/sqrt(trimframe); end end rms = (rms-repmat(min(rms),[1,size(rms,2),1]))... ./repmat(max(rms)-min(rms),[1,size(rms,2),1]); nosil = find(rms>para.trimthreshold); if strcmpi(para.trim,'Trim') || strcmpi(para.trim,'TrimStart') ... || strcmpi(para.trim,'TrimBegin') nosil1 = min(nosil); if nosil1 > 1 nosil1 = nosil1-1; end n1 = floor((nosil1-1)*trimhop)+1; else n1 = 1; end if strcmpi(para.trim,'Trim') || strcmpi(para.trim,'TrimEnd') nosil2 = max(nosil); if nosil2 < length(rms) nosil2 = nosil2+1; end n2 = floor((nosil2-1)*trimhop)+1; else n2 = length(tk); end wh = ones(n2-n1+1,1); dt = round(.02*f{h}); ha = hann(dt*2); wh(1:dt) = ha(1:dt); wh(end-dt+1:end) = ha(dt+1:end); tk = tk(n1:n2); dk = dk(n1:n2,1,:);%.*repmat(wh,[1 1 size(dk,3)]); end if isfield(para,'sampling') && para.sampling if and(f{k}, not(f{k} == para.sampling)) for j = 1:size(dk,3) rk(:,:,j) = resample(dk(:,:,j),para.sampling,f{k}); end dk = rk; tk = repmat((0:size(dk,1)-1)',[1 1 size(tk,3)])... /para.sampling + tk(1,:,:); end f{k} = para.sampling; end d{h}{k} = dk; t{h}{k} = tk; %if isfield(para,'reverse') && para.reverse % d{h}{k} = flipdim(d{h}{k},1); %end end end a = set(a,'Data',d,'Time',t,'Sampling',f,'Clusters',cl); if isfield(para,'label') if isnumeric(para.label) n = get(a,'Name'); l = cell(1,length(d)); for k = 1:length(d) if para.label l{k} = n{k}(para.label); else l{k} = n{k}; end end a = set(a,'Label',l); elseif iscell(para.label) idx = mod(get(a,'Index'),length(para.label)); if not(idx) idx = length(para.label); end a = set(a,'Label',para.label{idx}); elseif ischar(para.label) l = cell(1,length(d)); for k = 1:length(d) l{k} = para.label; end a = set(a,'Label',l); end end function [new orig] = beforechunk(orig,option,missing) option.normal = 0; a = miraudio(orig,option); d = get(a,'Data'); old = get(orig,'AcrossChunks'); if isempty(old) old.sqrsum = 0; old.samples = 0; end new = mircompute(@crossum,d); new = new{1}{1}; new.sqrsum = old.sqrsum + new.sqrsum; new.samples = old.samples + new.samples; function s = crossum(d) s.sqrsum = sum(d.^2); s.samples = length(d); function [y orig] = eachchunk(orig,option,missing) y = miraudio(orig,option); function y = combinechunk(old,new) do = get(old,'Data'); to = get(old,'Time'); dn = get(new,'Data'); tn = get(new,'Time'); y = set(old,'Data',{{[do{1}{1};dn{1}{1}]}},... 'Time',{{[to{1}{1};tn{1}{1}]}});