changeset 1:9cadc470e3da

reorganize, add more
author pmeerw@pan
date Fri, 30 Oct 2009 23:07:52 +0100
parents deadffdf5d60
children 13be24d74cd2
files Makefile README.txt alsacap.c audiodelay.cpp audiodelay/Makefile audiodelay/audiodelay.cpp rtaudio-test.cpp
diffstat 7 files changed, 824 insertions(+), 150 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Fri Oct 30 23:07:52 2009 +0100
@@ -0,0 +1,23 @@
+PROGRAMS = audiodelay alsacap rtaudio-test
+RM = rm -f
+
+CC       = gcc
+CXX       = g++
+CFLAGS   = -O2 -Wall
+
+all: $(PROGRAMS)
+
+alsacap: alsacap.c
+	$(CC) $(CFLAGS) -o $@ alsacap.c -lasound
+
+audiodelay: audiodelay.cpp 
+	$(CXX) $(CFLAGS) -o $@ audiodelay.cpp -lpthread -lasound -lrtaudio
+
+rtaudio-test: rtaudio-test.cpp 
+	$(CXX) $(CFLAGS) -o $@ rtaudio-test.cpp -lpthread -lasound -lrtaudio
+
+clean: 
+	-$(RM) *.o $(PROGRAMS) *~ 
+
+strip: 
+	strip $(PROGRAMS)
--- a/README.txt	Fri Oct 30 22:45:25 2009 +0100
+++ b/README.txt	Fri Oct 30 23:07:52 2009 +0100
@@ -1,4 +1,4 @@
 README
 
 audiodelay	measures delay between audio output and record using RtAudio
