]> Creatis software - CreaPhase.git/blob - octave_packages/audio-1.1.4/auplot.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / audio-1.1.4 / auplot.m
1 ## Copyright (C) 1999 Paul Kienzle
2 ##
3 ## This program is free software; you can redistribute it and/or modify
4 ## it under the terms of the GNU General Public License as published by
5 ## the Free Software Foundation; either version 2 of the License, or
6 ## (at your option) any later version.
7 ##
8 ## This program is distributed in the hope that it will be useful,
9 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 ## GNU General Public License for more details.
12 ##
13 ## You should have received a copy of the GNU General Public License
14 ## along with this program; If not, see <http://www.gnu.org/licenses/>.
15
16 ## -*- texinfo -*-
17 ## @deftypefn {Function File} {[@var{y},@var{t},@var{scale}] = } auplot (@var{x})
18 ## @deftypefnx {Function File} {[@var{y},@var{t},@var{scale}] = } auplot (@var{x},@var{fs})
19 ## @deftypefnx {Function File} {[@var{y},@var{t},@var{scale}] = } auplot (@var{x},@var{fs},@var{offset})
20 ## @deftypefnx {Function File} {[@var{y},@var{t},@var{scale}] = } auplot (@var{...},@var{plotstr})
21 ##
22 ## Plot the waveform data, displaying time on the @var{x} axis.  If you are
23 ## plotting a slice from the middle of an array, you may want to specify
24 ## the @var{offset} into the array to retain the appropriate time index. If
25 ## the waveform contains multiple channels, then the data are scaled to
26 ## the range [-1,1] and shifted so that they do not overlap. If a @var{plotstr}
27 ## is given, it is passed as the third argument to the plot command. This 
28 ## allows you to set the linestyle easily. @var{fs} defaults to 8000 Hz, and 
29 ## @var{offset} defaults to 0 samples.
30 ##
31 ## Instead of plotting directly, you can ask for the returned processed 
32 ## vectors. If @var{y} has multiple channels, the plot should have the y-range
33 ## [-1 2*size(y,2)-1]. scale specifies how much the matrix was scaled
34 ## so that each signal would fit in the specified range.
35 ##
36 ## Since speech samples can be very long, we need a way to plot them
37 ## rapidly. For long signals, auplot windows the data and keeps the
38 ## minimum and maximum values in the window.  Together, these values
39 ## define the minimal polygon which contains the signal.  The number of
40 ## points in the polygon is set with the global variable auplot_points.
41 ## The polygon may be either 'filled' or 'outline', as set by the global
42 ## variable auplot_format.  For moderately long data, the window does
43 ## not contain enough points to draw an interesting polygon. In this
44 ## case, simply choosing an arbitrary point from the window looks best.
45 ## The global variable auplot_window sets the size of the window
46 ## required for creating polygons.  You can turn off the polygons
47 ## entirely by setting auplot_format to 'sampled'.  To turn off fast
48 ## plotting entirely, set auplot_format to 'direct', or set
49 ## auplot_points=1. There is no reason to do this since your screen
50 ## resolution is limited and increasing the number of points plotted
51 ## will not add any information.  auplot_format, auplot_points and
52 ## auplot_window may be set in .octaverc.  By default auplot_format is
53 ## 'outline', auplot_points=1000 and auplot_window=7.
54 ## @end deftypefn
55
56 ## 2000-03 Paul Kienzle
57 ##     accept either row or column data
58 ##     implement fast plotting
59 ## 2000-04 Paul Kienzle
60 ##     return signal and time vectors if asked
61
62 ## TODO: test offset and plotstr
63 ## TODO: convert offset to time range in the form used by au
64 ## TODO: rename to au; if nargout return data within time range
65 ## TODO:     otherwise plot the data
66 function [y_r, t_r, scale_r] = auplot(x, fs, offset, plotstr)
67
68   global auplot_points=1000;
69   global auplot_format="outline";
70   global auplot_window=7;
71
72   if nargin<1 || nargin>4
73     usage("[y, t, scale] = auplot(x [, fs [, offset [, plotstr]]])");
74   endif
75   if nargin<2, fs = 8000; offset=0; plotstr = []; endif
76   if nargin<3, offset=0; plotstr = []; endif
77   if nargin<4, plotstr = []; endif
78   if ischar(fs), plotstr=fs; fs=8000; endif
79   if ischar(offset), plotstr=offset; offset=0; endif
80   if isempty(plotstr), plotstr=";;"; endif
81   
82
83   if (size(x,1)<size(x,2)), x=x'; endif
84
85   [samples, channels] = size(x);
86   r = ceil(samples/auplot_points);
87   c = floor(samples/r);
88   hastail = (samples>c*r);
89
90   if r==1 || strcmp(auplot_format,"direct")
91     ## full plot
92     t=[0:samples-1]*1000/fs;
93     y=x;
94   elseif r<auplot_window || strcmp(auplot_format,"sampled")
95     ## sub-sampled plot
96     y=x(1:r:samples,:);
97     t=[0:size(y,1)-1]*1000*r/fs;
98   elseif strcmp(auplot_format,"filled")
99     ## filled plot
100     if hastail
101       t=zeros(2*(c+1),1);
102       y=zeros(2*(c+1),channels);
103       t(2*c+1)=t(2*c+2)=c*1000*r/fs;
104     else
105       t=zeros(2*c,1);
106       y=zeros(2*c,channels);
107     endif
108     t(1:2:2*c) = t(2:2:2*c) = [0:c-1]*1000*r/fs;
109     for chan=1:channels
110       head=reshape(x(1:r*c,chan),r,c);
111       y(1:2:2*c,chan) = max(head)';
112       y(2:2:2*c,chan) = min(head)';
113       if (hastail)
114         tail=x(r*c+1:samples,chan);
115         y(2*c+1,chan)=max(tail);
116         y(2*c+2,chan)=min(tail);
117       endif
118     endfor
119   elseif strcmp(auplot_format,"outline")
120     ## outline plot
121     if hastail
122       y=zeros(2*(c+1)+1,channels);
123       t=[0:c]; 
124     else 
125       y=zeros(2*c+1,channels);
126       t=[0:c-1]; 
127     endif
128     t=[t, fliplr(t), 0]*1000*r/fs;
129     for chan=1:channels
130       head=reshape(x(1:r*c,chan),r,c);
131       if hastail
132         tail=x(r*c+1:samples,chan);
133         y(:,chan)=[max(head), max(tail), min(tail), \
134                    fliplr(min(head)),  max(head(:,1))]';
135       else
136         y(:,chan)=[max(head), fliplr(min(head)), max(head(:,1))]';
137       endif
138     endfor
139   else
140     error("auplot_format must be 'outline', 'filled', 'sampled' or 'direct'");
141   endif
142
143   t=t+offset*1000/fs;
144   grid;
145   if channels > 1
146     scale = max(abs(y(:)));
147     if (scale > 0) y=y/scale; endif
148     for i=1:channels
149       y(:,i) = y(:,i) + 2*(i-1);
150     end
151   else
152     scale = 1;
153   end
154
155   if nargout >= 1, y_r = y; endif
156   if nargout >= 2, t_r = t; endif
157   if nargout >= 3, scale_r = scale; endif
158   if nargout == 0
159     if channels > 1
160       unwind_protect ## protect plot state
161         ylabel(sprintf('signal scaled by %f', scale));
162         axis([min(t), max(t), -1, 2*channels-1]);
163         plot(t,y,plotstr);
164       unwind_protect_cleanup
165         axis(); ylabel("");
166       end_unwind_protect
167     else
168       plot(t,y,plotstr);
169     end
170   endif
171 end
172
173 %!demo
174 %! [x, fs] = auload(file_in_loadpath("sample.wav"));
175 %! subplot(211); title("single channel"); auplot(x,fs);
176 %! subplot(212); title("2 channels, x and 3x"); auplot([x, 3*x], fs);
177 %! oneplot(); title("");
178
179 %!demo
180 %! [x, fs] = auload(file_in_loadpath("sample.wav"));
181 %! global auplot_points; pts=auplot_points; 
182 %! global auplot_format; fmt=auplot_format;
183 %! auplot_points=300;
184 %! subplot(221); title("filled"); auplot_format="filled"; auplot(x,fs);
185 %! subplot(223); title("outline"); auplot_format="outline"; auplot(x,fs);
186 %! auplot_points=900;
187 %! subplot(222); title("sampled"); auplot_format="sampled"; auplot(x,fs);
188 %! subplot(224); title("direct"); auplot_format="direct"; auplot(x,fs);
189 %! auplot_format=fmt; auplot_points=pts; title(""); oneplot();
190
191 %!demo
192 %! [x, fs] = auload(file_in_loadpath("sample.wav"));
193 %! title("subrange example"); auplot(au(x,fs,300,450),fs)
194 %! title("");
195
196 %!error auplot
197 %!error auplot(1,2,3,4,5)