changeset 47:82075c94eed1

adding a bunch of stuff, including graphics and pitch toolboxes.
author samer
date Sat, 17 Jan 2015 15:20:35 +0000
parents 63cefb01cbab
children a12a6902f23e
files arrows/stats/stats_pca_cell.m dsp/bin2freq.m graphics/.DS_Store graphics/animseq.m graphics/colour/bipolarjoin.m graphics/colour/desat.m graphics/colour/dullify.m graphics/colour/hsvx.m graphics/colour/luminocity.m graphics/colour/rgbmap.m graphics/colour/setcolours.m graphics/colour/setuicolours.m graphics/extend_ctxmenu.m graphics/imagepx.m graphics/imagexy.m graphics/lglg.m graphics/lin.m graphics/noticks.m graphics/panzoom.m graphics/plotseq.m graphics/scat.m graphics/scatc.m graphics/scatui.m graphics/semilgx.m graphics/semilgy.m graphics/set_ctxmenu.m graphics/tfdimage.m graphics/tfscale.m graphics/xaxis.m graphics/xticks.m graphics/yaxis.m graphics/yticks.m pitch/chromatic.m pitch/harmminor.m pitch/hz2pc.m pitch/hz2pitch.m pitch/imajor.m pitch/iminor.m pitch/ipenta.m pitch/ivals2pitches.m pitch/lp_major.m pitch/lp_minor.m pitch/major.m pitch/melminor.m pitch/minor.m pitch/pentatonic.m pitch/pitch2hz.m pitch/pitch2name.m pitch/trans_china_major.m pitch/trans_china_minor.m pitch/trans_euro_major.m pitch/trans_euro_minor.m pitch/trans_major17.m
diffstat 53 files changed, 760 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/arrows/stats/stats_pca_cell.m	Sat Jan 17 14:13:07 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-function o=astats_pca_cell(I)
-	o=arr(@stats_pca);
-	function pca=stats_pca(stats)
-		if iscell(stats)
-			m1=mstep(stats);
-			[V,D]=eig(m1.cov);
-			J=(1+size(D,1))-I;
-			pca.eigvecs=V(:,J);
-			pca.eigvals=diag(D);
-			pca.eigvals=pca.eigvals(J);
-			pca.mean=m1.mu;
-		else
-			pca.dummy=1;
-		end
-	end
-	function M=mstep(S)
-		M.mu=S{2}/S{1};
-		M.cov=msym(S{3}/S{1} - M.mu*M.mu'); 
-	end
-
-	function M=mstep_z(S)
-		M.mu=zeros(size(S{3},1),1);
-		M.cov=S{3}/S{2}; 
-	end
-
-	function A=msym(X), A=(X+X')/2; end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dsp/bin2freq.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,9 @@
+function f=bin2freq(k,N,fs)
+% K2F: convert DFT freq bin to freq in Hz
+%
+% f=bin2freq(k,N,fs):
+% k:	index of frequency bin in DFT
+% N:	frame size of FT
+% fs: sampling frequency
+
+f=k*fs/N;
Binary file graphics/.DS_Store has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/animseq.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,40 @@
+function varargout=animdata(upd,X,varargin)
+% animdata - use arbitrary function to animate data sequence
+%
+% animdata :: 
+%    A->unit   ~'function to update animation',
+%    seq A     ~'data sequence to plot',
+%    options {
+%       pre   :: action / @nop ~'called before each plot';
+%       post  :: action / @nop ~'called after eacn plot';
+%       defer :: bool   / 0    ~'if 1, just return state transformer function';
+%       fps   :: nonneg / 0    ~'if positive, used timed iterator at this rate'
+%    }
+% -> (A->A,handle) ~'action to iterate',
+%    A             ~'initial state'.
+
+
+
+	opts=prefs('fps',0,'pre',@nop,'post',@nop,'defer',0,varargin{:});
+
+	if opts.defer, 
+		stfn=@plotnext_h; 
+	elseif opts.fps>0
+		stfn=@plotnext; 
+		API=iterate_timed(stfn,X,1/opts.fps,opts); 
+		if nargout==1, varargout{1}=API; end
+	else
+		stfn=@plotnext; 
+		iterate(stfn,X,opts); 
+		if nargout==1, varargout{1}={stfn,X}; else varargout={stfn,X}; end
+	end
+
+
+	function S=plotnext(S), upd(head(S)); S=next(S); end
+	function [S,h]=plotnext_h(S),
+		upd(head(S)); S=next(S);
+		if nargout>1, h=get(gca,'title'); end
+	end
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/colour/bipolarjoin.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,10 @@
+function c=bipolarjoin(a,b)
+% BIPOLARJOIN - Create bipolar colormap ('black' in the middle) by joining two maps
+%
+% map=bipolarjoin(neg,pos) - return colourmap [flipud(neg); pos]
+% ie colormap neg is reversed. If no output argument specified, colormap is 
+% installed in current figure.
+if size(a,1)~=size(b,1), error('Colormaps must be of same length'); end
+
+out=[flipud(a); b];
+if nargout<1, colormap(out); else c=out; end;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/colour/desat.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,14 @@
+function D=desat(C,s)
+% desat(C,s)
+% desaturate colormap - moves all colours towards
+% a grey of roughly equivalent brightness
+% C - colourmap (N by 3 matrix)
+% s - saturation: 1 no change, 0 completely grey
+
+% this matrix transforms to grey
+G=[0.3 0.5 0.2]'*[1 1 1];
+D=s*C + (1-s)*C*G;
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/colour/dullify.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,12 @@
+function D=contrast(C,s)
+% contrast(C,s)
+% adjust contrast of colourmap - moves all 
+% colours towards a medium grey.
+% C - colourmap (N by 3 matrix)
+% s - contrast: 1 no change, 0 completely grey
+
+D=s*C + (1-s)*0.5*ones(size(C));
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/colour/hsvx.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,24 @@
+% hsvx - HSV colour map with extended functionality
+%
+% hsvx :: N:natural -> [[N,3]] ~'same as hsv'.
+%
+% hsvx :: 
+%    N:natural ~'size of colormap to return', 
+%    0--1 ~'inital hue', 
+%    0--1 ~'saturation', 
+%    0--1 ~'value' 
+%    options {
+%       brightness :: bool/0 ~'try to get even perceptual brightness'
+%    }
+% -> [[N,3]].
+
+function M=hsvx(N,H0,S,V,varargin)
+
+	if nargin<2, H0=0; end
+	if nargin<3, S=1; end
+	if nargin<4, V=1; end
+
+	H=linspace(H0,H0+1,N+1);
+	M=hsv2rgb([mod(H(1:end-1),1)',repmat([S,V],N,1)]);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/colour/luminocity.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,7 @@
+function L=luminocity(C)
+% luminocity - Compute perceived brightness of colours
+%
+% luminocity :: [[N,3]] -> [[N]].
+
+if size(C,2)~=3 && size(C,1)==3, C=C'; end
+L=C*[.298936021 .58704307445 .114020904255]';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/colour/rgbmap.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,16 @@
+function clut=rgbmap(r,g,b)
+
+% rgbmap(r,g,b)
+% returns rgb colour map of size r*g*b
+R=[1 0 0]/(r-1);
+G=[0 1 0]/(g-1);
+B=[0 0 1]/(b-1);
+
+clut=zeros(r*g*b,3);
+for i=0:r-1
+	for j=0:g-1
+		for k=0:b-1
+			clut(1+k+(j+i*g)*b,:)=k*B+j*G+i*R;
+		end
+	end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/colour/setcolours.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,17 @@
+function setcolours(bg,fg)
+% setcolours - set default foreground and background colours for figures
+%
+% setcolours :: colour ~'background', colour ~'foreground' -> action.
+%
+% colour ::= [[1,3]] | {'k','r','g','b','c','m','y','w'}.
+%
+% Background colour is applied to figure and axes background.
+% Foreground colour is applied to axes lines and labels.
+
+set(0, ...
+	'DefaultAxesColor',bg, ...
+	'DefaultFigureColor',bg, ...
+	'DefaultTextColor',fg, ...
+	'DefaultAxesxColor',fg, ...
+	'DefaultAxesyColor',fg, ...
+	'DefaultAxeszColor',fg);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/colour/setuicolours.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,22 @@
+function setcolours(bg,fg,root)
+% setuicolours - set default foreground and background colours for UI elements
+%
+% setuicolours :: colour ~'background', colour ~'foreground' -> action.
+% setuicolours :: colour ~'background', colour ~'foreground', handle ~'root' -> action.
+%
+% colour ::= [[1,3]] | {'k','r','g','b','c','m','y','w'}.
+%
+% The 3-argument form takes the handle of the object to which properties will be attached.
+
+if nargin<3, root=0; end
+
+classes1={'Control','Panel'};
+classes2={'Container','FlowContainer','GridContainer'};
+
+set(root,'DefaultFigureColor',bg);
+foreach(@(c)set(root,dc(c,'Foreground'),fg,dc(c,'Background'),bg),classes1);
+foreach(@(c)set(root,dc(c,'Background'),bg),classes2);
+set(root,dc('Menu','Foreground'),fg);
+set(root,dc('Panel','Shadow'),0.7*bg,dc('Panel','Highlight'),min(1.3*bg,1));
+
+function p=dc(c,fb), p=['DefaultUI' c fb 'Color']; 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/extend_ctxmenu.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,16 @@
+function h=extend_ctxmenu(parent,commands,varargin)
+	opts=prefs(varargin{:});
+	h=get(parent,'UIContextMenu');
+	if isempty(h), 
+		h=uicontextmenu; 
+		set(parent,'UIContextMenu',h);
+	end
+
+	foreach(@(cmd)add_to_menu(h,cmd),commands);
+end
+
+function h=add_to_menu(menu,cmd)
+	h=uimenu('Parent',menu,'Label',cmd{1},'Callback',cmd{2});
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/imagepx.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,12 @@
+function H=imagepx(A,varargin)
+% IMAGEPX - like imagexy but pixels shifted to half integer centres
+%
+% The alignment is adjusted so that the *edges* of the pixels fall on
+% integer coordinates, and hence the values in the matrix are used to
+% colour image squares starting from [0,1]x[0,1] and going up to the
+% top-right corner at [N-1,N]x[M-1,M], where the matrix size is M-by-N.
+
+sz=size(A);
+h=imagesc(-0.5+(1:sz(2)),-0.5+(1:sz(1)),A,varargin{:});
+if nargout>0, H=h; end
+axis xy;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/imagexy.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,6 @@
+function H=imagexy(varargin)
+% IMAGEXY - Just like imagesc but with axis xy
+
+h=imagesc(varargin{:});
+if nargout>0, H=h; end
+axis xy;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/lglg.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,5 @@
+function lglg
+% lglg - set X and Y axes to log scale
+%
+% lglg :: action ().
+set( gca, 'XScale','log','YScale','log');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/lin.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,6 @@
+function lin
+% lin - set X and Y scales to linear
+%
+% lin :: action ().
+
+set( gca, 'XScale','linear','YScale','linear');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/noticks.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,20 @@
+function noticks(a,b)
+% noticks - removes ticks from current axis
+%
+% noticks % removes all ticks
+% noticks('x') % removes x ticks
+% noticks('yz') % removes y and z ticks
+
+if nargin==0
+	ax=gca; spec='xyz';
+elseif nargin==1
+	if ishandle(a), ax=a; spec='xyz';
+	else ax=gca; spec=a;
+	end
+else
+	ax=a; spec=b;
+end
+
+if ismember('x',spec), set( ax, 'XTick',[]); end
+if ismember('y',spec), set( ax, 'YTick',[]); end
+if ismember('z',spec), set( ax, 'ZTick',[]); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/panzoom.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,18 @@
+function panzoom(ax)
+
+	if nargin<1, ax=gca; end
+	fig=get(gca,'Parent');
+	set_ctxmenu(gca,{{'zoom',@myzoom},{'pan',@mypan}});
+
+
+	function myzoom(obj,ev)
+		hz=zoom(fig);
+		extend_ctxmenu(hz,{{'zoom off',@(a,b)zoom('off')},{'pan',@mypan}});
+		zoom('on');
+	end
+	function mypan(obj,ev)
+		hz=zoom(fig);
+		extend_ctxmenu(hz,{{'pan off',@(a,b)pan('off')},{'zoom',@myzoom}});
+		pan('on');
+	end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/plotseq.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,59 @@
+function varargout=plotseq(F,X,varargin)
+% plotseq - use arbitrary function to plot elements of sequence sequence 
+%
+% plotseq :: 
+%    (A->handle)   ~'function to make a plot',
+%    seq A         ~'data sequence to plot',
+%    options {
+%       ppre :: action unit ~'called before each plot';
+%       ppost :: action unit ~'called after eacn plot';
+%       mode :: {'gui','immed','null'} ~
+%          'Controls how the iteration proceeds. 
+%           gui: obtain next plot by clicking on title
+%           immed: use function ITERATE to loop immediately
+%           null: do nothing but return state fn and initial state'
+%    }
+% -> (plotseq_state -> plotseq_state) ~'state transformer',
+%    plotseq_state ~'initial state.
+%
+% This works best (at all?) if the plotting function draws in one axes.
+% The axes gains a clickable suffix to it's title. Button 1 click advances
+% to the next object in the data sequence. Button 2 click rewinds to the
+% beginning of the sequence. Alternatively the space bar advances and
+% 'b' rewinds.
+
+
+	opts=prefs('mode','gui','ppre',@nop,'ppost',@nop,varargin{:});
+
+	fig=getparam(opts,'fig',gcf);
+	figure(fig); ax=gca; hold off;
+	fn=@nextplot;
+	S0.i=1; S0.X=X;
+	switch opts.mode
+		case 'immed', iterate(fn,S0,opts);
+		case 'gui', 
+			disp('Click TITLE or [space] for next, button 2 click or [b] to rewind.');
+			rotate3d off;
+			zoom off; pan off;
+			iterate_gui(fn,S0,opts);
+	end
+
+	if nargout==1, varargout{1}={fn,S0}; else varargout={fn,S0}; end
+	
+
+	% state machine to control output
+	% 2nd return is handle of object to respond to mouse click for next/rewind
+	function [S,ti]=nextplot(S)
+		axes(ax);
+		opts.ppre(); 
+		F(head(S.X)); 
+		ti=get(gca,'Title');
+		set(ti,'String',sprintf('%s (%d)',get(ti,'String'),S.i));
+		opts.ppost();
+
+		S.i=S.i+1;
+		S.X=next(S.X);
+		if isempty(S.X), S=[]; end
+	end
+end % of main function
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/scat.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,48 @@
+function H=scat(x,varargin)
+
+% SCAT:	2D/3D scatter plot using dots
+% Usage: h=scat(x,...)
+%
+%    x - matrix of 2D or 3D points
+%    h - returns handle graphics object
+%
+% Valid options
+%    'perspective'::(0|1)/1 ~'use perspective projection in 3D'
+%    'axis'::(0|1)/1 ~'remove axes if 0'
+%    'box' ::(0|1)/1 ~'enable/disable axis box'
+%    'marker'::string ~'standard matlab marker code'
+%    'plotargs'::cell{} ~'extra arguments to plot'
+%
+% In 3D, sets up axes so that shapes are right.
+
+if isa(x,'data'), x=double(x); end
+
+marker=get(gca,'DefaultLineMarker');
+if strcmp(marker,'none'), marker=get(gcf,'DefaultLineMarker'); end
+if strcmp(marker,'none'), marker=get(0,'DefaultLineMarker'); end
+if strcmp(marker,'none'), marker='+'; end
+opts=prefs('perspective',1,'axis',1,'box',1,'marker',marker, ...
+	'plotargs',{},varargin{:});
+if size(x,2)<=4 && size(x,1)>8, x=x'; end
+
+if isfield(opts,'markersize'), 
+	opts.plotargs=[{'MarkerSize',opts.markersize},opts.plotargs]; 
+end
+
+if (size(x,1)>=3),
+	h=plot3(x(1,:),x(2,:),x(3,:),opts.marker,opts.plotargs{:});
+	if opts.perspective, camproj('perspective'); end
+	axis equal;
+	axis vis3d;
+elseif ~isempty(x)
+	h=plot(x(1,:),x(2,:),opts.marker,opts.plotargs{:});
+else
+	h=[];
+end
+
+%set(gca,'DrawMode','fast');
+%set(gcf,'Renderer','painters');
+if (nargout>0), H=h; end
+
+if ~opts.box, box off; else; box on; end
+if ~opts.axis, axis off; end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/scatc.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,43 @@
+function h=scatc(x,C,S,varargin)
+% scatc - 2 or 3D scatter plot with colours and sizes
+%
+% scatc :: [[N,E]] ~'N points in E space', [[N]]~'colours' -> handle.
+% scatc :: 
+%    [[N,E]] ~'N points in E space', 
+%    [[N]]   ~'colours', 
+%    [[N]] | real  ~'array of sizes or single marker size'
+% -> handle.
+%
+% If E<3, does 2D scatter, otherwise, does 3D scatter plot.
+% Draws filled circles. 
+
+if size(x,2)<=4 && size(x,1)>4, x=x'; end
+if nargin<3 || isempty(S),
+	% use default marker size
+	S=get(gca,'DefaultLineMarkerSize').^2; 
+elseif length(S)==1,
+	S=S*ones(size(x,2),1);
+end
+
+if size(x,1)<3,
+	h=scatter(x(1,:),x(2,:),S,C);
+else
+	h=scatter3(x(1,:),x(2,:),x(3,:),S,C);
+end
+
+set(h, ...
+	'MarkerFaceColor','flat', ...
+	'MarkerEdgeColor','k', ...
+	'LineWidth',0.2, ...
+	varargin{:});
+
+axis equal;
+if size(x,1)>2
+	axis vis3d;
+	axis off;
+	set(gca,'DrawMode','fast');
+	set(gca,'Projection','perspective');
+else
+	box on;
+	% axis off;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/scatui.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,50 @@
+function handles=scatui(fig2,plotfn,X,varargin)
+% scatui - scat with interactive point clicking ui
+%
+% scatui ::
+%    handle          ~'figure to do secondary plot',
+%    (natural->unit) ~'function to do secondary plot',
+%    [[N,E]]         ~'array of N points in E-space'
+% -> action handle.
+%
+% This does several things:
+% 1. Plots 3d scatter plot as stereo pairs in fig 1
+% 2. Sets up stereo 3D cursor.
+% 3. Sets up button click callbacks so you can
+%    click to select one of the points
+% 4. Starts the whole thing rotating so you can
+%    see what shape it is without going cross-eyed
+	  
+	% transpose if it looks appropriate
+	if size(X,1)<5, X=X'; end
+	if size(X,2)>2
+		pick=@(t,o)pick3d(t,get(o,'XData'),get(o,'YData'),get(o,'ZData'));
+		curf=@(t,varargin)cursor3d(t(1:3),varargin{:});
+	else
+		pick=@(t,o)pick3d(t,get(o,'XData'),get(o,'YData'),zeros(size(X,1),1));
+		curf=@(t,varargin)cursor2d(t(1:2),varargin{:});
+	end
+
+	% do scat in current figure
+	handles=scat(X,varargin{:}); fig1=gcf;
+	curs=[];
+
+	% get info about scatter plot
+	set(handles,'ButtonDownFcn',@btndown);
+
+	function btndown(obj,dummy)
+		r=get(get(obj,'Parent'),'CurrentPoint'); % get clicked point from axes
+		[x,i]=pick(r,obj);      	% find nearest point
+		if isempty(curs)
+			curs=curf(x);
+		else	
+			curf(x,curs);      	% move cursor
+		end	
+		% title(sprintf('pick: %d',i));
+		figure(fig2); plotfn(i); 	% do plot in other figure
+		figure(fig1); drawnow;  	% return to this figure
+	end
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/semilgx.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,1 @@
+set( gca, 'XScale','log','YScale','linear');
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/semilgy.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,1 @@
+set( gca, 'XScale','linear','YScale','log');
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/set_ctxmenu.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,13 @@
+function h=set_ctxmenu(parent,commands,varargin)
+	opts=prefs(varargin{:});
+	h=uicontextmenu;
+
+	foreach(@(cmd)add_to_menu(h,cmd),commands);
+	set(parent,'UIContextMenu',h);
+end
+
+function h=add_to_menu(menu,cmd)
+	h=uimenu('Parent',menu,'Label',cmd{1},'Callback',cmd{2});
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/tfdimage.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,41 @@
+function tfdimage(TFD,N,m,fs,range,varargin)
+% TFDIMAGE:	image of time frequency distribution with correct axes
+%
+% tfdimage(TFD,N,M,fs[,range])
+%
+% TFD:	image matrix
+% fs:	sampling rate in Hz
+% N:		frame size (used to determine frequency scale)
+% m:		hop size (used to derermine time scale)
+% range: if present, determines manual colour scaler. range(1)=dBs of dynamic range,
+%        and range(2) is max value.
+%        if range=[], uses default manual offset (13.5).
+
+if nargin<4, fs=1; end
+opts=options('offset',0,varargin{:});
+	
+[T,F]=tfscale(fs,N,m,size(TFD));
+if fs>1000,
+	imagesc(T+opts.offset,F/1000,10*log10(TFD));
+else
+	imagesc(T+opts.offset,F,10*log10(TFD));
+end
+if nargin>=5
+	if isempty(range), range=13.5; end
+	
+	dBs=range(1);
+	cax=caxis; cax(1)=cax(2)-dBs;
+	if length(range)>1,
+		cax=cax+range(2)-cax(2);
+	end
+	caxis(cax);
+end
+axis xy
+xlabel('time/s');
+if fs>1000,
+	ylabel('frequency/kHz');
+else
+	ylabel('frequency/Hz');
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/tfscale.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,13 @@
+function [t,f]=tfscale(fs,N,m,size);
+% TFSCALE: time and frequency scales for tfds
+% [t,f]=tfscale(fs,block,hop,size)
+%	fs:	sampling rate in Hz
+%	block:	frame size for FFT - determines frequency resolution
+%	hop:		hop size - determines time resolution
+%  size:		[height width] of tfd matrix - determines extents
+
+w=size(2);
+h=size(1);
+t=[0 (w-1)*m/fs];
+f=[0 (h-1)*fs/N];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/xaxis.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,9 @@
+function xax=xaxis(x)
+% set x axis to span given range
+ax=axis;
+if nargin==0,
+	xax=ax(1:2);
+else
+	axis([x(1) x(end) ax(3) ax(4)]);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/xticks.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,12 @@
+function xticks(T,labels)
+% XTICKS - set X-tick positions and optionally labels
+%
+% xticks :: [[N]] -> unit.
+% xticks :: [[N]] {[N]->text} -> unit.
+
+set(gca,'XTick',T);
+if nargin>1,
+	set(gca,'XTickLabel',labels);                          
+end                                                        
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/yaxis.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,9 @@
+function yax=yaxis(y)
+% set y axis to span given range
+ax=axis;
+if nargin>0,
+	axis([ax(1) ax(2) y(1) y(end)]);
+end
+
+if nargout>0, yax=ax(3:4); end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/yticks.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,12 @@
+function yticks(T,labels)
+% YTICKS - set Y-tick positions and optionally labels
+%
+% yticks :: [[N]] -> unit.
+% yticks :: [[N]] {[N]->text} -> unit.
+
+set(gca,'YTick',T);
+if nargin>1,
+	set(gca,'YTickLabel',labels);                          
+end                                                        
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/chromatic.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,8 @@
+function y=chromatic(i)
+% chromatic - Return degrees of chromatic scale in semitones relative to tonic
+%
+% chromatic :: unit -> [[12]->natural].
+% chromatic :: [[N]->natural] -> [[N]->natural].
+
+y=0:11;
+if nargin>0, y=y(i); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/harmminor.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,8 @@
+function y=harmminor(i)
+% major - Return degrees of major scale in semitones relative to tonic
+%
+% major :: unit -> [[7]->natural].
+% major :: [[N]->natural] -> [[N]->natural].
+
+y=[0,2,3,5,7,8,11];
+if nargin>0, y=y(i); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/hz2pc.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,1 @@
+function o=hz2pc(f), o=mod(12*log2(f/440),12)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/hz2pitch.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,6 @@
+function n=hz2pitch(f)
+% hz2pitch -  convert frequency to pitch in semitones
+%
+% hz2pitch :: nonneg ~'frequency in Hertz' -> real ~'Semitones from A @ 440Hz'.
+n=12*log2(f/440);
+						
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/imajor.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,4 @@
+function y=imajor, y=[2,2,1,2,2,2,1]
+% imajor - Return intervals major scale in semitones 
+%
+% imajor :: unit -> [[7]->natural].
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/iminor.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,8 @@
+function y=minor(i)
+% major - Return degrees of major scale in semitones relative to tonic
+%
+% major :: unit -> [[7]->natural].
+% major :: [[N]->natural] -> [[N]->natural].
+
+y=[0,2,3,5,7,8,10];
+if nargin>0, y=y(i); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/ipenta.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,6 @@
+function y=ipenta, y=[3,2,2,3,2]
+% major - Return degrees of major scale in semitones relative to tonic
+%
+% major :: unit -> [[7]->natural].
+% major :: [[N]->natural] -> [[N]->natural].
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/ivals2pitches.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,8 @@
+function pm=ivals2pitches(n,i)
+% ivals2pitches - make array of pitches in semitones from intervals in scale
+%
+% ivals2pitchs :: 
+%    N:natural ~'number of notes in scale to return', 
+%    [[1,M]]   ~'intervals defining scale'
+% -> [[1,N]]   ~'pitches in semitones'.
+	pm=cumsum(gathern(2,n,cycle(window(i))));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/lp_major.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,3 @@
+function y=lp_major
+
+y=[5,0,2,0,3,3,0,4,0,3,1,2];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/lp_minor.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,3 @@
+function y=lp_major
+
+y=[3,0,2,3,0,3,0,3,2,1,1,1];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/major.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,8 @@
+function y=major(i)
+% major - Return degrees of major scale in semitones relative to tonic
+%
+% major :: unit -> [[7]->natural].
+% major :: [[N]->natural] -> [[N]->natural].
+
+y=[0,2,4,5,7,9,11];
+if nargin>0, y=y(i); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/melminor.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,8 @@
+function y=minor(i)
+% major - Return degrees of major scale in semitones relative to tonic
+%
+% major :: unit -> [[7]->natural].
+% major :: [[N]->natural] -> [[N]->natural].
+
+y=[0,2,3,5,7,9,11];
+if nargin>0, y=y(i); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/minor.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,8 @@
+function y=minor(i)
+% major - Return degrees of major scale in semitones relative to tonic
+%
+% major :: unit -> [[7]->natural].
+% major :: [[N]->natural] -> [[N]->natural].
+
+y=[0,2,3,5,7,8,10];
+if nargin>0, y=y(i); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/pentatonic.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,8 @@
+function y=pentatonic(i)
+% major - Return degrees of major scale in semitones relative to tonic
+%
+% major :: unit -> [[7]->natural].
+% major :: [[N]->natural] -> [[N]->natural].
+
+y=[0,3,5,7,10];
+if nargin>0, y=y(i); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/pitch2hz.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,9 @@
+function f=pitch2hz(n)
+% PITCH2HZ - convert pitch in semitones rel A440 to frequency
+% freq=pitch2hz(n)
+% f: frequency in Hz
+% n: pitch in semitones relative to A 440Hz.
+f=440*exp(log(2)*n/12);
+
+
+						
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/pitch2name.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,17 @@
+function names=pitch2name(p,oct)
+
+if nargin<2,oct=0; end
+
+if iscell(p), p=cell2mat(p); end
+nm={'A' 'A#' 'B' 'C' 'C#' 'D' 'D#' 'E' 'F' 'F#' 'G' 'G#'};
+
+for k=1:length(p)
+	if isfinite(p(k)),
+		names{k}=nm{1+mod(p(k),12)};
+		if oct, names{k}=[ names{k} num2str(floor((p(k)+57)/12))]; end
+	else
+		names{k}='-';
+	end
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/trans_china_major.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,14 @@
+function T=trans_china_major
+T = [ 3974  1  7543  12 2408  110  3   2469  9  9179  78  1001;
+		1     6  47    0  8     0    0   0     0  4     1   0;
+		9015  33 4434  3  7606  268  17  3301  3  2231  16  634; 
+		17    0  6     18 8     2    0   4     0  0     0   0;   
+		2238  11 9746  14 3475  127  10  6550  13 1680  1   207; 
+		38    0  462   1  528   146  1   563   2  132   6   7;   
+		2     0  11    0  28    2    11  132   3  20    0   0;   
+		3271  3  2750  5  7511  1043 132 5303  5  8001  35  356; 
+		1     0  0     0  11    14   5   2     12 40    0   3;   
+		7912  12 2074  2  2035  164  29  10505 35 4172  8   543; 
+		54    0  13    0  1     5    0   24    0  46    33  3;   
+		246   1  310   0  109   5    0   131   5  1950  2   150
+	]';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/trans_china_minor.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,15 @@
+function T=trans_china_minor
+T = [ 10 0 14 1 13 4  0 6  0 0 10 0;
+		0  0 0  0 0  0  0 0  0 0 0  0;
+		16 0 12 0 6  0  0 10 0 0 0  0;
+		0  0 2  0 0  2  0 0  0 0 0  0;
+		2  0 11 1 7  0  0 11 0 0 0  0;
+		2  0 2  0 0  10 0 8  0 0 0  0;
+		0  0 0  0 0  0  0 0  0 0 0  0;
+		19 0 1  0 2  6  0 3  0 1 10 3;
+		0  0 0  0 0  0  0 0  0 0 0  0;
+		0  0 0  0 1  0  0 1  0 0 0  2;
+		10 0 2  0 0  0  0 8  0 0 2  0;
+		0  0 0  0 2  0  0 0  0 3 0  3
+	]';
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/trans_euro_major.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,14 @@
+function T=trans_euro_major
+T = [ 14864 31  10673 82  8237  994   44   6498  10  3258  317 8598;  
+		14    45  169   3   20    0     0    1     1   26    1   29;    
+		15581 136 10615 207 12222 2601  51   4316  0   840   46  2377;  
+		86    6   296   94  39    190   0    37    4   0     6   0;    
+		7085  15  17405 23  12519 9033  315  10362 12  1182  1   141;   
+		277   7   4354  224 14055 5507  15   5887  12  1657  23  518;   
+		15    0   53    1   119   31    117  886   6   125   0   14;    
+		9950  4   2243  99  10619 12706 671  20597 61  7895  172 1723;  
+		4     0   1     0   10    13    3    60    32  99    8   15;    
+		1241  34  826   2   326   1296  132  13155 70  5092  202 3482;  
+		204   1   18    24  2     12    0    143   20  353   196 4;     
+		7292  30  2273  0   198   145   19   1559  17  5330  4   2207
+	]';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/trans_euro_minor.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,14 @@
+function T=trans_euro_minor
+T = [ 1718 56  1609 741  3  284  2   632  126  35  998  548; 
+		149  23  4    45   0  5    2   0    1    0   15   0;   
+		2309 2   606  1761 18 168  0   422  4    6   76   88;  
+		682  117 2570 1117 1  1755 7   391  90   1   103  5;   
+		8    0   7    0    2  48   0   5    0    0   0    0;   
+		190  20  350  2122 35 1092 25  1811 161  4   89   5;   
+		0    0   0    10   0  28   12  68   11   1   9    0;   
+		804  4   190  674  9  2273 56  2071 734  191 401  37;  
+		56   3   5    42   0  180  16  1019 242  1   314  4;   
+		10   0   4    1    0  7    4   217  0    16  151  45;  
+		615  19  60   269  1  82   15  459  499  178 521  9;   
+		575  0   50   6    1  0    0   71   7    22  7    70  
+	]';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pitch/trans_major17.m	Sat Jan 17 15:20:35 2015 +0000
@@ -0,0 +1,25 @@
+function T=trans_major17
+% trans_major17 - Transition COUNTS for major modality
+
+% rest     1  #1   b2     2   #2   b3     3   #3     4   #4     5   #5   b6     6   b7     7
+T = [ ...
+     0, 1974,  3,   0, 1096,   1,  23, 1644,   0,  706,  10, 3082,   3,   3,  487,  27,  241;
+  3678, 3416,  6,   2, 2806,   1,  21, 1974,   0,  210,  13, 1321, 0.2,   3,  839,  99, 2321;
+     0,    0,  4,   0,   42,   1,   0,    4,   0,    0,   0,    0,   0,   0,    3,   0,    2;
+     0,    4,  0, 0.2,    0,   0, 0.2,    1,   0,    0,   0,    0,   0,   0,    0, 0.2,    0;
+  1521, 4190, 33, 0.2, 2632,   3,  66, 3282,   0,  678,  17,  825,   0,   0,  201,  12,  586;
+   0.2,    0,0.2,   0,  0.2,   1,   0,   18,   0,    0,   0,    0,   0,   0,    0,   0,    0;
+    17,   30,  0,   2,  108,   0,  29,    1,   0,   71,   0,   10,   0,   1,    0,   1,    0;
+  2357, 1555,  3,   1, 4865,   4,   1, 3142, 0.2, 2644,  88, 2365,   3,   0,  281, 0.2,   29;
+     0,    0,  0,   0,    0,   0,   0,  0.2,   0,    0,   0,    0,   0,   0,    0,   0,    0;
+   537,   54,  1,   1, 1260, 0.2,  84, 4127,   0, 1506,   4, 1712,   0,   3,  441,   6,  125;
+    13,    3,  0,   0,   16,   0, 0.2,   37,   0,   10,  40,  257,   2,   0,   40,   0,    3;
+  2284, 2557,0.2,   0,  530, 0.2,  37, 2854,   0, 3653, 207, 4835,   6,  13, 2076,  54,  369;
+     2,    0,  0,   0,    0,   0,   0,    1,   0,    1,   1,  0.2,   6,   0,   27,   0,    3;
+     2,    1,  0,   0,  0.2,   0,   0,    1,   0,    3,   0,   21,   0,   3,    0,   3,    0;
+   410,  238,  4,   0,  168, 0.2, 0.2,   65,   0,  342,  37, 3642,  16,   1, 1261,  70,  854;
+    25,   62,  0, 0.2,    3,   0,   8,    1,   0,    3,   0,   43, 0.2,   7,  119,  48,  0.2;
+   275, 2025,  3,   0,  510,   0,   0,   35,   0,   29,   4,  323,   4, 0.2, 1327,   1,  448;
+]';
+
+