From: Jan Stary <hans@stare.cz>
To: sox-users@lists.sourceforge.net
Subject: Re: how to interpret tell_off, and the right way to use sox_seek
Date: Mon, 6 Nov 2017 22:09:35 +0100 [thread overview]
Message-ID: <20171106210932.GA41280@www.stare.cz> (raw)
In-Reply-To: <CAOphizLLcY6LX=q3SZk0MwGq9SMeutbmLkMrhWyPStxu79hMZQ@mail.gmail.com>
On Nov 06 12:14:59, dan.hitt@gmail.com wrote:
> On Mon, Nov 6, 2017 at 11:06 AM, Jan Stary <hans@stare.cz> wrote:
> >> I do take your message to imply that SoX will read no more samples
> >> than the number of in a file total, so that, e.g., if you read the
> >> same 10 blocks of samples and sox_seek() to the beginning of them
> >> repeatedly, eventually your reads will fail. And in fact, if the
> >> length of the file is 50 blocks, those reads will fail as soon as you
> >> have done this 5 times. If this is not correct, please let me know!!
> >> :)
> >
> > There is a difference between SoX the utility and libsox the library.
> > I am not sure if SoX itself ever reads a block of audio more than once
> > (I can imagina situations where it would), but that's not a constraint
> > on what the libsox library can do. If it has a sox_seek(), then I suppose
> > it does what the name says; in particular, it lets you read the same
> > block of audio over ano over again as long as you keep seekign back.
> > (Disclaimer: I have never used libsox directly,
> > I only use SoX the binary.)
>
> This is the crux of the matter, and appears not to be the case.
>
> I wrote a little program to test exactly this assertion, that you
> cannot repeatedly
> call sox_seek().
>
> The answer here appears to be that indeed you cannot.
>
> Here's the test program:
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <sox.h>
>
> int main( int argc, char** argv ) {
> if ( argc < 2 ) {
> fprintf(stderr,"Call with one arg, the name of a sound file.\n" );
> exit(1);
> }
> int istat = sox_init();
> if (istat != SOX_SUCCESS ) {
> fprintf(stderr, "Failed to initialize sox, error %d.\n", istat);
> exit(1);
> }
> char* infile = argv[1];
> sox_format_t* s = sox_open_read( infile, 0, 0, 0 );
> if ( ! s ) {
> fprintf(stderr,"Failed to open `%s' .\n", infile);
> exit(1);
> }
> int buf[1024];
> int count = 0;
> while ( 1 ) {
> int rcnt = sox_read( s, buf, 1024 );
> if ( rcnt <= 0 ) {
> printf( "Failed on read, attempt %d\n", count );
> exit( 0 );
> }
> int status = sox_seek( s, 0, SOX_SEEK_SET );
> if ( status ) {
> fprintf(stderr,"Failed on seek.\n" );
> exit(1);
> }
> count++;
> }
> return 0; // not reached
> }
>
$ cc -o soxseek soxseek.c -lsox -I/usr/local/include/ -L/usr/local/lib
$ sox -n /tmp/file.wav synth trim 0 $((1024 * 1000))s
$ ./soxseek /tmp/file.wav
Failed on read, attempt 1000
That makes me suspect it's just an end of file.
To quote the outdated and incomplete libsox manpage:
sox_read and sox_write return the number of samples successfully read
or written. If an error occurs, or the end-of-file is reached, the return
value is a short item count or SOX_EOF. TODO: sox_read does not
distiguish between end-of-file and error. Need an feof() and ferror()
concept to determine which occured.
> I ran it on a file a few megabytes long, and it did a few thousand
> seeks, then failed on the read.
The above does exactly 1000 reads of 1024,
which is exactly how many samples the file contains.
So ( rcnt <= 0 ) does not mean there was an error.
> So it behaves as though there's some kind of internal counter
> initialized to the length of the file, and each read decrements that
> counter by the amount read; when the counter runs out, then reads are
> no longer permitted.
Yes.
If I am reading your code right, it does not seek at all.
It just reads up to EOF. Which might be an error in sox_seek().
As I said, I haven't used libsox before, so I don't know if
this is a correct use of sox_seek(), but beware: not every
input is seekable (a regular file on disk should be, though).
> For me, that's the most important point: to try to have an exact
> characterization of the behavior of the library under these
> circumstances.
There is no good documentation of libsox. The libosx(3) man page
is both incomplete and outdated, and it has been for years.
You might want to look an the src/example*c files.
> >
> > ... (cut)
> > Is there anything left of the original problem then?
>
> No.
>
> That's been solved.
>
> But it would be useful to have confirmation that this behavior is
> intentional, or information on how to avoid the phenoomenon, but for
> now i've dealt with it, although perhaps unnecessarily given the right
> combination of function calls and arguments.
I still suspect that it is first of all unnecessary to read the input
again and again while seeking back again and again; but I can't be sure,
because I still have no idea about what you are doing.
> > ... (cut)
> >> A sort of analogous situation is with the file system and linux: if
> >> you're reading through a file the OS will keep it in memory so you
> >> don't have too much overhead just relying on the OS itself to seek
> >> back and forth in a file --- the caching has already been done.
> >
> > You already _have_ the data in memory once you have sox_read() them,
> > so I fail to see the analogy. Why would you seek back and read it
> > again _from_the_file_ once you have it in an array?
>
> Not necessarily, as you may be reusing the storage you've set aside.
So don't reuse it: keep the copy of what you have read
so that you don't have to read it over again.
> I think the best, simplest way to obtain the same samples over and
> over would be to seek to them, and read them again.
Why do you think that? Just sox_read() it into an array,
then keep reading that array, instead of reading from a file.
> Thanks again for your help, and if anything i've said is wrong, i'd
> appreciate any correction, clarification, or references.
I staill have no idea about what you are actually trying to do.
Jan
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Sox-users mailing list
Sox-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sox-users
next prev parent reply other threads:[~2017-11-06 21:09 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-04 7:26 how to interpret tell_off, and the right way to use sox_seek Dan Hitt
2017-11-06 11:10 ` Jan Stary
2017-11-06 18:08 ` Dan Hitt
2017-11-06 19:06 ` Jan Stary
2017-11-06 20:14 ` Dan Hitt
2017-11-06 21:09 ` Jan Stary [this message]
2017-11-06 21:47 ` Dan Hitt
2017-11-07 8:50 ` Jan Stary
2017-11-07 9:01 ` Jan Stary
2017-11-07 9:13 ` Jan Stary
2017-11-07 9:22 ` Jan Stary
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://lists.sourceforge.net/lists/listinfo/sox-users
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171106210932.GA41280@www.stare.cz \
--to=sox-users@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/sox.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).