static sound_file *fill_sf_record(const char *name, sound_file *sf)
{
  int i;

  sf->data_location = mus_header_data_location();
  sf->samples = mus_header_samples();
  sf->data_format = mus_header_format();
  sf->srate = mus_header_srate();
  /* if (sf->srate < 0) sf->srate = 0; */
  sf->chans = mus_header_chans();
  /* if (sf->chans < 0) sf->chans = 0; */
  sf->datum_size = mus_bytes_per_sample(sf->data_format);
  sf->header_type = mus_header_type();
  sf->original_sound_format = mus_header_original_format();
  sf->true_file_length = mus_header_true_length();

  sf->comment_start = mus_header_comment_start();
  sf->comment_end = mus_header_comment_end();
  if (((sf->header_type == MUS_AIFC) || 
       (sf->header_type == MUS_AIFF) || 
       (sf->header_type == MUS_RF64) || 
       (sf->header_type == MUS_RIFF)) &&
      (mus_header_aux_comment_start(0) != 0))

    {
      sf->aux_comment_start = (mus_long_t *)calloc(4, sizeof(mus_long_t));
      sf->aux_comment_end = (mus_long_t *)calloc(4, sizeof(mus_long_t));
      for (i = 0; i < 4; i++)
	{
	  sf->aux_comment_start[i] = mus_header_aux_comment_start(i);
	  sf->aux_comment_end[i] = mus_header_aux_comment_end(i);
	}
    }

  sf->type_specifier = mus_header_type_specifier();
  sf->bits_per_sample = mus_header_bits_per_sample();
  sf->fact_samples = mus_header_fact_samples();
  sf->block_align = mus_header_block_align();
  sf->write_date = local_file_write_date(name);

  if ((sf->header_type == MUS_AIFF) || (sf->header_type == MUS_AIFC))
    {
      int *marker_ids, *marker_positions;
      sf->markers = mus_header_mark_info(&marker_ids, &marker_positions);
      if (sf->markers > 0)
	{
	  sf->marker_ids = (int *)malloc(sf->markers * sizeof(int));
	  sf->marker_positions = (int *)malloc(sf->markers * sizeof(int));
	  memcpy((void *)(sf->marker_ids), (void *)marker_ids, sizeof(int) * sf->markers);
	  memcpy((void *)(sf->marker_positions), (void *)marker_positions, sizeof(int) * sf->markers);
	}
    }

  if (mus_header_loop_mode(0) > 0)
    {
      sf->loop_modes = (int *)calloc(2, sizeof(int));
      sf->loop_starts = (int *)calloc(2, sizeof(int));
      sf->loop_ends = (int *)calloc(2, sizeof(int));
      for (i = 0; i < 2; i++)
	{
	  sf->loop_modes[i] = mus_header_loop_mode(i);
	  if ((sf->header_type == MUS_AIFF) || 
	      (sf->header_type == MUS_AIFC))
	    {
	      sf->loop_starts[i] = mus_header_mark_position(mus_header_loop_start(i)); 
	      sf->loop_ends[i] = mus_header_mark_position(mus_header_loop_end(i));
	    }
	  else
	    {
	      sf->loop_starts[i] = mus_header_loop_start(i); 
	      sf->loop_ends[i] = mus_header_loop_end(i);
	    }
	}
      sf->base_detune = mus_header_base_detune();
      sf->base_note = mus_header_base_note();
    }

  return(sf);
}
Exemple #2
0
/* Create a soundfile header of the specified type. The usage msg above
   describes the kind of types you can create. (These are ones that
   sndlib can write and that can be useful to the average cmix user.
   There are other kinds of header sndlib can write -- for example,
   for 24-bit files -- but we want to keep the sfcreate syntax as
   simple as possible.

   We allocate a generous comment area, because expanding it after a
   sound has already been written would mean copying the entire file.
   (We use comments to store peak stats -- see sys/sndlibsupport.c.)
*/
int
main(int argc, char *argv[])
{
   int         i, fd, result, overwrite_file, old_format, old_header_type=0;
   int         data_location, old_data_location, old_nsamps, old_datum_size;
   int         force = FALSE;
   struct stat statbuf;

   /* get name of this program */
   progname = strrchr(argv[0], '/');
   if (progname == NULL)
      progname = argv[0];
   else
      progname++;

   if (argc < 2)
      usage();

   for (i = 1; i < argc; i++) {
      char *arg = argv[i];

      if (arg[0] == '-') {
         switch (arg[1]) {
            case 'c':
               if (++i >= argc)
                  usage();
               nchans = atoi(argv[i]);
               break;
            case 'r':
               if (++i >= argc)
                  usage();
               srate = atoi(argv[i]);
               break;
            case 'i':
               is_short = TRUE;
               break;
            case 'f':
               is_short = FALSE;
               break;
            case 'b':
               endian = CREATE_BIG_ENDIAN;
               break;
            case 'l':
               endian = CREATE_LITTLE_ENDIAN;
               break;
            case 't':
               if (++i >= argc)
                  usage();
               strncpy(format_name, argv[i], FORMAT_NAME_LENGTH - 1);
               format_name[FORMAT_NAME_LENGTH - 1] = 0; /* ensure termination */
               break;
            case '-':
               if (strcmp(arg, "--force") == 0)
                  force = TRUE;
               else
                  usage();
               break;
            default:  
               usage();
         }
      }
      else
         sfname = arg;
   }
   if (sfname == NULL)
      usage();

   if (check_params())
      usage();

   old_data_location = old_format = old_datum_size = old_nsamps = 0;

   /* Test for existing file. If there is one, and we can read and write it,
      and the force flag is set, then we'll overwrite its header.  Note that
      we slap on a header even if the file doesn't have one already, as 
      would be the case with a raw sound file (or a precious text file...).
      If there isn't an existing file, we'll create a new one.
   */
   overwrite_file = FALSE;
   result = stat(sfname, &statbuf);
   if (result == -1) {
      if (errno == ENOENT) {       /* file doesn't exist, we'll create one */
         fd = open(sfname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
         if (fd == -1) {
            fprintf(stderr, "Error creating file \"%s\" (%s)\n",
                                                      sfname, strerror(errno));
            exit(1);
         }
      }
      else {
         fprintf(stderr,
              "File \"%s\" exists, but there was an error accessing it (%s)\n",
                                                      sfname, strerror(errno));
         exit(1);
      }
   }
   else {
      int drastic_change;

      overwrite_file = TRUE;

      /* File exists and we could stat it. If it's a regular file, open
         it and see if it looks like a sound file.
      */
      if (!S_ISREG(statbuf.st_mode)) {
         fprintf(stderr, "\"%s\" exists, but it's not a regular file.\n",
                                                                      sfname);
         exit(1);
      }
      fd = open(sfname, O_RDWR);
      if (fd == -1) {
         fprintf(stderr, "Error opening file (%s)\n", strerror(errno));
         exit(1);
      }
      if (sndlib_read_header(fd) == -1) {
         fprintf(stderr, "Error reading header (%s)\n", strerror(errno));
         exit(1);
      }
      old_header_type = mus_header_type();
      old_format = mus_header_format();
      if (NOT_A_SOUND_FILE(old_header_type)
                                         || INVALID_DATA_FORMAT(old_format)) {
         fprintf(stderr, "\nWARNING: \"%s\" exists, but doesn't look like "
                         "a sound file.\n\n", sfname);
         drastic_change = TRUE;
         old_header_type = MUS_RAW;
      }
      else if (old_header_type != header_type || old_format != data_format)
         drastic_change = TRUE;
      else
         drastic_change = FALSE;

      if (drastic_change && !force) {
         fprintf(stderr, "%s\n", OVERWRITE_WARNING);
         exit(1);
      }

      old_data_location = mus_header_data_location();
      old_nsamps = mus_header_samples();         /* samples, not frames */
      old_datum_size = mus_header_data_format_to_bytes_per_sample();
   }

   result = sndlib_write_header(fd, 0, header_type, data_format, srate, nchans,
                                                        NULL, &data_location);
   if (result == -1) {
      fprintf(stderr, "Error writing header (%s)\n", strerror(errno));
      exit(1);
   }

   /* If we're overwriting a header, we have to fiddle around a bit
      to get the correct data_size into the header.
      (These will not likely be the same if we're changing header types.)
   */
   if (overwrite_file) {
      int loc_byte_diff, datum_size, sound_bytes;

      /* need to do this again */
      if (sndlib_read_header(fd) == -1) {
         fprintf(stderr, "Error re-reading header (%s)\n", strerror(errno));
         exit(1);
      }

      if (data_format != old_format && old_header_type != MUS_RAW)
        if (! FORMATS_SAME_BYTE_ORDER(data_format, old_format))
            printf("WARNING: Byte order changed!\n");

      datum_size = mus_header_data_format_to_bytes_per_sample();

      loc_byte_diff = data_location - old_data_location;

      /* If the data locations have changed, we're effectively adding or
         subtracting sound data bytes. Depending on the number of bytes
         added, this could result in swapped channels or worse. We can't
         do anything about this, because our scheme for encoding peak stats
         in the header comment requires a fixed comment allocation in the
         header. (Otherwise, we could shrink or expand this to make things
         right.) The best we can do is warn the user.
      */
      if (loc_byte_diff) {
         if (loc_byte_diff > 0)
            printf("Losing %d bytes of sound data\n", loc_byte_diff);
         else if (loc_byte_diff < 0)
            printf("Gaining %d bytes of sound data\n", -loc_byte_diff);

         if (loc_byte_diff % datum_size)
            printf("%s\n", WORD_INTEGRITY_WARNING);
         else if (loc_byte_diff % (nchans * datum_size))
            printf("%s\n", CHANNEL_SWAP_WARNING);
         /* else got lucky: no shifted words or swapping */

         sound_bytes = (old_nsamps * old_datum_size) - loc_byte_diff;  
      }
      else                               /* same number of bytes as before */
         sound_bytes = old_nsamps * old_datum_size;  

      result = sndlib_set_header_data_size(fd, header_type, sound_bytes);
      if (result == -1) {
         fprintf(stderr, "Error updating header\n");
         exit(1);
      }

      close(fd);
   }
   else
      close(fd);

   return 0;
}
Exemple #3
0
/* ------------------------------------------------------ open_sound_file --- */
int
open_sound_file(
      const char     *funcname,       // for error messages
      const char     *sfname,         // name of sound file to open
      int     		 *header_type,    // Remaining args are pointers to storage for
      int     		 *data_format,    //    various bits of file header info.  If
      int     		 *data_location,  //    pointer is NULL, it will be ignored.
      double   		 *srate,          //    Info is undefined on error return (-1).
      int     		 *nchans,
      long     		 *nsamps)
{
   // See if file exists and is a regular file or link.
   struct stat sfst;
   if (stat(sfname, &sfst) == -1) {
      rterror(funcname, "\"%s\": %s", sfname, strerror(errno));
      return -1;
   }
   if (!S_ISREG(sfst.st_mode) && !S_ISLNK(sfst.st_mode)) {
      rterror(funcname, "\"%s\" is not a regular file or a link.\n", sfname);
      return -1;
   }

   // Open the file and read its header.
   int fd = sndlib_open_read(sfname);
   if (fd == -1) {
      rterror(funcname, "Can't read header from \"%s\" (%s)\n",
		   sfname, strerror(errno));
      return -1;
   }

   // Now info is available from sndlib query functions.

   int type = mus_header_type();

   if (NOT_A_SOUND_FILE(type)) {
      rterror(funcname, "\"%s\" is probably not a sound file\n", sfname);
      sndlib_close(fd, 0, 0, 0, 0);
      return -1;
   }

   int format = mus_header_format();

   if (INVALID_DATA_FORMAT(format)) {
      rterror(funcname, "\"%s\" has invalid sound data format\n", sfname);
      sndlib_close(fd, 0, 0, 0, 0);
      return -1;
   }

   if (!SUPPORTED_DATA_FORMAT(format)) {
      rterror(funcname, "Can't open \"%s\": can read only 16-bit integer, "
                        "24-bit integer and 32-bit float files.", sfname);
      sndlib_close(fd, 0, 0, 0, 0);
	  return -1;
   }

   if (header_type)
      *header_type = type;
   if (data_format)
      *data_format = format;
   if (data_location)
      *data_location = mus_header_data_location();
   if (srate)
      *srate = (double) mus_header_srate();
   if (nchans)
      *nchans = mus_header_chans();
   if (nsamps)
      *nsamps = mus_header_samples();

   return fd;
}