1 /* libSoX repeat effect Copyright (c) 2004 Jan Paul Schmidt <jps@fundament.org>
2 * Re-write (c) 2008 robs@users.sourceforge.net
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2.1 of the License, or (at
7 * your option) any later version.
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
12 * General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 unsigned num_repeats
, remaining_repeats
;
23 off_t num_samples
, remaining_samples
;
27 static int create(sox_effect_t
* effp
, int argc
, char * * argv
)
29 priv_t
* p
= (priv_t
*)effp
->priv
;
32 do {NUMERIC_PARAMETER(num_repeats
, 0, UINT_MAX
- 1)} while (0);
33 return argc
? lsx_usage(effp
) : SOX_SUCCESS
;
36 static int start(sox_effect_t
* effp
)
38 priv_t
* p
= (priv_t
*)effp
->priv
;
42 if (!(p
->tmp_file
= lsx_tmpfile())) {
43 lsx_fail("can't create temporary file: %s", strerror(errno
));
46 p
->num_samples
= p
->remaining_samples
= 0;
47 p
->remaining_repeats
= p
->num_repeats
+ 1;
51 static int flow(sox_effect_t
* effp
, const sox_sample_t
* ibuf
,
52 sox_sample_t
* obuf
, size_t * isamp
, size_t * osamp
)
54 priv_t
* p
= (priv_t
*)effp
->priv
;
55 if (fwrite(ibuf
, sizeof(*ibuf
), *isamp
, p
->tmp_file
) != *isamp
) {
56 lsx_fail("error writing temporary file: %s", strerror(errno
));
59 p
->num_samples
+= *isamp
;
60 (void)obuf
, *osamp
= 0; /* samples not output until drain */
64 static int drain(sox_effect_t
* effp
, sox_sample_t
* obuf
, size_t * osamp
)
66 priv_t
* p
= (priv_t
*)effp
->priv
;
69 while ((p
->remaining_samples
|| p
->remaining_repeats
) && odone
< *osamp
) {
70 if (!p
->remaining_samples
) {
71 p
->remaining_samples
= p
->num_samples
;
72 --p
->remaining_repeats
;
75 n
= min(p
->remaining_samples
, (off_t
)(*osamp
- odone
));
76 if ((fread(obuf
+ odone
, sizeof(*obuf
), n
, p
->tmp_file
)) != n
) {
77 lsx_fail("error reading temporary file: %s", strerror(errno
));
80 p
->remaining_samples
-= n
;
84 return p
->remaining_samples
|| p
->remaining_repeats
? SOX_SUCCESS
: SOX_EOF
;
87 static int stop(sox_effect_t
* effp
)
89 priv_t
* p
= (priv_t
*)effp
->priv
;
90 fclose(p
->tmp_file
); /* auto-deleted by lsx_tmpfile */
94 sox_effect_handler_t
const * lsx_repeat_effect_fn(void)
96 static sox_effect_handler_t effect
= {"repeat", "[count]",
97 SOX_EFF_MCHAN
| SOX_EFF_LENGTH
| SOX_EFF_MODIFY
,
98 create
, start
, flow
, drain
, stop
, NULL
, sizeof(priv_t
)};