Loop info

Download sourcecode: loopinfo.c
/*
Phill Phelps (zenpho@zenpho.co.uk) 2014 June 01

Recently I found a big collection of WAV files exported from soundfonts, and I needed to display the loop offset values so I could dial in the loops on a hardware sampler.

I wrote this very simple linux command line program (using the excellent libsndfile library) to help me do this.

Note: commandline argument handling is very crude - getopt.h is not used
*/

#include <stdio.h> 
#include <sndfile.h> 
#include <stdlib.h> 
#include <string.h> 

void disp_sfinfo(SF_INFO *sfinfo)
{
  printf("frames:\t\t%ld\n",      (long)sfinfo-> frames);
  printf("samplerate:\t%d\n",     sfinfo-> samplerate);
  printf("channels:\t%d\n",       sfinfo-> channels);
  printf("format number:\t%d\n",  sfinfo-> format);
  printf("sections:\t%d\n",       sfinfo-> sections);
  printf("seekable?:\t%d\n",      sfinfo-> seekable);
  printf("\n");
}

void disp_sfloopinfo(SF_LOOP_INFO *sfloopinfo)
{
  printf("WARNING - currently ignored\n");
  printf("\n");
}

void disp_sfinstrument(SF_INSTRUMENT *sfinstrument)
{
  printf("note:\t\t%d\n",         sfinstrument-> basenote);
  printf("detune:\t\t%d\n",         sfinstrument-> detune);
  printf("num loops:\t%d\n",     sfinstrument-> loop_count);
  int loop = 0;
  while(loop <  sfinstrument-> loop_count) {
    printf("loop [%d]\n", loop);
    printf("\tmode:\t%d\n",    sfinstrument-> loops[loop].mode);
    printf("\tstart:\t%d\n",   sfinstrument-> loops[loop].start);
    printf("\tend:\t%d\n",     sfinstrument-> loops[loop].end);
    loop++;
  }
  printf("\n");
}

void exitDisplayingUsage(char *command)
{
  // display usage and exit with returncode 1
  printf("usage: %s < filename>  [< display mode 0|1|2> ]\n", command);
  exit(1);
}

int main(int argc, char* argv[])
{
  char *command = argv[0];
  char *filename = NULL;
  SNDFILE *infile;
  SF_INFO sfinfo;
  SF_LOOP_INFO sfloopinfo;
  SF_INSTRUMENT sfinstrument;

  int displaymode = 0;
  /* 
    == Mode values ==
    0, just instrument info
    1, drum/loop/playlist info
    > 1, above plus basic info
  */

  // abort if the argument count is invalid
  if (argc <  2 || argc >  3)
  {
    exitDisplayingUsage(command);
  }
  // try to set the displaymode - abort on error
  else if (argc == 3)
  {
    if (sscanf(argv[2], "%i", &displaymode)!=1) // not an integer?
      exitDisplayingUsage(command);

    // clip range
    if (displaymode <  0) displaymode = 0;
    if (displaymode >  2) displaymode = 2;
  }


  // abort if we fail to read file
  memset(&sfinfo, 0, sizeof (sfinfo));
  filename = argv[1];
  if ((infile = sf_open(filename, SFM_READ, &sfinfo)) == NULL)
  {
    printf("==%s Error reading/parsing==\n", filename);
    sf_close(infile);
    exit(1);
  }

  // shoud we show basic info?
  if ( displaymode >  1 )
  {
    printf("==%s Basic information==\n", filename);
    disp_sfinfo(&sfinfo);
  }

  // should we show drum/beat/playlist info?
  if ( displaymode > = 1 )
  {  
    // report if we fail/succeed obtaining info
    memset(&sfloopinfo, 0, sizeof(sfloopinfo));
    if (sf_command(infile, SFC_GET_LOOP_INFO, &sfloopinfo, sizeof(sfloopinfo) ) == SF_FALSE)
      printf("==%s Error reading loop (drum/beat/playlist) info=='\n", filename);
    else
    {
      printf("==%s Loop (drum/beat/playlist) info==\n", filename);
      disp_sfloopinfo(&sfloopinfo);
    }
  }

  // should we show instrument info?
  if ( displaymode > = 0 )
  {
    // report if we fail/succeed obtaining info
    memset(&sfinstrument, 0, sizeof(sfinstrument));
    if (sf_command(infile, SFC_GET_INSTRUMENT, &sfinstrument, sizeof(sfinstrument) ) == SF_FALSE)
      printf("==%s Error reading instrument (MIDI/Sample) info==\n", filename);
    else
    {
      printf("==%s Instrument (MIDI/Sample) info==\n", filename);
      disp_sfinstrument(&sfinstrument);
    }
  }

  exit(0);
}