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