ref: fb0d5415f4388223a510a342ccae0264d93f07d1
parent: d0114fd159961b078a003e006aa198a0588c5bd1
author: robs <robs>
date: Tue Feb 24 12:42:23 EST 2009
more work on crop
--- a/src/crop.c
+++ b/src/crop.c
@@ -25,27 +25,13 @@
typedef struct {
int argc;
- struct {sox_bool from_end; char * str; uint32_t at;} pos[2];
+ struct {int flag; char * str; uint32_t at;} pos[2];
} priv_t;
-#if 0
-uint64_t sox_crop_get_start(sox_effect_t * effp)
-{
- priv_t * p = (priv_t *)effp->priv;
- return p->pos[0].at;
-}
-
-void sox_crop_clear_start(sox_effect_t * effp)
-{
- priv_t * p = (priv_t *)effp->priv;
- p->pos[0].at = 0;
-}
-#endif
-
static int parse(sox_effect_t * effp, char * * argv, sox_rate_t rate)
{
priv_t * p = (priv_t *)effp->priv;
- char const * s;
+ char const * s, * q;
int i;
for (i = p->argc - 1; i == 0 || i == 1; --i) {
@@ -52,11 +38,9 @@
if (argv) /* 1st parse only */
p->pos[i].str = lsx_strdup(argv[i]);
s = p->pos[i].str;
- if (*s == '-') {
- p->pos[i].from_end = sox_true;
- ++s;
- }
- if (!lsx_parsesamples(rate, s, &p->pos[i].at, 't'))
+ if (strchr("+-" + 1 - i, *s))
+ p->pos[i].flag = *s++;
+ if (!(q = lsx_parsesamples(rate, s, &p->pos[i].at, 't')) || *q)
break;
}
return i >= 0 ? lsx_usage(effp) : SOX_SUCCESS;
@@ -75,11 +59,11 @@
priv_t * p = (priv_t *)effp->priv;
int i;
- p->pos[1].at = INT32_MAX;
+ p->pos[1].at = UINT32_MAX / 2 / effp->in_signal.channels;
parse(effp, 0, effp->in_signal.rate); /* Re-parse now rate is known */
for (i = 0; i < 2; ++i) {
p->pos[i].at *= effp->in_signal.channels;
- if (p->pos[i].from_end) {
+ if (p->pos[i].flag == '-') {
if (effp->in_signal.length == SOX_UNSPEC) {
lsx_fail("cannot crop from end: audio length is not known");
return SOX_EOF;
@@ -91,13 +75,26 @@
p->pos[i].at = effp->in_signal.length - p->pos[i].at;
}
}
- if (p->pos[0].at > p->pos[1].at) {
- lsx_fail("start position must be less than stop position");
- return SOX_EOF;
+ if (p->pos[1].flag != '+') {
+ if (p->pos[0].at > p->pos[1].at) {
+ lsx_fail("start position must be less than stop position");
+ return SOX_EOF;
+ }
+ if (!(p->pos[1].at -= p->pos[0].at))
+ p->pos[0].at = 0;
}
- if (!(p->pos[1].at -= p->pos[0].at))
- p->pos[0].at = 0;
- return p->pos[0].at || p->pos[1].at != effp->in_signal.length ? SOX_SUCCESS : SOX_EFF_NULL;
+ if (effp->in_signal.length) {
+ if (!p->pos[0].at && p->pos[1].at == effp->in_signal.length)
+ return SOX_EFF_NULL;
+ if (p->pos[0].at > effp->in_signal.length ||
+ (p->argc > 1 && p->pos[0].at + p->pos[1].at > effp->in_signal.length)) {
+ lsx_fail("audio is too short");
+ return SOX_EOF;
+ }
+ effp->out_signal.length = p->argc == 2 ?
+ p->pos[1].at : effp->in_signal.length - p->pos[0].at;
+ }
+ return SOX_SUCCESS;
}
static int flow(sox_effect_t * effp, sox_sample_t const * ibuf,
@@ -117,7 +114,7 @@
{
priv_t * p = (priv_t *)effp->priv;
if (p->pos[0].at || (p->pos[1].at && p->argc == 2))
- lsx_warn("input audio too short to crop as requested");
+ lsx_warn("input audio was too short to crop as requested");
return SOX_SUCCESS;
}
@@ -132,9 +129,44 @@
sox_effect_handler_t const * lsx_crop_effect_fn(void)
{
static sox_effect_handler_t handler = {
- "crop", "before [from]",
+ "crop", "[-]before [[+|-]from]\n"
+ " n\tposition relative to start\n"
+ " -n\tposition relative to end\n"
+ " +n\tposition relative to previous",
SOX_EFF_MCHAN | /* SOX_EFF_LENGTH | */ SOX_EFF_MODIFY | SOX_EFF_DEPRECATED,
+
create, start, flow, NULL, stop, kill, sizeof(priv_t)
};
return &handler;
}
+
+#if 0
+size_t sox_crop_get_start(sox_effect_t * effp)
+{
+ return ((priv_t *)effp->priv)->pos[0].at;
+}
+
+void sox_crop_clear_start(sox_effect_t * effp)
+{
+ ((priv_t *)effp->priv)->pos[0].at = 0;
+}
+
+/*---------------------- emulation of the `trim' effect ----------------------*/
+
+static int trim_getopts(sox_effect_t * effp, int argc, char * * argv)
+{
+ priv_t * p = (priv_t *)effp->priv;
+ p->pos[1].flag = '+';
+ return lsx_crop_effect_fn()->getopts(effp, argc, argv);
+}
+
+sox_effect_handler_t const * lsx_trim_effect_fn(void)
+{
+ static sox_effect_handler_t handler;
+ handler = *lsx_crop_effect_fn();
+ handler.name = "trim";
+ handler.usage = "start [length]";
+ handler.getopts = trim_getopts;
+ return &handler;
+}
+#endif