view libinterp/dldfcn/audiodevinfo.cc @ 19537:36a26a131209

Apply Octave coding style to audio project additions * libinterp/dldfcn/__player_audioplayer__.cc, libinterp/dldfcn/__recorder_audiorecorder__.cc, libinterp/dldfcn/audiodevinfo.cc, libinterp/dldfcn/audioinfo.cc, libinterp/dldfcn/audioread.cc, libinterp/dldfcn/audiowrite.cc, libinterp/dldfcn/player_class.cc, libinterp/dldfcn/player_class.h, libinterp/dldfcn/recorder_class.cc, libinterp/dldfcn/recorder_class.h, scripts/audio/@audioplayer/__get_properties__.m, scripts/audio/@audioplayer/audioplayer.m, scripts/audio/@audioplayer/display.m, scripts/audio/@audioplayer/get.m, scripts/audio/@audioplayer/isplaying.m, scripts/audio/@audioplayer/pause.m, scripts/audio/@audioplayer/play.m, scripts/audio/@audioplayer/playblocking.m, scripts/audio/@audioplayer/resume.m, scripts/audio/@audioplayer/set.m, scripts/audio/@audioplayer/stop.m, scripts/audio/@audioplayer/subsasgn.m, scripts/audio/@audioplayer/subsref.m, scripts/audio/@audiorecorder/__get_properties__.m, scripts/audio/@audiorecorder/audiorecorder.m, scripts/audio/@audiorecorder/display.m, scripts/audio/@audiorecorder/get.m, scripts/audio/@audiorecorder/getaudiodata.m, scripts/audio/@audiorecorder/getplayer.m, scripts/audio/@audiorecorder/isrecording.m, scripts/audio/@audiorecorder/pause.m, scripts/audio/@audiorecorder/play.m, scripts/audio/@audiorecorder/record.m, scripts/audio/@audiorecorder/recordblocking.m, scripts/audio/@audiorecorder/resume.m, scripts/audio/@audiorecorder/set.m, scripts/audio/@audiorecorder/stop.m, scripts/audio/@audiorecorder/subsasgn.m, scripts/audio/@audiorecorder/subsref.m: Apply consistent Octave indentation, spacing, and quoting styles. Strip trailing whitespace. Remove braces from one-line if-else blocks. Simplify some variable declarations.
author Mike Miller <mtmiller@ieee.org>
date Thu, 03 Oct 2013 07:52:58 -0400
parents 1f551d169db2
children ce02743b6f2a
line wrap: on
line source