-
+alsacap		display ALSA sound card capabilities
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/alsacap.c	Fri Oct 30 23:07:52 2009 +0100
@@ -0,0 +1,556 @@
+/*
+ * ALSA parameter test program
+ *
+ * compile with: gcc -o alsacap alsacap.c -lasound
+*/
+
+
+/*============================================================================
+				Includes
+============================================================================*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <alsa/asoundlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+
+/*============================================================================
+			Constant and type definitions
+============================================================================*/
+
+#define RATE_KHZ_LIMIT	200
+
+#define HWP_END		0
+#define HWP_RATE	1
+#define HWP_NCH		2
+#define HWP_FORMAT	3
+#define SIZE_HWP	7
+
+typedef struct {
+  int recdevices, verbose, card, dev;
+  char *device;
+  int hwparams[SIZE_HWP];
+}
+aiopts;
+
+
+/*============================================================================
+			Global variables
+============================================================================*/
+
+static snd_ctl_t *handle= NULL;
+static snd_pcm_t *pcm= NULL;
+static snd_ctl_card_info_t *info;
+static snd_pcm_info_t *pcminfo;
+static snd_pcm_hw_params_t *pars;
+static snd_pcm_format_mask_t *fmask;
+
+
+/*============================================================================
+			Prototypes
+============================================================================*/
+
+void usagemsg(int code);
+void errnumarg(char optchar);
+void errarg(char optchar);
+void errtoomany();
+
+void scancards(snd_pcm_stream_t stream, int thecard, int thedev);
+int sc_errcheck(int retval, const char *doingwhat, int cardnr, int devnr);
+
+void testconfig(snd_pcm_stream_t stream, const char *device, const int *hwpars);
+void tc_errcheck(int retval, const char *doingwhat);
+
+const char *alsaerrstr(const int errcode);
+const char *dirstr(int dir);
+
+int parse_alsaformat(const char *fmtstr);
+const char *alsafmtstr(int fmtnum);
+
+void printfmtmask(const snd_pcm_format_mask_t *fmask);
+
+
+/*============================================================================
+				Main program
+============================================================================*/
+
+int main(int argc, char **argv)
+{
+  aiopts options= { 0, 1, -1, -1, NULL };
+  snd_pcm_stream_t stream;
+  char *argpar;
+  int argind, hwpind;
+
+  snd_ctl_card_info_alloca(&info);
+  snd_pcm_info_alloca(&pcminfo);
+  snd_pcm_hw_params_alloca(&pars);
+  snd_pcm_format_mask_alloca(&fmask);
+
+  hwpind= 0;
+  for( argind= 1; argind< argc; ++argind )
+  {
+    if( argv[argind][0]!='-' ) {
+      fprintf(stderr, "Unrecognised command-line argument `%s'.\n", argv[argind]);
+      usagemsg(1);
+    }
+    if( argv[argind][2] )	argpar= argv[argind]+2;
+    else {
+      if( argind+1 >= argc ) argpar= NULL;
+      else argpar= argv[argind+1];
+    }
+    if( argv[argind][1]=='h' || !strcmp(argv[argind]+1, "-help") )
+      usagemsg(0);
+    else if( argv[argind][1]=='R' ) {
+      options.recdevices= 1;
+      argpar= NULL;	// set to NULL if unused to keep track of next arg index
+    }
+    else if( argv[argind][1]=='C' ) {
+      if( !argpar || !isdigit(*argpar) ) errnumarg('C');
+      options.card= strtol(argpar, NULL, 0);
+    }
+    else if( argv[argind][1]=='D' ) {
+      if( !argpar || !isdigit(*argpar) ) errnumarg('D');
+      options.dev= strtol(argpar, NULL, 0);
+    }
+    else if( argv[argind][1]=='d' ) {
+      if( !argpar )	errarg('d');
+      options.device= argpar;
+    }
+    else if( argv[argind][1]=='r' ) {
+      if( !argpar || !isdigit(*argpar) ) errnumarg('r');
+      if( hwpind+3 > SIZE_HWP ) errtoomany();
+      options.hwparams[hwpind++]= HWP_RATE;
+      options.hwparams[hwpind]= strtol(argpar, NULL, 0);
+      if( options.hwparams[hwpind] <= RATE_KHZ_LIMIT )
+	options.hwparams[hwpind] *= 1000;         // sanity check: Hz or kHz ?
+      ++hwpind;
+    }
+    else if( argv[argind][1]=='c' ) {
+      if( !argpar || !isdigit(*argpar) ) errnumarg('c');
+      if( hwpind+3 > SIZE_HWP ) errtoomany();
+      options.hwparams[hwpind++]= HWP_NCH;
+      options.hwparams[hwpind++]= strtol(argpar, NULL, 0);
+    }
+    else if( argv[argind][1]=='f' ) {
+      if( !argpar ) errarg('f');
+      if( hwpind+3 > SIZE_HWP ) errtoomany();
+      options.hwparams[hwpind++]= HWP_FORMAT;
+      options.hwparams[hwpind++]= parse_alsaformat(argpar);
+    }
+    else {
+      fprintf(stderr, "Unrecognised command-line option `%s'.\n", argv[argind]);
+      usagemsg(1);
+    }
+    if( argpar && !argv[argind][2] )
+      ++argind;  // additional increment if separate parameter argument was used
+  }
+  options.hwparams[hwpind]= HWP_END;
+  if( options.dev >= 0 && options.card < 0 ) {
+    fprintf(stderr, "The card has to be specified with -C if a device number is given (-D).\n");
+    exit(1);
+  }
+  if( options.device && (options.card>=0 || options.dev>=0) ) {
+    fprintf(stderr, "Specifying a device name (-d) and a card and possibly device number (-C, -D) is mutually exclusive.\n");
+    exit(1);
+  }
+  stream= options.recdevices? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK;
+
+  if( !options.device )
+    scancards(stream, options.card, options.dev);
+  else
+    testconfig(stream, options.device, options.hwparams);
+
+  exit(0);
+}
+
+
+
+/*============================================================================
+	Usage message and command-line argument error functions
+============================================================================*/
+
+void usagemsg(int code)
+{
+  fprintf(stderr, "Usage: alsacap [-R] [-C <card #> [-D <device #>]]\n"
+		  "       alsacap [-R] -d <device name> [-r <rate>|-c <# of channels>|-f <sample format>]...\n"
+      "ALSA capability lister.\n"
+      "First form: Scans one or all soundcards known to ALSA for devices, \n"
+      "subdevices and parameter ranges.  -R causes a scan for recording\n"
+      "rather than playback devices.  The other options specify the sound\n"
+      "card and possibly the device by number.\n"
+      "Second form: Displays ranges of configuration parameters for the given\n"
+      "ALSA device.  Unlike with the first form, a non-hardware device may be\n"
+      "given.  Up to three optional command-line arguments fix the rate,\n"
+      "number of channels and sample format in the order in which they are\n"
+      "given.  The remaining parameter ranges are output.  If unique, the\n"
+      "number of significant bits of the sample values is output.  (Some\n"
+      "sound cards ignore some of the bits.)\n");
+  exit(code);
+}
+
+void errnumarg(char optchar)
+{
+  fprintf(stderr, "The -%c option requires a numerical argument!  Aborting.\n", optchar);
+  exit(1);
+}
+
+void errarg(char optchar)
+{
+  fprintf(stderr, "The -%c option requires an argument!  Aborting.\n", optchar);
+  exit(1);
+}
+
+void errtoomany()
+{
+  fprintf(stderr, "Too many -r/-c/-f options given!  (Maximum is %d.)  Aborting.\n", (SIZE_HWP-1)/2);
+  exit(1);
+}
+
+
+/*============================================================================
+		Function for scanning all cards
+============================================================================*/
+
+#define HWCARDTEMPL	"hw:%d"
+#define HWDEVTEMPL	"hw:%d,%d"
+#define HWDEVLEN	32
+
+void scancards(snd_pcm_stream_t stream, int thecard, int thedev)
+{
+  char hwdev[HWDEVLEN+1];
+  unsigned min, max;
+  int card, err, dev, subd, nsubd;
+
+  printf("*** Scanning for %s devices", stream==SND_PCM_STREAM_CAPTURE? "recording" : "playback");
+  if( thecard >= 0 )
+    printf(" on card %d", thecard);
+  if( thedev >= 0 )
+    printf(", device %d", thedev);
+  printf(" ***\n");
+  hwdev[HWDEVLEN]= 0;
+  if( thecard >= 0 )
+    card= thecard;
+  else {
+    card= -1;
+    if( snd_card_next(&card) < 0 )
+      return;
+  }
+  while( card >= 0 )
+  {
+    snprintf(hwdev, HWDEVLEN, HWCARDTEMPL, card);
+    err= snd_ctl_open(&handle, hwdev, 0);
+    if( sc_errcheck(err, "opening control interface", card, -1) ) goto nextcard;
+    err= snd_ctl_card_info(handle, info);
+    if( sc_errcheck(err, "obtaining card info", card, -1) ) {
+      snd_ctl_close(handle);
+      goto nextcard;
+    }
+    printf("Card %d, ID `%s', name `%s'\n", card, snd_ctl_card_info_get_id(info),
+		snd_ctl_card_info_get_name(info));
+    if( thedev >= 0 )
+      dev= thedev;
+    else {
+      dev= -1;
+      if( snd_ctl_pcm_next_device(handle, &dev) < 0 ) {
+	snd_ctl_close(handle);
+	goto nextcard;
+      }
+    }
+    while( dev >= 0 )
+    {
+      snd_pcm_info_set_device(pcminfo, dev);
+      snd_pcm_info_set_subdevice(pcminfo, 0);
+      snd_pcm_info_set_stream(pcminfo, stream);
+      err= snd_ctl_pcm_info(handle, pcminfo);
+      if( thedev<0 && err == -ENOENT ) goto nextdev;
+      if( sc_errcheck(err, "obtaining device info", card, dev) ) goto nextdev;
+      nsubd= snd_pcm_info_get_subdevices_count(pcminfo);
+      if( sc_errcheck(nsubd, "obtaining device info", card, dev) ) goto nextdev;
+      printf("  Device %d, ID `%s', name `%s', %d subdevices (%d available)\n",
+	  dev, snd_pcm_info_get_id(pcminfo), snd_pcm_info_get_name(pcminfo),
+	  nsubd, snd_pcm_info_get_subdevices_avail(pcminfo));
+      snprintf(hwdev, HWDEVLEN, HWDEVTEMPL, card, dev);
+      err= snd_pcm_open(&pcm, hwdev, stream, SND_PCM_NONBLOCK);
+      if( sc_errcheck(err, "opening sound device", card, dev) ) goto nextdev;
+      err= snd_pcm_hw_params_any(pcm, pars);
+      if( sc_errcheck(err, "obtaining hardware parameters", card, dev) ) {
+	snd_pcm_close(pcm);
+	goto nextdev;
+      }
+      snd_pcm_hw_params_get_channels_min(pars, &min);
+      snd_pcm_hw_params_get_channels_max(pars, &max);
+      if( min == max )
+	if( min == 1 )	printf("    1 channel, ");
+        else		printf("    %d channels, ", min);
+      else		printf("    %u..%u channels, ", min, max);
+      snd_pcm_hw_params_get_rate_min(pars, &min, NULL);
+      snd_pcm_hw_params_get_rate_max(pars, &max, NULL);
+      printf("sampling rate %u..%u Hz\n    Sample formats: ", min, max);
+      snd_pcm_hw_params_get_format_mask(pars, fmask);
+      printfmtmask(fmask);
+      snd_pcm_close(pcm);
+      printf("\n");
+      pcm= NULL;
+      for( subd= 0; subd< nsubd; ++subd ) {
+	snd_pcm_info_set_subdevice(pcminfo, subd);
+	err= snd_ctl_pcm_info(handle, pcminfo);
+	if( sc_errcheck(err, "obtaining subdevice info", card, dev) ) goto nextdev;
+	printf("      Subdevice %d, name `%s'\n", subd, snd_pcm_info_get_subdevice_name(pcminfo));
+      }
+nextdev:
+      if( thedev >= 0 || snd_ctl_pcm_next_device(handle, &dev) < 0 )
+	break;
+    }
+    snd_ctl_close(handle);
+nextcard:
+    if( thecard >= 0 || snd_card_next(&card) < 0 )
+      break;
+  }
+}
+
+
+int sc_errcheck(int retval, const char *doingwhat, int cardnr, int devnr)
+{
+  if( retval<0 ) {
+    if( devnr>= 0 )
+      fprintf(stderr, "Error %s for card %d, device %d: %s.  Skipping.\n", doingwhat, cardnr, devnr, alsaerrstr(retval));
+    else
+      fprintf(stderr, "Error %s for card %d: %s.  Skipping.\n", doingwhat, cardnr, alsaerrstr(retval));
+    return 1;
+  }
+  return 0;
+}
+
+
+
+/*============================================================================
+	Function for investigating device configurations
+============================================================================*/
+
+void testconfig(snd_pcm_stream_t stream, const char *device, const int *hwpars)
+{
+  unsigned min, max, param;
+  int err, count, dir, result;
+
+  printf("*** Exploring configuration space of device `%s' for %s ***\n", device,
+	  stream==SND_PCM_STREAM_CAPTURE? "recording" : "playback");
+
+  if (stream==SND_PCM_STREAM_CAPTURE && stream==SND_PCM_STREAM_PLAYBACK)
+    dir = 0;
+  else if (stream==SND_PCM_STREAM_CAPTURE)
+    dir = -1;
+  else
+    dir = 1;
+
+  err= snd_pcm_open(&pcm, device, stream, SND_PCM_NONBLOCK);
+  tc_errcheck(err, "opening sound device");
+  err= snd_pcm_hw_params_any(pcm, pars);
+  tc_errcheck(err, "initialising hardware parameters");
+  for( count= 0; hwpars[count]!=HWP_END; count += 2 )
+    
+    switch(hwpars[count])
+    {
+      case HWP_RATE:param= hwpars[count+1];
+      		    err= snd_pcm_hw_params_set_rate_near(pcm, pars, &param, &result);
+      		    if( err<0 )
+		      fprintf(stderr, "Could not set sampling rate to %d Hz: %s.  "
+		  "Continuing regardless.\n", hwpars[count+1], alsaerrstr(err));
+		    else
+		      printf("Set sampling rate %d Hz --> got %u Hz, %s requested.\n", hwpars[count+1], param, dirstr(dir));
+        break;
+      case HWP_NCH:err= snd_pcm_hw_params_set_channels(pcm, pars, hwpars[count+1]);
+      		   if( err<0 )
+		     fprintf(stderr, "Could not set # of channels to %d: %s.  "
+		  "Continuing regardless.\n", hwpars[count+1], alsaerrstr(err));
+		    else
+		      printf("Set number of channels to %d.\n", hwpars[count+1]);
+        break;
+      case HWP_FORMAT:err= snd_pcm_hw_params_set_format(pcm, pars, hwpars[count+1]);
+		      if( err<0 )
+		        fprintf(stderr, "Could not set sample format to %s: %s."
+	    "  Continuing regardless.\n", alsafmtstr(hwpars[count+1]), alsaerrstr(err));
+		       else
+		 	 printf("Set sample format to %s.\n", alsafmtstr(hwpars[count+1]));
+        break;
+      default:
+        break;
+    }
+  if( count>0 )
+    printf("Parameter ranges remaining after these settings:\n");
+  snd_pcm_hw_params_get_channels_min(pars, &min);
+  snd_pcm_hw_params_get_channels_max(pars, &max);
+  if( min==max )
+    if( min==1 )
+      printf("1 channel\n");
+    else
+      printf("%u channels\n", min);
+  else
+    printf("%u..%u channels\n", min, max);
+  snd_pcm_hw_params_get_rate_min(pars, &min, NULL);
+  snd_pcm_hw_params_get_rate_max(pars, &max, NULL);
+  if( min==max )
+    printf("Sampling rate %u Hz\nSample formats: ", min);
+  else
+    printf("Sampling rate %u..%u Hz\nSample formats: ", min, max);
+  snd_pcm_hw_params_get_format_mask(pars, fmask);
+  printfmtmask(fmask);
+  printf("\n");
+  result= snd_pcm_hw_params_get_sbits(pars);
+  if( result >= 0 )    // only available if bit width of all formats is the same
+    printf("Significant bits: %d\n", result);
+  snd_pcm_close(pcm);
+}
+
+
+void tc_errcheck(int retval, const char *doingwhat)
+{
+  if( retval<0 ) {
+    fprintf(stderr, "Error %s: %s.  Aborting.\n", doingwhat, alsaerrstr(retval));
+    if( pcm )
+      snd_pcm_close(pcm);
+    exit(1);
+  }
+}
+
+
+/*============================================================================
+			String-building functions
+============================================================================*/
+
+struct alsaerr { int err; char *msg; };
+struct alsaerr aelist[]= {
+  {-EBADFD, "PCM device is in a bad state"},
+  {-EPIPE, "An underrun occurred"},
+  {-ESTRPIPE, "A suspend event occurred"},
+  {-ENOTTY, "Hotplug device has been removed"},
+  {-ENODEV, "Hotplug device has been removed"},
+  {-ENOENT, "Device does not exist"},
+  {0, NULL}
+};
+const char *alsaerrstr(const int errcode)
+{
+  struct alsaerr *search;
+
+  if( errcode >= 0 )
+    return "No error";
+  for( search= aelist; search->msg && search->err!=errcode; ++search);
+  if( search->msg )
+    return search->msg;
+  else
+    return strerror(-errcode);
+}
+
+
+const char *dirstr(int dir)
+{
+  if( !dir )
+    return "=";
+  else if( dir<0 )
+    return "<";
+  else
+    return ">";
+}
+
+
+/*============================================================================
+      Functions for parsing and string output of ALSA sample formats
+============================================================================*/
+
+struct fmtdef { char *fmtname; int format; };
+static struct fmtdef fmtlist[]= {
+  {"S8", SND_PCM_FORMAT_S8},
+  {"U8", SND_PCM_FORMAT_U8},
+  {"S16_LE", SND_PCM_FORMAT_S16_LE},
+  {"S16_BE", SND_PCM_FORMAT_S16_BE},
+  {"U16_LE", SND_PCM_FORMAT_U16_LE},
+  {"U16_BE", SND_PCM_FORMAT_U16_BE},
+  {"S24_LE", SND_PCM_FORMAT_S24_LE},
+  {"S24_BE", SND_PCM_FORMAT_S24_BE},
+  {"U24_LE", SND_PCM_FORMAT_U24_LE},
+  {"U24_BE", SND_PCM_FORMAT_U24_BE},
+  {"S32_LE", SND_PCM_FORMAT_S32_LE},
+  {"S32_BE", SND_PCM_FORMAT_S32_BE},
+  {"U32_LE", SND_PCM_FORMAT_U32_LE},
+  {"U32_BE", SND_PCM_FORMAT_U32_BE},
+  {"FLOAT_LE", SND_PCM_FORMAT_FLOAT_LE},
+  {"FLOAT_BE", SND_PCM_FORMAT_FLOAT_BE},
+  {"FLOAT64_LE", SND_PCM_FORMAT_FLOAT64_LE},
+  {"FLOAT64_BE", SND_PCM_FORMAT_FLOAT64_BE},
+  {"IEC958_SUBFRAME_LE", SND_PCM_FORMAT_IEC958_SUBFRAME_LE},
+  {"IEC958_SUBFRAME_BE", SND_PCM_FORMAT_IEC958_SUBFRAME_BE},
+  {"MU_LAW", SND_PCM_FORMAT_MU_LAW},
+  {"A_LAW", SND_PCM_FORMAT_A_LAW},
+  {"IMA_ADPCM", SND_PCM_FORMAT_IMA_ADPCM},
+  {"MPEG", SND_PCM_FORMAT_MPEG},
+  {"GSM", SND_PCM_FORMAT_GSM},
+  {"SPECIAL", SND_PCM_FORMAT_SPECIAL},
+  {"S24_3LE", SND_PCM_FORMAT_S24_3LE},
+  {"S24_3BE", SND_PCM_FORMAT_S24_3BE},
+  {"U24_3LE", SND_PCM_FORMAT_U24_3LE},
+  {"U24_3BE", SND_PCM_FORMAT_U24_3BE},
+  {"S20_3LE", SND_PCM_FORMAT_S20_3LE},
+  {"S20_3BE", SND_PCM_FORMAT_S20_3BE},
+  {"U20_3LE", SND_PCM_FORMAT_U20_3LE},
+  {"U20_3BE", SND_PCM_FORMAT_U20_3BE},
+  {"S18_3LE", SND_PCM_FORMAT_S18_3LE},
+  {"S18_3BE", SND_PCM_FORMAT_S18_3BE},
+  {"U18_3LE", SND_PCM_FORMAT_U18_3LE},
+  {"U18_3BE", SND_PCM_FORMAT_U18_3BE},
+  {"S16", SND_PCM_FORMAT_S16},
+  {"U16", SND_PCM_FORMAT_U16},
+  {"S24", SND_PCM_FORMAT_S24},
+  {"U24", SND_PCM_FORMAT_U24},
+  {"S32", SND_PCM_FORMAT_S32},
+  {"U32", SND_PCM_FORMAT_U32},
+  {"FLOAT", SND_PCM_FORMAT_FLOAT},
+  {"FLOAT64", SND_PCM_FORMAT_FLOAT64},
+  {"IEC958_SUBFRAME", SND_PCM_FORMAT_IEC958_SUBFRAME},
+  {NULL, 0}
+};
+
+int parse_alsaformat(const char *fmtstr)
+{
+  struct fmtdef *search;
+
+  for( search= fmtlist; search->fmtname && strcmp(search->fmtname, fmtstr); ++search );
+  if( !search->fmtname ) {
+    fprintf(stderr, "Unknown sample format `%s'.  Aborting.\n", fmtstr);
+    exit(1);
+  }
+  return search->format;
+}
+
+const char *alsafmtstr(int fmtnum)
+{
+  struct fmtdef *search;
+
+  for( search= fmtlist; search->fmtname && search->format!=fmtnum; ++search );
+  if( !search->fmtname )
+    return "(unknown)";
+  else
+    return search->fmtname;
+}
+
+
+/*============================================================================
+      			Printout functions
+============================================================================*/
+
+void printfmtmask(const snd_pcm_format_mask_t *fmask)
+{
+  int fmt, prevformat= 0;
+
+  for( fmt= 0; fmt <= SND_PCM_FORMAT_LAST; ++fmt )
+    if( snd_pcm_format_mask_test(fmask, (snd_pcm_format_t)fmt) ) {
+      if( prevformat )
+	printf(", ");
+      printf("%s", snd_pcm_format_name((snd_pcm_format_t)fmt));
+      prevformat= 1;
+    }
+  if( !prevformat )
+    printf("(none)");
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audiodelay.cpp	Fri Oct 30 23:07:52 2009 +0100
@@ -0,0 +1,131 @@
+/******************************************/
+/*
+  audiodelay.cpp
+  by Peter Meerwald, pmeerw@pmeerw.net, 2009.
+
+  This program tests the delay between audio output and input.
+*/
+/******************************************/
+
+#include "RtAudio.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+
+const char *progname = "audiodelay";
+
+typedef signed short  AUDIOSAMPLE_TYPE;
+#define FORMAT RTAUDIO_SINT16
+
+static volatile unsigned int nmeasurements = 0;
+static float accum_measurements = 0.0f;
+
+static int inout(void *out_buf, void *in_buf, unsigned int nbuf_frames,
+           double stream_time, RtAudioStreamStatus status, void *data) {
+  if (status) 
+    printf("%s: stream over/underflow detected\n", progname);
+
+  static unsigned int count_inout = 0;
+  static struct timeval tv_start;
+  static struct timeval tv_stop;
+
+  AUDIOSAMPLE_TYPE *pout = (AUDIOSAMPLE_TYPE *)out_buf, *pin = (AUDIOSAMPLE_TYPE *)in_buf;
+
+  memset(out_buf, 0, nbuf_frames*sizeof(AUDIOSAMPLE_TYPE) * 2);
+  if ((count_inout % (512*128/nbuf_frames)) == 0) {
+      for (unsigned int i = nbuf_frames/2-4; i < nbuf_frames/2+4; i++) {
+        pout[2*i] = 32000;
+        pout[2*i+1] = 32000;
+      }
+    
+      gettimeofday(&tv_start, 0);
+  }
+
+  if (1) {
+    for (unsigned int i = 0; i < nbuf_frames; i++) {
+      if (pin[2*i] > 15000 || pin[2*i+1] > 15000) {
+
+        gettimeofday(&tv_stop, 0);
+      
+        unsigned int msec = (tv_stop.tv_sec - tv_start.tv_sec) * 1000;
+        if (tv_stop.tv_usec < tv_start.tv_usec)
+          msec -= (tv_start.tv_usec - tv_stop.tv_usec) / 1000;
+        else 
+          msec += (tv_stop.tv_usec - tv_start.tv_usec) / 1000;
+
+        accum_measurements += msec;
+        nmeasurements++;
+        printf("%s: measured delay %u ms, offset %u, average %.2f\n", progname, msec, i, accum_measurements / nmeasurements);
+            
+        break;
+      }
+    }
+  }
+
+  count_inout++;
+
+  return 0;
+}
+
+int main(int argc, char *argv[]) {
+  unsigned int channels = 2, sample_rate = 44100, buf_bytes, odevice = 0, idevice = 0, ioffset = 0, ooffset = 0;
+
+  RtAudio adac;
+  if (adac.getDeviceCount() < 1) {
+    std::cout << "\nNo audio devices found!\n";
+    exit(EXIT_FAILURE);
+  }
+
+  // Let RtAudio print messages to stderr.
+  adac.showWarnings(true);
+
+  // Set the same number of channels for both input and output.
+  unsigned int buf_frames = 128;
+  RtAudio::StreamParameters iparams, oparams;
+  iparams.deviceId = idevice;
+  iparams.nChannels = channels;
+  iparams.firstChannel = ioffset;
+  oparams.deviceId = odevice;
+  oparams.nChannels = channels;
+  oparams.firstChannel = ooffset;
+
+  RtAudio::StreamOptions options;
+  options.flags = 0; // RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE, RTAUDIO_SCHEDULE_REALTIME
+  options.numberOfBuffers = 2;
+  options.priority = 0; // for RTAUDIO_SCHEDULE_REALTIME
+
+  try {
+    adac.openStream(&oparams, &iparams, FORMAT, sample_rate, &buf_frames, &inout, (void *)&buf_bytes, &options);
+  }
+  catch (RtError& e) {
+    printf("%s: %s\n", progname, e.getMessage().c_str());
+    exit(EXIT_FAILURE);
+  }
+
+  buf_bytes = buf_frames * channels * sizeof(AUDIOSAMPLE_TYPE);
+
+  try {
+    adac.startStream();
+
+    printf("%s: stream latency %ld frames, %d sample rate\n", progname, adac.getStreamLatency(), adac.getStreamSampleRate());
+
+    printf("%s: running ... press <enter> to quit (%d buffer frames)\n", progname, buf_frames);
+    getchar();
+
+    // Stop the stream.
+    adac.stopStream();
+  }
+  catch (RtError& e) {
+    printf("%s: %s\n", progname, e.getMessage().c_str());
+    goto cleanup;
+  }
+
+cleanup:
+  if (adac.isStreamOpen()) 
+    adac.closeStream();
+
+  return 0;
+}
--- a/audiodelay/Makefile	Fri Oct 30 22:45:25 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-PROGRAMS = audiodelay
-RM = rm -f
-
-CC       = g++
-DEFS     =   -DHAVE_GETTIMEOFDAY -D__LINUX_ALSA__
-CFLAGS   = -O2 -Wall
-LIBRARY  = -lpthread -lasound -lrtaudio
-
-all: $(PROGRAMS)
-
-audiodelay: audiodelay.cpp 
-	$(CC) $(CFLAGS) $(DEFS) -o audiodelay audiodelay.cpp $(LIBRARY)
-
-clean: 
-	-$(RM) *.o $(PROGRAMS) *~ 
-
-strip: 
-	strip $(PROGRAMS)
--- a/audiodelay/audiodelay.cpp	Fri Oct 30 22:45:25 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/******************************************/
-/*
-  audiodelay.cpp
-  by Peter Meerwald, pmeerw@pmeerw.net, 2009.
-
-  This program tests the delay between audio output and input.
-*/
-/******************************************/
-
-#include "RtAudio.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-#include <sys/time.h>
-#include <time.h>
-
-const char *progname = "audiodelay";
-
-typedef signed short  AUDIOSAMPLE_TYPE;
-#define FORMAT RTAUDIO_SINT16
-
-static volatile unsigned int nmeasurements = 0;
-static float accum_measurements = 0.0f;
-
-static int inout(void *out_buf, void *in_buf, unsigned int nbuf_frames,
-           double stream_time, RtAudioStreamStatus status, void *data) {
-  if (status) 
-    printf("%s: stream over/underflow detected\n", progname);
-
-  static unsigned int count_inout = 0;
-  static struct timeval tv_start;
-  static struct timeval tv_stop;
-
-  AUDIOSAMPLE_TYPE *pout = (AUDIOSAMPLE_TYPE *)out_buf, *pin = (AUDIOSAMPLE_TYPE *)in_buf;
-
-  memset(out_buf, 0, nbuf_frames*sizeof(AUDIOSAMPLE_TYPE) * 2);
-  if ((count_inout % (512*128/nbuf_frames)) == 0) {
-      for (unsigned int i = nbuf_frames/2-4; i < nbuf_frames/2+4; i++) {
-        pout[2*i] = 32000;
-        pout[2*i+1] = 32000;
-      }
-    
-      gettimeofday(&tv_start, 0);
-  }
-
-  if (1) {
-    for (unsigned int i = 0; i < nbuf_frames; i++) {
-      if (pin[2*i] > 15000 || pin[2*i+1] > 15000) {
-
-        gettimeofday(&tv_stop, 0);
-      
-        unsigned int msec = (tv_stop.tv_sec - tv_start.tv_sec) * 1000;
-        if (tv_stop.tv_usec < tv_start.tv_usec)
-          msec -= (tv_start.tv_usec - tv_stop.tv_usec) / 1000;
-        else 
-          msec += (tv_stop.tv_usec - tv_start.tv_usec) / 1000;
-
-        accum_measurements += msec;
-        nmeasurements++;
-        printf("%s: measured delay %u ms, offset %u, average %.2f\n", progname, msec, i, accum_measurements / nmeasurements);
-            
-        break;
-      }
-    }
-  }
-
-  count_inout++;
-
-  return 0;
-}
-
-int main(int argc, char *argv[]) {
-  unsigned int channels = 2, sample_rate = 44100, buf_bytes, odevice = 0, idevice = 0, ioffset = 0, ooffset = 0;
-
-  RtAudio adac;
-  if (adac.getDeviceCount() < 1) {
-    std::cout << "\nNo audio devices found!\n";
-    exit(EXIT_FAILURE);
-  }
-
-  // Let RtAudio print messages to stderr.
-  adac.showWarnings(true);
-
-  // Set the same number of channels for both input and output.
-  unsigned int buf_frames = 128;
-  RtAudio::StreamParameters iparams, oparams;
-  iparams.deviceId = idevice;
-  iparams.nChannels = channels;
-  iparams.firstChannel = ioffset;
-  oparams.deviceId = odevice;
-  oparams.nChannels = channels;
-  oparams.firstChannel = ooffset;
-
-  RtAudio::StreamOptions options;
-  options.flags = 0; // RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE, RTAUDIO_SCHEDULE_REALTIME
-  options.numberOfBuffers = 2;
-  options.priority = 0; // for RTAUDIO_SCHEDULE_REALTIME
-
-  try {
-    adac.openStream(&oparams, &iparams, FORMAT, sample_rate, &buf_frames, &inout, (void *)&buf_bytes, &options);
-  }
-  catch (RtError& e) {
-    printf("%s: %s\n", progname, e.getMessage().c_str());
-    exit(EXIT_FAILURE);
-  }
-
-  buf_bytes = buf_frames * channels * sizeof(AUDIOSAMPLE_TYPE);
-
-  try {
-    adac.startStream();
-
-    printf("%s: stream latency %ld frames, %d sample rate\n", progname, adac.getStreamLatency(), adac.getStreamSampleRate());
-
-    printf("%s: running ... press <enter> to quit (%d buffer frames)\n", progname, buf_frames);
-    getchar();
-
-    // Stop the stream.
-    adac.stopStream();
-  }
-  catch (RtError& e) {
-    printf("%s: %s\n", progname, e.getMessage().c_str());
-    goto cleanup;
-  }
-
-cleanup:
-  if (adac.isStreamOpen()) 
-    adac.closeStream();
-
-  return 0;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rtaudio-test.cpp	Fri Oct 30 23:07:52 2009 +0100
@@ -0,0 +1,113 @@
+#include <cmath>
+#include <stdlib.h>
+#include <iostream>
+#include <vector>
+#include "RtAudio.h"
+
+int myCallback(void *outputBuffer, void *inputBuffer, unsigned int bufferFrames, double streamTime, RtAudioStreamStatus status, void *userData) {
+  unsigned int i, j;
+  float *buffer = (float *) outputBuffer;
+
+  if ( status )
+    std::cout << "Stream underflow detected!" << std::endl;
+
+  if (!buffer)
+    return 0;
+
+  // Write interleaved audio data.
+  static int t = 0;
+  for ( i=0; i<bufferFrames/2; i++ ) {
+    for ( j=0; j<2; j++ ) {
+      *buffer++ = 0; // 0.25*cosf((t/(float)1000)); 
+
+    }
+    if (++t > 1000) t = 0;
+  }
+    
+  return 0;
+}
+
+int main() {
+  RtAudio audio;
+
+  // Determine the number of devices available
+  unsigned int devices = audio.getDeviceCount();
+  std::cout << devices << " devices found\n";
+
+  // Scan through devices for various capabilities
+  RtAudio::DeviceInfo info;
+  for ( unsigned int i=0; i<devices; i++ ) {
+
+    info = audio.getDeviceInfo( i );
+
+    if ( info.probed == true ) {
+      // Print, for example, the maximum number of output channels for each device
+      std::cout << "device: #" << i << " - " << info.name << "\n";
+      std::cout << "  output channels: " << info.outputChannels << "\n";
+      std::cout << "  input channels: " << info.inputChannels << "\n";
+      std::cout << "  duplex channels: " << info.duplexChannels << "\n";
+      std::cout << "  default input/output: " << info.isDefaultInput << " / " << info.isDefaultOutput << "\n";
+      
+      std::cout << "  sample rates:\n";
+      for (std::vector<unsigned int>::iterator i = info.sampleRates.begin(); i != info.sampleRates.end(); i++) {
+          std::cout << "    " << *i << "\n";
+      }
+      std::cout << "  data formats:\n";      
+      if (info.nativeFormats & RTAUDIO_SINT8) std::cout << "    signed 8-bit\n";
+      if (info.nativeFormats & RTAUDIO_SINT16) std::cout << "    signed 16-bit\n";
+      if (info.nativeFormats & RTAUDIO_SINT24) std::cout << "    signed 24-bit\n";
+      if (info.nativeFormats & RTAUDIO_SINT32) std::cout << "    signed 32-bit\n";
+      if (info.nativeFormats & RTAUDIO_FLOAT32) std::cout << "    32-bit float [-1,1]\n";
+      if (info.nativeFormats & RTAUDIO_FLOAT64) std::cout << "    64-bit float [-1,1]\n";
+    }
+    else
+      std::cout << "device: #" << i << " - not probed\n";
+  }
+
+  RtAudio::StreamParameters oparam;
+  oparam.deviceId = audio.getDefaultOutputDevice();
+  oparam.nChannels = 1;
+  oparam.firstChannel = 0;
+
+  RtAudio::StreamParameters iparam;
+  iparam.deviceId = audio.getDefaultInputDevice();
+  iparam.nChannels = 1;
+  iparam.firstChannel = 0;
+
+    
+  unsigned int sampleRate = 44100;
+  unsigned int bufferFrames = 256; // 256 sample frames
+
+  RtAudio::StreamOptions options;
+  options.flags = 0;
+  options.numberOfBuffers = 2;
+  options.streamName = "test";
+
+    
+  try {
+    audio.openStream( &oparam, &iparam, RTAUDIO_FLOAT32,
+                    sampleRate, &bufferFrames, &myCallback, (void*) 0, &options );
+    audio.startStream();
+  }
+  catch ( RtError& e ) {
+    std::cout << '\n' << e.getMessage() << '\n' << std::endl;
+    exit( EXIT_FAILURE );
+  }
+
+  char input;
+  std::cout << "\nPlaying ... press <enter> to quit.\n";
+  std::cin.get( input );
+
+  try {
+    // Stop the stream
+    audio.stopStream();
+  }
+  catch (RtError& e) {
+    e.printMessage();
+  }
+
+  if ( audio.isStreamOpen() ) 
+    audio.closeStream();
+
+  return EXIT_SUCCESS;
+}

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.