ref: d6f4cbe9d7570431dd9b56210cd0da17976a442b
parent: 9443899c13d7a00b1d8dc07fb14735379ea8f2d1
author: cbagwell <cbagwell>
date: Fri Sep 17 23:15:04 EDT 2004
Attempt seek()'s when using trim effect for speed.
--- a/Changelog
+++ b/Changelog
@@ -46,6 +46,9 @@
o When effects output data and reported ST_EOF at the
same time, that buffer was discarded as well as
data from any chained effect.
+ o Added patch from Eric Benson that attempts to do a seek()
+ if the first effect is trim. This greatly speeds up
+ processing large files.
sox-12.17.5
-----------
--- a/src/aiff.c
+++ b/src/aiff.c
@@ -73,14 +73,22 @@
int st_aiffseek(ft_t ft, st_size_t offset)
{
- aiff_t aiff = (aiff_t ) ft->priv;
+ aiff_t aiff = (aiff_t ) ft->priv;
+ st_size_t new_offset, align;
- ft->st_errno = st_seek(ft,offset*ft->info.size + aiff->dataStart,SEEK_SET);
+ new_offset = offset * ft->info.size;
+ /* Make sure requests aligns to a channel offset */
+ align = new_offset % (ft->info.channels*ft->info.size);
+ if (align != 0)
+ new_offset += align;
+ new_offset += aiff->dataStart;
- if( ft->st_errno == ST_SUCCESS )
- aiff->nsamples = ft->length - offset;
+ ft->st_errno = st_seek(ft, new_offset, SEEK_SET);
- return(ft->st_errno);
+ if (ft->st_errno == ST_SUCCESS)
+ aiff->nsamples = ft->length - new_offset;
+
+ return(ft->st_errno);
}
int st_aiffstartread(ft_t ft)
--- a/src/au.c
+++ b/src/au.c
@@ -103,14 +103,27 @@
int st_auseek(ft_t ft, st_size_t offset)
{
- au_t au = (au_t ) ft->priv;
+ au_t au = (au_t ) ft->priv;
- if (au->dec_routine != NULL)
- st_fail_errno(ft,ST_ENOTSUP,"Sorry, DEC unsupported");
- else
- return st_seek(ft,offset*ft->info.size + au->dataStart,SEEK_SET);
+ if (au->dec_routine != NULL)
+ {
+ st_fail_errno(ft,ST_ENOTSUP,"Sorry, DEC unsupported");
+ }
+ else
+ {
+ st_size_t new_offset, align;
- return(ft->st_errno);
+ new_offset = offset * ft->info.size;
+ /* Make sure requests aligns to a channel offset */
+ align = new_offset % (ft->info.channels*ft->info.size);
+ if (align != 0)
+ new_offset += align;
+ new_offset += au->dataStart;
+
+ ft->st_errno = st_seek(ft, new_offset, SEEK_SET);
+ }
+
+ return(ft->st_errno);
}
int st_austartread(ft_t ft)
--- a/src/prc.c
+++ b/src/prc.c
@@ -44,9 +44,17 @@
int st_prcseek(ft_t ft, st_size_t offset)
{
- prc_t prc = (prc_t ) ft->priv;
+ prc_t prc = (prc_t ) ft->priv;
+ st_size_t new_offset, align;
- return st_seek(ft,offset*ft->info.size + prc->dataStart,SEEK_SET);
+ new_offset = offset * ft->info.size;
+ /* Make sure requests aligns to a channel offset */
+ align = new_offset % (ft->info.channels*ft->info.size);
+ if (align != 0)
+ new_offset += align;
+ new_offset += prc->dataStart;
+
+ return st_seek(ft, new_offset, SEEK_SET);
}
int st_prcstartread(ft_t ft)
@@ -82,10 +90,10 @@
}
st_readw(ft, &(len));
- p->length=len;
- st_report("Found length=%d",len);
+ p->length=len;
+ st_report("Found length=%d",len);
- /* dummy read rest */
+ /* dummy read rest */
st_read(ft, head,1,14+2+2);
ft->info.encoding = ST_ENCODING_ALAW;
@@ -159,7 +167,7 @@
{
prc_t p = (prc_t ) ft->priv;
p->length += samp * ft->info.size;
- st_report("length now = %d", p->length);
+ st_report("length now = %d", p->length);
return st_rawwrite(ft, buf, samp);
}
@@ -180,7 +188,7 @@
return(ST_EOF);
}
prcwriteheader(ft);
- return ST_SUCCESS;
+ return ST_SUCCESS;
}
static void prcwriteheader(ft_t ft)
--- a/src/raw.c
+++ b/src/raw.c
@@ -83,6 +83,8 @@
int st_rawseek(ft_t ft, st_size_t offset)
{
+ st_size_t new_offset, align;
+
switch(ft->info.size) {
case ST_SIZE_BYTE:
case ST_SIZE_WORD:
@@ -94,7 +96,13 @@
return ft->st_errno;
}
- ft->st_errno = st_seek(ft,offset*ft->info.size,SEEK_SET);
+ new_offset = offset * ft->info.size;
+ /* Make sure requests aligns to a channel offset */
+ align = new_offset % (ft->info.channels*ft->info.size);
+ if (align != 0)
+ new_offset += align;
+
+ ft->st_errno = st_seek(ft, new_offset, SEEK_SET);
return ft->st_errno;
}
--- a/src/sf.c
+++ b/src/sf.c
@@ -70,10 +70,17 @@
int st_sfseek(ft_t ft, st_size_t offset)
{
- sf_t sf = (sf_t ) ft->priv;
+ st_size_t new_offset, align;
- return st_seek(ft,offset*ft->info.size + sf->dataStart,SEEK_SET);
+ sf_t sf = (sf_t ) ft->priv;
+ new_offset = offset * ft->info.size;
+ /* Make sure requests aligns to a channel offset */
+ align = new_offset % (ft->info.channels*ft->info.size);
+ if (align != 0)
+ new_offset += align;
+ new_offset += sf->dataStart;
+ return st_seek(ft, new_offset, SEEK_SET);
}
/*
--- a/src/smp.c
+++ b/src/smp.c
@@ -171,14 +171,22 @@
int st_smpseek(ft_t ft, st_size_t offset)
{
- smp_t smp = (smp_t) ft->priv;
+ int new_offset, align;
+ smp_t smp = (smp_t) ft->priv;
- ft->st_errno = st_seek(ft,offset*ft->info.size + smp->dataStart,SEEK_SET);
+ new_offset = offset * ft->info.size;
+ /* Make sure requests aligns to a channel offset */
+ align = new_offset % (ft->info.channels*ft->info.size);
+ if (align != 0)
+ new_offset += align;
+ new_offset += smp->dataStart;
- if( ft->st_errno == ST_SUCCESS )
- smp->NoOfSamps = ft->length - offset;
+ ft->st_errno = st_seek(ft, new_offset, SEEK_SET);
- return(ft->st_errno);
+ if( ft->st_errno == ST_SUCCESS )
+ smp->NoOfSamps = ft->length - new_offset;
+
+ return(ft->st_errno);
}
/*
* Do anything required before you start reading samples.
--- a/src/sndrtool.c
+++ b/src/sndrtool.c
@@ -16,17 +16,17 @@
#include <errno.h>
#endif
#ifdef HAVE_UNISTD_H
-#include <unistd.h> /* For SEEK_* defines if not found in stdio */
+#include <unistd.h> /* For SEEK_* defines if not found in stdio */
#endif
/* Private data used by writer */
typedef struct sndpriv {
st_size_t nsamples;
- st_size_t dataStart;
+ st_size_t dataStart;
} *snd_t;
-#ifndef SEEK_CUR
-#define SEEK_CUR 1
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
#endif
static void sndtwriteheader(ft_t ft, st_size_t nsamples);
@@ -33,10 +33,17 @@
int st_sndseek(ft_t ft, st_size_t offset)
{
- snd_t snd = (snd_t ) ft->priv;
+ st_size_t new_offset, align;
+ snd_t snd = (snd_t ) ft->priv;
- return st_seek(ft,offset*ft->info.size + snd->dataStart,SEEK_SET);
+ new_offset = offset * ft->info.size;
+ /* Make sure requests aligns to a channel offset */
+ align = new_offset % (ft->info.channels*ft->info.size);
+ if (align != 0)
+ new_offset += align;
+ new_offset += snd->dataStart;
+ return st_seek(ft, new_offset, SEEK_SET);
}
/*======================================================================*/
/* SNDSTARTREAD */
@@ -44,69 +51,69 @@
int st_sndtstartread(ft_t ft)
{
- snd_t snd = (snd_t ) ft->priv;
+ snd_t snd = (snd_t ) ft->priv;
char buf[97];
unsigned short rate;
- int rc;
+ int rc;
- /* Needed for rawread() */
- rc = st_rawstartread(ft);
- if (rc)
- return rc;
+ /* Needed for rawread() */
+ rc = st_rawstartread(ft);
+ if (rc)
+ return rc;
- /* sndt is in little endian format so
- * swap bytes on big endian machines.
- */
- if (ST_IS_BIGENDIAN)
- {
- ft->swap = ft->swap ? 0 : 1;
- }
+ /* sndt is in little endian format so
+ * swap bytes on big endian machines.
+ */
+ if (ST_IS_BIGENDIAN)
+ {
+ ft->swap = ft->swap ? 0 : 1;
+ }
- rate = 0;
+ rate = 0;
- /* determine file type */
+ /* determine file type */
/* if first 5 bytes == SOUND then this is probably a sndtool sound */
/* if first word (16 bits) == 0
and second word is between 4000 & 25000 then this is sounder sound */
/* otherwise, its probably raw, not handled here */
- if (fread(buf, 1, 2, ft->fp) != 2)
- {
- st_fail_errno(ft,errno,"SND: unexpected EOF");
- return(ST_EOF);
- }
- if (strncmp(buf,"\0\0",2) == 0)
- {
- /* sounder */
- st_readw(ft, &rate);
- if (rate < 4000 || rate > 25000 )
- {
- st_fail_errno(ft,ST_EFMT,"SND: sample rate out of range");
- return(ST_EOF);
- }
- fseek(ft->fp,4,SEEK_CUR);
- }
- else
- {
- /* sndtool ? */
- fread(&buf[2], 1, 6, ft->fp);
- if (strncmp(buf,"SOUND",5))
- {
- st_fail_errno(ft,ST_EFMT,"SND: unrecognized SND format");
- return(ST_EOF);
- }
- fseek(ft->fp,12,SEEK_CUR);
- st_readw(ft, &rate);
- fseek(ft->fp,6,SEEK_CUR);
- if (st_reads(ft, buf, 96) == ST_EOF)
- {
- st_fail_errno(ft,ST_EHDR,"SND: unexpected EOF in SND header");
- return(ST_EOF);
- }
- st_report("%s",buf);
- }
+ if (fread(buf, 1, 2, ft->fp) != 2)
+ {
+ st_fail_errno(ft,errno,"SND: unexpected EOF");
+ return(ST_EOF);
+ }
+ if (strncmp(buf,"\0\0",2) == 0)
+ {
+ /* sounder */
+ st_readw(ft, &rate);
+ if (rate < 4000 || rate > 25000 )
+ {
+ st_fail_errno(ft,ST_EFMT,"SND: sample rate out of range");
+ return(ST_EOF);
+ }
+ fseek(ft->fp,4,SEEK_CUR);
+ }
+ else
+ {
+ /* sndtool ? */
+ fread(&buf[2], 1, 6, ft->fp);
+ if (strncmp(buf,"SOUND",5))
+ {
+ st_fail_errno(ft,ST_EFMT,"SND: unrecognized SND format");
+ return(ST_EOF);
+ }
+ fseek(ft->fp,12,SEEK_CUR);
+ st_readw(ft, &rate);
+ fseek(ft->fp,6,SEEK_CUR);
+ if (st_reads(ft, buf, 96) == ST_EOF)
+ {
+ st_fail_errno(ft,ST_EHDR,"SND: unexpected EOF in SND header");
+ return(ST_EOF);
+ }
+ st_report("%s",buf);
+ }
ft->info.channels = 1;
ft->info.rate = rate;
@@ -124,21 +131,21 @@
/*======================================================================*/
int st_sndtstartwrite(ft_t ft)
{
- snd_t p = (snd_t ) ft->priv;
- int rc;
+ snd_t p = (snd_t ) ft->priv;
+ int rc;
- /* Needed for rawwrite() */
- rc = st_rawstartwrite(ft);
- if (rc)
- return rc;
+ /* Needed for rawwrite() */
+ rc = st_rawstartwrite(ft);
+ if (rc)
+ return rc;
- /* sndt is in little endian format so
- * swap bytes on big endian machines
- */
- if (ST_IS_BIGENDIAN)
- {
- ft->swap = ft->swap ? 0 : 1;
- }
+ /* sndt is in little endian format so
+ * swap bytes on big endian machines
+ */
+ if (ST_IS_BIGENDIAN)
+ {
+ ft->swap = ft->swap ? 0 : 1;
+ }
/* write header */
ft->info.channels = 1;
@@ -155,20 +162,20 @@
/*======================================================================*/
int st_sndrstartwrite(ft_t ft)
{
- int rc;
+ int rc;
- /* Needed for rawread() */
- rc = st_rawstartread(ft);
- if (rc)
- return rc;
+ /* Needed for rawread() */
+ rc = st_rawstartread(ft);
+ if (rc)
+ return rc;
- /* sndr is in little endian format so
- * swap bytes on big endian machines
- */
- if (ST_IS_BIGENDIAN)
- {
- ft->swap = ft->swap ? 0 : 1;
- }
+ /* sndr is in little endian format so
+ * swap bytes on big endian machines
+ */
+ if (ST_IS_BIGENDIAN)
+ {
+ ft->swap = ft->swap ? 0 : 1;
+ }
/* write header */
ft->info.channels = 1;
@@ -190,9 +197,9 @@
st_ssize_t st_sndtwrite(ft_t ft, st_sample_t *buf, st_ssize_t len)
{
- snd_t p = (snd_t ) ft->priv;
- p->nsamples += len;
- return st_rawwrite(ft, buf, len);
+ snd_t p = (snd_t ) ft->priv;
+ p->nsamples += len;
+ return st_rawwrite(ft, buf, len);
}
/*======================================================================*/
@@ -201,24 +208,24 @@
int st_sndtstopwrite(ft_t ft)
{
- snd_t p = (snd_t ) ft->priv;
- int rc;
+ snd_t p = (snd_t ) ft->priv;
+ int rc;
- /* Flush remaining buffer out */
- rc = st_rawstopwrite(ft);
- if (rc)
- return rc;
+ /* Flush remaining buffer out */
+ rc = st_rawstopwrite(ft);
+ if (rc)
+ return rc;
- /* fixup file sizes in header */
- if (fseek(ft->fp, 0L, 0) != 0){
- st_fail_errno(ft,errno,"can't rewind output file to rewrite SND header");
- return ST_EOF;
- }
-
- sndtwriteheader(ft, p->nsamples);
-
-
- return(ST_SUCCESS);
+ /* fixup file sizes in header */
+ if (fseek(ft->fp, 0L, 0) != 0){
+ st_fail_errno(ft,errno,"can't rewind output file to rewrite SND header");
+ return ST_EOF;
+ }
+
+ sndtwriteheader(ft, p->nsamples);
+
+
+ return(ST_SUCCESS);
}
/*======================================================================*/
--- a/src/sox.c
+++ b/src/sox.c
@@ -526,6 +526,59 @@
return ST_SUCCESS;
}
+void optimize_trim(void)
+{
+ int f;
+
+ /* Speed hack. If the "trim" effect is the first effect then
+ * peak inside its "effect descriptor" and see what the
+ * start location is. This has to be done after the start()
+ * is called to have the correct location.
+ */
+ if (neffects > 1 && strcmp(efftab[1].name, "trim") == 0)
+ {
+ int ok_to_seek = 1;
+ int seek_worked = 1;
+
+ /* Make sure all support seeking */
+ for (f = 0; f < input_count; f++)
+ {
+ if (!(file_desc[f]->h->flags & ST_FILE_SEEK) ||
+ !file_desc[f]->seekable)
+ ok_to_seek = 0;
+ }
+ if (ok_to_seek)
+ {
+ for (f = 0; f < input_count; f++)
+ {
+ if (file_desc[f]->h->seek(file_desc[f],
+ st_trim_get_seek(&efftab[1])) == ST_EOF)
+ {
+ seek_worked = 0;
+ break;
+ }
+ }
+ /* If any seek didn't work then try our best to go back
+ * to the beginning of file and do it the slow way.
+ * This can easily happen if some input files are shorter
+ * then the rest. Code below will fill in silence
+ * for those cases.
+ */
+ if (!seek_worked)
+ {
+ for (f = 0; f < input_count; f++)
+ {
+ file_desc[f]->h->seek(file_desc[f], 0);
+ }
+ }
+ else
+ {
+ st_trim_clear_start(&efftab[1]);
+ }
+ }
+ }
+}
+
/*
* Process input file -> effect table -> output file
* one buffer at a time
@@ -639,6 +692,9 @@
}
}
}
+
+ /* Try to save some time if first effect is "trim" by seeking */
+ optimize_trim();
#ifdef SOXMIX
for (f = 0; f < MAX_INPUT_FILES; f++)
--- a/src/st_i.h
+++ b/src/st_i.h
@@ -595,6 +595,8 @@
int st_trim_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
st_size_t *isamp, st_size_t *osamp);
int st_trim_stop(eff_t effp);
+st_size_t st_trim_get_seek(eff_t effp);
+void st_trim_clear_start(eff_t effp);
int st_vibro_getopts(eff_t effp, int argc, char **argv);
int st_vibro_start(eff_t effp);
--- a/src/trim.c
+++ b/src/trim.c
@@ -207,7 +207,14 @@
return (ST_SUCCESS);
}
+st_size_t st_trim_get_seek(eff_t effp)
+{
+ trim_t trim = (trim_t)effp->priv;
+ return trim->start;
+}
-
-
-
+void st_trim_clear_start(eff_t effp)
+{
+ trim_t trim = (trim_t)effp->priv;
+ trim->start = 0;
+}
--- a/src/wav.c
+++ b/src/wav.c
@@ -1638,23 +1638,31 @@
int st_wavseek(ft_t ft, st_size_t offset)
{
- wav_t wav = (wav_t) ft->priv;
+ wav_t wav = (wav_t) ft->priv;
+ int new_offset, align;
- switch (wav->formatTag)
- {
+ switch (wav->formatTag)
+ {
case WAVE_FORMAT_IMA_ADPCM:
case WAVE_FORMAT_ADPCM:
#ifdef ENABLE_GSM
case WAVE_FORMAT_GSM610:
#endif
- st_fail_errno(ft,ST_ENOTSUP,"Only PCM Supported");
+ st_fail_errno(ft,ST_ENOTSUP,"Only PCM Supported");
break;
default:
- ft->st_errno = st_seek(ft,offset*ft->info.size + wav->dataStart, SEEK_SET);
- }
+ new_offset = offset * ft->info.size;
+ /* Make sure requests aligns to a channel offset */
+ align = new_offset % (ft->info.channels*ft->info.size);
+ if (align != 0)
+ new_offset += align;
+ new_offset += wav->dataStart;
- if( ft->st_errno == ST_SUCCESS )
- wav->numSamples = ft->length - offset;
+ ft->st_errno = st_seek(ft, new_offset, SEEK_SET);
+ }
- return(ft->st_errno);
+ if( ft->st_errno == ST_SUCCESS )
+ wav->numSamples = ft->length - new_offset;
+
+ return(ft->st_errno);
}
--- a/src/wve.c
+++ b/src/wve.c
@@ -29,9 +29,17 @@
int st_wveseek(ft_t ft, st_size_t offset)
{
- wve_t wve = (wve_t ) ft->priv;
+ int new_offset, align;
+ wve_t wve = (wve_t ) ft->priv;
- return st_seek(ft,offset*ft->info.size + wve->dataStart,SEEK_SET);
+ new_offset = offset * ft->info.size;
+ /* Make sure requests aligns to a channel offset */
+ align = new_offset % (ft->info.channels*ft->info.size);
+ if (align != 0)
+ new_offset += align;
+ new_offset += wve->dataStart;
+
+ return st_seek(ft, offset, SEEK_SET);
}
int st_wvestartread(ft_t ft)