GNU Octave  4.0.0
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-2015 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 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 // <cstdint> requires c++11
28 #include <stdint.h>
29 
30 #include <string>
31 #include <vector>
32 
33 #include "mach-info.h"
34 
35 #include "defun-dld.h"
36 #include "error.h"
37 #include "gripes.h"
38 #include "oct-locbuf.h"
39 #include "oct-obj.h"
40 #include "ov.h"
41 #include "ov-int32.h"
42 #include "ov-struct.h"
43 #include "parse.h"
44 #include "unwind-prot.h"
45 
46 #if defined (HAVE_PORTAUDIO)
47 
48 #include <portaudio.h>
49 
50 PaSampleFormat
51 bits_to_format (int bits)
52 {
53  if (bits == 8)
54  return paInt8;
55  else if (bits == 16)
56  return paInt16;
57  else if (bits == 24)
58  return paInt24;
59  else if (bits == 32)
60  return paInt32;
61  else if (bits == -1)
62  return paFloat32;
63  else
64  return 0;
65 }
66 
67 #endif
68 
69 DEFUN_DLD (audiodevinfo, args, ,
70  "-*- texinfo -*-\n\
71 @deftypefn {Loadable Function} {@var{devinfo} =} audiodevinfo ()\n\
72 \n\
73 @deftypefnx {Loadable Function} {@var{devs} =} audiodevinfo (@var{io})\n\
74 @deftypefnx {Loadable Function} {@var{name} =} audiodevinfo (@var{io}, @var{id})\n\
75 @deftypefnx {Loadable Function} {@var{id} =} audiodevinfo (@var{io}, @var{name})\n\
76 @deftypefnx {Loadable Function} {@var{id} =} audiodevinfo (@var{io}, @var{rate}, @var{bits}, @var{chans})\n\
77 \n\
78 @deftypefnx {Loadable Function} {@var{supports} =} audiodevinfo (@var{io}, @var{id}, @var{rate}, @var{bits}, @var{chans})\n\
79 \n\
80 Return a structure describing the available audio input and output devices.\n\
81 \n\
82 The @var{devinfo} structure has two fields @qcode{\"input\"} and\n\
83 @qcode{\"output\"}. The value of each field is a structure array with fields\n\
84 @qcode{\"Name\"}, @nospell{\"DriverVersion\"} and @qcode{\"ID\"} describing\n\
85 an audio device.\n\
86 \n\
87 If the optional argument @var{io} is 1, return information about input\n\
88 devices only. If it is 0, return information about output devices only.\n\
89 \n\
90 If the optional argument @var{id} is provided, return information about\n\
91 the corresponding device.\n\
92 \n\
93 If the optional argument @var{name} is provided, return the id of the\n\
94 named device.\n\
95 \n\
96 Given a sampling rate, bits per sample, and number of channels for an input\n\
97 or output device, return the ID of the first device that supports playback\n\
98 or recording using the specified parameters.\n\
99 \n\
100 If also given a device ID, return true if the device supports playback or\n\
101 recording using those parameters.\n\
102 @end deftypefn")
103 {
104  octave_value retval;
105 
106 #ifdef HAVE_PORTAUDIO
107 
108  int nargin = args.length ();
109 
110  octave_scalar_map devinfo;
112  octave_value_list output;
113 
114  PaError err = Pa_Initialize ();
115 
116  if (err != paNoError)
117  {
118  error ("audiodevinfo: PortAudio initialization failed");
119  return retval;
120  }
121 
122  int num_devices = Pa_GetDeviceCount ();
123 
124  if (num_devices < 0)
125  {
126  error ("audiodevinfo: no audio device found");
127  return retval;
128  }
129 
130  octave_idx_type numinput = 0, numoutput = 0;
131  for (int i = 0; i < num_devices; i++)
132  {
133  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);
134 
135  if (! device_info)
136  {
137  warning ("Octave:invalid-audio-device",
138  "invalid audio device ID = %d", i);
139  continue;
140  }
141 
142  if (device_info->maxInputChannels != 0)
143  numinput++;
144 
145  if (device_info->maxOutputChannels != 0)
146  numoutput++;
147  }
148 
149  Cell input_name (dim_vector (1, numinput));
150  Cell input_driver_version (dim_vector (1, numinput));
151  Cell input_id (dim_vector (1, numinput));
152  Cell output_name (dim_vector (1, numoutput));
153  Cell output_driver_version (dim_vector (1, numoutput));
154  Cell output_id (dim_vector (1, numoutput));
155 
156  octave_idx_type idx_i = 0, idx_o = 0;
157  for (int i = 0; i < num_devices; i++)
158  {
159  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);
160 
161  if (! device_info)
162  {
163  warning ("Octave:invalid-audio-device",
164  "invalid audio device ID = %d", i);
165  continue;
166  }
167 
168  const PaHostApiInfo *api_info = Pa_GetHostApiInfo (device_info->hostApi);
169 
170  const char *driver = api_info ? api_info->name : "";
171 
172  char name[128];
173  sprintf (name, "%s (%s)", device_info->name, driver);
174 
175  if (device_info->maxInputChannels != 0)
176  {
177  input_name(idx_i) = name;
178  input_driver_version(idx_i) = driver;
179  input_id(idx_i) = i;
180  idx_i++;
181  }
182 
183  if (device_info->maxOutputChannels != 0)
184  {
185  output_name(idx_o) = name;
186  output_driver_version(idx_o) = driver;
187  output_id(idx_o) = i;
188  idx_o++;
189  }
190  }
191 
192  octave_map inputdev, outputdev;
193  inputdev.setfield ("Name", input_name);
194  inputdev.setfield ("DriverVersion", input_driver_version);
195  inputdev.setfield ("ID", input_id);
196  outputdev.setfield ("Name", output_name);
197  outputdev.setfield ("DriverVersion", output_driver_version);
198  outputdev.setfield ("ID", output_id);
199  devinfo.setfield ("input", inputdev);
200  devinfo.setfield ("output", outputdev);
201 
202  // Return information about input and output audio devices and
203  // their properties.
204  if (nargin == 0)
205  retval = devinfo;
206  // Return the number of input or output devices
207  else if (nargin == 1)
208  {
209  if (args(0).int_value () == 0)
210  retval = numoutput;
211  else if (args(0).int_value () == 1)
212  retval = numinput;
213  else
214  {
215  error ("audiodevinfo: please specify 0 for output and 1 for input devices");
216  return retval;
217  }
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  {
252  error ("audiodevinfo: please specify 0 for output and 1 for input devices");
253  return retval;
254  }
255  }
256  else
257  {
258  if (outin == 0)
259  {
260  for (int i = 0; i < numoutput; i++)
261  {
262  if (output_id(i).int_value () == args(1).int_value ())
263  {
264  retval = output_name(i);
265  found = true;
266  break;
267  }
268  }
269  }
270  else if (outin == 1)
271  {
272  for (int i = 0; i < numinput; i++)
273  {
274  if (input_id(i).int_value () == args(1).int_value ())
275  {
276  retval = input_name(i);
277  found = true;
278  break;
279  }
280  }
281  }
282  else
283  {
284  error ("audiodevinfo: please specify 0 for output and 1 for input devices");
285  return retval;
286  }
287  }
288  if (! found)
289  error ("audiodevinfo: no device meeting the specified criteria found");
290  }
291  else if (nargin == 3)
292  {
293  // FIXME: what was supposed to happen here?
294  }
295  // Return the id of the first device meeting specified criteria.
296  else if (nargin == 4)
297  {
298  int io = args(0).int_value ();
299  int rate = args(1).int_value ();
300  int bits = args(2).int_value ();
301  int chans = args(3).int_value ();
302 
303  for (int i = 0; i < num_devices; i++)
304  {
305  PaStreamParameters stream_parameters;
306  stream_parameters.device = i;
307  stream_parameters.channelCount = chans;
308  PaSampleFormat format = bits_to_format (bits);
309 
310  if (format != 0)
311  stream_parameters.sampleFormat = format;
312  else
313  {
314  error ("audiodevinfo: no such bits per sample format");
315  return retval;
316  }
317 
318  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);
319 
320  if (! device_info)
321  {
322  warning ("Octave:invalid-audio-device",
323  "invalid audio device ID = %d", i);
324  continue;
325  }
326 
327  stream_parameters.suggestedLatency
328  = device_info->defaultLowInputLatency;
329 
330  stream_parameters.hostApiSpecificStreamInfo = 0;
331 
332  if (io == 0)
333  {
334  if (device_info->maxOutputChannels < chans)
335  continue;
336 
337  err = Pa_IsFormatSupported (0, &stream_parameters, rate);
338 
339  if (err == paFormatIsSupported)
340  {
341  retval = i;
342  return retval;
343  }
344  }
345  else if (io == 1)
346  {
347  if (device_info->maxInputChannels < chans)
348  continue;
349 
350  err = Pa_IsFormatSupported (&stream_parameters, 0, rate);
351  if (err == paFormatIsSupported)
352  {
353  retval = i;
354  return retval;
355  }
356  }
357  }
358  retval = -1;
359  }
360  // Check if given device supports specified playback or recording modes.
361  else if (nargin == 5)
362  {
363  int io = args(0).int_value ();
364  int id = args(1).int_value ();
365  int rate = args(2).int_value ();
366  int bits = args(3).int_value ();
367  int chans = args(4).int_value ();
368  PaStreamParameters stream_parameters;
369  stream_parameters.device = id;
370  stream_parameters.channelCount = chans;
371  PaSampleFormat format = bits_to_format (bits);
372  if (format != 0)
373  stream_parameters.sampleFormat = format;
374  else
375  {
376  error ("audiodevinfo: no such bits per sample format");
377  return retval;
378  }
379 
380  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (id);
381 
382  if (! device_info)
383  {
384  error ("invalid audio device ID = %d", id);
385  return retval;
386  }
387 
388  stream_parameters.suggestedLatency
389  = device_info->defaultLowInputLatency;
390 
391  stream_parameters.hostApiSpecificStreamInfo = 0;
392  if (io == 0)
393  {
394  if (device_info->maxOutputChannels < chans)
395  {
396  retval = 0;
397  return retval;
398  }
399  err = Pa_IsFormatSupported (0, &stream_parameters, rate);
400  if (err == paFormatIsSupported)
401  {
402  retval = 1;
403  return retval;
404  }
405  }
406  else if (io == 1)
407  {
408  if (device_info->maxInputChannels < chans)
409  {
410  retval = 0;
411  return retval;
412  }
413  err = Pa_IsFormatSupported (&stream_parameters, 0, rate);
414  if (err == paFormatIsSupported)
415  {
416  retval = 1;
417  return retval;
418  }
419  }
420  else
421  {
422  error ("audiodevinfo: please specify 0 for output and 1 for input devices");
423  return retval;
424  }
425  retval = 0;
426  }
427  else
428  {
429  error ("audiodevinfo: wrong number of arguments");
430  return retval;
431  }
432 #else
433 
434  error ("portaudio not found on your system and thus audio functionality is not present");
435 
436 #endif
437 
438  return retval;
439 }
440 
441 /*
442 %!testif HAVE_PORTAUDIO
443 %! devinfo = audiodevinfo;
444 %! assert (rows (devinfo.input), 1);
445 %! assert (rows (devinfo.output), 1);
446 
447 %!testif HAVE_PORTAUDIO
448 %! devinfo = audiodevinfo;
449 %! nout = audiodevinfo (0);
450 %! nin = audiodevinfo (1);
451 %! assert (columns (devinfo.output), nout);
452 %! assert (columns (devinfo.input), nin);
453 
454 %!testif HAVE_PORTAUDIO
455 %! devinfo = audiodevinfo;
456 %! nout = audiodevinfo (0);
457 %! nin = audiodevinfo (1);
458 %! for i = 1:nout,
459 %! assert (devinfo.output(i).Name, audiodevinfo (0, devinfo.output(i).ID))
460 %! endfor
461 %! for i=1:nin,
462 %! assert (devinfo.input(i).Name, audiodevinfo (1, devinfo.input(i).ID))
463 %! endfor
464 
465 %!testif HAVE_PORTAUDIO
466 %! devinfo = audiodevinfo;
467 %! nout = audiodevinfo (0);
468 %! nin = audiodevinfo (1);
469 %! for i = 1:nout,
470 %! assert (devinfo.output(i).ID, audiodevinfo (0, devinfo.output(i).Name))
471 %! endfor
472 %! for i = 1:nin,
473 %! assert (devinfo.input(i).ID, audiodevinfo (1, devinfo.input(i).Name))
474 %! endfor
475 */
476 
477 #ifdef HAVE_PORTAUDIO
478 
479 enum audio_type { TYPE_INT8, TYPE_UINT8, TYPE_UINT16, TYPE_DOUBLE };
480 
481 class audioplayer : public octave_base_value
482 {
483 public:
484  audioplayer (void);
485  ~audioplayer (void);
486 
487  // Overloaded base functions
488  double player_value (void) const { return 0; }
489  virtual double scalar_value (bool = false) const { return 0; }
490  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
491  void print_raw (std::ostream& os, bool pr_as_read_syntax) const;
492 
493  // Properties
494  bool is_constant (void) const { return true; }
495  bool is_defined (void) const { return true; }
496  bool print_as_scalar (void) const { return true; }
497 
498  void init (void);
499  void init_fn (void);
500  void set_y (const octave_value& y);
501  void set_y (octave_function *fn);
502  void set_y (std::string fn);
503  Matrix& get_y (void);
504  RowVector get_left (void) const;
505  RowVector get_right (void) const;
506  void set_fs (int fs);
507  int get_fs (void);
508  void set_nbits (int nbits);
509  int get_nbits (void);
510  void set_id (int id);
511  int get_id (void);
512  int get_channels (void);
513  audio_type get_type (void);
514 
515  void set_sample_number (unsigned int sample);
516  unsigned int get_sample_number (void);
517  unsigned int get_total_samples (void);
518  void set_end_sample (unsigned int sample);
519  unsigned int get_end_sample (void);
520  void reset_end_sample (void);
521  void set_tag (const charMatrix& tag);
522  charMatrix get_tag (void);
523  void set_userdata (const octave_value& userdata);
524  octave_value get_userdata (void);
525  PaStream *get_stream (void);
526 
527  void playblocking (void);
528  void play (void);
529  void pause (void);
530  void resume (void);
531  void stop (void);
532  bool isplaying (void);
533 
534  octave_function *octave_callback_function;
535 
536 private:
537  int id;
538  int fs;
539  int nbits;
540  int channels;
541  unsigned int sample_number;
542  unsigned int end_sample;
543  charMatrix tag;
544  Matrix y;
545  octave_value userdata;
546  RowVector left;
547  RowVector right;
548  PaStream *stream;
549  PaStreamParameters output_parameters;
550  audio_type type;
551 
553 };
554 
555 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audioplayer, "audioplayer", "audioplayer");
556 
557 static int
558 octave_play_callback (const void *, void *output, unsigned long frames,
559  const PaStreamCallbackTimeInfo *,
560  PaStreamCallbackFlags, void *data)
561 {
562  audioplayer *player = static_cast<audioplayer *> (data);
563 
564  if (! player)
565  {
566  error ("audio player callback function called without player");
567  return paAbort;
568  }
569 
570  octave_value_list retval = feval (player->octave_callback_function,
571  ovl (static_cast<double> (frames)), 1);
572 
573  if (error_state || retval.length () < 2)
574  {
575  error ("audio player callback function failed");
576  return paAbort;
577  }
578 
579  const Matrix sound = retval(0).matrix_value ();
580  int return_status = retval(1).int_value ();
581 
582  if (error_state || (frames - sound.rows () != 0)
583  || sound.columns () < 1 || sound.columns () > 2)
584  {
585  error ("audio player callback function failed");
586  return paAbort;
587  }
588 
589  // Don't multiply the audio data by scale_factor here. Although it
590  // does move the operation outside of the loops below, it also causes
591  // a second copy of the data array to be made.
592 
593  const ColumnVector sound_l = sound.column (0);
594  const ColumnVector sound_r = (sound.columns () == 1
595  ? sound_l : sound.column (1));
596 
597  const double *p_l = sound_l.data ();
598  const double *p_r = sound_r.data ();
599 
600  switch (player->get_nbits ())
601  {
602  case 8:
603  {
604  static double scale_factor = std::pow (2.0, 7) - 1.0;
605 
606  int8_t *buffer = static_cast<int8_t *> (output);
607 
608  for (unsigned long i = 0; i < frames; i++)
609  {
610  buffer[2*i] = p_l[i] * scale_factor;
611  buffer[2*i+1] = p_r[i] * scale_factor;
612  }
613  }
614  break;
615 
616  case 16:
617  {
618  static double scale_factor = std::pow (2.0, 15) - 1.0;
619 
620  int16_t *buffer = static_cast<int16_t *> (output);
621 
622  for (unsigned long i = 0; i < frames; i++)
623  {
624  buffer[2*i] = p_l[i] * scale_factor;
625  buffer[2*i+1] = p_r[i] * scale_factor;
626  }
627  }
628  break;
629 
630  case 24:
631  {
632  static double scale_factor = std::pow (2.0, 23) - 1.0;
633 
634  static int big_endian = oct_mach_info::words_big_endian ();
635 
636  uint8_t *buffer = static_cast<uint8_t *> (output);
637 
638  for (unsigned long i = 0; i < frames; i++)
639  {
640  int32_t sample_l = p_l[i];
641  int32_t sample_r = p_r[i];
642 
643  sample_l &= 0x00ffffff;
644  sample_r &= 0x00ffffff;
645 
646  // FIXME: Would a mask work better?
647  uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
648  uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
649 
650  unsigned long offset = i * 6;
651 
652  buffer[offset+0] = _sample_l[0+big_endian] * scale_factor;
653  buffer[offset+1] = _sample_l[1+big_endian] * scale_factor;
654  buffer[offset+2] = _sample_l[2+big_endian] * scale_factor;
655 
656  buffer[offset+3] = _sample_r[0+big_endian] * scale_factor;
657  buffer[offset+4] = _sample_r[1+big_endian] * scale_factor;
658  buffer[offset+5] = _sample_r[2+big_endian] * scale_factor;
659  }
660  }
661  break;
662 
663  default:
664  error ("invalid player bit depth in callback function");
665  break;
666  }
667 
668  return return_status;
669 }
670 
671 static int
672 portaudio_play_callback (const void *, void *output, unsigned long frames,
673  const PaStreamCallbackTimeInfo*,
674  PaStreamCallbackFlags, void *data)
675 {
676  audioplayer *player = static_cast<audioplayer *> (data);
677 
678  if (! player)
679  {
680  error ("audio player callback function called without player");
681  return paAbort;
682  }
683 
684  // Don't multiply the audio data by scale_factor here. Although it
685  // would move the operation outside of the loops below, it also causes
686  // a second copy of the *entire* data array to be made when only a
687  // small portion (buffer_size elements) is usually needed for this
688  // callback.
689 
690  const RowVector sound_l = player->get_left ();
691  const RowVector sound_r = player->get_right ();
692 
693  const double *pl = sound_l.data ();
694  const double *pr = sound_r.data ();
695 
696  if (player->get_type () == TYPE_DOUBLE)
697  {
698  switch (player->get_nbits ())
699  {
700  case 8:
701  {
702  static double scale_factor = std::pow (2.0, 7) - 1.0;
703 
704  int8_t *buffer = static_cast<int8_t *> (output);
705 
706  for (unsigned long j = 0; j < frames; j++)
707  {
708  unsigned int sample_number = player->get_sample_number ();
709 
710  if (sample_number >= player->get_end_sample ())
711  return paComplete;
712 
713  unsigned long offset = j * 2;
714 
715  buffer[offset+0] = pl[sample_number] * scale_factor;
716  buffer[offset+1] = pr[sample_number] * scale_factor;
717 
718  player->set_sample_number (sample_number + 1);
719  }
720  }
721  break;
722 
723  case 16:
724  {
725  static double scale_factor = std::pow (2.0, 15) - 1.0;
726 
727  int16_t *buffer = static_cast<int16_t *> (output);
728 
729  for (unsigned long j = 0; j < frames; j++)
730  {
731  unsigned int sample_number = player->get_sample_number ();
732 
733  if (sample_number >= player->get_end_sample ())
734  return paComplete;
735 
736  unsigned long offset = j * 2;
737 
738  buffer[offset+0] = pl[sample_number] * scale_factor;
739  buffer[offset+1] = pr[sample_number] * scale_factor;
740 
741  player->set_sample_number (sample_number + 1);
742  }
743  }
744  break;
745 
746  case 24:
747  {
748  static double scale_factor = std::pow (2.0, 23) - 1.0;
749 
750  static int big_endian = oct_mach_info::words_big_endian ();
751 
752  uint8_t *buffer = static_cast<uint8_t *> (output);
753 
754  for (unsigned long j = 0; j < frames; j++)
755  {
756  unsigned int sample_number = player->get_sample_number ();
757 
758  if (sample_number >= player->get_end_sample ())
759  return paComplete;
760 
761  int32_t sample_l = pl[sample_number] * scale_factor;
762  int32_t sample_r = pr[sample_number] * scale_factor;
763 
764  sample_l &= 0x00ffffff;
765  sample_r &= 0x00ffffff;
766 
767  // FIXME: Would a mask work better?
768  uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
769  uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
770 
771  unsigned long offset = j * 6;
772 
773  buffer[offset+0] = _sample_l[0+big_endian];
774  buffer[offset+1] = _sample_l[1+big_endian];
775  buffer[offset+2] = _sample_l[2+big_endian];
776 
777  buffer[offset+3] = _sample_r[0+big_endian];
778  buffer[offset+4] = _sample_r[1+big_endian];
779  buffer[offset+5] = _sample_r[2+big_endian];
780 
781  player->set_sample_number (sample_number + 1);
782  }
783  }
784  break;
785 
786  default:
787  error ("invalid player bit depth in callback function");
788  break;
789  }
790  }
791  else if (player->get_type () == TYPE_INT8)
792  {
793  int8_t *buffer = static_cast<int8_t *> (output);
794 
795  for (unsigned long j = 0; j < frames; j++)
796  {
797  unsigned int sample_number = player->get_sample_number ();
798 
799  if (sample_number >= player->get_end_sample ())
800  return paComplete;
801 
802  unsigned long offset = j * 2;
803 
804  buffer[offset+0] = pl[sample_number];
805  buffer[offset+1] = pr[sample_number];
806 
807  player->set_sample_number (sample_number + 1);
808  }
809  }
810  else if (player->get_type () == TYPE_UINT8)
811  {
812  uint8_t *buffer = static_cast<uint8_t *> (output);
813 
814  for (unsigned long j = 0; j < frames; j++)
815  {
816  unsigned int sample_number = player->get_sample_number ();
817 
818  if (sample_number >= player->get_end_sample ())
819  return paComplete;
820 
821  unsigned long offset = j * 2;
822 
823  buffer[offset+0] = pl[sample_number];
824  buffer[offset+1] = pr[sample_number];
825 
826  player->set_sample_number (sample_number + 1);
827  }
828  }
829  else if (player->get_type () == TYPE_UINT16)
830  {
831  int16_t *buffer = static_cast<int16_t *> (output);
832 
833  for (unsigned long j = 0; j < frames; j++)
834  {
835  unsigned int sample_number = player->get_sample_number ();
836 
837  if (sample_number >= player->get_end_sample ())
838  return paComplete;
839 
840  unsigned long offset = j * 2;
841 
842  buffer[offset+0] = pl[sample_number];
843  buffer[offset+1] = pr[sample_number];
844 
845  player->set_sample_number (sample_number + 1);
846  }
847  }
848 
849  return paContinue;
850 }
851 
852 static void
853 safe_audioplayer_stop (audioplayer *player)
854 {
855  player->stop ();
856 }
857 
858 audioplayer::audioplayer (void)
859  : octave_callback_function (0),
860  id (-1), fs (0), nbits (16), channels (0), sample_number (0),
861  end_sample (-1), tag (""), y (), userdata (Matrix ()),
862  left (), right (), stream (0), output_parameters (), type ()
863 { }
864 
865 audioplayer::~audioplayer (void)
866 {
867  if (isplaying ())
868  {
869  warning ("Octave:audio-interrupt",
870  "interrupting playing audioplayer");
871  stop ();
872  }
873 }
874 
875 void
876 audioplayer::print (std::ostream& os, bool pr_as_read_syntax) const
877 {
878  print_raw (os, pr_as_read_syntax);
879  newline (os);
880 }
881 
882 void
883 audioplayer::print_raw (std::ostream& os, bool) const
884 {
885  os << 0;
886 }
887 
888 void
889 audioplayer::init_fn (void)
890 {
891  if (Pa_Initialize () != paNoError)
892  {
893  error ("audioplayer: initialization error!");
894  return;
895  }
896 
897  if (Pa_GetDeviceCount () < 1)
898  {
899  error ("audioplayer: no audio devices found or available!");
900  return;
901  }
902 
903  int device = get_id ();
904 
905  if (device == -1)
906  device = Pa_GetDefaultOutputDevice ();
907 
908  output_parameters.device = device;
909  output_parameters.channelCount = 2;
910  output_parameters.sampleFormat = bits_to_format (get_nbits ());
911 
912  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (device);
913 
914  if (! device_info)
915  warning ("Octave:invalid-default-audio-device",
916  "invalid default audio device ID = %d", device);
917 
918  output_parameters.suggestedLatency
919  = device_info ? device_info->defaultHighOutputLatency : -1;
920 
921  output_parameters.hostApiSpecificStreamInfo = 0;
922 }
923 
924 void
925 audioplayer::init (void)
926 {
927  // Both of these variables are unused. Should they be
928  // eliminated or is something not yet implemented?
929  //
930  // int channels = y.rows ();
931  // RowVector *sound_l = get_left ();
932 
933  if (Pa_Initialize () != paNoError)
934  {
935  error ("audioplayer: initialization error!");
936  return;
937  }
938 
939  if (Pa_GetDeviceCount () < 1)
940  {
941  error ("audioplayer: no audio devices found or available!");
942  return;
943  }
944 
945  int device = get_id ();
946 
947  if (device == -1)
948  device = Pa_GetDefaultOutputDevice ();
949 
950  output_parameters.device = device;
951  output_parameters.channelCount = 2;
952 
953  if (type == TYPE_DOUBLE)
954  output_parameters.sampleFormat = bits_to_format (get_nbits ());
955  else if (type == TYPE_INT8)
956  output_parameters.sampleFormat = paInt8;
957  else if (type == TYPE_UINT8)
958  output_parameters.sampleFormat = paUInt8;
959  else if (type == TYPE_UINT16)
960  output_parameters.sampleFormat = paInt16;
961 
962  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (device);
963 
964  if (! device_info)
965  warning ("Octave:invalid-default-audio-device",
966  "invalid default audio device ID = %d", device);
967 
968  output_parameters.suggestedLatency
969  = device_info ? device_info->defaultHighOutputLatency : -1;
970 
971  output_parameters.hostApiSpecificStreamInfo = 0;
972 }
973 
974 void
975 audioplayer::set_y (const octave_value& y_arg)
976 {
977  if (y_arg.is_int8_type ())
978  type = TYPE_INT8;
979  else if (y_arg.is_uint8_type ())
980  type = TYPE_UINT8;
981  else if (y_arg.is_int16_type ())
982  type = TYPE_UINT16;
983  else
984  type = TYPE_DOUBLE;
985 
986  y = y_arg.matrix_value ();
987 
988  if (y.rows () > 2)
989  y = y.transpose ();
990 
991  channels = y.rows ();
992  left = y.row (0);
993 
994  if (channels == 2)
995  right = y.row (1);
996 
997  reset_end_sample ();
998 }
999 
1000 void
1001 audioplayer::set_y (octave_function *fn)
1002 {
1003  octave_callback_function = fn;
1004  channels = 2;
1005  reset_end_sample ();
1006 }
1007 
1008 Matrix&
1009 audioplayer::get_y (void)
1010 {
1011  return y;
1012 }
1013 
1014 RowVector
1015 audioplayer::get_left (void) const
1016 {
1017  return left;
1018 }
1019 
1020 RowVector
1021 audioplayer::get_right (void) const
1022 {
1023  return channels == 1 ? left : right;
1024 }
1025 
1026 void
1027 audioplayer::set_fs (int fs_arg)
1028 {
1029  fs = fs_arg;
1030 }
1031 
1032 int
1033 audioplayer::get_fs (void)
1034 {
1035  return fs;
1036 }
1037 
1038 void
1039 audioplayer::set_nbits (int nbits_arg)
1040 {
1041  nbits = nbits_arg;
1042 }
1043 
1044 int
1045 audioplayer::get_nbits (void)
1046 {
1047  return nbits;
1048 }
1049 
1050 void
1051 audioplayer::set_id (int id_arg)
1052 {
1053  id = id_arg;
1054 }
1055 
1056 int
1057 audioplayer::get_id (void)
1058 {
1059  return id;
1060 }
1061 
1062 int
1063 audioplayer::get_channels (void)
1064 {
1065  return channels;
1066 }
1067 
1068 audio_type
1069 audioplayer::get_type (void)
1070 {
1071  return type;
1072 }
1073 
1074 void
1075 audioplayer::set_sample_number (unsigned int sample_number_arg)
1076 {
1077  sample_number = sample_number_arg;
1078 }
1079 
1080 unsigned int
1081 audioplayer::get_sample_number (void)
1082 {
1083  return sample_number;
1084 }
1085 
1086 unsigned int
1087 audioplayer::get_total_samples (void)
1088 {
1089  return left.length ();
1090 }
1091 
1092 void
1093 audioplayer::set_end_sample (unsigned int end_sample_arg)
1094 {
1095  end_sample = end_sample_arg;
1096 }
1097 
1098 unsigned int
1099 audioplayer::get_end_sample (void)
1100 {
1101  return end_sample;
1102 }
1103 
1104 void
1105 audioplayer::reset_end_sample (void)
1106 {
1107  set_end_sample (left.length ());
1108 }
1109 
1110 void
1111 audioplayer::set_tag (const charMatrix& tag_arg)
1112 {
1113  tag = tag_arg;
1114 }
1115 
1116 charMatrix
1117 audioplayer::get_tag (void)
1118 {
1119  return tag;
1120 }
1121 
1122 void
1123 audioplayer::set_userdata (const octave_value& userdata_arg)
1124 {
1125  userdata = userdata_arg;
1126 }
1127 
1129 audioplayer::get_userdata (void)
1130 {
1131  return userdata;
1132 }
1133 
1134 void
1135 audioplayer::playblocking (void)
1136 {
1137  if (get_stream ())
1138  stop ();
1139 
1140  const unsigned int buffer_size = get_fs () / 20;
1141  OCTAVE_LOCAL_BUFFER (uint32_t, buffer, buffer_size * 2);
1142 
1143  PaError err;
1144  err = Pa_OpenStream (&stream, 0, &(output_parameters), get_fs (),
1145  buffer_size, paClipOff, 0, 0);
1146  if (err != paNoError)
1147  {
1148  error ("audioplayer: unable to open audio playback stream");
1149  return;
1150  }
1151 
1152  err = Pa_StartStream (stream);
1153  if (err != paNoError)
1154  {
1155  error ("audioplayer: unable to start start audio playback stream");
1156  return;
1157  }
1158 
1159  unsigned int start, end;
1160  start = get_sample_number ();
1161  end = get_end_sample ();
1162 
1163  unwind_protect frame;
1164 
1165  frame.add_fcn (safe_audioplayer_stop, this);
1166 
1167  for (unsigned int i = start; i < end; i += buffer_size)
1168  {
1169  OCTAVE_QUIT;
1170  if (octave_callback_function != 0)
1171  octave_play_callback (0, buffer, buffer_size, 0, 0, this);
1172  else
1173  portaudio_play_callback (0, buffer, buffer_size, 0, 0, this);
1174 
1175  err = Pa_WriteStream (stream, buffer, buffer_size);
1176  }
1177 }
1178 
1179 void
1180 audioplayer::play (void)
1181 {
1182  if (get_stream ())
1183  stop ();
1184 
1185  const unsigned int buffer_size = get_fs () / 20;
1186 
1187  PaError err;
1188  if (octave_callback_function != 0)
1189  err = Pa_OpenStream (&stream, 0, &(output_parameters),
1190  get_fs (), buffer_size, paClipOff,
1191  octave_play_callback, this);
1192  else
1193  err = Pa_OpenStream (&stream, 0, &(output_parameters),
1194  get_fs (), buffer_size, paClipOff,
1195  portaudio_play_callback, this);
1196 
1197  if (err != paNoError)
1198  {
1199  error ("audioplayer: failed to open audio playback stream");
1200  return;
1201  }
1202 
1203  err = Pa_StartStream (stream);
1204  if (err != paNoError)
1205  {
1206  error ("audioplayer: failed to start audio playback stream");
1207  return;
1208  }
1209 }
1210 
1211 void
1212 audioplayer::pause (void)
1213 {
1214  if (get_stream () == 0)
1215  return;
1216 
1217  PaError err;
1218  err = Pa_StopStream (stream);
1219  if (err != paNoError)
1220  {
1221  error ("audiorecorder: failed to stop audio recording stream");
1222  return;
1223  }
1224 }
1225 
1226 void
1227 audioplayer::resume (void)
1228 {
1229  if (get_stream () == 0)
1230  return;
1231 
1232  PaError err;
1233  err = Pa_StartStream (stream);
1234  if (err != paNoError)
1235  {
1236  error ("audiorecorder: failed to start audio recording stream");
1237  return;
1238  }
1239 }
1240 
1241 PaStream *
1242 audioplayer::get_stream (void)
1243 {
1244  return stream;
1245 }
1246 
1247 void
1248 audioplayer::stop (void)
1249 {
1250  if (get_stream () == 0)
1251  return;
1252 
1253  PaError err;
1254  set_sample_number (0);
1255  reset_end_sample ();
1256  if (! Pa_IsStreamStopped (get_stream ()))
1257  {
1258  err = Pa_AbortStream (get_stream ());
1259  if (err != paNoError)
1260  {
1261  error ("audioplayer: failed to stop audio playback stream");
1262  return;
1263  }
1264  }
1265 
1266  err = Pa_CloseStream (get_stream ());
1267  if (err != paNoError)
1268  {
1269  error ("audioplayer: failed to close audio playback stream");
1270  return;
1271  }
1272 
1273  stream = 0;
1274 }
1275 
1276 bool
1277 audioplayer::isplaying (void)
1278 {
1279  if (get_stream () == 0)
1280  return false;
1281 
1282  PaError err;
1283  err = Pa_IsStreamActive (stream);
1284  if (err != 0 && err != 1)
1285  {
1286  error ("audiorecorder: checking stream activity status failed");
1287  return false;
1288  }
1289 
1290  return (err == 1);
1291 }
1292 
1293 class audiorecorder : public octave_base_value
1294 {
1295 public:
1296  audiorecorder (void);
1297  ~audiorecorder (void);
1298 
1299  // Overloaded base functions
1300  double player_value (void) const { return 0; }
1301  virtual double scalar_value (bool = false) const { return 0; }
1302  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
1303  void print_raw (std::ostream& os, bool pr_as_read_syntax) const;
1304 
1305  // Properties
1306  bool is_constant (void) const { return true; }
1307  bool is_defined (void) const { return true; }
1308  bool print_as_scalar (void) const { return true; }
1309 
1310  void init (void);
1311  void set_fs (int fs);
1312  int get_fs (void);
1313  void set_nbits (int nbits);
1314  int get_nbits (void);
1315  void set_id (int id);
1316  int get_id (void);
1317  void set_channels (int channels);
1318  int get_channels (void);
1319  audio_type get_type (void);
1320 
1321  void set_sample_number (unsigned int sample);
1322  unsigned int get_sample_number (void);
1323  unsigned int get_total_samples (void);
1324  void set_end_sample (unsigned int sample);
1325  unsigned int get_end_sample (void);
1326  void reset_end_sample (void);
1327  void set_tag (const charMatrix& tag);
1328  charMatrix get_tag (void);
1329  void set_userdata (const octave_value& userdata);
1330  octave_value get_userdata (void);
1331  PaStream *get_stream (void);
1332 
1333  octave_value getaudiodata (void);
1334  audioplayer *getplayer (void);
1335  bool isrecording (void);
1336  audioplayer play (void);
1337  void record (void);
1338  void recordblocking (float seconds);
1339  void pause (void);
1340  void resume (void);
1341  void stop (void);
1342  void append (float sample_l, float sample_r);
1343 
1344  octave_function *octave_callback_function;
1345 
1346 private:
1347  int id;
1348  int fs;
1349  int nbits;
1350  int channels;
1351  unsigned int sample_number;
1352  unsigned int end_sample;
1353  charMatrix tag;
1354  Matrix y;
1355  octave_value userdata;
1356  std::vector<float> left;
1357  std::vector<float> right;
1358  PaStream *stream;
1359  PaStreamParameters input_parameters;
1360  audio_type type;
1361 
1363 };
1364 
1365 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audiorecorder, "audiorecorder", "audiorecorder");
1366 
1367 static int
1368 octave_record_callback (const void *input, void *, unsigned long frames,
1369  const PaStreamCallbackTimeInfo *,
1370  PaStreamCallbackFlags, void *data)
1371 {
1372  audiorecorder *recorder = static_cast<audiorecorder *> (data);
1373 
1374  if (! recorder)
1375  {
1376  error ("audio recorder callback function called without player");
1377  return paAbort;
1378  }
1379 
1380  int channels = recorder->get_channels ();
1381 
1382  Matrix sound (frames, 2);
1383  sound.resize (frames, 2);
1384 
1385  if (recorder->get_nbits () == 8)
1386  {
1387  static double scale_factor = std::pow (2.0, 7) - 1.0;
1388 
1389  const int8_t *input8 = static_cast<const int8_t *> (input);
1390 
1391  for (unsigned long i = 0; i < frames; i++)
1392  {
1393  float sample_l = input8[i*channels] / scale_factor;
1394  float sample_r = input8[i*channels + (channels - 1)] / scale_factor;
1395 
1396  sound(i,0) = sample_l;
1397  sound(i,1) = sample_r;
1398  }
1399  }
1400  else if (recorder->get_nbits () == 16)
1401  {
1402  static double scale_factor = std::pow (2.0, 15) - 1.0;
1403 
1404  const int16_t *input16 = static_cast<const int16_t *> (input);
1405 
1406  for (unsigned long i = 0; i < frames; i++)
1407  {
1408  float sample_l = input16[i*channels] / scale_factor;
1409  float sample_r = input16[i*channels + (channels - 1)] / scale_factor;
1410 
1411  sound(i,0) = sample_l;
1412  sound(i,1) = sample_r;
1413  }
1414  }
1415  else if (recorder->get_nbits () == 24)
1416  {
1417  static double scale_factor = std::pow (2.0, 23);
1418 
1419  // FIXME: Is there a better way?
1420  const uint8_t *input24 = static_cast<const uint8_t *> (input);
1421 
1422  int32_t sample_l32 = 0, sample_r32 = 0;
1423 
1424  uint8_t *sample_l = reinterpret_cast<uint8_t *> (&sample_l32);
1425  uint8_t *sample_r = reinterpret_cast<uint8_t *> (&sample_r32);
1426 
1427  for (unsigned long i = 0; i < frames; i++)
1428  {
1429  for (int j = 0; j < 3; j++)
1430  {
1431  sample_l[j] = input24[i*channels*3 + j];
1432  sample_r[j] = input24[i*channels*3 + (channels - 1)*3 + j];
1433  }
1434 
1435  if (sample_l32 & 0x00800000)
1436  sample_l32 |= 0xff000000;
1437 
1438  if (sample_r32 & 0x00800000)
1439  sample_r32 |= 0xff000000;
1440 
1441  sound(i,0) = sample_l32 / scale_factor;
1442  sound(i,1) = sample_r32 / scale_factor;
1443  }
1444  }
1445 
1446  octave_value_list retval
1447  = feval (recorder->octave_callback_function, ovl (sound), 1);
1448 
1449  return retval(0).int_value ();
1450 }
1451 
1452 static int
1453 portaudio_record_callback (const void *input, void *, unsigned long frames,
1454  const PaStreamCallbackTimeInfo *,
1455  PaStreamCallbackFlags, void *data)
1456 {
1457  audiorecorder *recorder = static_cast<audiorecorder *> (data);
1458 
1459  if (! recorder)
1460  {
1461  error ("audio recorder callback function called without player");
1462  return paAbort;
1463  }
1464 
1465  int channels = recorder->get_channels ();
1466 
1467  if (recorder->get_nbits () == 8)
1468  {
1469  static float scale_factor = std::pow (2.0f, 7) - 1.0f;
1470 
1471  const int8_t *input8 = static_cast<const int8_t *> (input);
1472 
1473  for (unsigned long i = 0; i < frames; i++)
1474  {
1475  float sample_l = input8[i*channels] / scale_factor;
1476  float sample_r = input8[i*channels + (channels - 1)] / scale_factor;
1477 
1478  recorder->append (sample_l, sample_r);
1479  }
1480  }
1481  else if (recorder->get_nbits () == 16)
1482  {
1483  static float scale_factor = std::pow (2.0f, 15) - 1.0f;
1484 
1485  const int16_t *input16 = static_cast<const int16_t *> (input);
1486 
1487  for (unsigned long i = 0; i < frames; i++)
1488  {
1489  float sample_l = input16[i*channels] / scale_factor;
1490  float sample_r = input16[i*channels + (channels - 1)] / scale_factor;
1491 
1492  recorder->append (sample_l, sample_r);
1493  }
1494  }
1495  else if (recorder->get_nbits () == 24)
1496  {
1497  static float scale_factor = std::pow (2.0f, 23);
1498 
1499  // FIXME: Is there a better way?
1500  const uint8_t *input24 = static_cast<const uint8_t *> (input);
1501 
1502  int32_t sample_l32 = 0, sample_r32 = 0;
1503 
1504  uint8_t *sample_l = reinterpret_cast<uint8_t *> (&sample_l32);
1505  uint8_t *sample_r = reinterpret_cast<uint8_t *> (&sample_r32);
1506 
1507  for (unsigned long i = 0; i < frames; i++)
1508  {
1509  for (int j = 0; j < 3; j++)
1510  {
1511  sample_l[j] = input24[i*channels*3 + j];
1512  sample_r[j] = input24[i*channels*3 + (channels - 1)*3 + j];
1513  }
1514 
1515  if (sample_l32 & 0x00800000)
1516  sample_l32 |= 0xff000000;
1517 
1518  if (sample_r32 & 0x00800000)
1519  sample_r32 |= 0xff000000;
1520 
1521  recorder->append (sample_l32 / scale_factor,
1522  sample_r32 / scale_factor);
1523  }
1524  }
1525 
1526  if (recorder->get_sample_number () >= recorder->get_end_sample ())
1527  return paComplete;
1528 
1529  return paContinue;
1530 }
1531 
1532 static void
1533 safe_audiorecorder_stop (audiorecorder *recorder)
1534 {
1535  recorder->stop ();
1536 }
1537 
1538 audiorecorder::audiorecorder (void)
1539  : octave_callback_function (0),
1540  id (-1), fs (44100), nbits (16), channels (2), sample_number (0),
1541  end_sample (-1), tag (""), y (), userdata (Matrix ()),
1542  left (), right (), stream (0), input_parameters (), type ()
1543 { }
1544 
1545 audiorecorder::~audiorecorder (void)
1546 {
1547  if (isrecording ())
1548  {
1549  warning ("Octave:audio-interrupt",
1550  "interrupting recording audiorecorder");
1551  stop ();
1552  }
1553 }
1554 
1555 void
1556 audiorecorder::print (std::ostream& os, bool pr_as_read_syntax) const
1557 {
1558  print_raw (os, pr_as_read_syntax);
1559  newline (os);
1560 }
1561 
1562 void
1563 audiorecorder::print_raw (std::ostream& os, bool) const
1564 {
1565  os << 0;
1566 }
1567 
1568 void
1569 audiorecorder::init (void)
1570 {
1571  if (Pa_Initialize () != paNoError)
1572  {
1573  error ("audiorecorder: initialization error!");
1574  return;
1575  }
1576 
1577  if (Pa_GetDeviceCount () < 1)
1578  {
1579  error ("audiorecorder: no audio devices found or available!");
1580  return;
1581  }
1582 
1583  int device = get_id ();
1584 
1585  if (device == -1)
1586  device = Pa_GetDefaultInputDevice ();
1587 
1588  input_parameters.device = device;
1589  input_parameters.channelCount = get_channels ();
1590  input_parameters.sampleFormat = bits_to_format (get_nbits ());
1591 
1592  const PaDeviceInfo *device_info = Pa_GetDeviceInfo (device);
1593 
1594  if (! device_info)
1595  warning ("Octave:invalid-default-audio-device",
1596  "invalid default audio device ID = %d", device);
1597 
1598  input_parameters.suggestedLatency
1599  = device_info ? device_info->defaultHighInputLatency : -1;
1600 
1601  input_parameters.hostApiSpecificStreamInfo = 0;
1602 }
1603 
1604 void
1605 audiorecorder::set_fs (int fs_arg)
1606 {
1607  fs = fs_arg;
1608 }
1609 
1610 int
1611 audiorecorder::get_fs (void)
1612 {
1613  return fs;
1614 }
1615 
1616 void
1617 audiorecorder::set_nbits (int nbits_arg)
1618 {
1619  nbits = nbits_arg;
1620 }
1621 
1622 int
1623 audiorecorder::get_nbits (void)
1624 {
1625  return nbits;
1626 }
1627 
1628 void
1629 audiorecorder::set_id (int id_arg)
1630 {
1631  id = id_arg;
1632 }
1633 
1634 int
1635 audiorecorder::get_id (void)
1636 {
1637  return id;
1638 }
1639 
1640 void
1641 audiorecorder::set_channels (int channels_arg)
1642 {
1643  assert (channels_arg == 1 || channels_arg == 2);
1644  channels = channels_arg;
1645 }
1646 
1647 int
1648 audiorecorder::get_channels (void)
1649 {
1650  return channels;
1651 }
1652 
1653 audio_type
1654 audiorecorder::get_type (void)
1655 {
1656  return type;
1657 }
1658 
1659 void
1660 audiorecorder::set_sample_number (unsigned int sample_number_arg)
1661 {
1662  sample_number = sample_number_arg;
1663 }
1664 
1665 unsigned int
1666 audiorecorder::get_sample_number (void)
1667 {
1668  return sample_number;
1669 }
1670 
1671 unsigned int
1672 audiorecorder::get_total_samples (void)
1673 {
1674  return left.size ();
1675 }
1676 
1677 void
1678 audiorecorder::set_end_sample (unsigned int end_sample_arg)
1679 {
1680  end_sample = end_sample_arg;
1681 }
1682 
1683 unsigned int
1684 audiorecorder::get_end_sample (void)
1685 {
1686  return end_sample;
1687 }
1688 
1689 void
1690 audiorecorder::reset_end_sample (void)
1691 {
1692  set_end_sample (left.size ());
1693 }
1694 
1695 void
1696 audiorecorder::set_tag (const charMatrix& tag_arg)
1697 {
1698  tag = tag_arg;
1699 }
1700 
1701 charMatrix
1702 audiorecorder::get_tag (void)
1703 {
1704  return tag;
1705 }
1706 
1707 void
1708 audiorecorder::set_userdata (const octave_value& userdata_arg)
1709 {
1710  userdata = userdata_arg;
1711 }
1712 
1714 audiorecorder::get_userdata (void)
1715 {
1716  return userdata;
1717 }
1718 
1720 audiorecorder::getaudiodata (void)
1721 {
1722  Matrix audio (2, left.size ());
1723 
1724  for (unsigned int i = 0; i < left.size (); i++)
1725  {
1726  audio(0,i) = left[i];
1727  audio(1,i) = right[i];
1728  }
1729 
1730  return audio;
1731 }
1732 
1733 audioplayer *
1734 audiorecorder::getplayer (void)
1735 {
1736  audioplayer *player = new audioplayer ();
1737 
1738  player->set_y (getaudiodata ());
1739  player->set_fs (get_fs ());
1740  player->set_nbits (get_nbits ());
1741  player->init ();
1742 
1743  return player;
1744 }
1745 
1746 bool
1747 audiorecorder::isrecording (void)
1748 {
1749  if (get_stream () == 0)
1750  return false;
1751 
1752  PaError err;
1753  err = Pa_IsStreamActive (stream);
1754  if (err != 0 && err != 1)
1755  {
1756  error ("audiorecorder: checking stream activity status failed");
1757  return false;
1758  }
1759 
1760  return (err == 1);
1761 }
1762 
1763 void
1764 audiorecorder::record (void)
1765 {
1766  if (get_stream ())
1767  stop ();
1768 
1769  left.clear ();
1770  right.clear ();
1771 
1772  const unsigned int buffer_size = get_fs () / 20;
1773 
1774  PaError err;
1775  if (octave_callback_function != 0)
1776  {
1777  err = Pa_OpenStream (&stream, &(input_parameters), 0,
1778  get_fs (), buffer_size, paClipOff,
1779  octave_record_callback, this);
1780  }
1781  else
1782  {
1783  err = Pa_OpenStream (&stream, &(input_parameters), 0,
1784  get_fs (), buffer_size, paClipOff,
1785  portaudio_record_callback, this);
1786  }
1787  if (err != paNoError)
1788  {
1789  error ("audiorecorder: unable to open audio recording stream");
1790  return;
1791  }
1792  err = Pa_StartStream (stream);
1793  if (err != paNoError)
1794  {
1795  error ("audiorecorder: unable to start audio recording stream");
1796  return;
1797  }
1798 }
1799 
1800 void
1801 audiorecorder::recordblocking (float seconds)
1802 {
1803  if (get_stream ())
1804  stop ();
1805 
1806  left.clear ();
1807  right.clear ();
1808 
1809  const unsigned int buffer_size = get_fs () / 20;
1810  OCTAVE_LOCAL_BUFFER (uint8_t, buffer, buffer_size * 2 * 3);
1811 
1812  PaError err;
1813  err = Pa_OpenStream (&stream, &(input_parameters), 0,
1814  get_fs (), buffer_size, paClipOff, 0, this);
1815  if (err != paNoError)
1816  {
1817  error ("audiorecorder: unable to open audio recording stream");
1818  return;
1819  }
1820 
1821  err = Pa_StartStream (stream);
1822  if (err != paNoError)
1823  {
1824  error ("audiorecorder: unable to start audio recording stream");
1825  return;
1826  }
1827 
1828  unsigned int frames = seconds * get_fs ();
1829 
1830  unwind_protect frame;
1831 
1832  frame.add_fcn (safe_audiorecorder_stop, this);
1833 
1834  for (unsigned int i = 0; i < frames; i += buffer_size)
1835  {
1836  OCTAVE_QUIT;
1837  Pa_ReadStream (get_stream (), buffer, buffer_size);
1838 
1839  if (octave_callback_function != 0)
1840  octave_record_callback (buffer, 0, buffer_size, 0, 0, this);
1841  else
1842  portaudio_record_callback (buffer, 0, buffer_size, 0, 0, this);
1843  }
1844 }
1845 
1846 void
1847 audiorecorder::pause (void)
1848 {
1849  if (get_stream () == 0)
1850  return;
1851 
1852  PaError err;
1853  err = Pa_StopStream (stream);
1854  if (err != paNoError)
1855  {
1856  error ("audiorecorder: unable to stop audio recording stream");
1857  return;
1858  }
1859 }
1860 
1861 void
1862 audiorecorder::resume (void)
1863 {
1864  if (get_stream () == 0)
1865  return;
1866 
1867  PaError err;
1868  err = Pa_StartStream (stream);
1869  if (err != paNoError)
1870  {
1871  error ("audiorecorder: unable to start audio recording stream");
1872  return;
1873  }
1874 }
1875 
1876 void
1877 audiorecorder::stop (void)
1878 {
1879  if (get_stream () == 0)
1880  return;
1881 
1882  PaError err;
1883  if (! Pa_IsStreamStopped (get_stream ()))
1884  {
1885  err = Pa_AbortStream (get_stream ());
1886  if (err != paNoError)
1887  {
1888  error ("audioplayer: unable to stop audio playback stream");
1889  return;
1890  }
1891  }
1892 
1893  err = Pa_CloseStream (stream);
1894  if (err != paNoError)
1895  {
1896  error ("audiorecorder: unable to close audio recording stream");
1897  return;
1898  }
1899 
1900  set_sample_number (0);
1901  reset_end_sample ();
1902  stream = 0;
1903 }
1904 
1905 void
1906 audiorecorder::append (float sample_l, float sample_r)
1907 {
1908  left.push_back (sample_l);
1909  right.push_back (sample_r);
1910  set_sample_number (get_sample_number () + 1);
1911 }
1912 
1913 PaStream *
1914 audiorecorder::get_stream (void)
1915 {
1916  return stream;
1917 }
1918 
1919 #endif
1920 
1921 DEFUN_DLD (__recorder_audiorecorder__, args, ,
1922  "-*- texinfo -*-\n\
1923 @deftypefn {Loadable Function} {@var{recorder} =} __recorder_audiorecorder__ (@var{fs}, @var{nbits}, @var{channels})\n\
1924 @deftypefnx {Loadable Function} {@var{recorder} =} __recorder_audiorecorder__ (@var{fs}, @var{nbits}, @var{channels}, @var{id})\n\
1925 @deftypefnx {Loadable Function} {@var{recorder} =} __recorder_audiorecorder__ (@var{fcn}, @dots{})\n\
1926 Undocumented internal function.\n\
1927 @end deftypefn")
1928 {
1929  octave_value retval;
1930 
1931 #ifdef HAVE_PORTAUDIO
1932 
1933  int nargin = args.length ();
1934 
1935  audiorecorder* recorder = new audiorecorder ();
1936 
1937  int offset = 0;
1938 
1939  if (nargin > 0)
1940  {
1941  bool is_function = (args(0).is_string () || args(0).is_function_handle ()
1942  || args(0).is_inline_function ());
1943 
1944  if (is_function)
1945  {
1946  error ("audioplayer: callbacks not yet implemented");
1947  return retval;
1948 
1949  // recorder->octave_callback_function = args(0).function_value ();
1950  // offset = 1;
1951  }
1952  }
1953 
1954  switch (nargin - offset)
1955  {
1956  case 3:
1957  recorder->set_fs (args(0 + offset).int_value ());
1958  recorder->set_nbits (args(1 + offset).int_value ());
1959  recorder->set_channels (args(2 + offset).int_value ());
1960  break;
1961 
1962  case 4:
1963  recorder->set_fs (args(0 + offset).int_value ());
1964  recorder->set_nbits (args(1 + offset).int_value ());
1965  recorder->set_channels (args(2 + offset).int_value ());
1966  recorder->set_id (args(3 + offset).int_value ());
1967  break;
1968  }
1969 
1970  recorder->init ();
1971 
1972  retval = recorder;
1973 
1974 #else
1975 
1976  error ("portaudio not found on your system and thus audio functionality is not present");
1977 
1978 #endif
1979 
1980  return retval;
1981 }
1982 
1983 #ifdef HAVE_PORTAUDIO
1984 
1985 static audiorecorder *
1986 get_recorder (const octave_value& ov)
1987 {
1988  const octave_base_value& rep = ov.get_rep ();
1989 
1990  octave_base_value *ncrep = const_cast<octave_base_value *> (&rep);
1991 
1992  return dynamic_cast<audiorecorder *> (ncrep);
1993 }
1994 
1995 #endif
1996 
1997 DEFUN_DLD (__recorder_getaudiodata__, args, ,
1998  "-*- texinfo -*-\n\
1999 @deftypefn {Loadable Function} {@var{data}} __recorder_getaudiodata__ (@var{recorder})\n\
2000 Undocumented internal function.\n\
2001 @end deftypefn")
2002 {
2003  octave_value retval;
2004 
2005 #ifdef HAVE_PORTAUDIO
2006 
2007  audiorecorder *recorder = get_recorder (args(0));
2008 
2009  if (! recorder)
2010  {
2011  print_usage ();
2012  return retval;
2013  }
2014 
2015  retval = recorder->getaudiodata ();
2016 
2017 #else
2018 
2019  error ("portaudio not found on your system and thus audio functionality is not present");
2020 
2021 #endif
2022 
2023  return retval;
2024 }
2025 
2026 DEFUN_DLD (__recorder_get_channels__, args, ,
2027  "-*- texinfo -*-\n\
2028 @deftypefn {Loadable Function} {@var{n} =} __recorder_get_channels__ (@var{recorder})\n\
2029 Undocumented internal function.\n\
2030 @end deftypefn")
2031 {
2032  octave_value retval;
2033 
2034 #ifdef HAVE_PORTAUDIO
2035 
2036  if (args.length () == 1)
2037  {
2038  audiorecorder *recorder = get_recorder (args(0));
2039 
2040  if (! recorder)
2041  {
2042  print_usage ();
2043  return retval;
2044  }
2045 
2046  retval = recorder->get_channels ();
2047  }
2048 
2049 #else
2050 
2051  error ("portaudio not found on your system and thus audio functionality is not present");
2052 
2053 #endif
2054 
2055  return retval;
2056 }
2057 
2058 DEFUN_DLD (__recorder_get_fs__, args, ,
2059  "-*- texinfo -*-\n\
2060 @deftypefn {Loadable Function} {@var{fs} =} __recorder_get_fs__ (@var{recorder})\n\
2061 Undocumented internal function.\n\
2062 @end deftypefn")
2063 {
2064  octave_value retval;
2065 
2066 #ifdef HAVE_PORTAUDIO
2067 
2068  if (args.length () == 1)
2069  {
2070  audiorecorder *recorder = get_recorder (args(0));
2071 
2072  if (! recorder)
2073  {
2074  print_usage ();
2075  return retval;
2076  }
2077 
2078  retval = recorder->get_fs ();
2079  }
2080 
2081 #else
2082 
2083  error ("portaudio not found on your system and thus audio functionality is not present");
2084 
2085 #endif
2086 
2087  return retval;
2088 }
2089 
2090 DEFUN_DLD (__recorder_get_id__, args, ,
2091  "-*- texinfo -*-\n\
2092 @deftypefn {Loadable Function} {@var{id} =} __recorder_get_id__ (@var{recorder})\n\
2093 Undocumented internal function.\n\
2094 @end deftypefn")
2095 {
2096  octave_value retval;
2097 
2098 #ifdef HAVE_PORTAUDIO
2099 
2100  if (args.length () == 1)
2101  {
2102  audiorecorder *recorder = get_recorder (args(0));
2103 
2104  if (! recorder)
2105  {
2106  print_usage ();
2107  return retval;
2108  }
2109 
2110  retval = recorder->get_id ();
2111  }
2112 
2113 #else
2114 
2115  error ("portaudio not found on your system and thus audio functionality is not present");
2116 
2117 #endif
2118 
2119  return retval;
2120 }
2121 
2122 DEFUN_DLD (__recorder_get_nbits__, args, ,
2123  "-*- texinfo -*-\n\
2124 @deftypefn {Loadable Function} {@var{nbits} =} __recorder_get_nbits__ (@var{recorder})\n\
2125 Undocumented internal function.\n\
2126 @end deftypefn")
2127 {
2128  octave_value retval;
2129 
2130 #ifdef HAVE_PORTAUDIO
2131 
2132  if (args.length () == 1)
2133  {
2134  audiorecorder *recorder = get_recorder (args(0));
2135 
2136  if (! recorder)
2137  {
2138  print_usage ();
2139  return retval;
2140  }
2141 
2142  retval = recorder->get_nbits ();
2143  }
2144 
2145 #else
2146 
2147  error ("portaudio not found on your system and thus audio functionality is not present");
2148 
2149 #endif
2150 
2151  return retval;
2152 }
2153 
2154 DEFUN_DLD (__recorder_get_sample_number__, args, ,
2155  "-*- texinfo -*-\n\
2156 @deftypefn {Loadable Function} {@var{n} =} __recorder_get_sample_number__ (@var{recorder})\n\
2157 Undocumented internal function.\n\
2158 @end deftypefn")
2159 {
2160  octave_value retval;
2161 
2162 #ifdef HAVE_PORTAUDIO
2163 
2164  if (args.length () == 1)
2165  {
2166  audiorecorder *recorder = get_recorder (args(0));
2167 
2168  if (! recorder)
2169  {
2170  print_usage ();
2171  return retval;
2172  }
2173 
2174  retval = recorder->get_sample_number ();
2175  }
2176 
2177 #else
2178 
2179  error ("portaudio not found on your system and thus audio functionality is not present");
2180 
2181 #endif
2182 
2183  return retval;
2184 }
2185 
2186 DEFUN_DLD (__recorder_get_tag__, args, ,
2187  "-*- texinfo -*-\n\
2188 @deftypefn {Loadable Function} {@var{tag} =} __recorder_get_tag__ (@var{recorder})\n\
2189 Undocumented internal function.\n\
2190 @end deftypefn")
2191 {
2192  octave_value retval;
2193 
2194 #ifdef HAVE_PORTAUDIO
2195 
2196  if (args.length () == 1)
2197  {
2198  audiorecorder *recorder = get_recorder (args(0));
2199 
2200  if (! recorder)
2201  {
2202  print_usage ();
2203  return retval;
2204  }
2205 
2206  retval = recorder->get_tag ();
2207  }
2208 
2209 #else
2210 
2211  error ("portaudio not found on your system and thus audio functionality is not present");
2212 
2213 #endif
2214 
2215  return retval;
2216 }
2217 
2218 DEFUN_DLD (__recorder_get_total_samples__, args, ,
2219  "-*- texinfo -*-\n\
2220 @deftypefn {Loadable Function} {@var{n} =} __recorder_get_total_samples__ (@var{recorder})\n\
2221 Undocumented internal function.\n\
2222 @end deftypefn")
2223 {
2224  octave_value retval;
2225 
2226 #ifdef HAVE_PORTAUDIO
2227 
2228  if (args.length () == 1)
2229  {
2230  audiorecorder *recorder = get_recorder (args(0));
2231 
2232  if (! recorder)
2233  {
2234  print_usage ();
2235  return retval;
2236  }
2237 
2238  retval = recorder->get_total_samples ();
2239  }
2240 
2241 #else
2242 
2243  error ("portaudio not found on your system and thus audio functionality is not present");
2244 
2245 #endif
2246 
2247  return retval;
2248 }
2249 
2250 DEFUN_DLD (__recorder_get_userdata__, args, ,
2251  "-*- texinfo -*-\n\
2252 @deftypefn {Loadable Function} {@var{data} =} __recorder_get_userdata__ (@var{recorder})\n\
2253 Undocumented internal function.\n\
2254 @end deftypefn")
2255 {
2256  octave_value retval;
2257 
2258 #ifdef HAVE_PORTAUDIO
2259 
2260  if (args.length () == 1)
2261  {
2262  audiorecorder *recorder = get_recorder (args(0));
2263 
2264  if (! recorder)
2265  {
2266  print_usage ();
2267  return retval;
2268  }
2269 
2270  retval = recorder->get_userdata ();
2271  }
2272 
2273 #else
2274 
2275  error ("portaudio not found on your system and thus audio functionality is not present");
2276 
2277 #endif
2278 
2279  return retval;
2280 }
2281 
2282 DEFUN_DLD (__recorder_isrecording__, args, ,
2283  "-*- texinfo -*-\n\
2284 @deftypefn {Loadable Function} {} __recorder_isrecording__ (@var{recorder})\n\
2285 Undocumented internal function.\n\
2286 @end deftypefn")
2287 {
2288  octave_value retval;
2289 
2290 #ifdef HAVE_PORTAUDIO
2291 
2292  if (args.length () == 1)
2293  {
2294  audiorecorder *recorder = get_recorder (args(0));
2295 
2296  if (! recorder)
2297  {
2298  print_usage ();
2299  return retval;
2300  }
2301 
2302  retval = recorder->isrecording () ? true : false;
2303  }
2304 
2305 #else
2306 
2307  error ("portaudio not found on your system and thus audio functionality is not present");
2308 
2309 #endif
2310 
2311  return retval;
2312 }
2313 
2314 DEFUN_DLD (__recorder_pause__, args, ,
2315  "-*- texinfo -*-\n\
2316 @deftypefn {Loadable Function} {} __recorder_pause__ (@var{recorder})\n\
2317 Undocumented internal function.\n\
2318 @end deftypefn")
2319 {
2320  octave_value retval;
2321 
2322 #ifdef HAVE_PORTAUDIO
2323 
2324  if (args.length () == 1)
2325  {
2326  audiorecorder *recorder = get_recorder (args(0));
2327 
2328  if (! recorder)
2329  {
2330  print_usage ();
2331  return retval;
2332  }
2333 
2334  recorder->pause ();
2335  }
2336 
2337 #else
2338 
2339  error ("portaudio not found on your system and thus audio functionality is not present");
2340 
2341 #endif
2342 
2343  return retval;
2344 }
2345 
2346 DEFUN_DLD (__recorder_recordblocking__, args, ,
2347  "-*- texinfo -*-\n\
2348 @deftypefn {Loadable Function} {} __recorder_recordblocking__ (@var{recorder}, @var{seconds})\n\
2349 Undocumented internal function.\n\
2350 @end deftypefn")
2351 {
2352  octave_value retval;
2353 
2354 #ifdef HAVE_PORTAUDIO
2355 
2356  audiorecorder *recorder = get_recorder (args(0));
2357 
2358  if (! recorder)
2359  {
2360  print_usage ();
2361  return retval;
2362  }
2363 
2364  recorder->recordblocking (args(1).float_value ());
2365 
2366 #else
2367 
2368  error ("portaudio not found on your system and thus audio functionality is not present");
2369 
2370 #endif
2371 
2372  return retval;
2373 }
2374 
2375 DEFUN_DLD (__recorder_record__, args, ,
2376  "-*- texinfo -*-\n\
2377 @deftypefn {Loadable Function} {} __recorder_record__ (@var{recorder})\n\
2378 @deftypefnx {Loadable Function} {} __recorder_record__ (@var{recorder}, @var{seconds})\n\
2379 Undocumented internal function.\n\
2380 @end deftypefn")
2381 {
2382  octave_value retval;
2383 
2384 #ifdef HAVE_PORTAUDIO
2385 
2386  audiorecorder *recorder = get_recorder (args(0));
2387 
2388  if (! recorder)
2389  {
2390  print_usage ();
2391  return retval;
2392  }
2393 
2394  if (args.length () == 1)
2395  recorder->record ();
2396  else if (args.length () == 2)
2397  {
2398  recorder->set_end_sample (args(1).int_value () * recorder->get_fs ());
2399  recorder->record ();
2400  }
2401  else
2402  error ("audiorecorder: wrong number of arguments passed to record");
2403 
2404 #else
2405 
2406  error ("portaudio not found on your system and thus audio functionality is not present");
2407 
2408 #endif
2409 
2410  return retval;
2411 }
2412 
2413 DEFUN_DLD (__recorder_resume__, args, ,
2414  "-*- texinfo -*-\n\
2415 @deftypefn {Loadable Function} {} __recorder_resume__ (@var{recorder})\n\
2416 Undocumented internal function.\n\
2417 @end deftypefn")
2418 {
2419  octave_value retval;
2420 
2421 #ifdef HAVE_PORTAUDIO
2422 
2423  if (args.length () == 1)
2424  {
2425  audiorecorder *recorder = get_recorder (args(0));
2426 
2427  if (! recorder)
2428  {
2429  print_usage ();
2430  return retval;
2431  }
2432 
2433  recorder->resume ();
2434  }
2435 
2436 #else
2437 
2438  error ("portaudio not found on your system and thus audio functionality is not present");
2439 
2440 #endif
2441 
2442  return retval;
2443 }
2444 
2445 DEFUN_DLD (__recorder_set_fs__, args, ,
2446  "-*- texinfo -*-\n\
2447 @deftypefn {Loadable Function} {} __recorder_set_fs__ (@var{recorder}, @var{fs})\n\
2448 Undocumented internal function.\n\
2449 @end deftypefn")
2450 {
2451  octave_value retval;
2452 
2453 #ifdef HAVE_PORTAUDIO
2454 
2455  if (args.length () == 2)
2456  {
2457  audiorecorder *recorder = get_recorder (args(0));
2458 
2459  if (! recorder)
2460  {
2461  print_usage ();
2462  return retval;
2463  }
2464 
2465  recorder->set_fs (args(1).int_value ());
2466  }
2467 
2468 #else
2469 
2470  error ("portaudio not found on your system and thus audio functionality is not present");
2471 
2472 #endif
2473 
2474  return retval;
2475 }
2476 
2477 DEFUN_DLD (__recorder_set_tag__, args, ,
2478  "-*- texinfo -*-\n\
2479 @deftypefn {Loadable Function} {} __recorder_set_tag__ (@var{recorder}, @var{tag})\n\
2480 Undocumented internal function.\n\
2481 @end deftypefn")
2482 {
2483  octave_value retval;
2484 
2485 #ifdef HAVE_PORTAUDIO
2486 
2487  if (args.length () == 2)
2488  {
2489  audiorecorder *recorder = get_recorder (args(0));
2490 
2491  if (! recorder)
2492  {
2493  print_usage ();
2494  return retval;
2495  }
2496 
2497  recorder->set_tag (args(1).char_matrix_value ());
2498  }
2499 
2500 #else
2501 
2502  error ("portaudio not found on your system and thus audio functionality is not present");
2503 
2504 #endif
2505 
2506  return retval;
2507 }
2508 
2509 DEFUN_DLD (__recorder_set_userdata__, args, ,
2510  "-*- texinfo -*-\n\
2511 @deftypefn {Loadable Function} {} __recorder_set_userdata__ (@var{recorder}, @var{data})\n\
2512 Undocumented internal function.\n\
2513 @end deftypefn")
2514 {
2515  octave_value retval;
2516 
2517 #ifdef HAVE_PORTAUDIO
2518 
2519  if (args.length () == 2)
2520  {
2521  audiorecorder *recorder = get_recorder (args(0));
2522 
2523  if (! recorder)
2524  {
2525  print_usage ();
2526  return retval;
2527  }
2528 
2529  recorder->set_userdata (args(1));
2530  }
2531 
2532 #else
2533 
2534  error ("portaudio not found on your system and thus audio functionality is not present");
2535 
2536 #endif
2537 
2538  return retval;
2539 }
2540 
2541 DEFUN_DLD (__recorder_stop__, args, ,
2542  "-*- texinfo -*-\n\
2543 @deftypefn {Loadable Function} {} __recorder_stop__ (@var{recorder})\n\
2544 Undocumented internal function.\n\
2545 @end deftypefn")
2546 {
2547  octave_value retval;
2548 
2549 #ifdef HAVE_PORTAUDIO
2550 
2551  audiorecorder *recorder = get_recorder (args(0));
2552 
2553  if (! recorder)
2554  {
2555  print_usage ();
2556  return retval;
2557  }
2558 
2559  recorder->stop ();
2560 
2561 #else
2562 
2563  error ("portaudio not found on your system and thus audio functionality is not present");
2564 
2565 #endif
2566 
2567  return retval;
2568 }
2569 
2570 DEFUN_DLD (__player_audioplayer__, args, ,
2571  "-*- texinfo -*-\n\
2572 @deftypefn {Loadable Function} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs})\n\
2573 @deftypefnx {Loadable Function} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs}, @var{nbits})\n\
2574 @deftypefnx {Loadable Function} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs}, @var{nbits}, @var{id})\n\
2575 Undocumented internal function.\n\
2576 @end deftypefn")
2577 {
2578  octave_value retval;
2579 
2580 #ifdef HAVE_PORTAUDIO
2581 
2582  int nargin = args.length ();
2583 
2584  if (nargin < 2 || nargin > 4)
2585  {
2586  print_usage ();
2587  return retval;
2588  }
2589 
2590  audioplayer* recorder = new audioplayer ();
2591 
2592  if (! recorder)
2593  {
2594  print_usage ();
2595  return retval;
2596  }
2597 
2598  bool is_function = (args(0).is_string () || args(0).is_function_handle ()
2599  || args(0).is_inline_function ());
2600 
2601  if (is_function)
2602  {
2603  error ("audioplayer: callbacks not yet implemented");
2604  return retval;
2605 
2606  // recorder->set_y (args(0).function_value ());
2607  }
2608  else
2609  recorder->set_y (args(0));
2610 
2611  recorder->set_fs (args(1).int_value ());
2612 
2613  switch (nargin)
2614  {
2615  case 3:
2616  recorder->set_nbits (args(2).int_value ());
2617  break;
2618 
2619  case 4:
2620  recorder->set_nbits (args(2).int_value ());
2621  recorder->set_id (args(3).int_value ());
2622  break;
2623  }
2624 
2625  if (is_function)
2626  recorder->init_fn ();
2627  else
2628  recorder->init ();
2629 
2630  retval = recorder;
2631 
2632 #else
2633 
2634  error ("portaudio not found on your system and thus audio functionality is not present");
2635 
2636 #endif
2637 
2638  return retval;
2639 }
2640 
2641 #ifdef HAVE_PORTAUDIO
2642 
2643 static audioplayer *
2644 get_player (const octave_value& ov)
2645 {
2646  const octave_base_value& rep = ov.get_rep ();
2647 
2648  octave_base_value *ncrep = const_cast<octave_base_value *> (&rep);
2649 
2650  return dynamic_cast<audioplayer *> (ncrep);
2651 }
2652 
2653 #endif
2654 
2655 DEFUN_DLD (__player_get_channels__, args, ,
2656  "-*- texinfo -*-\n\
2657 @deftypefn {Loadable Function} {@var{n} =} __player_get_channels__ (@var{player})\n\
2658 Undocumented internal function.\n\
2659 @end deftypefn")
2660 {
2661  octave_value retval;
2662 
2663 #ifdef HAVE_PORTAUDIO
2664 
2665  if (args.length () == 1)
2666  {
2667  audioplayer *player = get_player (args(0));
2668 
2669  if (! player)
2670  {
2671  print_usage ();
2672  return retval;
2673  }
2674 
2675  retval = player->get_channels ();
2676  }
2677 
2678 #else
2679 
2680  error ("portaudio not found on your system and thus audio functionality is not present");
2681 
2682 #endif
2683 
2684  return retval;
2685 }
2686 
2687 DEFUN_DLD (__player_get_fs__, args, ,
2688  "-*- texinfo -*-\n\
2689 @deftypefn {Loadable Function} {@var{fs} =} __player_get_fs__ (@var{player})\n\
2690 Undocumented internal function.\n\
2691 @end deftypefn")
2692 {
2693  octave_value retval;
2694 
2695 #ifdef HAVE_PORTAUDIO
2696 
2697  if (args.length () == 1)
2698  {
2699  audioplayer *player = get_player (args(0));
2700 
2701  if (! player)
2702  {
2703  print_usage ();
2704  return retval;
2705  }
2706 
2707  retval = player->get_fs ();
2708  }
2709 
2710 #else
2711 
2712  error ("portaudio not found on your system and thus audio functionality is not present");
2713 
2714 #endif
2715 
2716  return retval;
2717 }
2718 
2719 DEFUN_DLD (__player_get_id__, args, ,
2720  "-*- texinfo -*-\n\
2721 @deftypefn {Loadable Function} {@var{id} =} __player_get_id__ (@var{player})\n\
2722 Undocumented internal function.\n\
2723 @end deftypefn")
2724 {
2725  octave_value retval;
2726 
2727 #ifdef HAVE_PORTAUDIO
2728 
2729  if (args.length () == 1)
2730  {
2731  audioplayer *player = get_player (args(0));
2732 
2733  if (! player)
2734  {
2735  print_usage ();
2736  return retval;
2737  }
2738 
2739  retval = player->get_id ();
2740  }
2741 
2742 #else
2743 
2744  error ("portaudio not found on your system and thus audio functionality is not present");
2745 
2746 #endif
2747 
2748  return retval;
2749 }
2750 
2751 DEFUN_DLD (__player_get_nbits__, args, ,
2752  "-*- texinfo -*-\n\
2753 @deftypefn {Loadable Function} {@var{nbits} =} __player_get_nbits__ (@var{player})\n\
2754 Undocumented internal function.\n\
2755 @end deftypefn")
2756 {
2757  octave_value retval;
2758 
2759 #ifdef HAVE_PORTAUDIO
2760 
2761  if (args.length () == 1)
2762  {
2763  audioplayer *player = get_player (args(0));
2764 
2765  if (! player)
2766  {
2767  print_usage ();
2768  return retval;
2769  }
2770 
2771  retval = player->get_nbits ();
2772  }
2773 
2774 #else
2775 
2776  error ("portaudio not found on your system and thus audio functionality is not present");
2777 
2778 #endif
2779 
2780  return retval;
2781 }
2782 
2783 DEFUN_DLD (__player_get_sample_number__, args, ,
2784  "-*- texinfo -*-\n\
2785 @deftypefn {Loadable Function} {@var{n} =} __player_get_sample_number__ (@var{player})\n\
2786 Undocumented internal function.\n\
2787 @end deftypefn")
2788 {
2789  octave_value retval;
2790 
2791 #ifdef HAVE_PORTAUDIO
2792 
2793  if (args.length () == 1)
2794  {
2795  audioplayer *player = get_player (args(0));
2796 
2797  if (! player)
2798  {
2799  print_usage ();
2800  return retval;
2801  }
2802 
2803  retval = player->get_sample_number ();
2804  }
2805 
2806 #else
2807 
2808  error ("portaudio not found on your system and thus audio functionality is not present");
2809 
2810 #endif
2811 
2812  return retval;
2813 }
2814 
2815 DEFUN_DLD (__player_get_tag__, args, ,
2816  "-*- texinfo -*-\n\
2817 @deftypefn {Loadable Function} {@var{tag} =} __player_get_tag__ (@var{player})\n\
2818 Undocumented internal function.\n\
2819 @end deftypefn")
2820 {
2821  octave_value retval;
2822 
2823 #ifdef HAVE_PORTAUDIO
2824 
2825  if (args.length () == 1)
2826  {
2827  audioplayer *player = get_player (args(0));
2828 
2829  if (! player)
2830  {
2831  print_usage ();
2832  return retval;
2833  }
2834 
2835  retval = player->get_tag ();
2836  }
2837 
2838 #else
2839 
2840  error ("portaudio not found on your system and thus audio functionality is not present");
2841 
2842 #endif
2843 
2844  return retval;
2845 }
2846 
2847 DEFUN_DLD (__player_get_total_samples__, args, ,
2848  "-*- texinfo -*-\n\
2849 @deftypefn {Loadable Function} {@var{n} =} __player_get_total_samples__ (@var{player})\n\
2850 Undocumented internal function.\n\
2851 @end deftypefn")
2852 {
2853  octave_value retval;
2854 
2855 #ifdef HAVE_PORTAUDIO
2856 
2857  if (args.length () == 1)
2858  {
2859  audioplayer *player = get_player (args(0));
2860 
2861  if (! player)
2862  {
2863  print_usage ();
2864  return retval;
2865  }
2866 
2867  retval = player->get_total_samples ();
2868  }
2869 
2870 #else
2871 
2872  error ("portaudio not found on your system and thus audio functionality is not present");
2873 
2874 #endif
2875 
2876  return retval;
2877 }
2878 
2879 DEFUN_DLD (__player_get_userdata__, args, ,
2880  "-*- texinfo -*-\n\
2881 @deftypefn {Loadable Function} {@var{data} =} __player_get_userdata__ (@var{player})\n\
2882 Undocumented internal function.\n\
2883 @end deftypefn")
2884 {
2885  octave_value retval;
2886 
2887 #ifdef HAVE_PORTAUDIO
2888 
2889  if (args.length () == 1)
2890  {
2891  audioplayer *player = get_player (args(0));
2892 
2893  if (! player)
2894  {
2895  print_usage ();
2896  return retval;
2897  }
2898 
2899  retval = player->get_userdata ();
2900  }
2901 
2902 #else
2903 
2904  error ("portaudio not found on your system and thus audio functionality is not present");
2905 
2906 #endif
2907 
2908  return retval;
2909 }
2910 
2911 DEFUN_DLD (__player_isplaying__, args, ,
2912  "-*- texinfo -*-\n\
2913 @deftypefn {Loadable Function} {} __player_isplaying__ (@var{player})\n\
2914 Undocumented internal function.\n\
2915 @end deftypefn")
2916 {
2917  octave_value retval;
2918 
2919 #ifdef HAVE_PORTAUDIO
2920 
2921  if (args.length () == 1)
2922  {
2923  audioplayer *player = get_player (args(0));
2924 
2925  if (! player)
2926  {
2927  print_usage ();
2928  return retval;
2929  }
2930 
2931  retval = player->isplaying () ? true : false;
2932  }
2933 
2934 #else
2935 
2936  error ("portaudio not found on your system and thus audio functionality is not present");
2937 
2938 #endif
2939 
2940  return retval;
2941 }
2942 
2943 DEFUN_DLD (__player_pause__, args, ,
2944  "-*- texinfo -*-\n\
2945 @deftypefn {Loadable Function} {} __player_pause__ (@var{player})\n\
2946 Undocumented internal function.\n\
2947 @end deftypefn")
2948 {
2949  octave_value retval;
2950 
2951 #ifdef HAVE_PORTAUDIO
2952 
2953  if (args.length () == 1)
2954  {
2955  audioplayer *player = get_player (args(0));
2956 
2957  if (! player)
2958  {
2959  print_usage ();
2960  return retval;
2961  }
2962 
2963  player->pause ();
2964  }
2965 
2966 #else
2967 
2968  error ("portaudio not found on your system and thus audio functionality is not present");
2969 
2970 #endif
2971 
2972  return retval;
2973 }
2974 
2975 DEFUN_DLD (__player_playblocking__, args, ,
2976  "-*- texinfo -*-\n\
2977 @deftypefn {Loadable Function} {} __player_playblocking__ (@var{player})\n\
2978 @deftypefnx {Loadable Function} {} __player_playblocking__ (@var{player}, @var{start})\n\
2979 @deftypefnx {Loadable Function} {} __player_playblocking__ (@var{player}, [@var{start}, @var{end}])\n\
2980 Undocumented internal function.\n\
2981 @end deftypefn")
2982 {
2983  octave_value retval;
2984 
2985 #ifdef HAVE_PORTAUDIO
2986 
2987  audioplayer *player = get_player (args(0));
2988 
2989  if (! player)
2990  {
2991  print_usage ();
2992  return retval;
2993  }
2994 
2995  if (args.length () == 1)
2996  player->playblocking ();
2997  else
2998  {
2999  if (args(1).is_matrix_type ())
3000  {
3001  RowVector range = args(1).row_vector_value ();
3002 
3003  unsigned int start = range.elem (0) - 1;
3004  unsigned int end = range.elem (1) - 1;
3005 
3006  if (start > player->get_total_samples ()
3007  || start > end || end > player->get_total_samples ())
3008  {
3009  error ("audioplayer: invalid range specified for playback");
3010  return retval;
3011  }
3012 
3013  player->set_sample_number (start);
3014  player->set_end_sample (end);
3015  }
3016  else
3017  {
3018  unsigned int start = args(1).int_value () - 1;
3019 
3020  if (start > player->get_total_samples ())
3021  {
3022  error ("audioplayer: invalid range specified for playback");
3023  return retval;
3024  }
3025 
3026  player->set_sample_number (start);
3027  }
3028 
3029  player->playblocking ();
3030  }
3031 
3032 #else
3033 
3034  error ("portaudio not found on your system and thus audio functionality is not present");
3035 
3036 #endif
3037 
3038  return retval;
3039 }
3040 
3041 DEFUN_DLD (__player_play__, args, ,
3042  "-*- texinfo -*-\n\
3043 @deftypefn {Loadable Function} {} __player_play__ (@var{player})\n\
3044 @deftypefnx {Loadable Function} {} __player_play__ (@var{player}, @var{start})\n\
3045 @deftypefnx {Loadable Function} {} __player_play__ (@var{player}, [@var{start}, @var{end}])\n\
3046 Undocumented internal function.\n\
3047 @end deftypefn")
3048 {
3049  octave_value retval;
3050 
3051 #ifdef HAVE_PORTAUDIO
3052 
3053  if (args.length () == 1)
3054  {
3055  audioplayer *player = get_player (args(0));
3056 
3057  if (! player)
3058  {
3059  print_usage ();
3060  return retval;
3061  }
3062 
3063  player->play ();
3064  }
3065  else
3066  {
3067  audioplayer *player = get_player (args(0));
3068 
3069  if (args(1).is_matrix_type ())
3070  {
3071  RowVector range = args(1).row_vector_value ();
3072 
3073  unsigned int start = range.elem (0) - 1;
3074  unsigned int end = range.elem (1) - 1;
3075 
3076  if (start > player->get_total_samples ()
3077  || start > end || end > player->get_total_samples ())
3078  {
3079  error ("audioplayer: invalid range specified for playback");
3080  return retval;
3081  }
3082 
3083  player->set_sample_number (start);
3084  player->set_end_sample (end);
3085  }
3086  else
3087  {
3088  unsigned int start = args(1).int_value () - 1;
3089 
3090  if (start > player->get_total_samples ())
3091  {
3092  error ("audioplayer: invalid range specified for playback");
3093  return retval;
3094  }
3095 
3096  player->set_sample_number (start);
3097  }
3098 
3099  player->play ();
3100  }
3101 
3102 #else
3103 
3104  error ("portaudio not found on your system and thus audio functionality is not present");
3105 
3106 #endif
3107 
3108  return retval;
3109 }
3110 
3111 DEFUN_DLD (__player_resume__, args, ,
3112  "-*- texinfo -*-\n\
3113 @deftypefn {Loadable Function} {} __player_resume__ (@var{player})\n\
3114 Undocumented internal function.\n\
3115 @end deftypefn")
3116 {
3117  octave_value retval;
3118 
3119 #ifdef HAVE_PORTAUDIO
3120 
3121  if (args.length () == 1)
3122  {
3123  audioplayer *player = get_player (args(0));
3124 
3125  if (! player)
3126  {
3127  print_usage ();
3128  return retval;
3129  }
3130 
3131  player->resume ();
3132  }
3133 
3134 #else
3135 
3136  error ("portaudio not found on your system and thus audio functionality is not present");
3137 
3138 #endif
3139 
3140  return retval;
3141 }
3142 
3143 DEFUN_DLD (__player_set_fs__, args, ,
3144  "-*- texinfo -*-\n\
3145 @deftypefn {Loadable Function} {} __player_set_fs__ (@var{player}, @var{fs})\n\
3146 Undocumented internal function.\n\
3147 @end deftypefn")
3148 {
3149  octave_value retval;
3150 
3151 #ifdef HAVE_PORTAUDIO
3152 
3153  if (args.length () == 2)
3154  {
3155  audioplayer *player = get_player (args(0));
3156 
3157  if (! player)
3158  {
3159  print_usage ();
3160  return retval;
3161  }
3162 
3163  player->set_fs (args(1).int_value ());
3164  }
3165 
3166 #else
3167 
3168  error ("portaudio not found on your system and thus audio functionality is not present");
3169 
3170 #endif
3171 
3172  return retval;
3173 }
3174 
3175 DEFUN_DLD (__player_set_tag__, args, ,
3176  "-*- texinfo -*-\n\
3177 @deftypefn {Loadable Function} {} __player_set_tag__ (@var{player}, @var{tag})\n\
3178 Undocumented internal function.\n\
3179 @end deftypefn")
3180 {
3181  octave_value retval;
3182 
3183 #ifdef HAVE_PORTAUDIO
3184 
3185  if (args.length () == 2)
3186  {
3187  audioplayer *player = get_player (args(0));
3188 
3189  if (! player)
3190  {
3191  print_usage ();
3192  return retval;
3193  }
3194 
3195  player->set_tag (args(1).char_matrix_value ());
3196  }
3197 
3198 #else
3199 
3200  error ("portaudio not found on your system and thus audio functionality is not present");
3201 
3202 #endif
3203 
3204  return retval;
3205 }
3206 
3207 DEFUN_DLD (__player_set_userdata__, args, ,
3208  "-*- texinfo -*-\n\
3209 @deftypefn {Loadable Function} {} __player_set_userdata__ (@var{player}, @var{data})\n\
3210 Undocumented internal function.\n\
3211 @end deftypefn")
3212 {
3213  octave_value retval;
3214 
3215 #ifdef HAVE_PORTAUDIO
3216 
3217  if (args.length () == 2)
3218  {
3219  audioplayer *player = get_player (args(0));
3220 
3221  if (! player)
3222  {
3223  print_usage ();
3224  return retval;
3225  }
3226 
3227  player->set_userdata (args(1));
3228  }
3229 
3230 #else
3231 
3232  error ("portaudio not found on your system and thus audio functionality is not present");
3233 
3234 #endif
3235 
3236  return retval;
3237 }
3238 
3239 DEFUN_DLD (__player_stop__, args, ,
3240  "-*- texinfo -*-\n\
3241 @deftypefn {Loadable Function} {} __player_stop__ (@var{player})\n\
3242 Undocumented internal function.\n\
3243 @end deftypefn")
3244 {
3245  octave_value retval;
3246 
3247 #ifdef HAVE_PORTAUDIO
3248 
3249  if (args.length () == 1)
3250  {
3251  audioplayer *player = get_player (args (0));
3252 
3253  if (! player)
3254  {
3255  print_usage ();
3256  return retval;
3257  }
3258 
3259  player->stop ();
3260  }
3261 
3262 #else
3263 
3264  error ("portaudio not found on your system and thus audio functionality is not present");
3265 
3266 #endif
3267 
3268  return retval;
3269 }
Definition: Cell.h:35
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:130
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
octave_idx_type length(void) const
Definition: oct-obj.h:89
int int_value(bool req_int=false, bool frc_str_conv=false) const
Definition: ov.h:730
virtual double scalar_value(bool frc_str_conv=false) const
Definition: ov-base.h:475
void error(const char *fmt,...)
Definition: error.cc:476
bool is_int8_type(void) const
Definition: ov.h:619
octave_value_list feval(const std::string &name, const octave_value_list &args, int nargout)
Definition: oct-parse.cc:8625
void setfield(const std::string &key, const octave_value &val)
Definition: oct-map.cc:171
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:164
T & elem(octave_idx_type n)
Definition: Array.h:380
static int left
Definition: randmtzig.c:189
octave_idx_type rows(void) const
Definition: Array.h:313
virtual void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-base.cc:401
#define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
Definition: ov-base.h:142
F77_RET_T const double const double * f
void add_fcn(void(*fcn)(void))
const T * data(void) const
Definition: Array.h:479
int error_state
Definition: error.cc:101
octave_int< T > pow(const octave_int< T > &a, const octave_int< T > &b)
Matrix transpose(void) const
Definition: dMatrix.h:114
virtual bool print_as_scalar(void) const
Definition: ov-base.h:612
static bool words_big_endian(void)
Definition: mach-info.cc:171
octave_idx_type length(void) const
Definition: ov.cc:1525
Definition: dMatrix.h:35
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:773
virtual bool is_defined(void) const
Definition: ov-base.h:333
void setfield(const std::string &key, const Cell &val)
Definition: oct-map.cc:265
bool is_int16_type(void) const
Definition: ov.h:622
void warning(const char *fmt,...)
Definition: error.cc:681
virtual bool is_constant(void) const
Definition: ov-base.h:429
octave_value_list ovl(const octave_value &a0)
Definition: oct-obj.h:178
bool is_uint8_type(void) const
Definition: ov.h:631
const octave_base_value & get_rep(void) const
Definition: ov.h:1085
ColumnVector column(octave_idx_type i) const
Definition: dMatrix.cc:645
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:197
static int input(yyscan_t yyscanner)
virtual void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov-base.cc:407
#define DEFUN_DLD(name, args_name, nargout_name, doc)
Definition: defun-dld.h:59
#define OCTAVE_QUIT
Definition: quit.h:130
octave_idx_type columns(void) const
Definition: Array.h:322