/*

Copyright (C) 2013 Vytautas JanĨauskas

This file is part of Octave.

Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING.  If not, see
<http://www.gnu.org/licenses/>.

*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "oct.h"
#include "ov-struct.h"
#include <portaudio.h>

PaSampleFormat
bits_to_format (int bits)
{
  if (bits == 8)
    return paInt8;
  else if (bits == 16)
    return paInt16;
  else if (bits == 24)
    return paInt24;
  else if (bits == 32)
    return paInt32;
  else if (bits == -1)
    return paFloat32;
  else
    return 0;
}

DEFUN_DLD (audiodevinfo, args, ,
"-*- texinfo -*-\n\
@deftypefn{Loadable Function} @var{devinfo} = audiodevinfo\n\
\n\
Returns a structure with two fields called \"input\" and \"output\". \
Each structure contains an array of structures with three fields called \
\"Name\", \"DriverVersion\" and \"ID\". Each structure contains information \
about a PortAudio device.\n\
\n\
@end deftypefn\n\
\n\
@deftypefn{Loadable Function} @var{devs} = audiodevinfo (@var{IO})\n\
\n\
Returns the number of input or output devices available. Set @var{IO} to 1 \
for input devices and to 0 for output devices.\n\
@end deftypefn\n\
\n\
@deftypefn{Loadable Function} @var{name} = audiodevinfo (@var{IO}, @var{ID})\n\
\n\
Returns the name of a device specified by numerical @var{ID}. Set @var{IO} \
to 1 for input devices and to 0 for output devices.\n\
@end deftypefn\n\
\n\
@deftypefn{Loadable Function} @var{id} = audiodevinfo (@var{IO}, @var{name})\n\
\n\
Returns the id of a device specified by name. Set @var{IO} \
to 1 for input devices and to 0 for output devices.\n\
@end deftypefn\n\
\n\
@deftypefn{Loadable Function} @var{id} = audiodevinfo (@var{IO}, @var{rate},\
 @var{bits}, @var{chans})\n\
\n\
Returns the id of the first device that supports playback or recording\
 using the specified sampling rate (@var{rate}), bits per sample (@var{bits})\
 and number of channels (@var{chans}). Set @var{IO} to 1 for input devices\
 ant to 0 for output devices.\
@end deftypefn\n\
\n\
@deftypefn{Loadable Function} @var{supports} = audiodevinfo (@var{IO}, @var{ID},\
 @var{rate}, @var{bits}, @var{chans})\n\
\n\
Returns 1 if the device bearing @var{ID} supports specified sampling rate\
 (@var{rate}), bits per sample (@var{bits}) and number of channels (@var{chans}).\
 Returns 0 otherwise. Set @var{IO} to 1 for input devices and to 0 for output\
 devices.\n\
@end deftypefn")
{
  octave_value retval;
#ifdef HAVE_PORTAUDIO
  int nargin = args.length ();
  PaError err;
  octave_scalar_map devinfo;
  octave_value_list input;
  octave_value_list output;

  err = Pa_Initialize ();
  if (err != paNoError)
    {
      error ("audiodevinfo: cannot initialize PortAudio");
      return retval;
    }

  int num_devices = Pa_GetDeviceCount ();
  if (num_devices < 0)
    {
      error ("audiodevinfo: no audio device found");
      return retval;
    }

  octave_idx_type numinput = 0, numoutput = 0;
  for (int i = 0; i < num_devices; i++)
    {
      const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);
      if (device_info->maxInputChannels != 0)
        numinput++;
      if (device_info->maxOutputChannels != 0)
        numoutput++;
    }

  Cell input_name (dim_vector (1, numinput));
  Cell input_driver_version (dim_vector (1, numinput));
  Cell input_id (dim_vector (1, numinput));
  Cell output_name (dim_vector (1, numoutput));
  Cell output_driver_version (dim_vector (1, numoutput));
  Cell output_id (dim_vector (1, numoutput));

  octave_idx_type idx_i = 0, idx_o = 0;
  for (int i = 0; i < num_devices; i++)
    {
      const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);
      const char *driver;
      char name[128];
      driver = Pa_GetHostApiInfo (device_info->hostApi)->name;
      sprintf (name, "%s (%s)", device_info->name, driver);

      if (device_info->maxInputChannels != 0)
        {
          input_name(idx_i) = name;
          input_driver_version(idx_i) = driver;
          input_id(idx_i) = i;
          idx_i++;
        }

      if (device_info->maxOutputChannels != 0)
        {
          output_name(idx_o) = name;
          output_driver_version(idx_o) = driver;
          output_id(idx_o) = i;
          idx_o++;
        }
    }

  octave_map inputdev, outputdev;
  inputdev.setfield ("Name", input_name);
  inputdev.setfield ("DriverVersion", input_driver_version);
  inputdev.setfield ("ID", input_id);
  outputdev.setfield ("Name", output_name);
  outputdev.setfield ("DriverVersion", output_driver_version);
  outputdev.setfield ("ID", output_id);
  devinfo.setfield ("input", inputdev);
  devinfo.setfield ("output", outputdev);

  // Return information about input and output audio devices and
  // their properties.
  if (nargin == 0)
    retval = devinfo;
  // Return the number of input or output devices
  else if (nargin == 1)
    {
      if (args(0).int_value () == 0)
        retval = octave_value (numoutput);
      else if (args(0).int_value () == 1)
        retval = octave_value (numinput);
      else
        {
          error ("audiodevinfo: please specify 0 for output and 1 for input devices");
          return retval;
        }
    }
  // Return device name when given id or id when given device name.
  else if (nargin == 2)
    {
      bool found = false;
      int outin = args(0).int_value ();
      if (args(1).is_string ())
        {
          if (outin == 0)
            {
              for (int i = 0; i < numoutput; i++)
                {
                  if (output_name(i).string_value () == args(1).string_value ())
                    {
                      retval = output_id(i);
                      found = true;
                      break;
                    }
                }
            }
          else if (outin == 1)
            {
              for (int i = 0; i < numinput; i++)
                {
                  if (input_name(i).string_value () == args(1).string_value ())
                    {
                      retval = input_id(i);
                      found = true;
                      break;
                    }
                }
            }
          else
            {
              error ("audiodevinfo: please specify 0 for output and 1 for input devices");
              return retval;
            }
        }
      else
        {
          if (outin == 0)
            {
              for (int i = 0; i < numoutput; i++)
                {
                  if (output_id(i).int_value () == args(1).int_value ())
                    {
                      retval = output_name(i);
                      found = true;
                      break;
                    }
                }
            }
          else if (outin == 1)
            {
              for (int i = 0; i < numinput; i++)
                {
                  if (input_id(i).int_value () == args(1).int_value ())
                    {
                      retval = input_name(i);
                      found = true;
                      break;
                    }
                }
            }
          else
            {
              error ("audiodevinfo: please specify 0 for output and 1 for input devices");
              return retval;
            }
        }
      if (not found)
        error ("audiodevinfo: no device meeting the specified criteria found");
    }
  else if (nargin == 3)
    {
      //
    }
  // Return the id of the first device meeting specified criteria.
  else if (nargin == 4)
    {
      int io = args(0).int_value ();
      int rate = args(1).int_value ();
      int bits = args(2).int_value ();
      int chans = args(3).int_value ();
      for (int i = 0; i < num_devices; i++)
        {
          PaStreamParameters stream_parameters;
          stream_parameters.device = i;
          stream_parameters.channelCount = chans;
          PaSampleFormat format = bits_to_format (bits);
          if (format != 0)
            stream_parameters.sampleFormat = format;
          else
            {
              error ("audiodevinfo: no such bits per sample format");
              return retval;
            }
          stream_parameters.suggestedLatency =
              Pa_GetDeviceInfo (i)->defaultLowInputLatency;
          stream_parameters.hostApiSpecificStreamInfo = NULL;
          if (io == 0)
            {
              if (Pa_GetDeviceInfo (i)->maxOutputChannels < chans)
                continue;

              err = Pa_IsFormatSupported (NULL, &stream_parameters, rate);
              if (err == paFormatIsSupported)
                {
                  retval = i;
                  return retval;
                }
            }
          else if (io == 1)
            {
              if (Pa_GetDeviceInfo (i)->maxInputChannels < chans)
                continue;

              err = Pa_IsFormatSupported (&stream_parameters, NULL, rate);
              if (err == paFormatIsSupported)
                {
                  retval = i;
                  return retval;
                }
            }
        }
      retval = -1;
    }
  // Check if given device supports specified playback or recording modes.
  else if (nargin == 5)
    {
      int io = args(0).int_value ();
      int id = args(1).int_value ();
      int rate = args(2).int_value ();
      int bits = args(3).int_value ();
      int chans = args(4).int_value ();
      PaStreamParameters stream_parameters;
      stream_parameters.device = id;
      stream_parameters.channelCount = chans;
      PaSampleFormat format = bits_to_format (bits);
      if (format != 0)
        stream_parameters.sampleFormat = format;
      else
        {
          error ("audiodevinfo: no such bits per sample format");
          return retval;
        }
      stream_parameters.suggestedLatency =
        Pa_GetDeviceInfo (id)->defaultLowInputLatency;
      stream_parameters.hostApiSpecificStreamInfo = NULL;
      if (io == 0)
        {
          if (Pa_GetDeviceInfo (id)->maxOutputChannels < chans)
            {
              retval = 0;
              return retval;
            }
          err = Pa_IsFormatSupported (NULL, &stream_parameters, rate);
          if (err == paFormatIsSupported)
            {
              retval = 1;
              return retval;
            }
        }
      else if (io == 1)
        {
          if (Pa_GetDeviceInfo (id)->maxInputChannels < chans)
            {
              retval = 0;
              return retval;
            }
          err = Pa_IsFormatSupported (&stream_parameters, NULL, rate);
          if (err == paFormatIsSupported)
            {
              retval = 1;
              return retval;
            }
        }
      else
        {
          error ("audiodevinfo: please specify 0 for output and 1 for input devices");
          return retval;
        }
      retval = 0;
    }
  else
    {
      error ("audiodevinfo: wrong number of arguments");
      return retval;
    }
#else
  error ("portaudio not found on your system and thus audio functionality is not present");
#endif
  return retval;
}

/*
%!test
%! devinfo = audiodevinfo;
%! assert(rows(devinfo.('input')) == 1);
%! assert(rows(devinfo.('output')) == 1);

%!test
%! devinfo = audiodevinfo;
%! nout = audiodevinfo(0);
%! nin = audiodevinfo(1);
%! assert(columns(devinfo.('output')) == nout);
%! assert(columns(devinfo.('input')) == nin);

%!test
%! devinfo = audiodevinfo;
%! nout = audiodevinfo(0);
%! nin = audiodevinfo(1);
%! for i=1:nout,
%!   assert(devinfo.('output')(i).('Name') == audiodevinfo(0, devinfo.('output')(i).('ID')))
%! end
%! for i=1:nin,
%!   assert(devinfo.('input')(i).('Name') == audiodevinfo(0, devinfo.('input')(i).('ID')))
%! end

%!test
%! devinfo = audiodevinfo;
%! nout = audiodevinfo(0);
%! nin = audiodevinfo(1);
%! for i=1:nout,
%!   assert(devinfo.('output')(i).('ID') == audiodevinfo(0, devinfo.('output')(i).('Name')))
%! end
%! for i=1:nin,
%!   assert(devinfo.('input')(i).('ID') == audiodevinfo(0, devinfo.('input')(i).('Name')))
%! end
*/