ref: b547a29888c8b6452b3f14c24bb4dda01ade6cd3
parent: 542cab5f35508e4bd8dd52db069a562f5f86d33a
author: Ulrich Klauer <ulrich@chirlu.de>
date: Mon Oct 15 22:04:05 EDT 2012
Introduce an extended syntax for audio positions Introduce a new lsx_parseposition function (similar to lsx_parsesamples) that makes a trim-like syntax for specifying audio positions available to all effects; it is possible to give a position relative to the start of audio ("=2:00"), to the end of audio ("-1:30"), or to a previous position ("+1:00"). The original lsx_parsesamples function is replaced by a wrapper for an internal parsesamples function that allows a start value and an initial combine mode (add/subtract) to be passed in, which lsx_parseposition needs. This commit only introduces the function and common documentation. No effects are using lsx_parseposition yet.
--- a/sox.1
+++ b/sox.1
@@ -1459,6 +1459,23 @@
A power gain in dB.
Zero gives no gain; less than zero gives an attenuation.
.TP
+\fIposition\fR
+A position within the audio stream; the syntax is
+[\fB=\fR\^|\^\fB+\fR\^|\^\fB\-\fR]\fItimespec\fR, where \fItimespec\fR is a
+time specification (see below). The optional first character indicates
+whether the \fItimespec\fR is to be interpreted relative to the start
+(\fB=\fR) or end (\fB\-\fR) of audio, or to the previous \fIposition\fR if
+the effect accepts multiple position arguments (\fB+\fR). The audio length
+must be known for end-relative locations to work; some effects do accept
+\fB\-0\fR for end-of-audio, though, even if the length is unknown. Which of
+\fB=\fR, \fB+\fR, \fB\-\fR is the default depends on the effect and is shown
+in its syntax as, e.g., \fIposition(+)\fR.
+.SP
+Examples: \fB=2:00\fR (two minutes into the audio stream), \fB\-100s\fR (one
+hundred samples before the end of audio), \fB+0:12+10s\fR (twelve seconds
+and ten samples after the previous position), \fB\-0.5+1s\fR (one sample less
+than half a second before the end of audio).
+.TP
\fIwidth\fR[\fBh\fR\^|\^\fBk\fR\^|\^\fBo\fR\^|\^\fBq\fR]
Used to specify the band-width of a filter. A number of different
methods to specify the width are available (though not all for every effect).
@@ -1498,8 +1515,8 @@
.PP
Time specifications can also be chained with \fB+\fR or \fB\-\fR into a new
time specification where the right part is added to or subtracted from the
-left, respectively: `3:00\-200s' means two hundred samples before the three
-minute mark.
+left, respectively: `3:00\-200s' means two hundred samples less than three
+minutes.
.SP
To see if SoX has support for an optional effect, enter
.B sox \-h
--- a/src/effects_i.c
+++ b/src/effects_i.c
@@ -1,7 +1,7 @@
/* Implements a libSoX internal interface for implementing effects.
* All public functions & data are prefixed with lsx_ .
*
- * Copyright (c) 2005-8 Chris Bagwell and SoX contributors
+ * Copyright (c) 2005-2012 Chris Bagwell and SoX contributors
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -150,12 +150,18 @@
* for a bare number like "123". It can either be 't' or 's'.
* Returns NULL on error, pointer to next char to parse otherwise.
*/
+static char const * parsesamples(sox_rate_t rate, const char *str0, uint64_t *samples, int def, int combine);
+
char const * lsx_parsesamples(sox_rate_t rate, const char *str0, uint64_t *samples, int def)
{
- char * str = (char *)str0;
- char combine = '+';
*samples = 0;
+ return parsesamples(rate, str0, samples, def, '+');
+}
+static char const * parsesamples(sox_rate_t rate, const char *str0, uint64_t *samples, int def, int combine)
+{
+ char * str = (char *)str0;
+
do {
uint64_t samples_part;
sox_bool found_samples = sox_false, found_time = sox_false;
@@ -227,7 +233,7 @@
*samples - samples_part : 0;
break;
}
- if (strchr("+-", *str))
+ if (*str && strchr("+-", *str))
combine = *str++;
else combine = '\0';
} while (combine);
@@ -309,6 +315,67 @@
return 0;
}
#endif
+
+/*
+ * lsx_parseposition
+ *
+ * Parse a string for an audio position. Similar to lsx_parsesamples
+ * above, but an initial '=', '+' or '-' indicates that the specified time
+ * is relative to the start of audio, last used position or end of audio,
+ * respectively. Parameter def states which of these is the default.
+ * Parameters latest and end are the positions to which '+' and '-' relate;
+ * end may be SOX_UNKNOWN_LEN, in which case "-0" is the only valid
+ * end-relative input and will result in a position of SOX_UNKNOWN_LEN.
+ * Other parameters and return value are the same as for lsx_parsesamples.
+ *
+ * A test parse that only checks for valid syntax can be done by
+ * specifying samples = NULL. If this passes, a later reparse of the same
+ * input will only fail if it is relative to the end ("-"), not "-0", and
+ * the end position is unknown.
+ */
+char const * lsx_parseposition(sox_rate_t rate, const char *str0, uint64_t *samples, uint64_t latest, uint64_t end, int def)
+{
+ char *str = (char *)str0;
+ char anchor, combine;
+
+ if (!strchr("+-=", def))
+ return NULL; /* error: invalid default anchor */
+ anchor = def;
+ if (*str && strchr("+-=", *str))
+ anchor = *str++;
+
+ combine = '+';
+ if (strchr("+-", anchor)) {
+ combine = anchor;
+ if (*str && strchr("+-", *str))
+ combine = *str++;
+ }
+
+ if (!samples) {
+ /* dummy parse, syntax checking only */
+ uint64_t dummy = 0;
+ return parsesamples(0., str, &dummy, 't', '+');
+ }
+
+ switch (anchor) {
+ case '=': *samples = 0; break;
+ case '+': *samples = latest; break;
+ case '-': *samples = end; break;
+ }
+
+ if (anchor == '-' && end == SOX_UNKNOWN_LEN) {
+ /* "-0" only valid input here */
+ char const *l;
+ for (l = str; *l && strchr("0123456789:.ets+-", *l); ++l);
+ if (l == str+1 && *str == '0') {
+ /* *samples already set to SOX_UNKNOWN_LEN */
+ return l;
+ }
+ return NULL; /* error: end-relative position, but end unknown */
+ }
+
+ return parsesamples(rate, str, samples, 't', combine);
+}
/* a note is given as an int,
* 0 => 440 Hz = A
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -2,7 +2,7 @@
*
* This file is meant for libSoX internal use only
*
- * Copyright 2001-2008 Chris Bagwell and SoX Contributors
+ * Copyright 2001-2012 Chris Bagwell and SoX Contributors
*
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
@@ -74,6 +74,7 @@
double max, /* Maximum value on the y-axis. (e.g. +1) */
double phase); /* Phase at 1st point; 0..2pi. (e.g. pi/2 for cosine) */
char const * lsx_parsesamples(sox_rate_t rate, const char *str, uint64_t *samples, int def);
+char const * lsx_parseposition(sox_rate_t rate, const char *str, uint64_t *samples, uint64_t latest, uint64_t end, int def);
int lsx_parse_note(char const * text, char * * end_ptr);
double lsx_parse_frequency_k(char const * text, char * * end_ptr, int key);
#define lsx_parse_frequency(a, b) lsx_parse_frequency_k(a, b, INT_MAX)