1function [dualwt,info] = dtwfbinit(dualwtdef,varargin) 2%-*- texinfo -*- 3%@deftypefn {Function} dtwfbinit 4%@verbatim 5%DTWFBINIT Dual-Tree Wavelet Filterbank Initialization 6% Usage: dualwt=dtwfbinit(dualwtdef); 7% 8% Input parameters: 9% dualwtdef : Dual-tree filterbank definition. 10% 11% Output parameters: 12% dualwt : Dual-tree filtarbank structure. 13% 14% dtwfinit() (a call without aguments) creates an empty structure. It 15% has the same fields as the struct. returned from WFBTINIT plus a field 16% to hold nodes from the second tree: 17% 18% .nodes Filterbank nodes of the first tree 19% 20% .dualnodes Filterbank nodes of the second tree 21% 22% .children Indexes of children nodes 23% 24% .parents Indexes of a parent node 25% 26% .forder Frequency ordering of the resultant frequency bands. 27% 28% dtwfinit({dualw,J,flag}) creates a structure representing a dual-tree 29% wavelet filterbank of depth J, using dual-tree wavelet filters 30% specified by dualw. The shape of the tree is controlled by flag. 31% Please see help on DTWFB or DTWFBREAL for description of the 32% parameters. 33% 34% [dualwt,info]=dtwfinit(...) additionally returns info struct which 35% provides some information about the computed window: 36% 37% info.tight 38% True if the overall tree construct a tight frame. 39% 40% info.dw 41% A structure containing basic dual-tree filters as returned from 42% fwtinit(dualwtdef,'wfiltdt_'). 43% 44% Additional optional flags 45% ------------------------- 46% 47% 'freq','nat' 48% Frequency or natural ordering of the resulting coefficient subbands. 49% Default ordering is 'freq'. 50%@end verbatim 51%@strong{Url}: @url{http://ltfat.github.io/doc/wavelets/dtwfbinit.html} 52%@end deftypefn 53 54% Copyright (C) 2005-2016 Peter L. Soendergaard <peter@sonderport.dk>. 55% This file is part of LTFAT version 2.3.1 56% 57% This program is free software: you can redistribute it and/or modify 58% it under the terms of the GNU General Public License as published by 59% the Free Software Foundation, either version 3 of the License, or 60% (at your option) any later version. 61% 62% This program is distributed in the hope that it will be useful, 63% but WITHOUT ANY WARRANTY; without even the implied warranty of 64% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 65% GNU General Public License for more details. 66% 67% You should have received a copy of the GNU General Public License 68% along with this program. If not, see <http://www.gnu.org/licenses/>. 69 70 71% Output structure definition. 72% The structure has the same fields as returned by wfbtinit 73% but contains additional field .dualnodes containing 74% filters of the dual tree 75%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 76dualwt = wfbtinit(); 77dualwt.dualnodes = {}; 78%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 79info.istight = 0; 80 81if nargin < 1 82 return; 83end 84 85% Frequency or natural ordering 86definput.import = {'wfbtcommon'}; 87[flags,kv]=ltfatarghelper({},definput,varargin); 88 89% Strict throws an error if filterbank is not tight and ana: or syn: 90% is not specified. 91do_strict = 0; 92% Dual returns the 'other' filterbank. 93do_dual = 0; 94 95% Check 'strict' 96if iscell(dualwtdef) && ischar(dualwtdef{1}) && strcmpi(dualwtdef{1},'strict') 97 do_strict = 1; 98 dualwtdef = dualwtdef{2:end}; 99end 100% Check 'dual' 101if iscell(dualwtdef) && ischar(dualwtdef{1}) && strcmpi(dualwtdef{1},'dual') 102 do_dual = 1; 103 dualwtdef = dualwtdef{2:end}; 104end 105 106% FIRST, check if dtwdef is already a struct 107if isstruct(dualwtdef) 108 if isfield(dualwtdef,'nodes') && isfield(dualwtdef,'dualnodes') 109 dualwt = dualwtdef; 110 111 if do_dual || do_strict 112 nodesArg = dualwt.nodes; 113 114 % Undo the frequency ordering 115 if dualwt.freqOrder 116 dualwt = nat2freqOrder(dualwt,'rev'); 117 end 118 119 doDualTreeFilt = cellfun(@(nEl) strcmp(nEl.wprefix,'wfiltdt_'),... 120 nodesArg); 121 122 if do_dual 123 nodesArg = cellfun(@(nEl) {'dual',nEl},nodesArg,... 124 'UniformOutput',0); 125 end 126 if do_strict 127 nodesArg = cellfun(@(nEl) {'strict',nEl},nodesArg,... 128 'UniformOutput',0); 129 130 end 131 info.istight = 1; 132 dualwt.nodes = {}; 133 dualwt.dualnodes = {}; 134 135 136 rangeRest = 1:numel(nodesArg); 137 rangeRest(dualwt.parents==0) = []; 138 139 for ii=rangeRest 140 if doDualTreeFilt(ii) 141 % This is dual-tree specific filterbank 142 [dualwt.nodes{ii},infotmp] = fwtinit(nodesArg{ii},'wfiltdt_'); 143 dualwt.dualnodes{ii} = dualwt.nodes{ii}; 144 dualwt.nodes{ii}.h(:,2) = []; 145 dualwt.nodes{ii}.g(:,2) = []; 146 dualwt.dualnodes{ii}.h(:,1) = []; 147 dualwt.dualnodes{ii}.g(:,1) = []; 148 else 149 [dualwt.nodes{ii},infotmp] = fwtinit(nodesArg{ii}); 150 dualwt.dualnodes{ii} = dualwt.nodes{ii}; 151 end 152 info.istight = info.istight && infotmp.istight; 153 end 154 155 % Treat root separately 156 [rootNode,infotmp] = fwtinit(nodesArg{dualwt.parents==0}); 157 dualwt = replaceRoots(dualwt,rootNode); 158 info.istight = info.istight && infotmp.istight; 159 160 % Do the filter frequency shuffling again, since the filters were 161 % overwritten in fwtinit. 162 if dualwt.freqOrder 163 dualwt = nat2freqOrder(dualwt); 164 end 165 end 166 167 % Do filter shuffling if flags.do_freq differs from the wt.freqOrder. 168 % Frequency and natural oreding coincide for DWT. 169 if dualwt.freqOrder && ~flags.do_freq 170 dualwt = nat2freqOrder(dualwt,'rev'); 171 dualwt.freqOrder = ~dualwt.freqOrder; 172 elseif ~dualwt.freqOrder && flags.do_freq 173 dualwt = nat2freqOrder(dualwt); 174 dualwt.freqOrder = ~dualwt.freqOrder; 175 end 176 else 177 error('%s: Invalid dual-tree structure format.',upper(mfilename)); 178 end 179 return; 180end 181 182% Parse the other params 183% Tree type 184definput.flags.treetype = {'dwt','full','doubleband','quadband',... 185 'octaband','root'}; 186% First stage filterbank 187definput.keyvals.first = []; 188% Leaf filterbank 189definput.keyvals.leaf = []; 190% Depth of the tree 191definput.keyvals.J = []; 192wdef = dualwtdef{1}; 193[flags2,kv2,J]=ltfatarghelper({'J'},definput,dualwtdef(2:end)); 194complainif_notposint(J,'J'); 195 196% Now dtwdef is this {dtw,J,flag,'first',w} 197if do_dual 198 wdef = {'dual',wdef}; 199end 200if do_strict 201 wdef = {'strict',wdef}; 202end 203 204if ~(ischar(wdef) || iscell(wdef)) 205 error('%s: Unrecognized format of dual-tree filters.',upper(mfilename)); 206end 207 208% Get the dual-tree filters 209[w, dtinfo] = fwtinit(wdef,'wfiltdt_'); 210 211info.istight = dtinfo.istight; 212info.dw = w; 213 214% Determine the first-stage wavelet filters 215if ~isfield(dtinfo,'defaultfirst') && isempty(kv2.first) 216 error('%s: No first stage wavelet filters specified.',upper(mfilename)); 217end 218 219 220if ~isempty(kv2.first) 221 if do_dual 222 kv2.first = {'dual',kv2.first}; 223 end 224 if do_strict 225 kv2.first = {'strict',kv2.first}; 226 end 227 228 [kv2.first, firstinfo] = fwtinit(kv2.first); 229 isfirsttight = firstinfo.istight; 230else 231 kv2.first = dtinfo.defaultfirst; 232 isfirsttight = dtinfo.defaultfirstinfo.istight; 233end 234 235 236 237isleaftight = []; 238if ~(flags2.do_dwt || flags2.do_root) 239 % Determine leaf nodes (only valid for wavelet packets) 240 if ~isfield(dtinfo,'defaultleaf') && isempty(kv2.leaf) 241 error('%s: No leaf wavelet filters specified.',... 242 upper(mfilename)); 243 else 244 if isempty(kv2.leaf) 245 kv2.leaf = dtinfo.defaultleaf; 246 isleaftight = dtinfo.defaultleafinfo.istight; 247 else 248 if do_dual 249 kv2.leaf = {'dual',kv2.leaf}; 250 end 251 if do_strict 252 kv2.leaf = {'strict',kv2.leaf}; 253 end 254 [kv2.leaf, leafinfo] = fwtinit(kv2.leaf); 255 isleaftight = leafinfo.istight; 256 end 257 end 258end 259 260 261% Extract filters for dual trees 262% This is a bit clumsy... 263w1 = w; 264w1.h = w1.h(:,1); 265w1.g = w1.g(:,1); 266 267w2 = w; 268w2.h = w2.h(:,2); 269w2.g = w2.g(:,2); 270 271 272% Initialize both trees 273dualwt = wfbtinit({w1,J,flags2.treetype}, 'nat'); 274dtw2 = wfbtinit({w2,J,flags2.treetype}, 'nat'); 275% Merge tree definitions to a single struct. 276dualwt.dualnodes = dtw2.nodes; 277dualwt = replaceRoots(dualwt,kv2.first); 278 279 280% Replace the 'packet leaf nodes' (see Bayram) 281if ~(flags2.do_dwt || flags2.do_root) 282 filtNo = numel(w1.g); 283 if flags2.do_doubleband 284 for jj=1:J-1 285 dualwt = wfbtput(2*(jj+1)-1,1:filtNo-1,kv2.leaf,dualwt,'force'); 286 end 287 elseif flags2.do_quadband 288 idx = 1:filtNo-1; 289 idx = [idx,idx+filtNo]; 290 dualwt = wfbtput(2,idx,kv2.leaf,dualwt,'force'); 291 for jj=1:J-1 292 dualwt = wfbtput(3*(jj+1)-2,1:filtNo-1,kv2.leaf,dualwt,'force'); 293 dualwt = wfbtput(3*(jj+1)-1,1:2*filtNo-1,kv2.leaf,dualwt,'force'); 294 end 295 elseif flags2.do_octaband 296 idx = 1:filtNo-1;idx = [idx,idx+filtNo]; 297 dualwt = wfbtput(2,idx,kv2.leaf,dualwt,'force'); 298 idx = 1:2*filtNo-1;idx = [idx,idx+2*filtNo]; 299 dualwt = wfbtput(3,idx,kv2.leaf,dualwt,'force'); 300 for jj=1:J-1 301 dualwt = wfbtput(4*(jj+1)-3,1:filtNo-1,kv2.leaf,dualwt,'force'); 302 dualwt = wfbtput(4*(jj+1)-2,1:2*filtNo-1,kv2.leaf,dualwt,'force'); 303 dualwt = wfbtput(4*(jj+1)-1,1:4*filtNo-1,kv2.leaf,dualwt,'force'); 304 end 305 elseif flags2.do_full 306 for jj=2:J-1 307 idx = 1:filtNo^jj-1; 308 idx(filtNo^(jj-1))=[]; 309 dualwt = wfbtput(jj,idx,kv2.leaf,dualwt,'force'); 310 end 311 else 312 error('%s: Something is seriously wrong!',upper(mfilename)); 313 end 314end 315 316 317% Do filter shuffling if frequency ordering is required, 318dualwt.freqOrder = flags.do_freq; 319if flags.do_freq 320 dualwt = nat2freqOrder(dualwt); 321end 322 323% 324info.istight = isfirsttight && info.istight; 325if ~isempty(isleaftight) 326 info.istight = info.istight && isleaftight; 327end 328 329 330function dtw = replaceRoots(dtw,rootNode) 331% Replace the root nodes 332 333firstTmp = rootNode; 334firstTmp.h = cellfun(@(hEl) setfield(hEl,'offset',hEl.offset+1),... 335 firstTmp.h,'UniformOutput',0); 336firstTmp.g = cellfun(@(gEl) setfield(gEl,'offset',gEl.offset+1),... 337 firstTmp.g,'UniformOutput',0); 338 339% First tree root 340dtw.nodes{dtw.parents==0} = rootNode; 341% Second tree root (shifted by 1 sample) 342dtw.dualnodes{dtw.parents==0} = firstTmp; 343 344 345 346 347