1 /* libSoX effect: Pad With Silence (c) 2006 robs@users.sourceforge.net
3 * This library is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as published by
5 * the Free Software Foundation; either version 2.1 of the License, or (at
6 * your option) any later version.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11 * General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 unsigned npads
; /* Number of pads requested */
23 char * str
; /* Command-line argument to parse for this pad */
24 size_t start
; /* Start padding when in_pos equals this */
25 size_t pad
; /* Number of samples to pad */
28 size_t in_pos
; /* Number of samples read from the input stream */
29 unsigned pads_pos
; /* Number of pads completed so far */
30 size_t pad_pos
; /* Number of samples through the current pad */
33 static int parse(sox_effect_t
* effp
, char * * argv
, sox_rate_t rate
)
35 priv_t
* p
= (priv_t
*)effp
->priv
;
39 for (i
= 0; i
< p
->npads
; ++i
) {
40 if (argv
) /* 1st parse only */
41 p
->pads
[i
].str
= lsx_strdup(argv
[i
]);
42 next
= lsx_parsesamples(rate
, p
->pads
[i
].str
, &p
->pads
[i
].pad
, 't');
43 if (next
== NULL
) break;
45 p
->pads
[i
].start
= i
? SOX_SIZE_MAX
: 0;
47 if (*next
!= '@') break;
48 next
= lsx_parsesamples(rate
, next
+1, &p
->pads
[i
].start
, 't');
49 if (next
== NULL
|| *next
!= '\0') break;
51 if (i
> 0 && p
->pads
[i
].start
<= p
->pads
[i
-1].start
) break;
54 return lsx_usage(effp
);
58 static int create(sox_effect_t
* effp
, int argc
, char * * argv
)
60 priv_t
* p
= (priv_t
*)effp
->priv
;
62 p
->pads
= lsx_calloc(p
->npads
= argc
, sizeof(*p
->pads
));
63 return parse(effp
, argv
, 1e5
); /* No rate yet; parse with dummy */
66 static int start(sox_effect_t
* effp
)
68 priv_t
* p
= (priv_t
*)effp
->priv
;
71 parse(effp
, 0, effp
->in_signal
.rate
); /* Re-parse now rate is known */
72 p
->in_pos
= p
->pad_pos
= p
->pads_pos
= 0;
73 for (i
= 0; i
< p
->npads
; ++i
)
79 static int flow(sox_effect_t
* effp
, const sox_sample_t
* ibuf
,
80 sox_sample_t
* obuf
, size_t * isamp
, size_t * osamp
)
82 priv_t
* p
= (priv_t
*)effp
->priv
;
83 size_t c
, idone
= 0, odone
= 0;
84 *isamp
/= effp
->in_signal
.channels
;
85 *osamp
/= effp
->in_signal
.channels
;
89 for (; idone
< *isamp
&& odone
< *osamp
&& !(p
->pads_pos
!= p
->npads
&& p
->in_pos
== p
->pads
[p
->pads_pos
].start
); ++idone
, ++odone
, ++p
->in_pos
)
90 for (c
= 0; c
< effp
->in_signal
.channels
; ++c
) *obuf
++ = *ibuf
++;
93 if (p
->pads_pos
!= p
->npads
&& p
->in_pos
== p
->pads
[p
->pads_pos
].start
) {
94 for (; odone
< *osamp
&& p
->pad_pos
< p
->pads
[p
->pads_pos
].pad
; ++odone
, ++p
->pad_pos
)
95 for (c
= 0; c
< effp
->in_signal
.channels
; ++c
) *obuf
++ = 0;
96 if (p
->pad_pos
== p
->pads
[p
->pads_pos
].pad
) { /* Move to next pad? */
101 } while (idone
< *isamp
&& odone
< *osamp
);
103 *isamp
= idone
* effp
->in_signal
.channels
;
104 *osamp
= odone
* effp
->in_signal
.channels
;
108 static int drain(sox_effect_t
* effp
, sox_sample_t
* obuf
, size_t * osamp
)
110 priv_t
* p
= (priv_t
*)effp
->priv
;
111 static size_t isamp
= 0;
112 if (p
->pads_pos
!= p
->npads
&& p
->in_pos
!= p
->pads
[p
->pads_pos
].start
)
113 p
->in_pos
= SOX_SIZE_MAX
; /* Invoke the final pad (with no given start) */
114 return flow(effp
, 0, obuf
, &isamp
, osamp
);
117 static int stop(sox_effect_t
* effp
)
119 priv_t
* p
= (priv_t
*)effp
->priv
;
120 if (p
->pads_pos
!= p
->npads
)
121 lsx_warn("Input audio too short; pads not applied: %u", p
->npads
-p
->pads_pos
);
125 static int lsx_kill(sox_effect_t
* effp
)
127 priv_t
* p
= (priv_t
*)effp
->priv
;
129 for (i
= 0; i
< p
->npads
; ++i
)
130 free(p
->pads
[i
].str
);
135 sox_effect_handler_t
const * lsx_pad_effect_fn(void)
137 static sox_effect_handler_t handler
= {
138 "pad", "{length[@position]}", SOX_EFF_MCHAN
|SOX_EFF_LENGTH
|SOX_EFF_MODIFY
,
139 create
, start
, flow
, drain
, stop
, lsx_kill
, sizeof(priv_t
)