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 */