changeset 17718:6ed0a8532bcf

Overhaul stft and synthesis functions * scripts/signal/stft.m: Redo docstring to list all calling forms. Use default values to simplify input processing. Use switch statements instead of if/elseif trees for clarity. * scripts/signal/synthesis.m: Use numel() to simplify input validation. Use range st+1:st+inc, rather than st:st+inc-1 to avoid bad indexing error when window size is equal to increment. Use in-place operator for efficiency.
author Rik <rik@octave.org>
date Mon, 21 Oct 2013 16:57:02 -0700
parents 76f448d8089d
children ed9a21a90221
files scripts/signal/stft.m scripts/signal/synthesis.m
diffstat 2 files changed, 39 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/signal/stft.m	Mon Oct 21 18:51:21 2013 -0400
+++ b/scripts/signal/stft.m	Mon Oct 21 16:57:02 2013 -0700
@@ -17,7 +17,12 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{y}, @var{c}] =} stft (@var{x}, @var{win_size}, @var{inc}, @var{num_coef}, @var{win_type})
+## @deftypefn  {Function File} {@var{y} =} stft (@var{x})
+## @deftypefnx {Function File} {@var{y} =} stft (@var{x}, @var{win_size})
+## @deftypefnx {Function File} {@var{y} =} stft (@var{x}, @var{win_size}, @var{inc})
+## @deftypefnx {Function File} {@var{y} =} stft (@var{x}, @var{win_size}, @var{inc}, @var{num_coef})
+## @deftypefnx {Function File} {@var{y} =} stft (@var{x}, @var{win_size}, @var{inc}, @var{num_coef}, @var{win_type})
+## @deftypefnx {Function File} {[@var{y}, @var{c}] =} stft (@dots{})
 ## Compute the short-time Fourier transform of the vector @var{x} with
 ## @var{num_coef} coefficients by applying a window of @var{win_size} data
 ## points and an increment of @var{inc} points.
@@ -26,19 +31,19 @@
 ## is applied:
 ##
 ## @table @asis
-## @item @nospell{hanning}
+## @item @qcode{"hanning"}
 ## win_type = 1
 ##
-## @item @nospell{hamming}
+## @item @qcode{"hamming"}
 ## win_type = 2
 ##
-## @item rectangle
+## @item @qcode{"rectangle"}
 ## win_type = 3
 ## @end table
 ##
 ## The window names can be passed as strings or by the @var{win_type} number.
 ##
-## If not all arguments are specified, the following defaults are used:
+## The following defaults are used for unspecifed arguments:
 ## @var{win_size} = 80, @var{inc} = 24, @var{num_coef} = 64, and
 ## @var{win_type} = 1.
 ##
@@ -49,71 +54,48 @@
 ## @code{[@var{y}, @var{c}] = stft (@code{x}, @dots{})} returns the
 ## entire STFT-matrix @var{y} and a 3-element vector @var{c} containing
 ## the window size, increment, and window type, which is needed by the
-## synthesis function.
+## @code{synthesis} function.
+## @seealso{synthesis}
 ## @end deftypefn
 
 ## Author: AW <Andreas.Weingessel@ci.tuwien.ac.at>
 ## Description: Short-Time Fourier Transform
 
-function [y, c] = stft (x, win_size, inc, num_coef, win_type)
+function [y, c] = stft (x, win_size = 80, inc = 24, num_coef = 64, win_type = 1)
 
-  ## Default values of unspecified arguments.
-  if (nargin < 5)
-    win_type = 1;
-    if (nargin < 4)
-      num_coef = 64;
-      if (nargin < 3)
-        inc = 24;
-        if (nargin < 2)
-          win_size = 80;
-        endif
-      endif
-    endif
-  elseif (nargin == 5)
-    if (ischar (win_type))
-      if (strcmp (win_type, "hanning"))
-        win_type = 1;
-      elseif (strcmp (win_type, "hamming"))
-        win_type = 2;
-      elseif (strcmp (win_type, "rectangle"))
-        win_type = 3;
-      else
-        error ("stft: unknown window type '%s'", win_type);
-      endif
-    endif
-  else
+  if (nargin < 1 || nargin > 5)
     print_usage ();
   endif
 
+  if (ischar (win_type))
+    switch (tolower (win_type))
+      case "hanning"    win_type = 1;
+      case "hamming"    win_type = 2;
+      case "rectangle"  win_type = 3;
+      otherwise
+        error ("stft: unknown window type '%s'", win_type);
+    endswitch
+  endif
+
   ## Check whether X is a vector.
-  [nr, nc] = size (x);
-  if (nc != 1)
-    if (nr == 1)
-      x = x';
-      nr = nc;
-    else
-      error ("stft: X must be a vector");
-    endif
+  if (! isvector (x))
+    error ("stft: X must be a vector");
   endif
+  x = x(:);
 
   ncoef = 2 * num_coef;
   if (win_size > ncoef)
     win_size = ncoef;
     printf ("stft: window size adjusted to %f\n", win_size);
   endif
-  num_win = fix ((nr - win_size) / inc);
+  num_win = fix ((rows (x) - win_size) / inc);
 
   ## compute the window coefficients
-  if (win_type == 3)
-    ## Rectangular window.
-    win_coef = ones (win_size, 1);
-  elseif (win_type == 2)
-    ## Hamming window.
-    win_coef = hamming (win_size);
-  else
-    ## Hanning window.
-    win_coef = hanning (win_size);
-  endif
+  switch (win_type)
+    case 1  win_coef = hanning (win_size);
+    case 2  win_coef = hamming (win_size);
+    case 3  win_coef = ones (win_size, 1);
+  endswitch
 
   ## Create a matrix Z whose columns contain the windowed time-slices.
   z = zeros (ncoef, num_win + 1);
--- a/scripts/signal/synthesis.m	Mon Oct 21 18:51:21 2013 -0400
+++ b/scripts/signal/synthesis.m	Mon Oct 21 16:57:02 2013 -0700
@@ -17,7 +17,7 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} synthesis (@var{y}, @var{c})
+## @deftypefn {Function File} {@var{x} =} synthesis (@var{y}, @var{c})
 ## Compute a signal from its short-time Fourier transform @var{y} and a
 ## 3-element vector @var{c} specifying window size, increment, and
 ## window type.
@@ -27,6 +27,7 @@
 ## @example
 ## [@var{y}, @var{c}] = stft (@var{x} , @dots{})
 ## @end example
+## @seealso{stft}
 ## @end deftypefn
 
 ## Author: AW <Andreas.Weingessel@ci.tuwien.ac.at>
@@ -38,8 +39,7 @@
     print_usage ();
   endif
 
-  [nr, nc] = size (c);
-  if (nr * nc != 3)
+  if (numel (c) != 3)
     error ("synthesis: C must contain exactly 3 elements");
   endif
 
@@ -59,12 +59,12 @@
 
   z = real (ifft (y));
   st = fix ((w_size-inc) / 2);
-  z = z(st:st+inc-1, :);
-  w_coeff = w_coeff(st:st+inc-1);
+  z = z(st+1:st+inc, :);
+  w_coeff = w_coeff(st+1:st+inc);
 
   nc = columns (z);
   for i = 1:nc
-    z(:, i) = z(:, i) ./ w_coeff;
+    z(:, i) ./= w_coeff;
   endfor
 
   x = reshape (z, inc * nc, 1);