1########################################################################
2##
3## Copyright (C) 2016-2021 The Octave Project Developers
4##
5## See the file COPYRIGHT.md in the top-level directory of this
6## distribution or <https://octave.org/copyright/>.
7##
8## This file is part of Octave.
9##
10## Octave is free software: you can redistribute it and/or modify it
11## under the terms of the GNU General Public License as published by
12## the Free Software Foundation, either version 3 of the License, or
13## (at your option) any later version.
14##
15## Octave is distributed in the hope that it will be useful, but
16## WITHOUT ANY WARRANTY; without even the implied warranty of
17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18## GNU General Public License for more details.
19##
20## You should have received a copy of the GNU General Public License
21## along with Octave; see the file COPYING.  If not, see
22## <https://www.gnu.org/licenses/>.
23##
24########################################################################
25
26## -*- texinfo -*-
27## @deftypefn  {} {} soundsc (@var{y})
28## @deftypefnx {} {} soundsc (@var{y}, @var{fs})
29## @deftypefnx {} {} soundsc (@var{y}, @var{fs}, @var{nbits})
30## @deftypefnx {} {} soundsc (@dots{}, [@var{ymin}, @var{ymax}])
31## Scale the audio data @var{y} and play it at sample rate @var{fs} to the
32## default audio device.
33##
34## The audio signal @var{y} can be a vector or a two-column array, representing
35## mono or stereo audio, respectively.
36##
37## If @var{fs} is not given, a default sample rate of 8000 samples per second
38## is used.
39##
40## The optional argument @var{nbits} specifies the bit depth to play to the
41## audio device and defaults to 8 bits.
42##
43## By default, @var{y} is automatically normalized to the range [-1, 1].  If
44## the range [@var{ymin}, @var{ymax}] is given, then elements of @var{y}
45## that fall within the range @var{ymin} @leq{} @var{y} @leq{} @var{ymax}
46## are scaled to the range [-1, 1] instead.
47##
48## For more control over audio playback, use the @code{audioplayer} class.
49## @seealso{sound, record}
50## @end deftypefn
51
52function soundsc (y, fs, nbits, yrange)
53
54  if (nargin < 1 || nargin > 4)
55    print_usage ();
56  endif
57
58  if (nargin < 4)
59    yrange = [];
60  endif
61
62  if (nargin < 2 || isempty (fs))
63    fs = 8000;
64  elseif (nargin == 2 && numel (fs) > 1)
65    yrange = fs;
66    fs = 8000;
67  elseif (! (isscalar (fs) && (fs > 0)))
68    error ("soundsc: sample rate FS must be a positive number");
69  endif
70
71  if (nargin < 3 || isempty (nbits))
72    nbits = 8;
73  elseif (nargin == 3 && numel (nbits) > 1)
74    yrange = nbits;
75    nbits = 8;
76  elseif (! (isscalar (nbits) && (nbits == 8 || nbits == 16 || nbits == 24)))
77    error ("soundsc: bit depth NBITS must be 8, 16, or 24");
78  endif
79
80  if (isreal (yrange) && (numel (yrange) == 2) && (yrange(1) <= yrange(2)))
81    ymin = yrange(1);
82    ymax = yrange(2);
83  elseif (isempty (yrange))
84    ymin = min (y(:));
85    ymax = max (y(:));
86  else
87    error ("soundsc: audio range must be a 2-element [YMIN, YMAX] vector");
88  endif
89
90  ymin = double (ymin);
91  ymax = double (ymax);
92  ymedian = (ymax + ymin) / 2;
93  yscale = 2 / (ymax - ymin);
94
95  y = (double (y) - ymedian) .* yscale;
96
97  play = audioplayer (y, fs, nbits);
98
99  playblocking (play);
100
101endfunction
102
103
104## Tests of soundsc must not actually play anything.
105
106## Test input validation
107%!error soundsc ()
108%!error soundsc (1,2,3,4,5)
109%!error soundsc (1, -1)
110%!error soundsc (1, [], 2)
111%!error soundsc (1, [2 1])
112%!error soundsc (1, [1 2 3])
113%!error soundsc (1, 8000, [2 1])
114%!error soundsc (1, 8000, [1 2 3])
115%!error soundsc (1, 8000, 8, [2 1])
116%!error soundsc (1, 8000, 8, [1 2 3])
117