hi *,

i've got a strange issue with libsndfile.

in foo (http://foo.sf.net) the SFM_RDWR mode is used, because target
soundfiles are created independently of the write process before, then
the file gets opened with SFM_RDWR to determine the target soundfile's
parameters (samplerate, channels...).

with SF_FORMAT_AIFF | SF_FORMAT_FLOAT (and SF_FORMAT_DOUBLE, btw., 2
channels) i notice a strange behavior: directly after creating the
file (without sf_writing anything) the number of frames of the file is
4 (SF_FORMAT_DOUBLE: 2 frames).  this doesn't happen neither with the
SF_FORMAT_PCM_* things, nor with SF_FORMAT_WAV.  with just 1 channel
the values are 6 resp. 3.

when reopening the file for writing (SFM_RDWR mode), there is no
difference between seeking to (0, SEEK_SET) and (0, SEEK_END), both
seek to 0.  surprisingly, seeking to (4, SEEK_SET) doesn't return an
error.

after writing 512 frames after seeking (in all three cases) and having
closed the file, the number of frames is now 511 (1022 with 1
channel).

am i missing something, or is this a bug in libsndfile?  attached my
test prog.

bests,

martin



/*
 * compile with:
 *
 * gcc -o soundfile -Wall -lsndfile soundfile.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sndfile.h>


int
show_nframes (char *filename)
{
  SF_INFO info;
  SNDFILE *file;
  int mode;

/*   mode = SFM_READ; /\* nframes (directly after creating) is correct *\/ */
  mode = SFM_RDWR; /* nframes is incorrect */

  info.format = 0;

  if ((file = sf_open(filename, mode, &info)) == NULL)
    {
      fprintf(stderr, "libsndfile(open): %s\n", sf_strerror(file));
      return -1;
    }

  fprintf(stderr, "nframes: %ld\n", (long)info.frames);

  if (sf_close(file))
    {
      fprintf(stderr, "libsndfile(close): %s\n", sf_strerror(file));
      return -1;
    }

  return 0;
} /* show_nframes */


int
main (int argc,
      char **argv)
{
  SF_INFO info;
  int mode;
  SNDFILE *file;
  char *filename = "/tmp/sndtest.aiff";

  /* create soundfile */
  mode = SFM_WRITE;
  info.samplerate = 48000;
  info.channels = 2;
  info.format = SF_FORMAT_AIFF | SF_FORMAT_FLOAT;

  /* delete if already there */
  {
    struct stat st;
    
    if (! stat(filename, &st))
      {
	remove(filename);
      }
  }

  /* open */
  if ((file = sf_open(filename, mode, &info)) == NULL)
    {
      fprintf(stderr, "libsndfile(open): %s\n", sf_strerror(file));
      exit(EXIT_FAILURE);
    }
  
  /* close without writing: just write header */
  if (sf_close(file))
    {
	fprintf(stderr, "libsndfile(close): %s\n", sf_strerror(file));
	exit(EXIT_FAILURE);
    }

  /* how many frames do we have now? */
  show_nframes(filename);

  /* open again for writing */
  mode = SFM_RDWR; /* !!! */
  info.format = 0;

  if ((file = sf_open(filename, mode, &info)) == NULL)
    {
      fprintf(stderr, "libsndfile(open): %s\n", sf_strerror(file));
      exit(EXIT_FAILURE);
    }
  
  /* now write some frames */
  {
    float buffer[1024];
    long err;
    int frames = 1024 / info.channels;

    /* seek
     *
     * surprisingly, in this case it doesn't matter whether we seek to
     * 0 from SEEK_SET or SEEK_END, in both cases we will seek to 0 */
    if ((err = sf_seek(file, 0, SEEK_SET)) == -1)
/*     if ((err = sf_seek(file, 0, SEEK_END)) == -1) */

    /* but this doesn't return an error, even worse: number of frames
     *  after writing is the same wrong number (511) as with the other
     *  seeks */
/*     if ((err = sf_seek(file, 4, SEEK_SET)) == -1) */
      {
	fprintf(stderr, "libsndfile: sf_seek(): %s\n", sf_strerror(file));
	exit(EXIT_FAILURE);
      }
    fprintf(stderr, "seeked to position %ld\n", err);

  /* write */
    if ((err = sf_writef_float(file, buffer, frames)) == -1)
    {
      fprintf(stderr, "libsndfile: sf_writef_float(): %s\n", sf_strerror(file));
      exit(EXIT_FAILURE);
    }
    fprintf(stderr, "wrote %ld frames\n", err);
  }

  /* close */
  if (sf_close(file))
    {
      fprintf(stderr, "libsndfile(close): %s\n", sf_strerror(file));
      exit(EXIT_FAILURE);
    }

  /* again: how many frames now? */
  show_nframes(filename);

  return EXIT_SUCCESS;
} /* main */

Reply via email to