├── .gitignore
├── COPYRIGHT.txt
├── LICENSE.txt
├── MATLAB
├── ComputeMapping.m
├── ComputeScore.m
├── TSAM.m
├── distmeshnd_sfa.m
├── elmMOD.m
├── elmMODmap.m
├── oscsend.m
├── period_detection.m
├── relative_mean_difference.m
└── unique_sfast.m
├── Max
├── TSAM.maxpat
└── TSAM_3DOGL.maxpat
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .DS_Store
3 |
--------------------------------------------------------------------------------
/COPYRIGHT.txt:
--------------------------------------------------------------------------------
1 | The Timbre Space Analyzer & Mapper (TSAM) is a collection of MAX patches
2 | and MATLAB functions for the analysis, modeling and malling of the
3 | timbre if siund synthesizers.
4 |
5 | The TSAM can be obtained at http://stefanofasciani.com/tsam.html
6 | TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
7 | Inquiries: stefanofasciani@stefanofasciani.com
8 |
9 | The TSAM is free software: you can redistribute it and/or modify it under the
10 | terms of the GNU Lesser General Public License as published by the Free Software
11 | Foundation, either version 3 of the License, or (at your option) any later version.
12 |
13 | The TSAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
14 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 | See the GNU Less General Public License for more details.
16 |
17 | You should have received a copy of the GNU Lesser General Public License along with TSAM.
18 | If not, see .
19 |
20 | If you use the TSAM or any part of it in any program or publication, please acknowledge
21 | its authors by adding a reference to this pubblication:
22 |
23 | S. Fasciani, 2016, "TSAM: a tool for analyzing, modeling, and mapping the timbre of sound
24 | synthesizers" in proceedings of the 13th Sound and Music Computing Conference, Hamburg, Germany.
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
--------------------------------------------------------------------------------
/MATLAB/ComputeMapping.m:
--------------------------------------------------------------------------------
1 | % This file is part of the Timbre Space Analyzer & Mapper (TSAM)
2 | %
3 | % The TSAM can be obtained at http://stefanofasciani.com/tsam.html
4 | % TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
5 | % Inquiries: stefanofasciani@stefanofasciani.com
6 | %
7 | % The TSAM is free software: you can redistribute it and/or modify it under the terms
8 | % of the GNU Lesser General Public License as published by the Free Software Foundation,
9 | % either version 3 of the License, or (at your option) any later version.
10 | %
11 | % The TSAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12 | % without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 | % See the GNU Less General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU Lesser General Public License along with TSAM.
16 | % If not, see .
17 | %
18 | % If you use the TSAM or any part of it in any program or publication, please acknowledge
19 | % its authors by adding a reference to this pubblication:
20 | %
21 | % S. Fasciani, 2016, "TSAM: a tool for analyzing, modeling, and mapping the timbre of sound
22 | % synthesizers" in proceedings of the 13th Sound and Music Computing Conference, Hamburg, Germany.
23 |
24 |
25 |
26 | function [ret]=ComputeMapping(MAXoscclient,MATLABoscserver,args)
27 |
28 |
29 | fignum=1;
30 |
31 | old=0;
32 |
33 | outfile=sprintf('%s%sMap.mat',args{8},args{7});
34 | featfile=sprintf('%s%sFeat.txt',args{8},args{7});
35 | paramfile=sprintf('%s%sParams.txt',args{8},args{7});
36 | if exist(outfile, 'file')
37 | delete(outfile);
38 | end
39 |
40 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',1);
41 |
42 | D=load(featfile);
43 | I=load(paramfile);
44 |
45 | if old
46 | I=I';
47 | end
48 |
49 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',15);
50 |
51 | num_params=std(I);
52 | num_params=size((num_params(num_params~=0)),2);
53 |
54 | num_combs=size(I,1);
55 |
56 | analysis_mode=args{1};
57 | range_enabled=args{2};
58 | period_enabled=args{3}(1);
59 | winsize=args{3}(2);
60 | hopsize=args{3}(3);
61 | dimensionality=args{4};
62 | mergegap=args{5};
63 | vectperstate=args{6};
64 | mask=args{10};
65 | actfuncid=args{11};
66 | actfunclist={'sig','sin','hardlim','tribas','radbas'};
67 | actfuncname=actfunclist{actfuncid};
68 | dimredfunct=args{12};
69 | sr=args{14};
70 |
71 | switch args{13}
72 | case 0
73 | featselect=args{9};
74 | featselect=featselect(featselect~=0);
75 | case 1
76 | featselect=1:108;
77 | case 2
78 | featselect=1:35;
79 | case 3
80 | featselect=3:18;
81 | case 4
82 | featselect=19:31;
83 | case 5
84 | featselect=[19:31 85:108];
85 | case 6
86 | featselect=36:47;
87 | case 7
88 | featselect=48:60;
89 | case 8
90 | featselect=61:84;
91 | case 9
92 | featselect=85:108;
93 | case 10
94 | featselect=args{15}+1;
95 | otherwise
96 | featselect=1:108;
97 | end
98 |
99 | %apply mask
100 | D=D.*repmat(mask,size(D,1),1);
101 |
102 | D=D(:,featselect);
103 |
104 | if ((analysis_mode==0)||(analysis_mode==2))
105 |
106 | cnt=1;
107 | average=[];
108 | range=[];
109 | period=[];
110 | D_post=[];
111 | if (analysis_mode==2)
112 | I=I(1:vectperstate:(size(D,1)),:);
113 | end
114 | %COMPUTING MEAN RANGE AND PERIOD FOR EACH SUB MATRIX PER STATE
115 | if vectperstate > 2
116 | for i=1:vectperstate:(size(D,1))
117 | temp=D(i:i+vectperstate-1,:);
118 | average=[average ; mean(temp)];
119 | if range_enabled
120 | range=[range ; (max(temp)-min(temp))];
121 | end
122 | if period_enabled
123 | period=[period ; period_detection(winsize,hopsize,temp,sr)];
124 | end
125 | cnt=cnt+1;
126 | end
127 |
128 |
129 | period_post=[];
130 | if period_enabled
131 | %removing zeros in period
132 | if numel(period(period==0)) > (numel(period)/2)
133 | for i=1:num_combs
134 | temp=period(i,:);
135 | period_post(i,1)=median(temp(temp~=0));
136 | end
137 | else
138 | for i=1:num_combs
139 | temp=period(i,:);
140 | temp(temp==0)=median(temp(temp~=0));
141 | period_post(i,:)=temp;
142 | end
143 | end
144 | %fprintf('feat period detected min = %f max = %f\n',min(min(period_post)),max(max(period_post)));
145 | end
146 | if (period_enabled==1 || range_enabled==1)
147 | average=average./max(max(abs(average)));
148 | range=range./max(max(abs(range)));
149 | period_post=period_post./max(max(abs(period_post)));
150 | end
151 | D_post=[average range period_post];
152 |
153 | else
154 |
155 | D_post=D;
156 |
157 | end
158 |
159 | D_post(:,all(isnan(D_post),1))=[];
160 | D_post(isnan(D_post))=0;
161 | D_post(:,find(sum(abs(D_post))==0))=[];
162 |
163 |
164 | elseif ((analysis_mode==1)||(analysis_mode==3))
165 |
166 | cnt=1;
167 | D_post=[];
168 | if (analysis_mode==3)
169 | I=I(1:vectperstate:(size(D,1)),:);
170 | end
171 | %PUTTING TEMPORAL ENVELOPE OF FEATURES IN A SINGLE VECTOR
172 | for i=1:vectperstate:(size(D,1))
173 | temp=[];
174 | for j=1:vectperstate
175 | temp=[temp D(i+j-1,:)];
176 | end
177 | D_post(cnt,:)=temp;
178 | cnt=cnt+1;
179 | end
180 | D_post(:,find(sum(abs(D_post))==0))=[];
181 |
182 | elseif (analysis_mode==4)
183 |
184 | average=[];
185 | range=[];
186 | D_post=[];
187 |
188 | for j=1:numel(mergegap)
189 | ranges=0:mergegap(j):(1+mergegap(j));
190 | for i=1:(numel(ranges)-1)
191 | I(find((I(:,j)<=ranges(i+1))&(I(:,j)>ranges(i))),j)=(ranges(i+1)+ranges(i))/2;
192 | end
193 | end
194 |
195 | Iuniq=unique(I,'rows');
196 |
197 | for i=1:size(Iuniq,1)
198 | idx=find(ismember(I,Iuniq(i,:),'rows'));
199 | temp=D(idx,:);
200 | if size(temp,1)>1
201 | average=[average ; mean(temp)];
202 | if range_enabled
203 | range=[range ; (max(temp)-min(temp))];
204 | end
205 | else
206 | average=[average ; temp];
207 | if range_enabled
208 | fprintf('Warning: range on single descriptors vector\n');
209 | range=[range ; temp-temp];
210 | end
211 | end
212 | end
213 |
214 | if (range_enabled==1)
215 | average=average./max(max(abs(average)));
216 | range=range./max(max(abs(range)));
217 | end
218 |
219 | D_post=[average range];
220 | D_post(:,all(isnan(D_post),1))=[];
221 | D_post(isnan(D_post))=0;
222 | D_post(:,find(sum(abs(D_post))==0))=[];
223 |
224 | I=Iuniq;
225 |
226 | end
227 |
228 | num_combs=size(I,1);
229 |
230 | if num_combs<8
231 | fprintf('number of parameter combination is lower than 8');
232 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',-1);
233 | return
234 | end
235 |
236 | num_feat=size(D_post,2);
237 |
238 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',25);
239 |
240 | %COMPUTING AND REMOVING THE MEAN FROM EACH FEATURE
241 | mean_vect=mean(D_post);
242 |
243 | for i=1:num_combs
244 | D_post(i,:)=D_post(i,:)-mean_vect;
245 | end
246 |
247 | D_post=D_post./(max(max(D_post)));
248 |
249 | if dimensionality0.01))
311 | net=elmMOD(distmeshout',D_star',hiddenneurons,actfuncname);
312 | net.accuracy=net.accuracy/sqrt(size(D_star,1));
313 | hiddenneurons=hiddenneurons+10;
314 | accuracy=net.accuracy;
315 | end
316 |
317 |
318 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',90);
319 |
320 |
321 | %MAX AND MIN FOR DIRECT D STAR NAVIGATION
322 | for i=1:size(D_star,2)
323 | D_star_minmax(1,i)=min(D_star(:,i));
324 | D_star_minmax(2,i)=max(D_star(:,i));
325 | end
326 |
327 | for i=1:size(D_star_minmax,2)
328 | D_star_map_min(i)=D_star_minmax(1,i);
329 | D_star_map_range(i)=D_star_minmax(2,i)-D_star_minmax(1,i);
330 | end
331 |
332 | D_star_min_range=[D_star_map_min;D_star_map_range];
333 |
334 |
335 | outfile=sprintf('%s%sMap-DS.txt',args{8},args{7});
336 | save(outfile,'D_star','-ASCII','-double');
337 |
338 | outfile=sprintf('%s%sMap-DU.txt',args{8},args{7});
339 | save(outfile,'distmeshout','-ASCII','-double');
340 |
341 | outfile=sprintf('%s%sMap-I.txt',args{8},args{7});
342 | save(outfile,'I','-ASCII','-double');
343 |
344 | outfile=sprintf('%s%sMap-Dmnrg.txt',args{8},args{7});
345 | save(outfile,'D_star_min_range','-ASCII','-double');
346 |
347 | %minIdist maxIdist accuracy
348 | info=[max(pdist((I))) min(pdist((I)))+0.1*min(pdist((I))) net.accuracy];
349 | outfile=sprintf('%s%sMap-Info.txt',args{8},args{7});
350 | save(outfile,'info','-ASCII','-double');
351 |
352 | temp=net.inweight;
353 | outfile=sprintf('%s%sMap-Iw.txt',args{8},args{7});
354 | save(outfile,'temp','-ASCII','-double');
355 |
356 | temp=net.outweight;
357 | outfile=sprintf('%s%sMap-Ow.txt',args{8},args{7});
358 | save(outfile,'temp','-ASCII','-double');
359 |
360 | temp=net.bias;
361 | outfile=sprintf('%s%sMap-Bs.txt',args{8},args{7});
362 | save(outfile,'temp','-ASCII','-double');
363 |
364 | temp=find((strcmp(net.actfunct,actfunclist))==1);
365 | outfile=sprintf('%s%sMap-Act.txt',args{8},args{7});
366 | save(outfile,'temp','-ASCII','-double');
367 |
368 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',100);
369 |
370 | return
371 |
372 |
373 |
374 |
375 | %EXTRA FUNCTIONS
376 |
377 | function h=huniform_sfa(p,varargin)
378 |
379 | % Copyright (C) 2004-2012 Per-Olof Persson. See COPYRIGHT.TXT for details.
380 |
381 | % The original file was modified for the integration with the
382 | % Timbre Space Mapping for VST Synthesizers (TSM4VSTS).
383 |
384 | h=ones(size(p,1),1);
385 |
386 | function d=drectangle2D_sfa(p,x1,x2,y1,y2)
387 |
388 | % Copyright (C) 2004-2012 Per-Olof Persson. See COPYRIGHT.TXT for details.
389 |
390 | % The original file was modified for the integration with the
391 | % Timbre Space Mapping for VST Synthesizers (TSM4VSTS).
392 |
393 | d=-min(min(min(-y1+p(:,2),y2-p(:,2)),-x1+p(:,1)),x2-p(:,1));
394 |
395 | function d=drectangle3D_sfa(p,x1,x2,y1,y2,z1,z2)
396 |
397 | % Copyright (C) 2004-2012 Per-Olof Persson. See COPYRIGHT.TXT for details.
398 |
399 | % The original file was modified for the integration with the
400 | % Timbre Space Mapping for VST Synthesizers (TSM4VSTS).
401 |
402 | d=-min(min(min(min(min(-z1+p(:,3),z2-p(:,3)),-y1+p(:,2)),y2-p(:,2)),-x1+p(:,1)),x2-p(:,1));
403 |
--------------------------------------------------------------------------------
/MATLAB/ComputeScore.m:
--------------------------------------------------------------------------------
1 | % This file is part of the Timbre Space Analyzer & Mapper (TSAM)
2 | %
3 | % The TSAM can be obtained at http://stefanofasciani.com/tsam.html
4 | % TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
5 | % Inquiries: stefanofasciani@stefanofasciani.com
6 | %
7 | % The TSAM is free software: you can redistribute it and/or modify it under the terms
8 | % of the GNU Lesser General Public License as published by the Free Software Foundation,
9 | % either version 3 of the License, or (at your option) any later version.
10 | %
11 | % The TSAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12 | % without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 | % See the GNU Less General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU Lesser General Public License along with TSAM.
16 | % If not, see .
17 | %
18 | % If you use the TSAM or any part of it in any program or publication, please acknowledge
19 | % its authors by adding a reference to this pubblication:
20 | %
21 | % S. Fasciani, 2016, "TSAM: a tool for analyzing, modeling, and mapping the timbre of sound
22 | % synthesizers" in proceedings of the 13th Sound and Music Computing Conference, Hamburg, Germany.
23 |
24 |
25 |
26 | function [ret]=ComputeScore(MAXoscclient,MATLABoscserver,args)
27 |
28 | fignum=1;
29 |
30 | old=0;
31 |
32 | featfile=sprintf('%s%sFeat.txt',args{8},args{7});
33 | paramfile=sprintf('%s%sParams.txt',args{8},args{7});
34 |
35 |
36 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',1);
37 |
38 | D=load(featfile);
39 | I=load(paramfile);
40 |
41 | if old
42 | I=I';
43 | end
44 |
45 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',15);
46 |
47 | num_params=std(I);
48 | num_params=size((num_params(num_params~=0)),2);
49 | num_desc=size(D,2);
50 |
51 | analysis_mode=args{1};
52 | range_enabled=1;
53 | winsize=args{3}(2);
54 | hopsize=args{3}(3);
55 | dimensionality=args{4};
56 | mergegap=args{5};
57 | vectperstate=args{6};
58 | mask=args{10};
59 | sr=args{14};
60 |
61 | %apply mask
62 | D=D.*repmat(mask,size(D,1),1);
63 |
64 | param_score=zeros(1,10);
65 | corrmat=zeros(10,108*2);
66 |
67 | if ((analysis_mode==0)||(analysis_mode==2))
68 |
69 | noisiness_sustain=zeros(num_desc,1);
70 | variance_sustain=zeros(num_desc,1);
71 | independence_sustain=zeros(num_desc,1);
72 | paramcorrelation_sustain=zeros(num_desc,1);
73 |
74 | variance_sustain_range=zeros(num_desc,1);
75 | independence_sustain_range=zeros(num_desc,1);
76 | paramcorrelation_sustain_range=zeros(num_desc,1);
77 |
78 | num_combs=size(I,1);
79 |
80 | cnt=1;
81 | average=[];
82 | range=[];
83 | D_post=[];
84 | if (analysis_mode==2)
85 | I=I(1:vectperstate:(size(D,1)),:);
86 | end
87 |
88 | %COMPUTING MEAN AND RANGE FOR EACH SUB MATRIX PER STATE
89 | if vectperstate > 2
90 | for i=1:vectperstate:(size(D,1))
91 | temp=D(i:i+vectperstate-1,:);
92 | noisiness_sustain=noisiness_sustain+relative_mean_difference(temp');
93 | average=[average ; mean(temp)];
94 | if range_enabled
95 | range=[range ; (max(temp)-min(temp))];
96 | end
97 | end
98 |
99 | noisiness_sustain=noisiness_sustain./num_combs;
100 |
101 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',65);
102 |
103 | D_post=[average range];
104 | D_post(:,all(isnan(D_post),1))=[];
105 | D_post(isnan(D_post))=0;
106 | variance_sustain=(relative_mean_difference((D_post(:,1:num_desc))'));
107 | variance_sustain_range=(relative_mean_difference((D_post(:,1+num_desc:2*num_desc))'));
108 |
109 | else
110 |
111 | D_post=D;
112 | D_post(:,all(isnan(D_post),1))=[];
113 | D_post(isnan(D_post))=0;
114 | variance_sustain=(relative_mean_difference(D_post'));
115 |
116 | end
117 |
118 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',70);
119 |
120 | %INDEPENDENCE
121 | %on average
122 | temp1=D_post(:,1:num_desc);
123 | independence_sustain=((nansum(abs(corr(temp1,temp1)))-1)/(num_desc-1))';
124 | independence_sustain=1-independence_sustain;
125 |
126 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',75);
127 |
128 | %on on range
129 | temp1=D_post(:,1+num_desc:2*num_desc);
130 | independence_sustain_range=((nansum(abs(corr(temp1,temp1)))-1)/(num_desc-1))';
131 | independence_sustain_range=1-independence_sustain_range;
132 |
133 |
134 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',80);
135 |
136 | %CORRELATION WITH PARAM
137 | %on average
138 | temp1=D_post(:,1:num_desc);
139 | for i=1:(size(temp1,2))
140 | cnt=0;
141 | temp4=0;
142 | temp2=temp1(:,i);
143 | for j=1:size(I,2)
144 | if sum(I(:,j))~=0
145 | temp3=I(:,j);
146 | temp5=nansum(abs(corr(temp2,temp3)));
147 | paramcorrelation_sustain(i)=paramcorrelation_sustain(i)+temp5;
148 | param_score(j)=param_score(j)+temp5;
149 | corrmat(j,i)=temp5;
150 | cnt=cnt+1;
151 | end
152 | end
153 | paramcorrelation_sustain(i)=paramcorrelation_sustain(i)/cnt;
154 | end
155 |
156 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',85);
157 |
158 | %on on range
159 | temp1=D_post(:,1+num_desc:2*num_desc);
160 | for i=1:(size(temp1,2))
161 | cnt=0;
162 | temp4=0;
163 | temp2=temp1(:,i);
164 | for j=1:size(I,2)
165 | if sum(I(:,j))~=0
166 | temp3=I(:,j);
167 | temp5=nansum(abs(corr(temp2,temp3)));
168 | paramcorrelation_sustain_range(i)=paramcorrelation_sustain_range(i)+temp5;
169 | param_score(j)=param_score(j)+temp5;
170 | corrmat(j,i+108)=temp5;
171 | cnt=cnt+1;
172 | end
173 | end
174 | paramcorrelation_sustain_range(i)=paramcorrelation_sustain_range(i)/cnt;
175 | end
176 |
177 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',95);
178 |
179 | outmat=[noisiness_sustain' ; variance_sustain' ; independence_sustain' ; paramcorrelation_sustain' ; zeros(1,num_desc) ; variance_sustain_range' ; independence_sustain_range' ; paramcorrelation_sustain_range'];
180 | outfile=sprintf('%s%sScoreDsc.txt',args{8},args{7});
181 | if exist(outfile, 'file')
182 | delete(outfile);
183 | end
184 | save(outfile,'outmat','-ASCII','-double');
185 |
186 | outmat=param_score./(abs(max(param_score)));
187 | outfile=sprintf('%s%sScorePrm.txt',args{8},args{7});
188 | if exist(outfile, 'file')
189 | delete(outfile);
190 | end
191 | save(outfile,'outmat','-ASCII','-double');
192 |
193 | outmat=corrmat;
194 | outfile=sprintf('%s%sCorrMat.txt',args{8},args{7});
195 | if exist(outfile, 'file')
196 | delete(outfile);
197 | end
198 | save(outfile,'outmat','-ASCII','-double');
199 |
200 | oscsend(MAXoscclient,'/score','i',1);
201 |
202 | elseif ((analysis_mode==1)||(analysis_mode==3))
203 |
204 | noisiness_envelope=zeros(num_desc,1);
205 | variance_envelope=zeros(num_desc,1);
206 | independence_envelope=zeros(num_desc,1);
207 | paramcorrelation_envelope=zeros(num_desc,1);
208 |
209 | num_combs=size(I,1);
210 |
211 | cnt=1;
212 | D_post=[];
213 | range=[];
214 | if (analysis_mode==3)
215 | I=I(1:vectperstate:(size(D,1)),:);
216 | end
217 | %PUTTING TEMPORAL ENVELOPE OF FEATURES IN A SINGLE VECTOR
218 |
219 | for i=1:vectperstate:(size(D,1))
220 | temp=D(i:i+vectperstate-1,:);
221 | for j=1:num_desc
222 | noisiness_envelope(j)=noisiness_envelope(j)+sum(abs(diff(diff(temp(:,j))>0)))/(length(diff(temp(:,j)))-1);
223 | variance_envelope(j)=variance_envelope(j)+relative_mean_difference(temp(:,j)');
224 | end
225 | independence_envelope=independence_envelope+((nansum(abs(corr(temp,temp)))-1)/(num_desc-1))';
226 | end
227 |
228 | noisiness_envelope=noisiness_envelope./num_combs;
229 | variance_envelope=variance_envelope./num_combs;
230 | independence_envelope=independence_envelope./num_combs;
231 | independence_envelope=1-independence_envelope;
232 |
233 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',80);
234 |
235 | for i=1:vectperstate:(size(D,1))
236 | temp=[];
237 | for j=1:vectperstate
238 | temp=[temp D(i+j-1,:)];
239 | end
240 | D_post(cnt,:)=temp;
241 | cnt=cnt+1;
242 | end
243 | %D_post(:,find(sum(abs(D_post))==0))=[];
244 |
245 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',85);
246 |
247 | cnt=0;
248 | for j=1:size(I,2)
249 | if sum(I(:,j))~=0
250 | temp1=I(:,j);
251 | for k=1:num_desc
252 | temp2=D_post(:,k:num_desc:num_desc*vectperstate);
253 | temp5=(nansum(abs(corr(temp1,temp2)))/vectperstate);
254 | paramcorrelation_envelope(k)=paramcorrelation_envelope(k)+temp5;
255 | param_score(j)=param_score(j)+temp5;
256 | corrmat(j,k)=temp5;
257 | end
258 | cnt=cnt+1;
259 | end
260 | end
261 | paramcorrelation_envelope=paramcorrelation_envelope/cnt;
262 |
263 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',95);
264 |
265 | outmat=[noisiness_envelope' ; variance_envelope' ; independence_envelope' ; paramcorrelation_envelope' ; zeros(1,num_desc) ; zeros(1,num_desc) ; zeros(1,num_desc) ; zeros(1,num_desc)];
266 | outfile=sprintf('%s%sScoreDsc.txt',args{8},args{7});
267 | if exist(outfile, 'file')
268 | delete(outfile);
269 | end
270 | save(outfile,'outmat','-ASCII','-double');
271 |
272 | outmat=param_score./(abs(max(param_score)));
273 | outfile=sprintf('%s%sScorePrm.txt',args{8},args{7});
274 | if exist(outfile, 'file')
275 | delete(outfile);
276 | end
277 | save(outfile,'outmat','-ASCII','-double');
278 |
279 | outmat=corrmat;
280 | outfile=sprintf('%s%sCorrMat.txt',args{8},args{7});
281 | if exist(outfile, 'file')
282 | delete(outfile);
283 | end
284 | save(outfile,'outmat','-ASCII','-double');
285 |
286 | oscsend(MAXoscclient,'/score','i',1);
287 |
288 |
289 | elseif (analysis_mode==4)
290 |
291 | noisiness_sustain=zeros(num_desc,1);
292 | variance_sustain=zeros(num_desc,1);
293 | independence_sustain=zeros(num_desc,1);
294 | paramcorrelation_sustain=zeros(num_desc,1);
295 |
296 | variance_sustain_range=zeros(num_desc,1);
297 | independence_sustain_range=zeros(num_desc,1);
298 | paramcorrelation_sustain_range=zeros(num_desc,1);
299 |
300 | cnt=0;
301 | average=[];
302 | range=[];
303 | D_post=[];
304 |
305 | for j=1:numel(mergegap)
306 | ranges=0:mergegap(j):(1+mergegap(j));
307 | for i=1:(numel(ranges)-1)
308 | I(find((I(:,j)<=ranges(i+1))&(I(:,j)>ranges(i))),j)=(ranges(i+1)+ranges(i))/2;
309 | end
310 | end
311 |
312 | Iuniq=unique(I,'rows');
313 |
314 | num_combs=size(I,Iuniq);
315 |
316 | for i=1:size(Iuniq,1)
317 | idx=find(ismember(I,Iuniq(i,:),'rows'));
318 | temp=D(idx,:);
319 | if size(temp,1)>1
320 | noisiness_sustain=noisiness_sustain+relative_mean_difference(temp');
321 | cnt=cnt+1;
322 | average=[average ; mean(temp)];
323 | if range_enabled
324 | range=[range ; (max(temp)-min(temp))];
325 | end
326 | else
327 | noisiness_sustain=noisiness_sustain+relative_mean_difference(temp');
328 | average=[average ; temp];
329 | if range_enabled
330 | fprintf('Warning: range on single descriptors vector\n');
331 | range=[range ; temp-temp];
332 | end
333 | end
334 | end
335 |
336 | noisiness_sustain=noisiness_sustain./cnt;
337 |
338 | D_post=[average range];
339 | D_post(:,all(isnan(D_post),1))=[];
340 | D_post(isnan(D_post))=0;
341 | %D_post(:,find(sum(abs(D_post))==0))=[];
342 |
343 | variance_sustain=(relative_mean_difference((D_post(:,1:num_desc))'));
344 | variance_sustain_range=(relative_mean_difference((D_post(:,1+num_desc:2*num_desc))'));
345 |
346 | I=Iuniq;
347 |
348 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',70);
349 |
350 | %INDEPENDENCE
351 | %on average
352 | temp1=D_post(:,1:num_desc);
353 | independence_sustain=((nansum(abs(corr(temp1,temp1)))-1)/(num_desc-1))';
354 | independence_sustain=1-independence_sustain;
355 |
356 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',75);
357 |
358 | %on on range
359 | temp1=D_post(:,1+num_desc:2*num_desc);
360 | independence_sustain_range=((nansum(abs(corr(temp1,temp1)))-1)/(num_desc-1))';
361 | independence_sustain_range=1-independence_sustain_range;
362 |
363 |
364 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',80);
365 |
366 | %CORRELATION WITH PARAM
367 | %on average
368 | temp1=D_post(:,1:num_desc);
369 | for i=1:(size(temp1,2))
370 | cnt=0;
371 | temp4=0;
372 | temp2=temp1(:,i);
373 | for j=1:size(I,2)
374 | if sum(I(:,j))~=0
375 | temp3=I(:,j);
376 | temp5=nansum(abs(corr(temp2,temp3)));
377 | paramcorrelation_sustain(i)=paramcorrelation_sustain(i)+temp5;
378 | param_score(j)=param_score(j)+temp5;
379 | corrmat(j,i)=temp5;
380 | cnt=cnt+1;
381 | end
382 | end
383 | paramcorrelation_sustain(i)=paramcorrelation_sustain(i)/cnt;
384 | end
385 |
386 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',85);
387 |
388 | %on on range
389 | temp1=D_post(:,1+num_desc:2*num_desc);
390 | for i=1:(size(temp1,2))
391 | cnt=0;
392 | temp4=0;
393 | temp2=temp1(:,i);
394 | for j=1:size(I,2)
395 | if sum(I(:,j))~=0
396 | temp3=I(:,j);
397 | temp5=nansum(abs(corr(temp2,temp3)));
398 | paramcorrelation_sustain_range(i)=paramcorrelation_sustain_range(i)+temp5;
399 | param_score(j)=param_score(j)+temp5;
400 | corrmat(j,i+108)=temp5;
401 | cnt=cnt+1;
402 | end
403 | end
404 | paramcorrelation_sustain_range(i)=paramcorrelation_sustain_range(i)/cnt;
405 | end
406 |
407 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',95);
408 |
409 | outmat=[noisiness_sustain' ; variance_sustain' ; independence_sustain' ; paramcorrelation_sustain' ; zeros(1,num_desc) ; variance_sustain_range' ; independence_sustain_range' ; paramcorrelation_sustain_range'];
410 | outfile=sprintf('%s%sScoreDsc.txt',args{8},args{7});
411 | if exist(outfile, 'file')
412 | delete(outfile);
413 | end
414 | save(outfile,'outmat','-ASCII','-double');
415 |
416 | outmat=param_score./(abs(max(param_score)));
417 | outfile=sprintf('%s%sScorePrm.txt',args{8},args{7});
418 | if exist(outfile, 'file')
419 | delete(outfile);
420 | end
421 | save(outfile,'outmat','-ASCII','-double');
422 |
423 | outmat=corrmat;
424 | outfile=sprintf('%s%sCorrMat.txt',args{8},args{7});
425 | if exist(outfile, 'file')
426 | delete(outfile);
427 | end
428 | save(outfile,'outmat','-ASCII','-double');
429 |
430 | oscsend(MAXoscclient,'/score','i',1);
431 |
432 |
433 | end
434 |
435 |
436 | oscsend(MAXoscclient,'/status/cmpt/percentage','f',100);
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
--------------------------------------------------------------------------------
/MATLAB/TSAM.m:
--------------------------------------------------------------------------------
1 | % This file is part of the Timbre Space Analyzer & Mapper (TSAM)
2 | %
3 | % The TSAM can be obtained at http://stefanofasciani.com/tsam.html
4 | % TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
5 | % Inquiries: stefanofasciani@stefanofasciani.com
6 | %
7 | % The TSAM is free software: you can redistribute it and/or modify it under the terms
8 | % of the GNU Lesser General Public License as published by the Free Software Foundation,
9 | % either version 3 of the License, or (at your option) any later version.
10 | %
11 | % The TSAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12 | % without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 | % See the GNU Less General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU Lesser General Public License along with TSAM.
16 | % If not, see .
17 | %
18 | % If you use the TSAM or any part of it in any program or publication, please acknowledge
19 | % its authors by adding a reference to this pubblication:
20 | %
21 | % S. Fasciani, 2016, "TSAM: a tool for analyzing, modeling, and mapping the timbre of sound
22 | % synthesizers" in proceedings of the 13th Sound and Music Computing Conference, Hamburg, Germany.
23 |
24 |
25 | %global variables
26 | matlab_osc_port=9001;
27 | max_osc_port=9002;
28 | max_ip_address='127.0.0.1';
29 | quit=0;
30 | function_id=0;
31 |
32 | fprintf('Starting TSAM Engine\n');
33 |
34 |
35 | %OSC client communication initialization
36 | MAXoscclient=udp(max_ip_address,max_osc_port);
37 | fopen(MAXoscclient);
38 | oscsend(MAXoscclient,'/status/run','i',1);
39 |
40 | %OSC server communication initialization
41 | MATLABoscserver=osc_new_server(matlab_osc_port);
42 |
43 | %{1}anamode {2}range {3}period {4}dim {5}merge {6}name {7}path
44 | cmpt_args=[];
45 | rt_args=[];
46 |
47 | a=[];
48 | while quit==0
49 |
50 |
51 |
52 | %receive OSC message
53 | oscrm=osc_recv(MATLABoscserver);
54 | %check message validity
55 | if ~isempty(oscrm)
56 | % process all messages in cue
57 | for m=1:length(oscrm)
58 | %route OSC data
59 | oscpath=oscrm{m}.path;
60 | oscdata=cell2mat(oscrm{m}.data);
61 | if (isequal(oscpath,'/cmd/quit'))
62 | quit=oscdata;
63 | elseif (isequal(oscpath,'/cmpt/funct'))
64 | function_id=oscdata; %id=1 mapping; id=2 score
65 | elseif (isequal(oscpath,'/cmpt/anamode'))
66 | cmpt_args{1}=oscdata;
67 | elseif (isequal(oscpath,'/cmpt/range'))
68 | cmpt_args{2}=oscdata;
69 | elseif (isequal(oscpath,'/cmpt/period'))
70 | cmpt_args{3}=oscdata;
71 | elseif (isequal(oscpath,'/cmpt/dim'))
72 | cmpt_args{4}=oscdata;
73 | elseif (isequal(oscpath,'/cmpt/merge'))
74 | cmpt_args{5}=oscdata;
75 | elseif (isequal(oscpath,'/cmpt/vcprst'))
76 | cmpt_args{6}=oscdata;
77 | elseif (isequal(oscpath,'/cmpt/name'))
78 | cmpt_args{7}=oscdata;
79 | elseif (isequal(oscpath,'/cmpt/path'))
80 | cmpt_args{8}=oscdata;
81 | elseif (isequal(oscpath,'/cmpt/manualdesc'))
82 | cmpt_args{9}=oscdata;
83 | elseif (isequal(oscpath,'/cmpt/mskvect'))
84 | cmpt_args{10}=oscdata;
85 | elseif (isequal(oscpath,'/cmpt/actfunc'))
86 | cmpt_args{11}=oscdata;
87 | elseif (isequal(oscpath,'/cmpt/dimred'))
88 | cmpt_args{12}=oscdata;
89 | elseif (isequal(oscpath,'/cmpt/descsel'))
90 | cmpt_args{13}=oscdata;
91 | elseif (isequal(oscpath,'/cmpt/sr'))
92 | cmpt_args{14}=oscdata;
93 | elseif (isequal(oscpath,'/cmpt/topdesc'))
94 | cmpt_args{15}=oscdata;
95 | elseif (isequal(oscpath,'/cmpt/run'))
96 | if function_id==1
97 | ComputeMapping(MAXoscclient,MATLABoscserver,cmpt_args);
98 | oscsend(MAXoscclient,'/status/cmpt/run','i',0);
99 | elseif function_id==2
100 | ComputeScore(MAXoscclient,MATLABoscserver,cmpt_args);
101 | oscsend(MAXoscclient,'/status/cmpt/run','i',0);
102 | else
103 | fprintf('TSAM-MAIN function id = %d not valid\n',function_id);
104 | end
105 | else
106 | fprintf('TSAM-MAIN message not valid: path = %s; data = %f \n',oscpath,oscdata);
107 | end
108 | end
109 | end
110 |
111 |
112 |
113 |
114 | end
115 |
116 |
117 | %OSC server communication termination
118 | osc_free_server(MATLABoscserver);
119 | %OSC client communication termination
120 | oscsend(MAXoscclient,'/status/run','i',0);
121 | fclose(MAXoscclient);
122 |
123 |
124 | fprintf('Terminating TSAM Engine\n');
125 |
126 |
--------------------------------------------------------------------------------
/MATLAB/distmeshnd_sfa.m:
--------------------------------------------------------------------------------
1 | function [p,t,maxdp]=distmeshnd_sfa(moviefile,fdist,fh,h,box,fix,varargin)
2 | %DISTMESHND N-D Mesh Generator using Distance Functions.
3 | % [P,T]=DISTMESHND(FDIST,FH,H,BOX,FIX,FDISTPARAMS)
4 | %
5 | % P: Node positions (NxNDIM)
6 | % T: Triangle indices (NTx(NDIM+1))
7 | % FDIST: Distance function
8 | % FH: Edge length function
9 | % H: Smallest edge length
10 | % BOX: Bounding box [xmin,xmax;ymin,ymax; ...] (NDIMx2)
11 | % FIX: Fixed node positions (NFIXxNDIM)
12 | % FDISTPARAMS: Additional parameters passed to FDIST
13 | %
14 | % Example: Unit ball
15 | % dim=3;
16 | % d=inline('sqrt(sum(p.^2,2))-1','p');
17 | % [p,t]=distmeshnd(d,@huniform,0.2,[-ones(1,dim);ones(1,dim)],[]);
18 | %
19 | % See also: DISTMESH2D, DELAUNAYN, TRIMESH, MESHDEMOND.
20 |
21 | % Copyright (C) 2004-2012 Per-Olof Persson. See COPYRIGHT.TXT for details.
22 |
23 |
24 | % The original file was modified for the integration with the
25 | % Timbre Space Analyzer and Mapper (TSAM).
26 | %
27 | % The TSAM is free software: you can redistribute it and/or modify
28 | % it under the terms of the GNU Lesser General Public License as published by
29 | % the Free Software Foundation, either version 3 of the License, or
30 | % (at your option) any later version.
31 | %
32 | % The TSAM is distributed in the hope that it will be useful,
33 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
34 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 | % GNU Less General Public License for more details.
36 | %
37 | % You should have received a copy of the GNU Lesser General Public License
38 | % along with TSAM. If not, see .
39 | %
40 | % The TSAM can be obtained at http://stefanofasciani.com/tsam.html
41 | % TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
42 | % Inquiries: stefanofasciani@stefanofasciani.com
43 |
44 |
45 |
46 |
47 | dim=size(box,2);
48 | ptol=.01; ttol=.1; L0mult=1+.4/2^(dim-1); deltat=.1; geps=1e-1*h; deps=sqrt(eps)*h;
49 | min_term=1000000000000000;
50 | term_check=0;
51 | framecount=1;
52 | % 1. Create initial distribution in bounding box
53 | if dim==1
54 | p=(box(1):h:box(2))';
55 | else
56 | cbox=cell(1,dim);
57 | for ii=1:dim
58 | cbox{ii}=box(1,ii):h:box(2,ii);
59 | end
60 | pp=cell(1,dim);
61 | [pp{:}]=ndgrid(cbox{:});
62 | p=zeros(prod(size(pp{1})),dim);
63 | for ii=1:dim
64 | p(:,ii)=pp{ii}(:);
65 | end
66 | end
67 |
68 | % 2. Remove points outside the region, apply the rejection method
69 | p=p(feval(fdist,p,varargin{:})ttol*h
79 | p0=p;
80 | t=delaunayn(p);
81 | pmid=zeros(size(t,1),dim);
82 | for ii=1:dim+1
83 | pmid=pmid+p(t(:,ii),:)/(dim+1);
84 | end
85 | t=t(feval(fdist,pmid,varargin{:})<-geps,:);
86 | % 4. Describe each edge by a unique pair of nodes
87 | pair=zeros(0,2);
88 | localpairs=nchoosek(1:dim+1,2);
89 | for ii=1:size(localpairs,1)
90 | pair=[pair;t(:,localpairs(ii,:))];
91 | end
92 | pair=unique(sort(pair,2),'rows');
93 | % 5. Graphical output of the current mesh
94 | if dim==2
95 | if mod(count,10)==0
96 | cla,patch('vertices',p,'faces',t,'edgecol','k','facecol',[0.9,0.9,0.9]);
97 | hold on
98 | scatter(p(:,1),p(:,2),10,[1 0.1 0.4]);
99 | hold off
100 | axis on
101 | axis([-0.1 1.1 -0.1 1.1]);
102 | drawnow
103 | movie(framecount)=getframe(gcf);
104 | framecount=framecount+1;
105 | end
106 | elseif dim==3
107 | if mod(count,20)==0
108 | simpplot(p,t,'p(:,2)>0');
109 | title(['Retriangulation #',int2str(count)])
110 | hold on
111 | scatter3(p(:,1),p(:,2),p(:,3),10,[1 0.1 0.4]);
112 | hold off
113 | axis on
114 | axis([-0.1 1.1 -0.1 1.1 -0.1 1.1]);
115 | drawnow
116 | movie(framecount)=getframe(gcf);
117 | framecount=framecount+1;
118 | end
119 | else
120 | disp(sprintf('Retriangulation #%d',count))
121 | end
122 | count=count+1;
123 | end
124 |
125 | % 6. Move mesh points based on edge lengths L and forces F
126 | bars=p(pair(:,1),:)-p(pair(:,2),:);
127 | L=sqrt(sum(bars.^2,2));
128 | L0=feval(fh,(p(pair(:,1),:)+p(pair(:,2),:))/2);
129 | L0=L0*L0mult*(sum(L.^dim)/sum(L0.^dim))^(1/dim);
130 | F=max(L0-L,0);
131 | Fbar=[bars,-bars].*repmat(F./L,1,2*dim);
132 | dp=full(sparse(pair(:,[ones(1,dim),2*ones(1,dim)]), ...
133 | ones(size(pair,1),1)*[1:dim,1:dim], ...
134 | Fbar,N,dim));
135 | p=p+deltat*dp;
136 |
137 | % 7. Bring outside points back to the boundary
138 | d=feval(fdist,p,varargin{:}); ix=d>0;
139 | gradd=zeros(sum(ix),dim);
140 | for ii=1:dim
141 | a=zeros(1,dim);
142 | a(ii)=deps;
143 | d1x=feval(fdist,p(ix,:)+ones(sum(ix),1)*a,varargin{:});
144 | gradd(:,ii)=(d1x-d(ix))/deps;
145 | end
146 | p(ix,:)=p(ix,:)-d(ix)*ones(1,dim).*gradd;
147 |
148 | % 8. Termination criterion
149 | maxdp=max(deltat*sqrt(sum(dp(d<-geps,:).^2,2)));
150 | treshold=ptol*h;
151 |
152 | if maxdp500
167 | break;
168 | end
169 |
170 | end
171 |
172 | end
173 |
174 | %%save movie to avi file
175 | %movie2avi(movie, moviefile, 'compression', 'None','fps',10);
176 |
177 |
--------------------------------------------------------------------------------
/MATLAB/elmMOD.m:
--------------------------------------------------------------------------------
1 | function [out_struct] = elmMOD(regr_in,regr_out,NumberofHiddenNeurons,ActivationFunction)
2 |
3 |
4 | %%%% Authors: MR QIN-YU ZHU AND DR GUANG-BIN HUANG
5 | %%%% NANYANG TECHNOLOGICAL UNIVERSITY, SINGAPORE
6 | %%%% EMAIL: EGBHUANG@NTU.EDU.SG; GBHUANG@IEEE.ORG
7 | %%%% WEBSITE: http://www.ntu.edu.sg/eee/icis/cv/egbhuang.htm
8 | %%%% DATE: APRIL 2004
9 |
10 |
11 |
12 | % The original file was modified for the integration with the
13 | % Timbre Space Analyzer and Mapper (TSAM).
14 | %
15 | % The TSAM is free software: you can redistribute it and/or modify
16 | % it under the terms of the GNU Lesser General Public License as published by
17 | % the Free Software Foundation, either version 3 of the License, or
18 | % (at your option) any later version.
19 | %
20 | % The TSAM is distributed in the hope that it will be useful,
21 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
22 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 | % GNU Less General Public License for more details.
24 | %
25 | % You should have received a copy of the GNU Lesser General Public License
26 | % along with TSAM. If not, see .
27 | %
28 | % The TSAM can be obtained at http://stefanofasciani.com/tsam.html
29 | % TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
30 | % Inquiries: stefanofasciani@stefanofasciani.com
31 |
32 |
33 | %%%%%%%%%%% Load training dataset
34 | T=regr_out;
35 | P=regr_in;
36 | clear train_data; % Release raw training data array
37 |
38 | NumberofTrainingData=size(P,2);
39 | NumberofInputNeurons=size(P,1); % end if of Elm_Type
40 |
41 | %%%%%%%%%%% Random generate input weights InputWeight (w_i) and biases BiasofHiddenNeurons (b_i) of hidden neurons
42 | InputWeight=rand(NumberofHiddenNeurons,NumberofInputNeurons)*2-1;
43 | BiasofHiddenNeurons=rand(NumberofHiddenNeurons,1);
44 | tempH=InputWeight*P;
45 | clear P; % Release input of training data
46 | ind=ones(1,NumberofTrainingData);
47 | BiasMatrix=BiasofHiddenNeurons(:,ind); % Extend the bias matrix BiasofHiddenNeurons to match the demention of H
48 | tempH=tempH+BiasMatrix;
49 |
50 | %%%%%%%%%%% Calculate hidden neuron output matrix H
51 | switch lower(ActivationFunction)
52 | case {'sig','sigmoid'}
53 | %%%%%%%% Sigmoid
54 | H = 1 ./ (1 + exp(-tempH));
55 | case {'sin','sine'}
56 | %%%%%%%% Sine
57 | H = sin(tempH);
58 | case {'hardlim'}
59 | %%%%%%%% Hard Limit
60 | %H_test = hardlim(tempH);
61 | H = double(tempH >= 0);
62 | case {'tribas'}
63 | %%%%%%%% Triangular basis function
64 | %H = tribas(tempH);
65 | H = max(0,1-abs(tempH));
66 | case {'radbas'}
67 | %%%%%%%% Radial basis function
68 | H = exp(-(tempH.*tempH));
69 | %%%%%%%% More activation functions can be added here
70 | end
71 | clear tempH; % Release the temparary array for calculation of hidden neuron output matrix H
72 |
73 | %%%%%%%%%%% Calculate output weights OutputWeight (beta_i)
74 | OutputWeight=pinv(H') * T'; % implementation without regularization factor //refer to 2006 Neurocomputing paper
75 |
76 | %%%%%%%%%%% Calculate the training accuracy
77 | Y=(H' * OutputWeight)'; % Y: the actual output of the training data
78 |
79 | TrainingAccuracy=sqrt(mse(T - Y)); % Calculate training accuracy (RMSE) for regression case
80 |
81 | clear H;
82 |
83 | out_struct.accuracy=TrainingAccuracy;
84 | out_struct.outweight=OutputWeight;
85 | out_struct.inweight=InputWeight;
86 | out_struct.bias=BiasofHiddenNeurons;
87 | out_struct.actfunct=ActivationFunction;
88 |
89 |
90 |
--------------------------------------------------------------------------------
/MATLAB/elmMODmap.m:
--------------------------------------------------------------------------------
1 | function [out] = elmMODmap(in,struct)
2 |
3 | %%%% Authors: MR QIN-YU ZHU AND DR GUANG-BIN HUANG
4 | %%%% NANYANG TECHNOLOGICAL UNIVERSITY, SINGAPORE
5 | %%%% EMAIL: EGBHUANG@NTU.EDU.SG; GBHUANG@IEEE.ORG
6 | %%%% WEBSITE: http://www.ntu.edu.sg/eee/icis/cv/egbhuang.htm
7 | %%%% DATE: APRIL 2004
8 |
9 |
10 | % The original file was modified for the integration with the
11 | % Timbre Space Analyzer and Mapper (TSAM).
12 | %
13 | % The TSAM is free software: you can redistribute it and/or modify
14 | % it under the terms of the GNU Lesser General Public License as published by
15 | % the Free Software Foundation, either version 3 of the License, or
16 | % (at your option) any later version.
17 | %
18 | % The TSAM is distributed in the hope that it will be useful,
19 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | % GNU Less General Public License for more details.
22 | %
23 | % You should have received a copy of the GNU Lesser General Public License
24 | % along with TSAM. If not, see .
25 | %
26 | % The TSAM can be obtained at http://stefanofasciani.com/tsam.html
27 | % TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
28 | % Inquiries: stefanofasciani@stefanofasciani.com
29 |
30 |
31 | tempH=struct.inweight*in'; % Extend the bias matrix BiasofHiddenNeurons to match the demention of H
32 | tempH=tempH + struct.bias;
33 | switch lower(struct.actfunct)
34 | case {'sig','sigmoid'}
35 | %%%%%%%% Sigmoid
36 | H_test = 1 ./ (1 + exp(-tempH));
37 | case {'sin','sine'}
38 | %%%%%%%% Sine
39 | H_test = sin(tempH);
40 | case {'hardlim'}
41 | %%%%%%%% Hard Limit
42 | %H_test = hardlim(tempH);
43 | H_test = double(tempH >= 0);
44 | case {'tribas'}
45 | %%%%%%%% Triangular basis function
46 | %H_test = tribas(tempH);
47 | H_test = max(0,1-abs(tempH));
48 | case {'radbas'}
49 | %%%%%%%% Radial basis function
50 | %H_test = radbas(tempH);
51 | H_test = exp(-(tempH.*tempH));
52 | %%%%%%%% More activation functions can be added here
53 | end
54 | out=(H_test' * struct.outweight)'; % TY: the actual output of the testing data
55 |
--------------------------------------------------------------------------------
/MATLAB/oscsend.m:
--------------------------------------------------------------------------------
1 | function oscsend(u,path,varargin)
2 | % Sends a Open Sound Control (OSC) message through a UDP connection
3 | %
4 | % oscsend(u,path)
5 | % oscsend(u,path,types,arg1,arg2,...)
6 | % oscsedn(u,path,types,[args])
7 | %
8 | % u = UDP object with open connection.
9 | % path = path-string
10 | % types = string with types of arguments,
11 | % supported:
12 | % i = integer
13 | % f = float
14 | % s = string
15 | % N = Null (ignores corresponding argument)
16 | % I = Impulse (ignores corresponding argument)
17 | % T = True (ignores corresponding argument)
18 | % F = False (ignores corresponding argument)
19 | % B = boolean (not official: converts argument to T/F in the type)
20 | % not supported:
21 | % b = blob
22 | %
23 | % args = arguments as specified by types.
24 | %
25 | % EXAMPLE
26 | % u = udp('127.0.0.1',7488);
27 | % fopen(u);
28 | % oscsend(u,'/test','ifsINBTF', 1, 3.14, 'hello',[],[],false,[],[]);
29 | % fclose(u);
30 | %
31 | % See http://opensoundcontrol.org/ for more information about OSC.
32 |
33 | % MARK MARIJNISSEN 10 may 2011 (markmarijnissen@gmail.com)
34 |
35 |
36 |
37 | % The original file was modified for the integration with the
38 | % Timbre Space Analyzer and Mapper (TSAM).
39 | %
40 | % The TSAM is free software: you can redistribute it and/or modify
41 | % it under the terms of the GNU Lesser General Public License as published by
42 | % the Free Software Foundation, either version 3 of the License, or
43 | % (at your option) any later version.
44 | %
45 | % The TSAM is distributed in the hope that it will be useful,
46 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
47 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 | % GNU Less General Public License for more details.
49 | %
50 | % You should have received a copy of the GNU Lesser General Public License
51 | % along with TSAM. If not, see .
52 | %
53 | % The TSAM can be obtained at http://stefanofasciani.com/tsam.html
54 | % TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
55 | % Inquiries: stefanofasciani@stefanofasciani.com
56 |
57 |
58 |
59 | %figure out little endian for int/float conversion
60 | [~, ~, endian] = computer;
61 | littleEndian = endian == 'L';
62 |
63 | % set type
64 | if nargin >= 3,
65 | types = oscstr([',' varargin{1}]);
66 | else
67 | types = oscstr(',');
68 | end;
69 |
70 | % set args (either a matrix, or varargin)
71 | if nargin == 3 && length(types) > 2
72 | args = varargin{2};
73 | else
74 | args = varargin(2:end);
75 | end;
76 |
77 | % convert arguments to the right bytes
78 | data = [];
79 | for i=1:length(args)
80 | switch(types(i+1))
81 | case 'i'
82 | data = [data oscint(args{i},littleEndian)];
83 | case 'f'
84 | data = [data oscfloat(args{i},littleEndian)];
85 | case 's'
86 | data = [data oscstr(args{i})];
87 | case 'B'
88 | if args{i}
89 | types(i+1) = 'T';
90 | else
91 | types(i+1) = 'F';
92 | end;
93 | case {'N','I','T','F'}
94 | %ignore data
95 | otherwise
96 | warning(['Unsupported type: ' types(i+1)]);
97 | end;
98 | end;
99 |
100 | %write data to UDP
101 | data = [oscstr(path) types data];
102 | fwrite(u,data);
103 | end
104 |
105 | %Conversion from double to float
106 | function float = oscfloat(float,littleEndian)
107 | if littleEndian
108 | float = typecast(swapbytes(single(float)),'uint8');
109 | else
110 | float = typecast(single(float),'uint8');
111 | end;
112 | end
113 |
114 | %Conversion to int
115 | function int = oscint(int,littleEndian)
116 | if littleEndian
117 | int = typecast(swapbytes(int32(int)),'uint8');
118 | else
119 | int = typecast(int32(int),'uint8');
120 | end;
121 | end
122 |
123 | %Conversion to string (null-terminated, in multiples of 4 bytes)
124 | function string = oscstr(string)
125 | string = [string 0 0 0 0];
126 | string = string(1:end-mod(length(string),4));
127 | end
--------------------------------------------------------------------------------
/MATLAB/period_detection.m:
--------------------------------------------------------------------------------
1 | function [period_hz] = period_detection(window,hop,d,sr)
2 |
3 | % This file is part of the Timbre Space Analyzer & Mapper (TSAM)
4 | %
5 | % The TSAM can be obtained at http://stefanofasciani.com/tsam.html
6 | % TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
7 | % Inquiries: stefanofasciani@stefanofasciani.com
8 | %
9 | % The TSAM is free software: you can redistribute it and/or modify it under the terms
10 | % of the GNU Lesser General Public License as published by the Free Software Foundation,
11 | % either version 3 of the License, or (at your option) any later version.
12 | %
13 | % The TSAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
14 | % without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 | % See the GNU Less General Public License for more details.
16 | %
17 | % You should have received a copy of the GNU Lesser General Public License along with TSAM.
18 | % If not, see .
19 | %
20 | % If you use the TSAM or any part of it in any program or publication, please acknowledge
21 | % its authors by adding a reference to this pubblication:
22 | %
23 | % S. Fasciani, 2016, "TSAM: a tool for analyzing, modeling, and mapping the timbre of sound
24 | % synthesizers" in proceedings of the 13th Sound and Music Computing Conference, Hamburg, Germany.
25 |
26 |
27 | period_hz=zeros(1,size(d,2));
28 |
29 | for i=1:size(d,2)
30 |
31 | temp=d(:,i);
32 | temp=temp-max(temp);
33 | fil_out=filter(((window)/sr), [1 ((window)/sr)-1], temp);
34 | autocx=xcorr(fil_out,size(d,1),'coeff');
35 | [pk_loc,pk_val]=findpeaks(autocx(1:size(d,1)));
36 | pk_val(pk_val==1)=0;
37 | [~,idx]=max(pk_val);
38 | pk_loc=pk_loc(idx);
39 | if ~isempty(pk_loc)
40 | period_smp=((size(d,1)-pk_loc+2)*hop);
41 | period_time=(period_smp/sr);
42 | period_hz(i)=(1.0/period_time);
43 | else
44 | period_hz(i)=0;
45 | end
46 |
47 | end
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/MATLAB/relative_mean_difference.m:
--------------------------------------------------------------------------------
1 | function[relmeandiff]=relative_mean_difference(in)
2 |
3 | % This file is part of the Timbre Space Analyzer & Mapper (TSAM)
4 | %
5 | % The TSAM can be obtained at http://stefanofasciani.com/tsam.html
6 | % TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
7 | % Inquiries: stefanofasciani@stefanofasciani.com
8 | %
9 | % The TSAM is free software: you can redistribute it and/or modify it under the terms
10 | % of the GNU Lesser General Public License as published by the Free Software Foundation,
11 | % either version 3 of the License, or (at your option) any later version.
12 | %
13 | % The TSAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
14 | % without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 | % See the GNU Less General Public License for more details.
16 | %
17 | % You should have received a copy of the GNU Lesser General Public License along with TSAM.
18 | % If not, see .
19 | %
20 | % If you use the TSAM or any part of it in any program or publication, please acknowledge
21 | % its authors by adding a reference to this pubblication:
22 | %
23 | % S. Fasciani, 2016, "TSAM: a tool for analyzing, modeling, and mapping the timbre of sound
24 | % synthesizers" in proceedings of the 13th Sound and Music Computing Conference, Hamburg, Germany.
25 |
26 |
27 | relmeandiff=zeros(size(in,1),1);
28 | n=size(in,2);
29 |
30 | for i=1:n
31 | for j=1:n
32 | relmeandiff=relmeandiff+(abs(in(:,i)-in(:,j)));
33 | end
34 | end
35 |
36 | relmeandiff=(relmeandiff./(n*(n-1).*abs(mean(in,2))));
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/MATLAB/unique_sfast.m:
--------------------------------------------------------------------------------
1 | function [b,ndx,pos] = unique_sfast(a,flag1,flag2)
2 | %UNIQUE Set unique.
3 | % B = UNIQUE(A) for the array A returns the same values as in A but
4 | % with no repetitions. B will also be sorted. A can be a cell array of
5 | % strings.
6 | %
7 | % UNIQUE(A,'rows') for the matrix A returns the unique rows of A.
8 | %
9 | % [B,I,J] = UNIQUE(...) also returns index vectors I and J such
10 | % that B = A(I) and A = B(J) (or B = A(I,:) and A = B(J,:)).
11 | %
12 | % [B,I,J] = UNIQUE(...,'first') returns the vector I to index the
13 | % first occurrence of each unique value in A. UNIQUE(...,'last'),
14 | % the default, returns the vector I to index the last occurrence.
15 | %
16 | % See also UNION, INTERSECT, SETDIFF, SETXOR, ISMEMBER, SORT, ISSORTED.
17 |
18 | % Copyright 1984-2009 The MathWorks, Inc.
19 | % $Revision: 1.24.4.9 $ $Date: 2010/08/23 23:11:33 $
20 |
21 | % Cell array implementation in @cell/unique.m
22 |
23 |
24 | % The original file was modified for the integration with the
25 | % Timbre Space Analyzer and Mapper (TSAM).
26 | %
27 | % The TSAM is free software: you can redistribute it and/or modify
28 | % it under the terms of the GNU Lesser General Public License as published by
29 | % the Free Software Foundation, either version 3 of the License, or
30 | % (at your option) any later version.
31 | %
32 | % The TSAM is distributed in the hope that it will be useful,
33 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
34 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 | % GNU Less General Public License for more details.
36 | %
37 | % You should have received a copy of the GNU Lesser General Public License
38 | % along with TSAM. If not, see .
39 | %
40 | % The TSAM can be obtained at http://stefanofasciani.com/tsam.html
41 | % TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
42 | % Inquiries: stefanofasciani@stefanofasciani.com
43 |
44 |
45 | flagvals = {'rows' 'first' 'last'};
46 | if nargin > 1
47 | options = strcmpi(flag1,flagvals);
48 | if nargin > 2
49 | options = options + strcmpi(flag2,flagvals);
50 | if any(options > 1) || (options(2)+options(3) > 1)
51 | error(message('MATLAB:UNIQUE:RepeatedFlag'));
52 | end
53 | end
54 | if sum(options) < nargin-1
55 | error(message('MATLAB:UNIQUE:UnknownFlag'));
56 | end
57 | byrow = (options(1) > 0);
58 | if options(2) > 0
59 | order = 'first';
60 | else % if options(3) > 0 || sum(options(2:3) == 0)
61 | order = 'last';
62 | end
63 | elseif nargin == 1
64 | byrow = false;
65 | order = 'last';
66 | else
67 | error(message('MATLAB:UNIQUE:NotEnoughInputs'));
68 | end
69 |
70 | rows = size(a,1);
71 | cols = size(a,2);
72 |
73 | rowvec = (rows == 1) && (cols > 1);
74 |
75 | numelA = numel(a);
76 | nOut = nargout;
77 |
78 | if ~isa(a,'opaque')
79 |
80 | if ~byrow
81 |
82 | % Handle empty: no elements.
83 |
84 | if (numelA == 0)
85 | % Predefine b to be of the correct type.
86 | b = a([]);
87 | if max(size(a)) > 0
88 | b = reshape(b,0,1);
89 | ndx = zeros(0,1);
90 | pos = zeros(0,1);
91 | else
92 | ndx = [];
93 | pos = [];
94 | end
95 | return
96 |
97 | elseif (numelA == 1)
98 | % Scalar A: return the existing value of A.
99 | b = a; ndx = 1; pos = 1;
100 | return
101 |
102 | % General handling.
103 | else
104 |
105 | % Convert to columns
106 | a = a(:);
107 |
108 | % Convert to double array for purposes of faster sorting.
109 | % Additionally, UNIQUE calls DIFF, which requires double input.
110 |
111 | whichclass = class(a);
112 | isdouble = strcmp(whichclass,'double');
113 |
114 | if ~isdouble
115 | a = double(a);
116 | end
117 |
118 | % Sort if unsorted. Only check this for long lists.
119 |
120 | checksortcut = 1000;
121 |
122 | if numelA <= checksortcut || ~(issorted(a))
123 | if nOut <= 1
124 | b = sort(a);
125 | else
126 | [b,ndx] = sort(a);
127 | end
128 | else
129 | b = a;
130 | if nOut > 1
131 | ndx = (1:numelA)'; % If presorted, indices are 1,2,3,...
132 | end
133 | end
134 |
135 | % d indicates the location of non-matching entries.
136 |
137 | db = diff(b);
138 |
139 | % Since DIFF returns NaN in both Inf and NaN cases,
140 | % use slower method of detection if NaN's detected in DIFF(b).
141 | % After sort, Infs or NaNs will be at ends of list only.
142 |
143 | if (isnan(db(1)) || isnan(db(numelA-1)))
144 | d = b(1:numelA-1) ~= b(2:numelA);
145 | else
146 | d = db ~= 0;
147 | end
148 |
149 | if order(1) == 'l' % 'last'
150 | d(numelA,1) = true; % Final element is always a member of unique list.
151 | else % order == 'first'
152 | d = [true; d]; % First element is always a member of unique list.
153 | end
154 |
155 | b = b(d); % Create unique list by indexing into sorted list.
156 |
157 | if nOut == 3
158 | if order(1) == 'l' % 'last'
159 | pos = cumsum([1;full(d)]); % Lists position, starting at 1.
160 | pos(numelA+1) = []; % Remove extra element introduced by d.
161 | else % order == 'first'
162 | pos = cumsum(full(d)); % Lists position, starting at 1.
163 | end
164 | pos(ndx) = pos; % Re-reference POS to indexing of SORT.
165 | end
166 |
167 | % Create indices if needed.
168 | if nOut > 1
169 | ndx = ndx(d);
170 | end
171 |
172 | % Re-convert to correct output data type using FEVAL.
173 | if ~isdouble
174 | b = feval(whichclass,b);
175 | end
176 | end
177 |
178 | % If row vector, return as row vector.
179 | if rowvec
180 | b = b.';
181 | if nOut > 1
182 | ndx = ndx.';
183 | if nOut > 2
184 | pos = pos.';
185 | end
186 | end
187 | end
188 |
189 | else % 'rows' case
190 |
191 | % Handle empty: no rows.
192 |
193 | if (rows == 0)
194 | % Predefine b to be of the correct type.
195 | b = a([]);
196 | ndx = [];
197 | pos = [];
198 | b = reshape(b,0,cols);
199 | if cols > 0
200 | ndx = reshape(ndx,0,1);
201 | end
202 | return
203 |
204 | % Handle scalar: one row.
205 |
206 | elseif (rows == 1)
207 | b = a; ndx = 1; pos = 1;
208 | return
209 | end
210 |
211 | % General handling.
212 | % Conversion to double not done: SORTROWS is slower for doubles
213 | % than other types.
214 |
215 | if nOut > 1
216 | [b,ndx] = sortrows(a);
217 | else
218 | bbb = sortrows(a);
219 | [~,srtidx]=sort(a(:,1));
220 | b = a(srtidx,:);
221 |
222 | end
223 |
224 | % d indicates the location of non-matching entries.
225 |
226 | d = b(1:rows-1,:)~=b(2:rows,:);
227 |
228 | % d = 1 if differences between rows. d = 0 if the rows are equal.
229 |
230 | d = any(d,2);
231 | if order(1) == 'l' % 'last'
232 | d(rows,1) = true; % Final row is always member of unique list.
233 | else % order = 'first'
234 | d = [true; d]; % First row is always a member of unique list.
235 | end
236 |
237 | b = b(d,:); % Create unique list by indexing into sorted list.
238 |
239 | % Create position mapping vector using CUMSUM.
240 |
241 | if nOut == 3
242 | if order(1) == 'l' % 'last'
243 | pos = cumsum([1;full(d)]); % Lists position, starting at 1.
244 | pos(rows+1) = []; % Remove extra element introduced by d.
245 | else % order == 'first'
246 | pos = cumsum(full(d)); % Lists position, starting at 1.
247 | end
248 | pos(ndx) = pos; % Re-reference POS to indexing of SORT.
249 | end
250 |
251 | % Create indices if needed.
252 | if nOut > 1
253 | ndx = ndx(d);
254 | end
255 | end
256 |
257 | else
258 | % Handle objects that cannot be converted to doubles
259 | if ~byrow
260 |
261 | % Handle empty: no elements.
262 |
263 | if (numelA == 0)
264 | % Predefine b to be of the correct type.
265 | b = a([]);
266 | if max(size(a)) > 0
267 | b = reshape(b,0,1);
268 | ndx = zeros(0,1);
269 | pos = zeros(0,1);
270 | else
271 | ndx = [];
272 | pos = [];
273 | end
274 | return
275 |
276 | elseif (numelA == 1)
277 | % Scalar A: return the existing value of A.
278 | b = a; ndx = 1; pos = 1;
279 | return
280 |
281 | % General handling.
282 | else
283 |
284 | % Convert to columns
285 | a = a(:);
286 |
287 | % Sort if unsorted. Only check this for long lists.
288 |
289 | if nOut <= 1
290 | b = sort(a);
291 | else
292 | [b,ndx] = sort(a);
293 | end
294 |
295 | % d indicates the location of non-matching entries.
296 |
297 | d = b(1:numelA-1) ~= b(2:numelA);
298 |
299 | if order(1) == 'l' % 'last'
300 | d(numelA,1) = true; % Final element is always a member of unique list.
301 | else % order == 'first'
302 | d = [true; d]; % First element is always a member of unique list.
303 | end
304 |
305 | b = b(d); % Create unique list by indexing into sorted list.
306 |
307 | if nOut == 3
308 | if order(1) == 'l' % 'last'
309 | pos = cumsum([1;d]); % Lists position, starting at 1.
310 | pos(numelA+1) = []; % Remove extra element introduced by d.
311 | else % order == 'first'
312 | pos = cumsum(d); % Lists position, starting at 1.
313 | end
314 | pos(ndx) = pos; % Re-reference POS to indexing of SORT.
315 | end
316 |
317 | % Create indices if needed.
318 | if nOut > 1
319 | ndx = ndx(d);
320 | end
321 | end
322 |
323 | % If row vector, return as row vector.
324 | if rowvec
325 | b = b.';
326 | if nOut > 1
327 | ndx = ndx.';
328 | if nOut > 2
329 | pos = pos.';
330 | end
331 | end
332 | end
333 |
334 | else % 'rows' case
335 |
336 | % Handle empty: no rows.
337 |
338 | if (rows == 0)
339 | % Predefine b to be of the correct type.
340 | b = a([]);
341 | ndx = [];
342 | pos = [];
343 | b = reshape(b,0,cols);
344 | if cols > 0
345 | ndx = reshape(ndx,0,1);
346 | end
347 | return
348 |
349 | % Handle scalar: one row.
350 |
351 | elseif (rows == 1)
352 | b = a; ndx = 1; pos = 1;
353 | return
354 | end
355 |
356 | % General handling.
357 |
358 | if nOut > 1
359 | [b,ndx] = sortrows(a);
360 | else
361 | b = sortrows(a);
362 | end
363 |
364 | % d indicates the location of non-matching entries.
365 |
366 | d = b(1:rows-1,:)~=b(2:rows,:);
367 |
368 | % d = 1 if differences between rows. d = 0 if the rows are equal.
369 |
370 | d = any(d,2);
371 | if order(1) == 'l' % 'last'
372 | d(rows,1) = true; % Final row is always member of unique list.
373 | else % order == 'first'
374 | d = [true; d]; % First row is always a member of unique list.
375 | end
376 |
377 | b = b(d,:); % Create unique list by indexing into sorted list.
378 |
379 | % Create position mapping vector using CUMSUM.
380 |
381 | if nOut == 3
382 | pos = cumsum([1;d]); % Lists position, starting at 1.
383 | pos(rows+1) = []; % Remove extra element introduced by d.
384 | pos(ndx) = pos; % Re-reference POS to indexing of SORT.
385 | end
386 |
387 | % Create indices if needed.
388 | if nOut > 1
389 | ndx = ndx(d);
390 | end
391 | end
392 | end
393 |
--------------------------------------------------------------------------------
/Max/TSAM.maxpat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanofasciani/TSAM/502b29feb48a85b51c469e699e11993e6de592fb/Max/TSAM.maxpat
--------------------------------------------------------------------------------
/Max/TSAM_3DOGL.maxpat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanofasciani/TSAM/502b29feb48a85b51c469e699e11993e6de592fb/Max/TSAM_3DOGL.maxpat
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | =======================================
3 | TSAM - Timbre Space Analyzer and Mapper
4 | =======================================
5 |
6 | ==============================================================================
7 |
8 | The Timbre Space Analyzer & Mapper (TSAM) is a collection of MAX patches
9 | and MATLAB functions for the analysis, modeling and controlling of the
10 | timbre of sound synthesizers.
11 | The TSAM can be obtained at http://stefanofasciani.com/tsam.html
12 | TSAM Copyright (C) 2016 Stefano Fasciani, University of Wollongong
13 | Inquiries: stefanofasciani@stefanofasciani.com
14 |
15 | ==============================================================================
16 |
17 |
18 | ============
19 | REQUIREMENTS
20 | ============
21 |
22 | The TSAM is implemented in Cycling '74 Max 7 and MATLAB (OSX only).
23 |
24 | The TSAM has been developed and tested on the following platform:
25 | OSX 10.7.5
26 | MAX 7.2.4 (32-bit)
27 | MATLAB 7.12.0 (R2011a)
28 |
29 |
30 | The following Cycling '74 Max 7 libraries are required:
31 | (download the externals and include these in your Max path)
32 |
33 | - FTM http://ftm.ircam.fr/index.php/Main_Page
34 | - SFA-MaxLib http://stefanofasciani.com/?p=865
35 | - CNMAT Max/MSP Externals (Opensoundcontrol and OSC-route only)http://cnmat.berkeley.edu/downloads
36 | - Max Sound Box (ircamdescriptor~.mxo only) http://forumnet.ircam.fr/product/max-sound-box-en/
37 |
38 |
39 | The following MATLAB libraries/toolboxes are required :
40 | (download the files.m and include these in your MATLAB path)
41 |
42 | - Instrument Control Toolbox http://www.mathworks.com/products/instrument/
43 | - Statistics and Machine Learning Toolbox http://www.mathworks.com/products/statistics/
44 | - Signal Processing Toolbox ttp://www.mathworks.com/products/signal/
45 |
46 | ============
47 | INSTRUCTIONS
48 | ============
49 |
50 | The TSAM.maxpat and TSAM_3DOGL.maxpat are equivalent. The only difference is in the timbre space visualization.
51 | The TSAM.maxpat provides a 2D timbre space visualization, which is less CPU demanding.
52 | The TSAM_3DOGL.maxpat provides a 3D timbre space visualization (OpenGL), which is more CPU demanding.
53 | Both TSAM.maxpat and TSAM_3DOGL.maxpat provides 2D and 3D mapping capabilities.
54 |
55 | Run the TSAM.maxpat (or TSAM_3DOGL.maxpat) and run the TSAM.m script in MATLAB.
56 | The TSAM.m script communicates with the TSAM.maxpat via OSC.
57 | To terminate the TSAM.m push the "Stop Engine" button in the TSAM.maxpat main tab.
58 | When TSAM.m is running "Engine Stopped" changes state to "Engine Running".
59 | The TSAM.maxpat request to the TSAM.m sctipt the mapping computation and scoe computation
60 | (only when pressing the buttons "Compute Mapping" and "Compute Score" in the TSAM.maxpat main tab.
61 | For any other operation the TSAM.maxpat do not require the TSAM.m to run in background (e.g. for analysis
62 | or real time mapping).
63 |
64 | In MATLAB you can compile the TSAM.m into a matlab executable and run it from the terminal.
65 | To compile in MATLAB use the command below.
66 |
67 | mcc -m -v -I full_path_to_TSAM_MATLAB_folder -o compiled full_path_to_TSAM_MATLAB_folder/TSAM.m
68 |
69 | Matlab will generate automatically a shell script run_compiled.sh, then you can run the TSAM.m runing
70 | sudo run_compiled.sh from the terminal (you need superuser credentials)
71 |
72 |
--------------------------------------------------------------------------------