Re: how to interpret tell_off, and the right way to use sox_seek

Jan Stary <[email protected]>
Newsgroups gmane.comp.audio.sox
Message-ID <[email protected]>
On Nov 07 10:01:41, [email protected] wrote:
> On Nov 07 09:50:36, [email protected] wrote:
> > So I think you are right. It does seek back to the begining of the sine wave
> > (thus reporting 0 as the first sample value in the buffer), but it gets
> > exhausted at EOF anyway. I suspect now it is a bug in sox_seek()
> > if we are calling it right.
> 
> Much as I like sox, I don't trust this code very much:
> 
> int sox_seek(sox_format_t * ft, sox_uint64_t offset, int whence)
> {
>     /* FIXME: Implement SOX_SEEK_CUR and SOX_SEEK_END. */
>     if (whence != SOX_SEEK_SET)
>         return SOX_EOF; /* FIXME: return SOX_EINVAL */
> 
>     /* If file is a seekable file and this handler supports seeking,
>      * then invoke handler's function.
>      */
>     if (ft->seekable && ft->handler.seek)
>       return (*ft->handler.seek)(ft, offset);
>     return SOX_EOF; /* FIXME: return SOX_EBADF */
> }

This is wav's handler's seek() from src/wav.c (14.4.2):


static int seek(sox_format_t * ft, uint64_t offset)
{
  priv_t *   wav = (priv_t *) ft->priv;

  if (ft->encoding.bits_per_sample & 7)
    lsx_fail_errno(ft, SOX_ENOTSUP, "seeking not supported with this encoding");
  else if (wav->formatTag == WAVE_FORMAT_GSM610) {
    int alignment;
    size_t gsmoff;

    /* rounding bytes to blockAlign so that we
     * don't have to decode partial block. */
    gsmoff = offset * wav->blockAlign / wav->samplesPerBlock +
             wav->blockAlign * ft->signal.channels / 2;
    gsmoff -= gsmoff % (wav->blockAlign * ft->signal.channels);

    ft->sox_errno = lsx_seeki(ft, (off_t)(gsmoff + wav->dataStart), SEEK_SET);
    if (ft->sox_errno == SOX_SUCCESS) {
      /* offset is in samples */
      uint64_t new_offset = offset;
      alignment = offset % wav->samplesPerBlock;
      if (alignment != 0)
          new_offset += (wav->samplesPerBlock - alignment);
      wav->numSamples = ft->signal.length - (new_offset / ft->signal.channels);
    }
  } else {
    double wide_sample = offset - (offset % ft->signal.channels);
    double to_d = wide_sample * ft->encoding.bits_per_sample / 8;
    off_t to = to_d;
    ft->sox_errno = (to != to_d)? SOX_EOF : lsx_seeki(ft, (off_t)wav->dataStart + (off_t)to, SEEK_SET);
    if (ft->sox_errno == SOX_SUCCESS)
      wav->numSamples -= (size_t)wide_sample / ft->signal.channels;
  }

  return ft->sox_errno;
}


It seems you are right: wav->numSamples get decremented no matter what.
That seems wrong, but I am not sure if that is exactly our problem.

This is the lsx_seeki() (in src/formats_i.c) that
eventually does fseeko() on the underlying (FILE*)ft->fp 


/* Implements traditional fseek() behavior.  Meant to abstract out
 * file operations so that they could one day also work on memory
 * buffers.
 *
 * N.B. Can only seek forwards on non-seekable streams!
 */
int lsx_seeki(sox_format_t * ft, off_t offset, int whence)
{
    if (ft->seekable == 0) {
        /* If a stream peel off chars else EPERM */
        if (whence == SEEK_CUR) {
            while (offset > 0 && !feof((FILE*)ft->fp)) {
                getc((FILE*)ft->fp);
                offset--;
                ++ft->tell_off;
            }
            if (offset)
                lsx_fail_errno(ft,SOX_EOF, "offset past EOF");
            else
                ft->sox_errno = SOX_SUCCESS;
        } else
            lsx_fail_errno(ft,SOX_EPERM, "file not seekable");
    } else {
        if (fseeko((FILE*)ft->fp, offset, whence) == -1)
            lsx_fail_errno(ft,errno, "%s", strerror(errno));
        else
            ft->sox_errno = SOX_SUCCESS;
    }
    return ft->sox_errno;
}


Jan


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.