GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
audiodevinfo.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2013-2018 Vytautas JanĨauskas
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <cstdint>
28 
29 #include <algorithm>
30 #include <ostream>
31 #include <string>
32 #include <vector>
33 
34 #include "Matrix.h"
35 #include "mach-info.h"
36 #include "oct-locbuf.h"
37 #include "quit.h"
38 #include "unwind-prot.h"
39 
40 #include "Cell.h"
41 #include "defun-dld.h"
42 #include "error.h"
43 #include "errwarn.h"
44 #include "oct-map.h"
45 #include "ov-int32.h"
46 #include "ov.h"
47 #include "ovl.h"
48 #include "parse.h"
49 
50 #if defined (HAVE_PORTAUDIO)
51 
52 #include <portaudio.h>
53 
54 PaSampleFormat
55 bits_to_format (int bits)
56 {
57  if (bits == 8)
58  return paInt8;
59  else if (bits == 16)
60  return paInt16;
61  else if (bits == 24)
62  return paInt24;
63  else if (bits == 32)
64  return paInt32;
65  else if (bits == -1)
66  return paFloat32;
67  else
68  return 0;
69 }
70 
71 #endif
72 
73 DEFUN_DLD (audiodevinfo, args, ,
74  doc: /* -*- texinfo -*-
75 @deftypefn {} {@var{devinfo} =} audiodevinfo ()
76 
77 @deftypefnx {} {@var{devs} =} audiodevinfo (@var{io})
78 @deftypefnx {} {@var{name} =} audiodevinfo (@var{io}, @var{id})
79 @deftypefnx {} {@var{id} =} audiodevinfo (@var{io}, @var{name})
80 @deftypefnx {} {@var{id} =} audiodevinfo (@var{io}, @var{rate}, @var{bits}, @var{chans})
81 
82 @deftypefnx {} {@var{supports} =} audiodevinfo (@var{io}, @var{id}, @var{rate}, @var{bits}, @var{chans})
83 
84 Return a structure describing the available audio input and output devices.
85 
86 The @var{devinfo} structure has two fields @qcode{"input"} and
87 @qcode{"output"}. The value of each field is a structure array with
88 fields @qcode{"Name"}, @nospell{"DriverVersion"} and @qcode{"ID"}
89 describing an audio device.
90 
91 If the optional argument @var{io} is 1, return information about input
92 devices only. If it is 0, return information about output devices
93 only. If @var{io} is the only argument supplied, return the number of
94 input or output devices available.
95 
96 If the optional argument @var{id} is provided, return information about
97 the corresponding device.
98 
99 If the optional argument @var{name} is provided, return the id of the
100 named device.
101 
102 Given a sampling rate, bits per sample, and number of channels for an input
103 or output device, return the ID of the first device that supports playback
104 or recording using the specified parameters.
105 
106 If also given a device ID, return true if the device supports playback or
107 recording using those parameters.
108 @end deftypefn */)
109 {
110 #if defined (HAVE_PORTAUDIO)
111 
112  int nargin = args.length ();
113 
114  if (nargin > 5)
115  print_usage ();
116 
117  octave_scalar_map devinfo;
119  octave_value_list output;
120 
121  PaError err = Pa_Initialize ();
122 
123  if (err != paNoError)
124  error ("audiodevinfo: PortAudio initialization failed");
125 
126  int num_devices = Pa_GetDeviceCount ();
127 
128  if (num_devices < 0)
129  num_devices = 0;
130 
131  octave_idx_type numinput = 0, numoutput = 0;
132  for (int i = 0; i < num_devices; i++)
133  {
134  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);
135 
136  if (! device_info)
137  {
138  warning ("Octave:invalid-audio-device",
139  "invalid audio device ID = %d", i);
140  continue;
141  }
142 
143  if (device_info->maxInputChannels != 0)
144  numinput++;
145 
146  if (device_info->maxOutputChannels != 0)
147  numoutput++;
148  }
149 
150  Cell input_name (dim_vector (1, numinput));
151  Cell input_driver_version (dim_vector (1, numinput));
152  Cell input_id (dim_vector (1, numinput));
153  Cell output_name (dim_vector (1, numoutput));
154  Cell output_driver_version (dim_vector (1, numoutput));
155  Cell output_id (dim_vector (1, numoutput));
156 
157  octave_idx_type idx_i = 0, idx_o = 0;
158  for (int i = 0; i < num_devices; i++)
159  {
160  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);
161 
162  if (! device_info)
163  {
164  warning ("Octave:invalid-audio-device",
165  "invalid audio device ID = %d", i);
166  continue;
167  }
168 
169  const PaHostApiInfo *api_info = Pa_GetHostApiInfo (device_info->hostApi);
170 
171  const char *driver = (api_info ? api_info->name : "");
172 
173  char name[128];
174  sprintf (name, "%s (%s)", device_info->name, driver);
175 
176  if (device_info->maxInputChannels != 0)
177  {
178  input_name(idx_i) = name;
179  input_driver_version(idx_i) = driver;
180  input_id(idx_i) = i;
181  idx_i++;
182  }
183 
184  if (device_info->maxOutputChannels != 0)
185  {
186  output_name(idx_o) = name;
187  output_driver_version(idx_o) = driver;
188  output_id(idx_o) = i;
189  idx_o++;
190  }
191  }
192 
193  octave_map inputdev, outputdev;
194  inputdev.setfield ("Name", input_name);
195  inputdev.setfield ("DriverVersion", input_driver_version);
196  inputdev.setfield ("ID", input_id);
197  outputdev.setfield ("Name", output_name);
198  outputdev.setfield ("DriverVersion", output_driver_version);
199  outputdev.setfield ("ID", output_id);
200  devinfo.setfield ("input", inputdev);
201  devinfo.setfield ("output", outputdev);
202 
204 
205  // Return information about input and output audio devices and
206  // their properties.
207  if (nargin == 0)
208  retval = devinfo;
209  // Return the number of input or output devices
210  else if (nargin == 1)
211  {
212  if (args(0).int_value () == 0)
213  retval = numoutput;
214  else if (args(0).int_value () == 1)
215  retval = numinput;
216  else
217  error ("audiodevinfo: please specify 0 for output and 1 for input devices");
218  }
219  // Return device name when given id or id when given device name.
220  else if (nargin == 2)
221  {
222  bool found = false;
223  int outin = args(0).int_value ();
224  if (args(1).is_string ())
225  {
226  if (outin == 0)
227  {
228  for (int i = 0; i < numoutput; i++)
229  {
230  if (output_name(i).string_value () == args(1).string_value ())
231  {
232  retval = output_id(i);
233  found = true;
234  break;
235  }
236  }
237  }
238  else if (outin == 1)
239  {
240  for (int i = 0; i < numinput; i++)
241  {
242  if (input_name(i).string_value () == args(1).string_value ())
243  {
244  retval = input_id(i);
245  found = true;
246  break;
247  }
248  }
249  }
250  else
251  error ("audiodevinfo: please specify 0 for output and 1 for input devices");
252  }
253  else
254  {
255  if (outin == 0)
256  {
257  for (int i = 0; i < numoutput; i++)
258  {
259  if (output_id(i).int_value () == args(1).int_value ())
260  {
261  retval = output_name(i);
262  found = true;
263  break;
264  }
265  }
266  }
267  else if (outin == 1)
268  {
269  for (int i = 0; i < numinput; i++)
270  {
271  if (input_id(i).int_value () == args(1).int_value ())
272  {
273  retval = input_name(i);
274  found = true;
275  break;
276  }
277  }
278  }
279  else
280  error ("audiodevinfo: please specify 0 for output and 1 for input devices");
281  }
282 
283  if (! found)
284  error ("audiodevinfo: no device meeting the specified criteria found");
285  }
286  else if (nargin == 3)
287  {
288  // FIXME: what was supposed to happen here?
289  }
290  // Return the id of the first device meeting specified criteria.
291  else if (nargin == 4)
292  {
293  int io = args(0).int_value ();
294  int rate = args(1).int_value ();
295  int bits = args(2).int_value ();
296  int chans = args(3).int_value ();
297 
298  for (int i = 0; i < num_devices; i++)
299  {
300  PaStreamParameters stream_parameters;
301  stream_parameters.device = i;
302  stream_parameters.channelCount = chans;
303  PaSampleFormat format = bits_to_format (bits);
304 
305  if (format != 0)
306  stream_parameters.sampleFormat = format;
307  else
308  error ("audiodevinfo: no such bits per sample format");
309 
310  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);
311 
312  if (! device_info)
313  {
314  warning ("Octave:invalid-audio-device",
315  "invalid audio device ID = %d", i);
316  continue;
317  }
318 
319  stream_parameters.suggestedLatency
320  = device_info->defaultLowInputLatency;
321 
322  stream_parameters.hostApiSpecificStreamInfo = nullptr;
323 
324  if (io == 0)
325  {
326  if (device_info->maxOutputChannels < chans)
327  continue;
328 
329  err = Pa_IsFormatSupported (nullptr, &stream_parameters, rate);
330 
331  if (err == paFormatIsSupported)
332  {
333  retval = i;
334  return retval;
335  }
336  }
337  else if (io == 1)
338  {
339  if (device_info->maxInputChannels < chans)
340  continue;
341 
342  err = Pa_IsFormatSupported (&stream_parameters, nullptr, rate);
343  if (err == paFormatIsSupported)
344  {
345  retval = i;
346  return retval;
347  }
348  }
349  }
350  retval = -1;
351  }
352  // Check if given device supports specified playback or recording modes.
353  else if (nargin == 5)
354  {
355  int io = args(0).int_value ();
356  int id = args(1).int_value ();
357  int rate = args(2).int_value ();
358  int bits = args(3).int_value ();
359  int chans = args(4).int_value ();
360  PaStreamParameters stream_parameters;
361  stream_parameters.device = id;
362  stream_parameters.channelCount = chans;
363  PaSampleFormat format = bits_to_format (bits);
364  if (format != 0)
365  stream_parameters.sampleFormat = format;
366  else
367  error ("audiodevinfo: no such bits per sample format");
368 
369  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (id);
370 
371  if (! device_info)
372  error ("audiodevinfo: invalid audio device ID = %d", id);
373 
374  stream_parameters.suggestedLatency
375  = device_info->defaultLowInputLatency;
376 
377  stream_parameters.hostApiSpecificStreamInfo = nullptr;
378  if (io == 0)
379  {
380  if (device_info->maxOutputChannels < chans)
381  {
382  retval = 0;
383  return retval;
384  }
385  err = Pa_IsFormatSupported (nullptr, &stream_parameters, rate);
386  if (err == paFormatIsSupported)
387  {
388  retval = 1;
389  return retval;
390  }
391  }
392  else if (io == 1)
393  {
394  if (device_info->maxInputChannels < chans)
395  {
396  retval = 0;
397  return retval;
398  }
399  err = Pa_IsFormatSupported (&stream_parameters, nullptr, rate);
400  if (err == paFormatIsSupported)
401  {
402  retval = 1;
403  return retval;
404  }
405  }
406  else
407  error ("audiodevinfo: please specify 0 for output and 1 for input devices");
408 
409  retval = 0;
410  }
411 
412  return retval;
413 
414 #else
415  octave_unused_parameter (args);
416 
417  err_disabled_feature ("audiodevinfo",
418  "audio playback and recording through PortAudio");
419 #endif
420 }
421 
422 /*
423 %!testif HAVE_PORTAUDIO
424 %! devinfo = audiodevinfo;
425 %! assert (rows (devinfo.input), 1);
426 %! assert (rows (devinfo.output), 1);
427 
428 %!testif HAVE_PORTAUDIO
429 %! devinfo = audiodevinfo;
430 %! nout = audiodevinfo (0);
431 %! nin = audiodevinfo (1);
432 %! assert (columns (devinfo.output), nout);
433 %! assert (columns (devinfo.input), nin);
434 
435 %!testif HAVE_PORTAUDIO
436 %! devinfo = audiodevinfo;
437 %! nout = audiodevinfo (0);
438 %! nin = audiodevinfo (1);
439 %! for i = 1:nout,
440 %! assert (devinfo.output(i).Name, audiodevinfo (0, devinfo.output(i).ID));
441 %! endfor
442 %! for i=1:nin,
443 %! assert (devinfo.input(i).Name, audiodevinfo (1, devinfo.input(i).ID));
444 %! endfor
445 
446 %!testif HAVE_PORTAUDIO
447 %! devinfo = audiodevinfo;
448 %! nout = audiodevinfo (0);
449 %! nin = audiodevinfo (1);
450 %! for i = 1:nout,
451 %! assert (devinfo.output(i).ID, audiodevinfo (0, devinfo.output(i).Name));
452 %! endfor
453 %! for i = 1:nin,
454 %! assert (devinfo.input(i).ID, audiodevinfo (1, devinfo.input(i).Name));
455 %! endfor
456 */
457 
458 #if defined (HAVE_PORTAUDIO)
459 
460 enum audio_type { TYPE_INT8, TYPE_UINT8, TYPE_UINT16, TYPE_DOUBLE };
461 
462 class audioplayer : public octave_base_value
463 {
464 public:
465  audioplayer (void);
466  ~audioplayer (void);
467 
468  // Overloaded base functions
469  double player_value (void) const { return 0; }
470  virtual double scalar_value (bool = false) const { return 0; }
471  void print (std::ostream& os, bool pr_as_read_syntax = false);
472  void print_raw (std::ostream& os, bool pr_as_read_syntax) const;
473 
474  // Properties
475  bool is_constant (void) const { return true; }
476  bool is_defined (void) const { return true; }
477  bool print_as_scalar (void) const { return true; }
478 
479  void init (void);
480  void init_fn (void);
481  void set_y (const octave_value& y);
482  void set_y (octave_function *fn);
483  void set_y (std::string fn);
484  Matrix& get_y (void);
485  RowVector get_left (void) const;
486  RowVector get_right (void) const;
487  void set_fs (int fs);
488  int get_fs (void);
489  void set_nbits (int nbits);
490  int get_nbits (void);
491  void set_id (int id);
492  int get_id (void);
493  int get_channels (void);
494  audio_type get_type (void);
495 
496  void set_sample_number (unsigned int sample);
497  unsigned int get_sample_number (void);
498  unsigned int get_total_samples (void);
499  void set_end_sample (unsigned int sample);
500  unsigned int get_end_sample (void);
501  void reset_end_sample (void);
502  void set_tag (const charMatrix& tag);
503  charMatrix get_tag (void);
504  void set_userdata (const octave_value& userdata);
505  octave_value get_userdata (void);
506  PaStream * get_stream (void);
507 
508  void playblocking (void);
509  void play (void);
510  void pause (void);
511  void resume (void);
512  void stop (void);
513  bool isplaying (void);
514 
515  octave_function *octave_callback_function;
516 
517 private:
518  int id;
519  int fs;
520  int nbits;
521  int channels;
522  unsigned int sample_number;
523  unsigned int end_sample;
524  charMatrix tag;
525  Matrix y;
526  octave_value userdata;
527  RowVector left;
529  PaStream *stream;
530  PaStreamParameters output_parameters;
531  audio_type type;
532 
534 };
535 
536 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audioplayer, "audioplayer", "audioplayer");
537 
538 static int
539 octave_play_callback (const void *, void *output, unsigned long frames,
540  const PaStreamCallbackTimeInfo *,
541  PaStreamCallbackFlags, void *data)
542 {
543  audioplayer *player = static_cast<audioplayer *> (data);
544 
545  if (! player)
546  error ("audio player callback function called without player");
547 
549  = octave::feval (player->octave_callback_function,
550  ovl (static_cast<double> (frames)), 1);
551 
552  if (retval.length () < 2)
553  error ("audio player callback function failed");
554 
555  const Matrix sound = retval(0).matrix_value ();
556  int return_status = retval(1).int_value ();
557 
558  if (frames - sound.rows () != 0 || sound.columns () < 1
559  || sound.columns () > 2)
560  error ("audio player callback function failed");
561 
562  // Don't multiply the audio data by scale_factor here. Although it
563  // does move the operation outside of the loops below, it also causes
564  // a second copy of the data array to be made.
565 
566  const ColumnVector sound_l = sound.column (0);
567  const ColumnVector sound_r = (sound.columns () == 1
568  ? sound_l : sound.column (1));
569 
570  const double *p_l = sound_l.data ();
571  const double *p_r = sound_r.data ();
572 
573  switch (player->get_nbits ())
574  {
575  case 8:
576  {
577  static double scale_factor = std::pow (2.0, 7) - 1.0;
578 
579  int8_t *buffer = static_cast<int8_t *> (output);
580 
581  for (unsigned long i = 0; i < frames; i++)
582  {
583  buffer[2*i] = p_l[i] * scale_factor;
584  buffer[2*i+1] = p_r[i] * scale_factor;
585  }
586  }
587  break;
588 
589  case 16:
590  {
591  static double scale_factor = std::pow (2.0, 15) - 1.0;
592 
593  int16_t *buffer = static_cast<int16_t *> (output);
594 
595  for (unsigned long i = 0; i < frames; i++)
596  {
597  buffer[2*i] = p_l[i] * scale_factor;
598  buffer[2*i+1] = p_r[i] * scale_factor;
599  }
600  }
601  break;
602 
603  case 24:
604  {
605  static double scale_factor = std::pow (2.0, 23) - 1.0;
606 
607  static int big_endian = octave::mach_info::words_big_endian ();
608 
609  uint8_t *buffer = static_cast<uint8_t *> (output);
610 
611  for (unsigned long i = 0; i < frames; i++)
612  {
613  int32_t sample_l = p_l[i];
614  int32_t sample_r = p_r[i];
615 
616  sample_l &= 0x00ffffff;
617  sample_r &= 0x00ffffff;
618 
619  // FIXME: Would a mask work better?
620  uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
621  uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
622 
623  unsigned long offset = i * 6;
624 
625  buffer[offset+0] = _sample_l[0+big_endian] * scale_factor;
626  buffer[offset+1] = _sample_l[1+big_endian] * scale_factor;
627  buffer[offset+2] = _sample_l[2+big_endian] * scale_factor;
628 
629  buffer[offset+3] = _sample_r[0+big_endian] * scale_factor;
630  buffer[offset+4] = _sample_r[1+big_endian] * scale_factor;
631  buffer[offset+5] = _sample_r[2+big_endian] * scale_factor;
632  }
633  }
634  break;
635 
636  default:
637  error ("invalid player bit depth in callback function");
638  }
639 
640  return return_status;
641 }
642 
643 static int
644 portaudio_play_callback (const void *, void *output, unsigned long frames,
645  const PaStreamCallbackTimeInfo*,
646  PaStreamCallbackFlags, void *data)
647 {
648  audioplayer *player = static_cast<audioplayer *> (data);
649 
650  if (! player)
651  error ("audio player callback function called without player");
652 
653  // Don't multiply the audio data by scale_factor here. Although it
654  // would move the operation outside of the loops below, it also causes
655  // a second copy of the *entire* data array to be made when only a
656  // small portion (buffer_size elements) is usually needed for this
657  // callback.
658 
659  const RowVector sound_l = player->get_left ();
660  const RowVector sound_r = player->get_right ();
661 
662  const double *pl = sound_l.data ();
663  const double *pr = sound_r.data ();
664 
665  if (player->get_type () == TYPE_DOUBLE)
666  {
667  switch (player->get_nbits ())
668  {
669  case 8:
670  {
671  static double scale_factor = std::pow (2.0, 7) - 1.0;
672 
673  int8_t *buffer = static_cast<int8_t *> (output);
674 
675  for (unsigned long j = 0; j < frames; j++)
676  {
677  unsigned int sample_number = player->get_sample_number ();
678 
679  if (sample_number >= player->get_end_sample ())
680  return paComplete;
681 
682  unsigned long offset = j * 2;
683 
684  buffer[offset+0] = pl[sample_number] * scale_factor;
685  buffer[offset+1] = pr[sample_number] * scale_factor;
686 
687  player->set_sample_number (sample_number + 1);
688  }
689  }
690  break;
691 
692  case 16:
693  {
694  static double scale_factor = std::pow (2.0, 15) - 1.0;
695 
696  int16_t *buffer = static_cast<int16_t *> (output);
697 
698  for (unsigned long j = 0; j < frames; j++)
699  {
700  unsigned int sample_number = player->get_sample_number ();
701 
702  if (sample_number >= player->get_end_sample ())
703  return paComplete;
704 
705  unsigned long offset = j * 2;
706 
707  buffer[offset+0] = pl[sample_number] * scale_factor;
708  buffer[offset+1] = pr[sample_number] * scale_factor;
709 
710  player->set_sample_number (sample_number + 1);
711  }
712  }
713  break;
714 
715  case 24:
716  {
717  static double scale_factor = std::pow (2.0, 23) - 1.0;
718 
719  static int big_endian = octave::mach_info::words_big_endian ();
720 
721  uint8_t *buffer = static_cast<uint8_t *> (output);
722 
723  for (unsigned long j = 0; j < frames; j++)
724  {
725  unsigned int sample_number = player->get_sample_number ();
726 
727  if (sample_number >= player->get_end_sample ())
728  return paComplete;
729 
730  int32_t sample_l = pl[sample_number] * scale_factor;
731  int32_t sample_r = pr[sample_number] * scale_factor;
732 
733  sample_l &= 0x00ffffff;
734  sample_r &= 0x00ffffff;
735 
736  // FIXME: Would a mask work better?
737  uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
738  uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
739 
740  unsigned long offset = j * 6;
741 
742  buffer[offset+0] = _sample_l[0+big_endian];
743  buffer[offset+1] = _sample_l[1+big_endian];
744  buffer[offset+2] = _sample_l[2+big_endian];
745 
746  buffer[offset+3] = _sample_r[0+big_endian];
747  buffer[offset+4] = _sample_r[1+big_endian];
748  buffer[offset+5] = _sample_r[2+big_endian];
749 
750  player->set_sample_number (sample_number + 1);
751  }
752  }
753  break;
754 
755  default:
756  error ("invalid player bit depth in callback function");
757  }
758  }
759  else if (player->get_type () == TYPE_INT8)
760  {
761  int8_t *buffer = static_cast<int8_t *> (output);
762 
763  for (unsigned long j = 0; j < frames; j++)
764  {
765  unsigned int sample_number = player->get_sample_number ();
766 
767  if (sample_number >= player->get_end_sample ())
768  return paComplete;
769 
770  unsigned long offset = j * 2;
771 
772  buffer[offset+0] = pl[sample_number];
773  buffer[offset+1] = pr[sample_number];
774 
775  player->set_sample_number (sample_number + 1);
776  }
777  }
778  else if (player->get_type () == TYPE_UINT8)
779  {
780  uint8_t *buffer = static_cast<uint8_t *> (output);
781 
782  for (unsigned long j = 0; j < frames; j++)
783  {
784  unsigned int sample_number = player->get_sample_number ();
785 
786  if (sample_number >= player->get_end_sample ())
787  return paComplete;
788 
789  unsigned long offset = j * 2;
790 
791  buffer[offset+0] = pl[sample_number];
792  buffer[offset+1] = pr[sample_number];
793 
794  player->set_sample_number (sample_number + 1);
795  }
796  }
797  else if (player->get_type () == TYPE_UINT16)
798  {
799  int16_t *buffer = static_cast<int16_t *> (output);
800 
801  for (unsigned long j = 0; j < frames; j++)
802  {
803  unsigned int sample_number = player->get_sample_number ();
804 
805  if (sample_number >= player->get_end_sample ())
806  return paComplete;
807 
808  unsigned long offset = j * 2;
809 
810  buffer[offset+0] = pl[sample_number];
811  buffer[offset+1] = pr[sample_number];
812 
813  player->set_sample_number (sample_number + 1);
814  }
815  }
816 
817  return paContinue;
818 }
819 
820 static void
821 safe_audioplayer_stop (audioplayer *player)
822 {
823  player->stop ();
824 }
825 
826 audioplayer::audioplayer (void)
827  : octave_callback_function (nullptr),
828  id (-1), fs (0), nbits (16), channels (0), sample_number (0),
829  end_sample (-1), tag (""), y (), userdata (Matrix ()),
830  left (), right (), stream (nullptr), output_parameters (), type ()
831 { }
832 
833 audioplayer::~audioplayer (void)
834 {
835  if (isplaying ())
836  {
837  warning ("Octave:audio-interrupt",
838  "interrupting playing audioplayer");
839  stop ();
840  }
841 }
842 
843 void
844 audioplayer::print (std::ostream& os, bool pr_as_read_syntax)
845 {
846  print_raw (os, pr_as_read_syntax);
847  newline (os);
848 }
849 
850 void
851 audioplayer::print_raw (std::ostream& os, bool) const
852 {
853  os << 0;
854 }
855 
856 void
857 audioplayer::init_fn (void)
858 {
859  if (Pa_Initialize () != paNoError)
860  error ("audioplayer: initialization error!");
861 
862  if (Pa_GetDeviceCount () < 1)
863  error ("audioplayer: no audio devices found or available!");
864 
865  int device = get_id ();
866 
867  if (device == -1)
868  device = Pa_GetDefaultOutputDevice ();
869 
870  output_parameters.device = device;
871  output_parameters.channelCount = 2;
872  output_parameters.sampleFormat = bits_to_format (get_nbits ());
873 
874  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (device);
875 
876  if (! device_info)
877  warning ("Octave:invalid-default-audio-device",
878  "invalid default audio device ID = %d", device);
879 
880  output_parameters.suggestedLatency
881  = (device_info ? device_info->defaultHighOutputLatency : -1);
882 
883  output_parameters.hostApiSpecificStreamInfo = nullptr;
884 }
885 
886 void
887 audioplayer::init (void)
888 {
889  // FIXME: Both of these variables are unused.
890  // Should they be eliminated or is something not yet implemented?
891  //
892  // int channels = y.rows ();
893  // RowVector *sound_l = get_left ();
894 
895  if (Pa_Initialize () != paNoError)
896  error ("audioplayer: initialization error!");
897 
898  if (Pa_GetDeviceCount () < 1)
899  error ("audioplayer: no audio devices found or available!");
900 
901  int device = get_id ();
902 
903  if (device == -1)
904  device = Pa_GetDefaultOutputDevice ();
905 
906  output_parameters.device = device;
907  output_parameters.channelCount = 2;
908 
909  if (type == TYPE_DOUBLE)
910  output_parameters.sampleFormat = bits_to_format (get_nbits ());
911  else if (type == TYPE_INT8)
912  output_parameters.sampleFormat = paInt8;
913  else if (type == TYPE_UINT8)
914  output_parameters.sampleFormat = paUInt8;
915  else if (type == TYPE_UINT16)
916  output_parameters.sampleFormat = paInt16;
917 
918  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (device);
919 
920  if (! device_info)
921  warning ("Octave:invalid-default-audio-device",
922  "invalid default audio device ID = %d", device);
923 
924  output_parameters.suggestedLatency
925  = (device_info ? device_info->defaultHighOutputLatency : -1);
926 
927  output_parameters.hostApiSpecificStreamInfo = nullptr;
928 }
929 
930 void
931 audioplayer::set_y (const octave_value& y_arg)
932 {
933  if (y_arg.is_int8_type ())
934  type = TYPE_INT8;
935  else if (y_arg.is_uint8_type ())
936  type = TYPE_UINT8;
937  else if (y_arg.is_int16_type ())
938  type = TYPE_UINT16;
939  else
940  type = TYPE_DOUBLE;
941 
942  y = y_arg.matrix_value ();
943 
944  if (y.rows () > 2)
945  y = y.transpose ();
946 
947  channels = y.rows ();
948  left = y.row (0);
949 
950  if (channels == 2)
951  right = y.row (1);
952 
953  reset_end_sample ();
954 }
955 
956 void
957 audioplayer::set_y (octave_function *fn)
958 {
959  octave_callback_function = fn;
960  channels = 2;
961  reset_end_sample ();
962 }
963 
964 Matrix&
965 audioplayer::get_y (void)
966 {
967  return y;
968 }
969 
970 RowVector
971 audioplayer::get_left (void) const
972 {
973  return left;
974 }
975 
976 RowVector
977 audioplayer::get_right (void) const
978 {
979  return channels == 1 ? left : right;
980 }
981 
982 void
983 audioplayer::set_fs (int fs_arg)
984 {
985  fs = fs_arg;
986 }
987 
988 int
989 audioplayer::get_fs (void)
990 {
991  return fs;
992 }
993 
994 void
995 audioplayer::set_nbits (int nbits_arg)
996 {
997  nbits = nbits_arg;
998 }
999 
1000 int
1001 audioplayer::get_nbits (void)
1002 {
1003  return nbits;
1004 }
1005 
1006 void
1007 audioplayer::set_id (int id_arg)
1008 {
1009  id = id_arg;
1010 }
1011 
1012 int
1013 audioplayer::get_id (void)
1014 {
1015  return id;
1016 }
1017 
1018 int
1019 audioplayer::get_channels (void)
1020 {
1021  return channels;
1022 }
1023 
1024 audio_type
1025 audioplayer::get_type (void)
1026 {
1027  return type;
1028 }
1029 
1030 void
1031 audioplayer::set_sample_number (unsigned int sample_number_arg)
1032 {
1033  sample_number = sample_number_arg;
1034 }
1035 
1036 unsigned int
1037 audioplayer::get_sample_number (void)
1038 {
1039  return sample_number;
1040 }
1041 
1042 unsigned int
1043 audioplayer::get_total_samples (void)
1044 {
1045  return left.numel ();
1046 }
1047 
1048 void
1049 audioplayer::set_end_sample (unsigned int end_sample_arg)
1050 {
1051  end_sample = end_sample_arg;
1052 }
1053 
1054 unsigned int
1055 audioplayer::get_end_sample (void)
1056 {
1057  return end_sample;
1058 }
1059 
1060 void
1061 audioplayer::reset_end_sample (void)
1062 {
1063  set_end_sample (left.numel ());
1064 }
1065 
1066 void
1067 audioplayer::set_tag (const charMatrix& tag_arg)
1068 {
1069  tag = tag_arg;
1070 }
1071 
1072 charMatrix
1073 audioplayer::get_tag (void)
1074 {
1075  return tag;
1076 }
1077 
1078 void
1079 audioplayer::set_userdata (const octave_value& userdata_arg)
1080 {
1081  userdata = userdata_arg;
1082 }
1083 
1085 audioplayer::get_userdata (void)
1086 {
1087  return userdata;
1088 }
1089 
1090 void
1091 audioplayer::playblocking (void)
1092 {
1093  if (get_stream ())
1094  stop ();
1095 
1096  const unsigned int buffer_size = get_fs () / 20;
1097  OCTAVE_LOCAL_BUFFER (uint32_t, buffer, buffer_size * 2);
1098 
1099  PaError err;
1100  err = Pa_OpenStream (&stream, nullptr, &(output_parameters), get_fs (),
1101  buffer_size, paClipOff, nullptr, nullptr);
1102  if (err != paNoError)
1103  error ("audioplayer: unable to open audio playback stream");
1104 
1105  err = Pa_StartStream (stream);
1106  if (err != paNoError)
1107  error ("audioplayer: unable to start audio playback stream");
1108 
1109  unsigned int start, end;
1110  start = get_sample_number ();
1111  end = get_end_sample ();
1112 
1114 
1115  frame.add_fcn (safe_audioplayer_stop, this);
1116 
1117  for (unsigned int i = start; i < end; i += buffer_size)
1118  {
1119  octave_quit ();
1120 
1121  if (octave_callback_function != nullptr)
1122  octave_play_callback (nullptr, buffer, buffer_size, nullptr, 0, this);
1123  else
1124  portaudio_play_callback (nullptr, buffer, buffer_size, nullptr, 0, this);
1125 
1126  err = Pa_WriteStream (stream, buffer, buffer_size);
1127  }
1128 }
1129 
1130 void
1131 audioplayer::play (void)
1132 {
1133  if (get_stream ())
1134  stop ();
1135 
1136  const unsigned int buffer_size = get_fs () / 20;
1137 
1138  PaError err;
1139  if (octave_callback_function != nullptr)
1140  err = Pa_OpenStream (&stream, nullptr, &(output_parameters),
1141  get_fs (), buffer_size, paClipOff,
1142  octave_play_callback, this);
1143  else
1144  err = Pa_OpenStream (&stream, nullptr, &(output_parameters),
1145  get_fs (), buffer_size, paClipOff,
1146  portaudio_play_callback, this);
1147 
1148  if (err != paNoError)
1149  error ("audioplayer: failed to open audio playback stream");
1150 
1151  err = Pa_StartStream (stream);
1152  if (err != paNoError)
1153  error ("audioplayer: failed to start audio playback stream");
1154 }
1155 
1156 void
1157 audioplayer::pause (void)
1158 {
1159  if (get_stream () == nullptr)
1160  return;
1161 
1162  PaError err;
1163  err = Pa_StopStream (stream);
1164  if (err != paNoError)
1165  error ("audiorecorder: failed to stop audio recording stream");
1166 }
1167 
1168 void
1169 audioplayer::resume (void)
1170 {
1171  if (get_stream () == nullptr)
1172  return;
1173 
1174  PaError err;
1175  err = Pa_StartStream (stream);
1176  if (err != paNoError)
1177  error ("audiorecorder: failed to start audio recording stream");
1178 }
1179 
1180 PaStream *
1181 audioplayer::get_stream (void)
1182 {
1183  return stream;
1184 }
1185 
1186 void
1187 audioplayer::stop (void)
1188 {
1189  if (get_stream () == nullptr)
1190  return;
1191 
1192  PaError err;
1193  set_sample_number (0);
1194  reset_end_sample ();
1195  if (! Pa_IsStreamStopped (get_stream ()))
1196  {
1197  err = Pa_AbortStream (get_stream ());
1198  if (err != paNoError)
1199  error ("audioplayer: failed to stop audio playback stream");
1200  }
1201 
1202  err = Pa_CloseStream (get_stream ());
1203  if (err != paNoError)
1204  error ("audioplayer: failed to close audio playback stream");
1205 
1206  stream = nullptr;
1207 }
1208 
1209 bool
1210 audioplayer::isplaying (void)
1211 {
1212  if (get_stream () == nullptr)
1213  return false;
1214 
1215  PaError err;
1216  err = Pa_IsStreamActive (stream);
1217  if (err != 0 && err != 1)
1218  error ("audiorecorder: checking stream activity status failed");
1219 
1220  return (err == 1);
1221 }
1222 
1223 class audiorecorder : public octave_base_value
1224 {
1225 public:
1226  audiorecorder (void);
1227  ~audiorecorder (void);
1228 
1229  // Overloaded base functions
1230  double player_value (void) const { return 0; }
1231  virtual double scalar_value (bool = false) const { return 0; }
1232  void print (std::ostream& os, bool pr_as_read_syntax = false);
1233  void print_raw (std::ostream& os, bool pr_as_read_syntax) const;
1234 
1235  // Properties
1236  bool is_constant (void) const { return true; }
1237  bool is_defined (void) const { return true; }
1238  bool print_as_scalar (void) const { return true; }
1239 
1240  void init (void);
1241  void set_fs (int fs);
1242  int get_fs (void);
1243  void set_nbits (int nbits);
1244  int get_nbits (void);
1245  void set_id (int id);
1246  int get_id (void);
1247  void set_channels (int channels);
1248  int get_channels (void);
1249  audio_type get_type (void);
1250 
1251  void set_sample_number (unsigned int sample);
1252  unsigned int get_sample_number (void);
1253  unsigned int get_total_samples (void);
1254  void set_end_sample (unsigned int sample);
1255  unsigned int get_end_sample (void);
1256  void reset_end_sample (void);
1257  void set_tag (const charMatrix& tag);
1258  charMatrix get_tag (void);
1259  void set_userdata (const octave_value& userdata);
1260  octave_value get_userdata (void);
1261  PaStream * get_stream (void);
1262 
1263  octave_value getaudiodata (void);
1264  audioplayer * getplayer (void);
1265  bool isrecording (void);
1266  audioplayer play (void);
1267  void record (void);
1268  void recordblocking (float seconds);
1269  void pause (void);
1270  void resume (void);
1271  void stop (void);
1272  void append (float sample_l, float sample_r);
1273 
1274  octave_function *octave_callback_function;
1275 
1276 private:
1277  int id;
1278  int fs;
1279  int nbits;
1280  int channels;
1281  unsigned int sample_number;
1282  unsigned int end_sample;
1283  charMatrix tag;
1284  Matrix y;
1285  octave_value userdata;
1286  std::vector<float> left;
1287  std::vector<float> right;
1288  PaStream *stream;
1289  PaStreamParameters input_parameters;
1290  audio_type type;
1291 
1293 };
1294 
1295 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audiorecorder, "audiorecorder", "audiorecorder");
1296 
1297 static int
1298 octave_record_callback (const void *input, void *, unsigned long frames,
1299  const PaStreamCallbackTimeInfo *,
1300  PaStreamCallbackFlags, void *data)
1301 {
1302  audiorecorder *recorder = static_cast<audiorecorder *> (data);
1303 
1304  if (! recorder)
1305  error ("audio recorder callback function called without player");
1306 
1307  int channels = recorder->get_channels ();
1308 
1309  Matrix sound (frames, 2);
1310  sound.resize (frames, 2);
1311 
1312  if (recorder->get_nbits () == 8)
1313  {
1314  static double scale_factor = std::pow (2.0, 7) - 1.0;
1315 
1316  const int8_t *input8 = static_cast<const int8_t *> (input);
1317 
1318  for (unsigned long i = 0; i < frames; i++)
1319  {
1320  float sample_l = input8[i*channels] / scale_factor;
1321  float sample_r = input8[i*channels + (channels - 1)] / scale_factor;
1322 
1323  sound(i,0) = sample_l;
1324  sound(i,1) = sample_r;
1325  }
1326  }
1327  else if (recorder->get_nbits () == 16)
1328  {
1329  static double scale_factor = std::pow (2.0, 15) - 1.0;
1330 
1331  const int16_t *input16 = static_cast<const int16_t *> (input);
1332 
1333  for (unsigned long i = 0; i < frames; i++)
1334  {
1335  float sample_l = input16[i*channels] / scale_factor;
1336  float sample_r = input16[i*channels + (channels - 1)] / scale_factor;
1337 
1338  sound(i,0) = sample_l;
1339  sound(i,1) = sample_r;
1340  }
1341  }
1342  else if (recorder->get_nbits () == 24)
1343  {
1344  static double scale_factor = std::pow (2.0, 23);
1345 
1346  // FIXME: Is there a better way?
1347  const uint8_t *input24 = static_cast<const uint8_t *> (input);
1348 
1349  int32_t sample_l32 = 0, sample_r32 = 0;
1350 
1351  uint8_t *sample_l = reinterpret_cast<uint8_t *> (&sample_l32);
1352  uint8_t *sample_r = reinterpret_cast<uint8_t *> (&sample_r32);
1353 
1354  for (unsigned long i = 0; i < frames; i++)
1355  {
1356  for (int j = 0; j < 3; j++)
1357  {
1358  sample_l[j] = input24[i*channels*3 + j];
1359  sample_r[j] = input24[i*channels*3 + (channels - 1)*3 + j];
1360  }
1361 
1362  if (sample_l32 & 0x00800000)
1363  sample_l32 |= 0xff000000;
1364 
1365  if (sample_r32 & 0x00800000)
1366  sample_r32 |= 0xff000000;
1367 
1368  sound(i,0) = sample_l32 / scale_factor;
1369  sound(i,1) = sample_r32 / scale_factor;
1370  }
1371  }
1372 
1374  = octave::feval (recorder->octave_callback_function, ovl (sound), 1);
1375 
1376  return retval(0).int_value ();
1377 }
1378 
1379 static int
1380 portaudio_record_callback (const void *input, void *, unsigned long frames,
1381  const PaStreamCallbackTimeInfo *,
1382  PaStreamCallbackFlags, void *data)
1383 {
1384  audiorecorder *recorder = static_cast<audiorecorder *> (data);
1385 
1386  if (! recorder)
1387  error ("audio recorder callback function called without player");
1388 
1389  int channels = recorder->get_channels ();
1390 
1391  if (recorder->get_nbits () == 8)
1392  {
1393  static float scale_factor = std::pow (2.0f, 7) - 1.0f;
1394 
1395  const int8_t *input8 = static_cast<const int8_t *> (input);
1396 
1397  for (unsigned long i = 0; i < frames; i++)
1398  {
1399  float sample_l = input8[i*channels] / scale_factor;
1400  float sample_r = input8[i*channels + (channels - 1)] / scale_factor;
1401 
1402  recorder->append (sample_l, sample_r);
1403  }
1404  }
1405  else if (recorder->get_nbits () == 16)
1406  {
1407  static float scale_factor = std::pow (2.0f, 15) - 1.0f;
1408 
1409  const int16_t *input16 = static_cast<const int16_t *> (input);
1410 
1411  for (unsigned long i = 0; i < frames; i++)
1412  {
1413  float sample_l = input16[i*channels] / scale_factor;
1414  float sample_r = input16[i*channels + (channels - 1)] / scale_factor;
1415 
1416  recorder->append (sample_l, sample_r);
1417  }
1418  }
1419  else if (recorder->get_nbits () == 24)
1420  {
1421  static float scale_factor = std::pow (2.0f, 23);
1422 
1423  // FIXME: Is there a better way?
1424  const uint8_t *input24 = static_cast<const uint8_t *> (input);
1425 
1426  int32_t sample_l32 = 0, sample_r32 = 0;
1427 
1428  uint8_t *sample_l = reinterpret_cast<uint8_t *> (&sample_l32);
1429  uint8_t *sample_r = reinterpret_cast<uint8_t *> (&sample_r32);
1430 
1431  for (unsigned long i = 0; i < frames; i++)
1432  {
1433  for (int j = 0; j < 3; j++)
1434  {
1435  sample_l[j] = input24[i*channels*3 + j];
1436  sample_r[j] = input24[i*channels*3 + (channels - 1)*3 + j];
1437  }
1438 
1439  if (sample_l32 & 0x00800000)
1440  sample_l32 |= 0xff000000;
1441 
1442  if (sample_r32 & 0x00800000)
1443  sample_r32 |= 0xff000000;
1444 
1445  recorder->append (sample_l32 / scale_factor,
1446  sample_r32 / scale_factor);
1447  }
1448  }
1449 
1450  if (recorder->get_sample_number () >= recorder->get_end_sample ())
1451  return paComplete;
1452 
1453  return paContinue;
1454 }
1455 
1456 static void
1457 safe_audiorecorder_stop (audiorecorder *recorder)
1458 {
1459  recorder->stop ();
1460 }
1461 
1462 audiorecorder::audiorecorder (void)
1463  : octave_callback_function (nullptr),
1464  id (-1), fs (44100), nbits (16), channels (2), sample_number (0),
1465  end_sample (-1), tag (""), y (), userdata (Matrix ()),
1466  left (), right (), stream (nullptr), input_parameters (), type ()
1467 { }
1468 
1469 audiorecorder::~audiorecorder (void)
1470 {
1471  if (isrecording ())
1472  {
1473  warning ("Octave:audio-interrupt",
1474  "interrupting recording audiorecorder");
1475  stop ();
1476  }
1477 }
1478 
1479 void
1480 audiorecorder::print (std::ostream& os, bool pr_as_read_syntax)
1481 {
1482  print_raw (os, pr_as_read_syntax);
1483  newline (os);
1484 }
1485 
1486 void
1487 audiorecorder::print_raw (std::ostream& os, bool) const
1488 {
1489  os << 0;
1490 }
1491 
1492 void
1493 audiorecorder::init (void)
1494 {
1495  if (Pa_Initialize () != paNoError)
1496  error ("audiorecorder: initialization error!");
1497 
1498  if (Pa_GetDeviceCount () < 1)
1499  error ("audiorecorder: no audio devices found or available!");
1500 
1501  int device = get_id ();
1502 
1503  if (device == -1)
1504  device = Pa_GetDefaultInputDevice ();
1505 
1506  input_parameters.device = device;
1507  input_parameters.channelCount = get_channels ();
1508  input_parameters.sampleFormat = bits_to_format (get_nbits ());
1509 
1510  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (device);
1511 
1512  if (! device_info)
1513  warning ("Octave:invalid-default-audio-device",
1514  "invalid default audio device ID = %d", device);
1515 
1516  input_parameters.suggestedLatency
1517  = (device_info ? device_info->defaultHighInputLatency : -1);
1518 
1519  input_parameters.hostApiSpecificStreamInfo = nullptr;
1520 }
1521 
1522 void
1523 audiorecorder::set_fs (int fs_arg)
1524 {
1525  fs = fs_arg;
1526 }
1527 
1528 int
1529 audiorecorder::get_fs (void)
1530 {
1531  return fs;
1532 }
1533 
1534 void
1535 audiorecorder::set_nbits (int nbits_arg)
1536 {
1537  nbits = nbits_arg;
1538 }
1539 
1540 int
1541 audiorecorder::get_nbits (void)
1542 {
1543  return nbits;
1544 }
1545 
1546 void
1547 audiorecorder::set_id (int id_arg)
1548 {
1549  id = id_arg;
1550 }
1551 
1552 int
1553 audiorecorder::get_id (void)
1554 {
1555  return id;
1556 }
1557 
1558 void
1559 audiorecorder::set_channels (int channels_arg)
1560 {
1561  assert (channels_arg == 1 || channels_arg == 2);
1562  channels = channels_arg;
1563 }
1564 
1565 int
1566 audiorecorder::get_channels (void)
1567 {
1568  return channels;
1569 }
1570 
1571 audio_type
1572 audiorecorder::get_type (void)
1573 {
1574  return type;
1575 }
1576 
1577 void
1578 audiorecorder::set_sample_number (unsigned int sample_number_arg)
1579 {
1580  sample_number = sample_number_arg;
1581 }
1582 
1583 unsigned int
1584 audiorecorder::get_sample_number (void)
1585 {
1586  return sample_number;
1587 }
1588 
1589 unsigned int
1590 audiorecorder::get_total_samples (void)
1591 {
1592  return left.size ();
1593 }
1594 
1595 void
1596 audiorecorder::set_end_sample (unsigned int end_sample_arg)
1597 {
1598  end_sample = end_sample_arg;
1599 }
1600 
1601 unsigned int
1602 audiorecorder::get_end_sample (void)
1603 {
1604  return end_sample;
1605 }
1606 
1607 void
1608 audiorecorder::reset_end_sample (void)
1609 {
1610  set_end_sample (left.size ());
1611 }
1612 
1613 void
1614 audiorecorder::set_tag (const charMatrix& tag_arg)
1615 {
1616  tag = tag_arg;
1617 }
1618 
1619 charMatrix
1620 audiorecorder::get_tag (void)
1621 {
1622  return tag;
1623 }
1624 
1625 void
1626 audiorecorder::set_userdata (const octave_value& userdata_arg)
1627 {
1628  userdata = userdata_arg;
1629 }
1630 
1632 audiorecorder::get_userdata (void)
1633 {
1634  return userdata;
1635 }
1636 
1638 audiorecorder::getaudiodata (void)
1639 {
1640  Matrix audio (2, left.size ());
1641 
1642  for (unsigned int i = 0; i < left.size (); i++)
1643  {
1644  audio(0,i) = left[i];
1645  audio(1,i) = right[i];
1646  }
1647 
1648  return audio;
1649 }
1650 
1651 audioplayer *
1652 audiorecorder::getplayer (void)
1653 {
1654  audioplayer *player = new audioplayer ();
1655 
1656  player->set_y (getaudiodata ());
1657  player->set_fs (get_fs ());
1658  player->set_nbits (get_nbits ());
1659  player->init ();
1660 
1661  return player;
1662 }
1663 
1664 bool
1665 audiorecorder::isrecording (void)
1666 {
1667  if (get_stream () == nullptr)
1668  return false;
1669 
1670  PaError err;
1671  err = Pa_IsStreamActive (stream);
1672  if (err != 0 && err != 1)
1673  error ("audiorecorder: checking stream activity status failed");
1674 
1675  return (err == 1);
1676 }
1677 
1678 void
1679 audiorecorder::record (void)
1680 {
1681  if (get_stream ())
1682  stop ();
1683 
1684  left.clear ();
1685  right.clear ();
1686 
1687  const unsigned int buffer_size = get_fs () / 20;
1688 
1689  PaError err;
1690  if (octave_callback_function != nullptr)
1691  {
1692  err = Pa_OpenStream (&stream, &(input_parameters), nullptr,
1693  get_fs (), buffer_size, paClipOff,
1694  octave_record_callback, this);
1695  }
1696  else
1697  {
1698  err = Pa_OpenStream (&stream, &(input_parameters), nullptr,
1699  get_fs (), buffer_size, paClipOff,
1700  portaudio_record_callback, this);
1701  }
1702  if (err != paNoError)
1703  error ("audiorecorder: unable to open audio recording stream");
1704 
1705  err = Pa_StartStream (stream);
1706  if (err != paNoError)
1707  error ("audiorecorder: unable to start audio recording stream");
1708 }
1709 
1710 void
1711 audiorecorder::recordblocking (float seconds)
1712 {
1713  if (get_stream ())
1714  stop ();
1715 
1716  left.clear ();
1717  right.clear ();
1718 
1719  const unsigned int buffer_size = get_fs () / 20;
1720  OCTAVE_LOCAL_BUFFER (uint8_t, buffer, buffer_size * 2 * 3);
1721 
1722  PaError err;
1723  err = Pa_OpenStream (&stream, &(input_parameters), nullptr,
1724  get_fs (), buffer_size, paClipOff, nullptr, this);
1725  if (err != paNoError)
1726  error ("audiorecorder: unable to open audio recording stream");
1727 
1728  err = Pa_StartStream (stream);
1729  if (err != paNoError)
1730  error ("audiorecorder: unable to start audio recording stream");
1731 
1732  unsigned int frames = seconds * get_fs ();
1733 
1735 
1736  frame.add_fcn (safe_audiorecorder_stop, this);
1737 
1738  for (unsigned int i = 0; i < frames; i += buffer_size)
1739  {
1740  octave_quit ();
1741 
1742  Pa_ReadStream (get_stream (), buffer, buffer_size);
1743 
1744  if (octave_callback_function != nullptr)
1745  octave_record_callback (buffer, nullptr, buffer_size, nullptr, 0, this);
1746  else
1747  portaudio_record_callback (buffer, nullptr, buffer_size, nullptr, 0, this);
1748  }
1749 }
1750 
1751 void
1752 audiorecorder::pause (void)
1753 {
1754  if (get_stream () == nullptr)
1755  return;
1756 
1757  PaError err;
1758  err = Pa_StopStream (stream);
1759  if (err != paNoError)
1760  error ("audiorecorder: unable to stop audio recording stream");
1761 }
1762 
1763 void
1764 audiorecorder::resume (void)
1765 {
1766  if (get_stream () == nullptr)
1767  return;
1768 
1769  PaError err;
1770  err = Pa_StartStream (stream);
1771  if (err != paNoError)
1772  error ("audiorecorder: unable to start audio recording stream");
1773 }
1774 
1775 void
1776 audiorecorder::stop (void)
1777 {
1778  if (get_stream () == nullptr)
1779  return;
1780 
1781  PaError err;
1782  if (! Pa_IsStreamStopped (get_stream ()))
1783  {
1784  err = Pa_AbortStream (get_stream ());
1785  if (err != paNoError)
1786  error ("audioplayer: unable to stop audio playback stream");
1787  }
1788 
1789  err = Pa_CloseStream (stream);
1790  if (err != paNoError)
1791  error ("audiorecorder: unable to close audio recording stream");
1792 
1793  set_sample_number (0);
1794  reset_end_sample ();
1795  stream = nullptr;
1796 }
1797 
1798 void
1799 audiorecorder::append (float sample_l, float sample_r)
1800 {
1801  left.push_back (sample_l);
1802  right.push_back (sample_r);
1803  set_sample_number (get_sample_number () + 1);
1804 }
1805 
1806 PaStream *
1807 audiorecorder::get_stream (void)
1808 {
1809  return stream;
1810 }
1811 
1812 #endif
1813 
1814 DEFUN_DLD (__recorder_audiorecorder__, args, ,
1815  doc: /* -*- texinfo -*-
1816 @deftypefn {} {@var{recorder} =} __recorder_audiorecorder__ (@var{fs}, @var{nbits}, @var{channels})
1817 @deftypefnx {} {@var{recorder} =} __recorder_audiorecorder__ (@var{fs}, @var{nbits}, @var{channels}, @var{id})
1818 @deftypefnx {} {@var{recorder} =} __recorder_audiorecorder__ (@var{fcn}, @dots{})
1819 Undocumented internal function.
1820 @end deftypefn */)
1821 {
1823 
1824 #if ! defined (HAVE_PORTAUDIO)
1825  octave_unused_parameter (args);
1826 
1827  err_disabled_feature ("__recorder_audiorecorder__",
1828  "audio playback and recording through PortAudio");
1829 #else
1830 
1831  int nargin = args.length ();
1832 
1833  audiorecorder *recorder = new audiorecorder ();
1834 
1835  if (nargin > 0)
1836  {
1837  bool is_function = (args(0).is_string () || args(0).is_function_handle ()
1838  || args(0).is_inline_function ());
1839 
1840  if (is_function)
1841  error ("audioplayer: callbacks not yet implemented");
1842  }
1843 
1844  if (nargin >= 3)
1845  {
1846  recorder->set_fs (args(0).int_value ());
1847  recorder->set_nbits (args(1).int_value ());
1848  recorder->set_channels (args(2).int_value ());
1849  }
1850 
1851  if (nargin == 4)
1852  {
1853  recorder->set_id (args(3).int_value ());
1854  }
1855 
1856  recorder->init ();
1857  retval = recorder;
1858 
1859 #endif
1860 
1861  return retval;
1862 }
1863 
1864 #if defined (HAVE_PORTAUDIO)
1865 
1866 static audiorecorder *
1867 get_recorder (const octave_value& ov)
1868 {
1869  const octave_base_value& rep = ov.get_rep ();
1870 
1871  octave_base_value *ncrep = const_cast<octave_base_value *> (&rep);
1872 
1873  audiorecorder *rec = dynamic_cast<audiorecorder *> (ncrep);
1874  if (! rec)
1875  error ("audiodevinfo.cc get_recorder: dynamic_cast to audiorecorder failed");
1876 
1877  return rec;
1878 }
1879 
1880 #endif
1881 
1882 DEFUN_DLD (__recorder_getaudiodata__, args, ,
1883  doc: /* -*- texinfo -*-
1884 @deftypefn {} {@var{data} =} __recorder_getaudiodata__ (@var{recorder})
1885 Undocumented internal function.
1886 @end deftypefn */)
1887 {
1889 #if ! defined (HAVE_PORTAUDIO)
1890  octave_unused_parameter (args);
1891 
1892  err_disabled_feature ("__recorder_getaudiodata__",
1893  "audio playback and recording through PortAudio");
1894 #else
1895  retval = get_recorder (args(0))->getaudiodata ();
1896 #endif
1897  return retval;
1898 }
1899 
1900 DEFUN_DLD (__recorder_get_channels__, args, ,
1901  doc: /* -*- texinfo -*-
1902 @deftypefn {} {@var{n} =} __recorder_get_channels__ (@var{recorder})
1903 Undocumented internal function.
1904 @end deftypefn */)
1905 {
1907 #if ! defined (HAVE_PORTAUDIO)
1908  octave_unused_parameter (args);
1909 
1910  err_disabled_feature ("__recorder_get_channels__",
1911  "audio playback and recording through PortAudio");
1912 #else
1913  retval = get_recorder (args(0))->get_channels ();
1914 #endif
1915  return retval;
1916 }
1917 
1918 DEFUN_DLD (__recorder_get_fs__, args, ,
1919  doc: /* -*- texinfo -*-
1920 @deftypefn {} {@var{fs} =} __recorder_get_fs__ (@var{recorder})
1921 Undocumented internal function.
1922 @end deftypefn */)
1923 {
1925 #if ! defined (HAVE_PORTAUDIO)
1926  octave_unused_parameter (args);
1927 
1928  err_disabled_feature ("__recorder_get_fs__",
1929  "audio playback and recording through PortAudio");
1930 #else
1931  retval = get_recorder (args(0))->get_fs ();
1932 #endif
1933  return retval;
1934 }
1935 
1936 DEFUN_DLD (__recorder_get_id__, args, ,
1937  doc: /* -*- texinfo -*-
1938 @deftypefn {} {@var{id} =} __recorder_get_id__ (@var{recorder})
1939 Undocumented internal function.
1940 @end deftypefn */)
1941 {
1943 #if ! defined (HAVE_PORTAUDIO)
1944  octave_unused_parameter (args);
1945 
1946  err_disabled_feature ("__recorder_get_id__",
1947  "audio playback and recording through PortAudio");
1948 #else
1949  retval = get_recorder (args(0))->get_id ();
1950 #endif
1951  return retval;
1952 }
1953 
1954 DEFUN_DLD (__recorder_get_nbits__, args, ,
1955  doc: /* -*- texinfo -*-
1956 @deftypefn {} {@var{nbits} =} __recorder_get_nbits__ (@var{recorder})
1957 Undocumented internal function.
1958 @end deftypefn */)
1959 {
1961 #if ! defined (HAVE_PORTAUDIO)
1962  octave_unused_parameter (args);
1963 
1964  err_disabled_feature ("__recorder_get_nbits__",
1965  "audio playback and recording through PortAudio");
1966 #else
1967  retval = get_recorder (args(0))->get_nbits ();
1968 #endif
1969  return retval;
1970 }
1971 
1972 DEFUN_DLD (__recorder_get_sample_number__, args, ,
1973  doc: /* -*- texinfo -*-
1974 @deftypefn {} {@var{n} =} __recorder_get_sample_number__ (@var{recorder})
1975 Undocumented internal function.
1976 @end deftypefn */)
1977 {
1979 #if ! defined (HAVE_PORTAUDIO)
1980  octave_unused_parameter (args);
1981 
1982  err_disabled_feature ("__recorder_get_sample_number__",
1983  "audio playback and recording through PortAudio");
1984 #else
1985  retval = get_recorder (args(0))->get_sample_number ();
1986 #endif
1987  return retval;
1988 }
1989 
1990 DEFUN_DLD (__recorder_get_tag__, args, ,
1991  doc: /* -*- texinfo -*-
1992 @deftypefn {} {@var{tag} =} __recorder_get_tag__ (@var{recorder})
1993 Undocumented internal function.
1994 @end deftypefn */)
1995 {
1997 #if ! defined (HAVE_PORTAUDIO)
1998  octave_unused_parameter (args);
1999 
2000  err_disabled_feature ("__recorder_get_tag__",
2001  "audio playback and recording through PortAudio");
2002 #else
2003  retval = get_recorder (args(0))->get_tag ();
2004 #endif
2005  return retval;
2006 }
2007 
2008 DEFUN_DLD (__recorder_get_total_samples__, args, ,
2009  doc: /* -*- texinfo -*-
2010 @deftypefn {} {@var{n} =} __recorder_get_total_samples__ (@var{recorder})
2011 Undocumented internal function.
2012 @end deftypefn */)
2013 {
2015 #if ! defined (HAVE_PORTAUDIO)
2016  octave_unused_parameter (args);
2017 
2018  err_disabled_feature ("__recorder_get_total_samples__",
2019  "audio playback and recording through PortAudio");
2020 #else
2021  retval = get_recorder (args(0))->get_total_samples ();
2022 #endif
2023  return retval;
2024 }
2025 
2026 DEFUN_DLD (__recorder_get_userdata__, args, ,
2027  doc: /* -*- texinfo -*-
2028 @deftypefn {} {@var{data} =} __recorder_get_userdata__ (@var{recorder})
2029 Undocumented internal function.
2030 @end deftypefn */)
2031 {
2033 #if ! defined (HAVE_PORTAUDIO)
2034  octave_unused_parameter (args);
2035 
2036  err_disabled_feature ("__recorder_get_userdata__",
2037  "audio playback and recording through PortAudio");
2038 #else
2039  retval = get_recorder (args(0))->get_userdata ();
2040 #endif
2041  return retval;
2042 }
2043 
2044 DEFUN_DLD (__recorder_isrecording__, args, ,
2045  doc: /* -*- texinfo -*-
2046 @deftypefn {} {} __recorder_isrecording__ (@var{recorder})
2047 Undocumented internal function.
2048 @end deftypefn */)
2049 {
2051 #if ! defined (HAVE_PORTAUDIO)
2052  octave_unused_parameter (args);
2053 
2054  err_disabled_feature ("__recorder_isrecording__",
2055  "audio playback and recording through PortAudio");
2056 #else
2057  retval = get_recorder (args(0))->isrecording ();
2058 #endif
2059  return retval;
2060 }
2061 
2062 DEFUN_DLD (__recorder_pause__, args, ,
2063  doc: /* -*- texinfo -*-
2064 @deftypefn {} {} __recorder_pause__ (@var{recorder})
2065 Undocumented internal function.
2066 @end deftypefn */)
2067 {
2068 #if ! defined (HAVE_PORTAUDIO)
2069  octave_unused_parameter (args);
2070 
2071  err_disabled_feature ("__recorder_pause__",
2072  "audio playback and recording through PortAudio");
2073 #else
2074  get_recorder (args(0))->pause ();
2075  return ovl ();
2076 #endif
2077 }
2078 
2079 DEFUN_DLD (__recorder_recordblocking__, args, ,
2080  doc: /* -*- texinfo -*-
2081 @deftypefn {} {} __recorder_recordblocking__ (@var{recorder}, @var{seconds})
2082 Undocumented internal function.
2083 @end deftypefn */)
2084 {
2085 #if ! defined (HAVE_PORTAUDIO)
2086  octave_unused_parameter (args);
2087 
2088  err_disabled_feature ("__recorder_recordblocking__",
2089  "audio playback and recording through PortAudio");
2090 #else
2091  float seconds = args(1).float_value ();
2092  get_recorder (args(0))->recordblocking (seconds);
2093  return ovl ();
2094 #endif
2095 }
2096 
2097 DEFUN_DLD (__recorder_record__, args, ,
2098  doc: /* -*- texinfo -*-
2099 @deftypefn {} {} __recorder_record__ (@var{recorder})
2100 @deftypefnx {} {} __recorder_record__ (@var{recorder}, @var{seconds})
2101 Undocumented internal function.
2102 @end deftypefn */)
2103 {
2104 #if ! defined (HAVE_PORTAUDIO)
2105  octave_unused_parameter (args);
2106 
2107  err_disabled_feature ("__recorder_record__",
2108  "audio playback and recording through PortAudio");
2109 #else
2110  audiorecorder *recorder = get_recorder (args(0));
2111 
2112  if (args.length () == 2)
2113  recorder->set_end_sample (args(1).int_value () * recorder->get_fs ());
2114 
2115  recorder->record ();
2116  return ovl ();
2117 #endif
2118 }
2119 
2120 DEFUN_DLD (__recorder_resume__, args, ,
2121  doc: /* -*- texinfo -*-
2122 @deftypefn {} {} __recorder_resume__ (@var{recorder})
2123 Undocumented internal function.
2124 @end deftypefn */)
2125 {
2126 #if ! defined (HAVE_PORTAUDIO)
2127  octave_unused_parameter (args);
2128 
2129  err_disabled_feature ("__recorder_resume__",
2130  "audio playback and recording through PortAudio");
2131 #else
2132  if (args.length () == 1)
2133  get_recorder (args(0))->resume ();
2134  return ovl ();
2135 #endif
2136 }
2137 
2138 DEFUN_DLD (__recorder_set_fs__, args, ,
2139  doc: /* -*- texinfo -*-
2140 @deftypefn {} {} __recorder_set_fs__ (@var{recorder}, @var{fs})
2141 Undocumented internal function.
2142 @end deftypefn */)
2143 {
2144 #if ! defined (HAVE_PORTAUDIO)
2145  octave_unused_parameter (args);
2146 
2147  err_disabled_feature ("__recorder_set_fs__",
2148  "audio playback and recording through PortAudio");
2149 #else
2150  if (args.length () == 2)
2151  get_recorder (args(0))->set_fs (args(1).int_value ());
2152  return ovl ();
2153 #endif
2154 }
2155 
2156 DEFUN_DLD (__recorder_set_tag__, args, ,
2157  doc: /* -*- texinfo -*-
2158 @deftypefn {} {} __recorder_set_tag__ (@var{recorder}, @var{tag})
2159 Undocumented internal function.
2160 @end deftypefn */)
2161 {
2162 #if ! defined (HAVE_PORTAUDIO)
2163  octave_unused_parameter (args);
2164 
2165  err_disabled_feature ("__recorder_set_tag__",
2166  "audio playback and recording through PortAudio");
2167 #else
2168  if (args.length () == 2)
2169  get_recorder (args(0))->set_tag (args(1).char_matrix_value ());
2170  return ovl ();
2171 #endif
2172 }
2173 
2174 DEFUN_DLD (__recorder_set_userdata__, args, ,
2175  doc: /* -*- texinfo -*-
2176 @deftypefn {} {} __recorder_set_userdata__ (@var{recorder}, @var{data})
2177 Undocumented internal function.
2178 @end deftypefn */)
2179 {
2180 #if ! defined (HAVE_PORTAUDIO)
2181  octave_unused_parameter (args);
2182 
2183  err_disabled_feature ("__recorder_set_userdata__",
2184  "audio playback and recording through PortAudio");
2185 #else
2186  if (args.length () == 2)
2187  get_recorder (args(0))->set_userdata (args(1));
2188  return ovl ();
2189 #endif
2190 }
2191 
2192 DEFUN_DLD (__recorder_stop__, args, ,
2193  doc: /* -*- texinfo -*-
2194 @deftypefn {} {} __recorder_stop__ (@var{recorder})
2195 Undocumented internal function.
2196 @end deftypefn */)
2197 {
2198 #if ! defined (HAVE_PORTAUDIO)
2199  octave_unused_parameter (args);
2200 
2201  err_disabled_feature ("__recorder_stop__",
2202  "audio playback and recording through PortAudio");
2203 #else
2204  if (args.length () == 1)
2205  get_recorder (args(0))->stop ();
2206  return ovl ();
2207 #endif
2208 }
2209 
2210 DEFUN_DLD (__player_audioplayer__, args, ,
2211  doc: /* -*- texinfo -*-
2212 @deftypefn {} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs})
2213 @deftypefnx {} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs}, @var{nbits})
2214 @deftypefnx {} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs}, @var{nbits}, @var{id})
2215 Undocumented internal function.
2216 @end deftypefn */)
2217 {
2219 #if ! defined (HAVE_PORTAUDIO)
2220  octave_unused_parameter (args);
2221 
2222  err_disabled_feature ("__player_audioplayer__",
2223  "audio playback and recording through PortAudio");
2224 #else
2225 
2226  audioplayer *recorder = new audioplayer ();
2227 
2228  if (! recorder)
2229  error ("__player_audioplayer__: Couldn't instantiate new audioplayer");
2230 
2231  bool is_function = (args(0).is_string () || args(0).is_function_handle ()
2232  || args(0).is_inline_function ());
2233 
2234  if (is_function)
2235  error ("audioplayer: callbacks not yet implemented");
2236 
2237  recorder->set_y (args(0));
2238  recorder->set_fs (args(1).int_value ());
2239 
2240  switch (args.length ())
2241  {
2242  case 3:
2243  recorder->set_nbits (args(2).int_value ());
2244  break;
2245 
2246  case 4:
2247  recorder->set_nbits (args(2).int_value ());
2248  recorder->set_id (args(3).int_value ());
2249  break;
2250  }
2251 
2252  if (is_function)
2253  recorder->init_fn ();
2254  else
2255  recorder->init ();
2256 
2257  retval = recorder;
2258 #endif
2259  return retval;
2260 }
2261 
2262 #if defined (HAVE_PORTAUDIO)
2263 
2264 static audioplayer *
2265 get_player (const octave_value& ov)
2266 {
2267  const octave_base_value& rep = ov.get_rep ();
2268 
2269  octave_base_value *ncrep = const_cast<octave_base_value *> (&rep);
2270 
2271  audioplayer *pl = dynamic_cast<audioplayer *> (ncrep);
2272  if (! pl)
2273  error ("audiodevinfo.cc get_player: dynamic_cast to audioplayer failed");
2274 
2275  return pl;
2276 }
2277 
2278 #endif
2279 
2280 DEFUN_DLD (__player_get_channels__, args, ,
2281  doc: /* -*- texinfo -*-
2282 @deftypefn {} {@var{n} =} __player_get_channels__ (@var{player})
2283 Undocumented internal function.
2284 @end deftypefn */)
2285 {
2287 #if ! defined (HAVE_PORTAUDIO)
2288  octave_unused_parameter (args);
2289 
2290  err_disabled_feature ("__player_get_channels__",
2291  "audio playback and recording through PortAudio");
2292 #else
2293  if (args.length () == 1)
2294  retval = get_player (args(0))->get_channels ();
2295 #endif
2296  return retval;
2297 }
2298 
2299 DEFUN_DLD (__player_get_fs__, args, ,
2300  doc: /* -*- texinfo -*-
2301 @deftypefn {} {@var{fs} =} __player_get_fs__ (@var{player})
2302 Undocumented internal function.
2303 @end deftypefn */)
2304 {
2306 #if ! defined (HAVE_PORTAUDIO)
2307  octave_unused_parameter (args);
2308 
2309  err_disabled_feature ("__player_get_fs__",
2310  "audio playback and recording through PortAudio");
2311 #else
2312  if (args.length () == 1)
2313  retval = get_player (args(0))->get_fs ();
2314 #endif
2315  return retval;
2316 }
2317 
2318 DEFUN_DLD (__player_get_id__, args, ,
2319  doc: /* -*- texinfo -*-
2320 @deftypefn {} {@var{id} =} __player_get_id__ (@var{player})
2321 Undocumented internal function.
2322 @end deftypefn */)
2323 {
2325 #if ! defined (HAVE_PORTAUDIO)
2326  octave_unused_parameter (args);
2327 
2328  err_disabled_feature ("__player_get_id__",
2329  "audio playback and recording through PortAudio");
2330 #else
2331  if (args.length () == 1)
2332  retval = get_player (args(0))->get_id ();
2333 #endif
2334  return retval;
2335 }
2336 
2337 DEFUN_DLD (__player_get_nbits__, args, ,
2338  doc: /* -*- texinfo -*-
2339 @deftypefn {} {@var{nbits} =} __player_get_nbits__ (@var{player})
2340 Undocumented internal function.
2341 @end deftypefn */)
2342 {
2344 #if ! defined (HAVE_PORTAUDIO)
2345  octave_unused_parameter (args);
2346 
2347  err_disabled_feature ("__player_get_nbits__",
2348  "audio playback and recording through PortAudio");
2349 #else
2350  if (args.length () == 1)
2351  retval = get_player (args(0))->get_nbits ();
2352 #endif
2353  return retval;
2354 }
2355 
2356 DEFUN_DLD (__player_get_sample_number__, args, ,
2357  doc: /* -*- texinfo -*-
2358 @deftypefn {} {@var{n} =} __player_get_sample_number__ (@var{player})
2359 Undocumented internal function.
2360 @end deftypefn */)
2361 {
2363 #if ! defined (HAVE_PORTAUDIO)
2364  octave_unused_parameter (args);
2365 
2366  err_disabled_feature ("__player_get_sample_number__",
2367  "audio playback and recording through PortAudio");
2368 #else
2369  if (args.length () == 1)
2370  retval = get_player (args(0))->get_sample_number ();
2371 #endif
2372  return retval;
2373 }
2374 
2375 DEFUN_DLD (__player_get_tag__, args, ,
2376  doc: /* -*- texinfo -*-
2377 @deftypefn {} {@var{tag} =} __player_get_tag__ (@var{player})
2378 Undocumented internal function.
2379 @end deftypefn */)
2380 {
2382 #if ! defined (HAVE_PORTAUDIO)
2383  octave_unused_parameter (args);
2384 
2385  err_disabled_feature ("__player_get_tag__",
2386  "audio playback and recording through PortAudio");
2387 #else
2388  if (args.length () == 1)
2389  retval = get_player (args(0))->get_tag ();
2390 #endif
2391  return retval;
2392 }
2393 
2394 DEFUN_DLD (__player_get_total_samples__, args, ,
2395  doc: /* -*- texinfo -*-
2396 @deftypefn {} {@var{n} =} __player_get_total_samples__ (@var{player})
2397 Undocumented internal function.
2398 @end deftypefn */)
2399 {
2401 #if ! defined (HAVE_PORTAUDIO)
2402  octave_unused_parameter (args);
2403 
2404  err_disabled_feature ("__player_get_total_samples__",
2405  "audio playback and recording through PortAudio");
2406 #else
2407  if (args.length () == 1)
2408  retval = get_player (args(0))->get_total_samples ();
2409 #endif
2410  return retval;
2411 }
2412 
2413 DEFUN_DLD (__player_get_userdata__, args, ,
2414  doc: /* -*- texinfo -*-
2415 @deftypefn {} {@var{data} =} __player_get_userdata__ (@var{player})
2416 Undocumented internal function.
2417 @end deftypefn */)
2418 {
2420 #if ! defined (HAVE_PORTAUDIO)
2421  octave_unused_parameter (args);
2422 
2423  err_disabled_feature ("__player_get_userdata__",
2424  "audio playback and recording through PortAudio");
2425 #else
2426  if (args.length () == 1)
2427  retval = get_player (args(0))->get_userdata ();
2428 #endif
2429  return retval;
2430 }
2431 
2432 DEFUN_DLD (__player_isplaying__, args, ,
2433  doc: /* -*- texinfo -*-
2434 @deftypefn {} {} __player_isplaying__ (@var{player})
2435 Undocumented internal function.
2436 @end deftypefn */)
2437 {
2439 #if ! defined (HAVE_PORTAUDIO)
2440  octave_unused_parameter (args);
2441 
2442  err_disabled_feature ("__player_isplaying__",
2443  "audio playback and recording through PortAudio");
2444 #else
2445  if (args.length () == 1)
2446  retval = get_player (args(0))->isplaying ();
2447 #endif
2448  return retval;
2449 }
2450 
2451 DEFUN_DLD (__player_pause__, args, ,
2452  doc: /* -*- texinfo -*-
2453 @deftypefn {} {} __player_pause__ (@var{player})
2454 Undocumented internal function.
2455 @end deftypefn */)
2456 {
2457 #if ! defined (HAVE_PORTAUDIO)
2458  octave_unused_parameter (args);
2459 
2460  err_disabled_feature ("__player_pause__",
2461  "audio playback and recording through PortAudio");
2462 #else
2463  if (args.length () == 1)
2464  get_player (args(0))->pause ();
2465  return ovl ();
2466 #endif
2467 }
2468 
2469 DEFUN_DLD (__player_playblocking__, args, ,
2470  doc: /* -*- texinfo -*-
2471 @deftypefn {} {} __player_playblocking__ (@var{player})
2472 @deftypefnx {} {} __player_playblocking__ (@var{player}, @var{start})
2473 @deftypefnx {} {} __player_playblocking__ (@var{player}, [@var{start}, @var{end}])
2474 Undocumented internal function.
2475 @end deftypefn */)
2476 {
2477 #if ! defined (HAVE_PORTAUDIO)
2478  octave_unused_parameter (args);
2479 
2480  err_disabled_feature ("__player_playblocking__",
2481  "audio playback and recording through PortAudio");
2482 #else
2483 
2484  audioplayer *player = get_player (args(0));
2485 
2486  if (args.length () == 1)
2487  {
2488  player->playblocking ();
2489  }
2490  else if (args.length () == 2)
2491  {
2492  if (args(1).is_matrix_type ())
2493  {
2494  RowVector range = args(1).row_vector_value ();
2495 
2496  unsigned int start = range.elem (0) - 1;
2497  unsigned int end = range.elem (1) - 1;
2498 
2499  if (start > player->get_total_samples ()
2500  || start > end || end > player->get_total_samples ())
2501  error ("audioplayer: invalid range specified for playback");
2502 
2503  player->set_sample_number (start);
2504  player->set_end_sample (end);
2505  }
2506  else
2507  {
2508  unsigned int start = args(1).int_value () - 1;
2509 
2510  if (start > player->get_total_samples ())
2511  error ("audioplayer: invalid range specified for playback");
2512 
2513  player->set_sample_number (start);
2514  }
2515 
2516  player->playblocking ();
2517  }
2518 
2519  return ovl ();
2520 #endif
2521 }
2522 
2523 DEFUN_DLD (__player_play__, args, ,
2524  doc: /* -*- texinfo -*-
2525 @deftypefn {} {} __player_play__ (@var{player})
2526 @deftypefnx {} {} __player_play__ (@var{player}, @var{start})
2527 @deftypefnx {} {} __player_play__ (@var{player}, [@var{start}, @var{end}])
2528 Undocumented internal function.
2529 @end deftypefn */)
2530 {
2531 #if ! defined (HAVE_PORTAUDIO)
2532  octave_unused_parameter (args);
2533 
2534  err_disabled_feature ("__player_play__",
2535  "audio playback and recording through PortAudio");
2536 #else
2537 
2538  if (args.length () == 1)
2539  {
2540  get_player (args(0))->play ();
2541  }
2542  else if (args.length () == 2)
2543  {
2544  audioplayer *player = get_player (args(0));
2545 
2546  if (args(1).is_matrix_type ())
2547  {
2548  RowVector range = args(1).row_vector_value ();
2549 
2550  unsigned int start = range.elem (0) - 1;
2551  unsigned int end = range.elem (1) - 1;
2552 
2553  if (start > player->get_total_samples ()
2554  || start > end || end > player->get_total_samples ())
2555  error ("audioplayer: invalid range specified for playback");
2556 
2557  player->set_sample_number (start);
2558  player->set_end_sample (end);
2559  }
2560  else
2561  {
2562  unsigned int start = args(1).int_value () - 1;
2563 
2564  if (start > player->get_total_samples ())
2565  error ("audioplayer: invalid range specified for playback");
2566 
2567  player->set_sample_number (start);
2568  }
2569 
2570  player->play ();
2571  }
2572 
2573  return ovl ();
2574 #endif
2575 }
2576 
2577 DEFUN_DLD (__player_resume__, args, ,
2578  doc: /* -*- texinfo -*-
2579 @deftypefn {} {} __player_resume__ (@var{player})
2580 Undocumented internal function.
2581 @end deftypefn */)
2582 {
2583 #if ! defined (HAVE_PORTAUDIO)
2584  octave_unused_parameter (args);
2585 
2586  err_disabled_feature ("__player_resume__",
2587  "audio playback and recording through PortAudio");
2588 #else
2589  if (args.length () == 1)
2590  get_player (args(0))->resume ();
2591  return ovl ();
2592 #endif
2593 }
2594 
2595 DEFUN_DLD (__player_set_fs__, args, ,
2596  doc: /* -*- texinfo -*-
2597 @deftypefn {} {} __player_set_fs__ (@var{player}, @var{fs})
2598 Undocumented internal function.
2599 @end deftypefn */)
2600 {
2601 #if ! defined (HAVE_PORTAUDIO)
2602  octave_unused_parameter (args);
2603 
2604  err_disabled_feature ("__player_set_fs__",
2605  "audio playback and recording through PortAudio");
2606 #else
2607  if (args.length () == 2)
2608  get_player (args(0))->set_fs (args(1).int_value ());
2609  return ovl ();
2610 #endif
2611 }
2612 
2613 DEFUN_DLD (__player_set_tag__, args, ,
2614  doc: /* -*- texinfo -*-
2615 @deftypefn {} {} __player_set_tag__ (@var{player}, @var{tag})
2616 Undocumented internal function.
2617 @end deftypefn */)
2618 {
2619 #if ! defined (HAVE_PORTAUDIO)
2620  octave_unused_parameter (args);
2621 
2622  err_disabled_feature ("__player_set_tag__",
2623  "audio playback and recording through PortAudio");
2624 #else
2625  if (args.length () == 2)
2626  get_player (args(0))->set_tag (args(1).char_matrix_value ());
2627  return ovl ();
2628 #endif
2629 }
2630 
2631 DEFUN_DLD (__player_set_userdata__, args, ,
2632  doc: /* -*- texinfo -*-
2633 @deftypefn {} {} __player_set_userdata__ (@var{player}, @var{data})
2634 Undocumented internal function.
2635 @end deftypefn */)
2636 {
2637 #if ! defined (HAVE_PORTAUDIO)
2638  octave_unused_parameter (args);
2639 
2640  err_disabled_feature ("__player_set_userdata__",
2641  "audio playback and recording through PortAudio");
2642 #else
2643  if (args.length () == 2)
2644  get_player (args(0))->set_userdata (args(1));
2645  return ovl ();
2646 #endif
2647 }
2648 
2649 DEFUN_DLD (__player_stop__, args, ,
2650  doc: /* -*- texinfo -*-
2651 @deftypefn {} {} __player_stop__ (@var{player})
2652 Undocumented internal function.
2653 @end deftypefn */)
2654 {
2655 #if ! defined (HAVE_PORTAUDIO)
2656  octave_unused_parameter (args);
2657 
2658  err_disabled_feature ("__player_stop__",
2659  "audio playback and recording through PortAudio");
2660 #else
2661  if (args.length () == 1)
2662  get_player (args(0))->stop ();
2663  return ovl ();
2664 #endif
2665 }
uint32_t id
Definition: graphics.cc:12193
OCTINTERP_API octave_value_list feval(const std::string &name, const octave_value_list &args=octave_value_list(), int nargout=0)
octave_idx_type rows(void) const
Definition: Array.h:404
static int left
Definition: randmtzig.cc:184
Definition: Cell.h:37
is already an absolute the name is checked against the file system instead of Octave s loadpath In this if otherwise an empty string is returned If the first argument is a cell array of search each directory of the loadpath for element of the cell array and return the first that matches If the second optional argument return a cell array containing the list of all files that have the same name in the path If no files are found
Definition: utils.cc:305
int int_value(bool req_int=false, bool frc_str_conv=false) const
Definition: ov.h:793
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:148
const T * data(void) const
Definition: Array.h:582
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE * f
void add_fcn(void(*fcn)(void))
void error(const char *fmt,...)
Definition: error.cc:578
void setfield(const std::string &key, const octave_value &val)
Definition: oct-map.cc:191
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:180
const octave_base_value & get_rep(void) const
Definition: ov.h:1327
octave_idx_type columns(void) const
Definition: Array.h:413
pause(0.05)
in this the arguments are accumulated from left to right
Definition: data.cc:390
bool is_int16_type(void) const
Definition: ov.h:666
virtual bool is_constant(void) const
Definition: ov-base.h:461
virtual void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-base.cc:401
octave_value & elem(octave_idx_type n)
Definition: ovl.h:162
#define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
Definition: ov-base.h:158
nd deftypefn *std::string name
Definition: sysdep.cc:647
octave_int< T > pow(const octave_int< T > &a, const octave_int< T > &b)
octave_value retval
Definition: data.cc:6246
bool append
Definition: load-save.cc:1618
ColumnVector column(octave_idx_type i) const
Definition: dMatrix.cc:421
idx type
Definition: ov.cc:3114
Definition: dMatrix.h:36
virtual bool print_as_scalar(void) const
Definition: ov-base.h:651
virtual double scalar_value(bool frc_str_conv=false) const
Definition: ov-base.h:507
OCTAVE_EXPORT octave_value_list or cell arrays Arguments are concatenated vertically The returned values are padded with blanks as needed to make each row of the string array have the same length Empty input strings are significant and will concatenated in the output For numerical input
Definition: strfns.cc:81
LS_TEXT format
Definition: load-save.cc:1616
bool is_int8_type(void) const
Definition: ov.h:663
bool words_big_endian(void)
Definition: mach-info.cc:69
void setfield(const std::string &key, const Cell &val)
Definition: oct-map.cc:283
void warning(const char *fmt,...)
Definition: error.cc:801
octave::unwind_protect frame
Definition: graphics.cc:12190
octave::sys::time start
Definition: graphics.cc:12337
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).isinteger())
virtual bool is_defined(void) const
Definition: ov-base.h:357
the element is set to zero In other the statement xample y
Definition: data.cc:5264
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:41
octave::sys::file_stat fs(filename)
args.length() nargin
Definition: file-io.cc:589
for i
Definition: data.cc:5264
#define DEFUN_DLD(name, args_name, nargout_name, doc)
Macro to define an at run time dynamically loadable builtin function.
Definition: defun-dld.h:58
OCTAVE_EXPORT octave_value_list error nd deftypefn *const octave_scalar_map err
Definition: error.cc:1049
OCTAVE_EXPORT octave_value_list or cell arrays Arguments are concatenated vertically The returned values are padded with blanks as needed to make each row of the string array have the same length Empty input strings are significant and will concatenated in the output For numerical each element is converted to the corresponding ASCII character A range error results if an input is outside the ASCII range(0-255). For cell arrays
octave_idx_type length(void) const
virtual void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov-base.cc:407
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
bool is_uint8_type(void) const
Definition: ov.h:675
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition: errwarn.cc:50
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
octave::stream os
Definition: file-io.cc:627
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:834