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 uint64_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 if (argc
== 1 && !strcmp(*argv
, "-")) {
33 p
->num_repeats
= UINT_MAX
;
36 do {NUMERIC_PARAMETER(num_repeats
, 0, UINT_MAX
- 1)} while (0);
37 return argc
? lsx_usage(effp
) : SOX_SUCCESS
;
40 static int start(sox_effect_t
* effp
)
42 priv_t
* p
= (priv_t
*)effp
->priv
;
46 if (!(p
->tmp_file
= lsx_tmpfile())) {
47 lsx_fail("can't create temporary file: %s", strerror(errno
));
50 p
->num_samples
= p
->remaining_samples
= 0;
51 p
->remaining_repeats
= p
->num_repeats
;
52 if (effp
->in_signal
.length
!= SOX_UNKNOWN_LEN
&& p
->num_repeats
!= UINT_MAX
)
53 effp
->out_signal
.length
= effp
->in_signal
.length
* (p
->num_repeats
+ 1);
55 effp
->out_signal
.length
= SOX_UNKNOWN_LEN
;
60 static int flow(sox_effect_t
* effp
, const sox_sample_t
* ibuf
,
61 sox_sample_t
* obuf
, size_t * isamp
, size_t * osamp
)
63 priv_t
* p
= (priv_t
*)effp
->priv
;
64 size_t len
= min(*isamp
, *osamp
);
65 memcpy(obuf
, ibuf
, len
* sizeof(*obuf
));
66 if (fwrite(ibuf
, sizeof(*ibuf
), len
, p
->tmp_file
) != len
) {
67 lsx_fail("error writing temporary file: %s", strerror(errno
));
70 p
->num_samples
+= len
;
71 *isamp
= *osamp
= len
;
75 static int drain(sox_effect_t
* effp
, sox_sample_t
* obuf
, size_t * osamp
)
77 priv_t
* p
= (priv_t
*)effp
->priv
;
80 *osamp
-= *osamp
% effp
->in_signal
.channels
;
82 while ((p
->remaining_samples
|| p
->remaining_repeats
) && odone
< *osamp
) {
83 if (!p
->remaining_samples
) {
84 p
->remaining_samples
= p
->num_samples
;
85 if (p
->remaining_repeats
!= UINT_MAX
)
86 --p
->remaining_repeats
;
89 n
= min(p
->remaining_samples
, *osamp
- odone
);
90 if ((fread(obuf
+ odone
, sizeof(*obuf
), n
, p
->tmp_file
)) != n
) {
91 lsx_fail("error reading temporary file: %s", strerror(errno
));
94 p
->remaining_samples
-= n
;
98 return p
->remaining_samples
|| p
->remaining_repeats
? SOX_SUCCESS
: SOX_EOF
;
101 static int stop(sox_effect_t
* effp
)
103 priv_t
* p
= (priv_t
*)effp
->priv
;
104 fclose(p
->tmp_file
); /* auto-deleted by lsx_tmpfile */
108 sox_effect_handler_t
const * lsx_repeat_effect_fn(void)
110 static sox_effect_handler_t effect
= {"repeat", "[count (1)]",
111 SOX_EFF_MCHAN
| SOX_EFF_LENGTH
| SOX_EFF_MODIFY
,
112 create
, start
, flow
, drain
, stop
, NULL
, sizeof(priv_t
)};