README.osx wasn't easily readable in Finder. Revert back to
[sox.git] / src / delay.c
blob6fabeb0b1ce4a3d02167950cc61cc6ce2972fa13
1 /* libSoX effect: Delay one or more channels (c) 2008 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
18 #include "sox_i.h"
19 #include <string.h>
21 typedef struct {
22 size_t argc;
23 char * * argv, * max_arg;
24 size_t delay, pad, buffer_size, buffer_index;
25 sox_sample_t * buffer;
26 } priv_t;
28 static int lsx_kill(sox_effect_t * effp)
30 priv_t * p = (priv_t *)effp->priv;
31 unsigned i;
33 for (i = 0; i < p->argc; ++i)
34 free(p->argv[i]);
35 free(p->argv);
36 return SOX_SUCCESS;
39 static int create(sox_effect_t * effp, int argc, char * * argv)
41 priv_t * p = (priv_t *)effp->priv;
42 size_t delay, max_samples = 0;
43 unsigned i;
45 --argc, ++argv;
46 p->argv = lsx_calloc(p->argc = argc, sizeof(*p->argv));
47 for (i = 0; i < p->argc; ++i) {
48 char const * next = lsx_parsesamples(1e5, p->argv[i] = lsx_strdup(argv[i]), &delay, 't');
49 if (!next || *next) {
50 lsx_kill(effp);
51 return lsx_usage(effp);
53 if (delay > max_samples) {
54 max_samples = delay;
55 p->max_arg = p->argv[i];
58 return SOX_SUCCESS;
61 static int stop(sox_effect_t * effp)
63 priv_t * p = (priv_t *)effp->priv;
64 free(p->buffer);
65 return SOX_SUCCESS;
68 static int start(sox_effect_t * effp)
70 priv_t * p = (priv_t *)effp->priv;
71 size_t max_delay;
73 if (!p->max_arg)
74 return SOX_EFF_NULL;
75 if (effp->flow < p->argc)
76 lsx_parsesamples(effp->in_signal.rate, p->argv[effp->flow], &p->buffer_size, 't');
77 lsx_parsesamples(effp->in_signal.rate, p->max_arg, &max_delay, 't');
78 p->buffer_index = p->delay = 0;
79 p->pad = max_delay - p->buffer_size;
80 p->buffer = lsx_malloc(p->buffer_size * sizeof(*p->buffer));
81 return SOX_SUCCESS;
84 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
85 sox_sample_t * obuf, size_t * isamp, size_t * osamp)
87 priv_t * p = (priv_t *)effp->priv;
88 size_t len = *isamp = *osamp = min(*isamp, *osamp);
90 if (!p->buffer_size)
91 memcpy(obuf, ibuf, len * sizeof(*obuf));
92 else for (; len; --len) {
93 if (p->delay < p->buffer_size) {
94 p->buffer[p->delay++] = *ibuf++;
95 *obuf++ = 0;
96 } else {
97 *obuf++ = p->buffer[p->buffer_index];
98 p->buffer[p->buffer_index++] = *ibuf++;
99 p->buffer_index %= p->buffer_size;
102 return SOX_SUCCESS;
105 static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp)
107 priv_t * p = (priv_t *)effp->priv;
108 size_t len = *osamp = min(p->delay + p->pad, *osamp);
110 for (; p->delay && len; --p->delay, --len) {
111 *obuf++ = p->buffer[p->buffer_index++];
112 p->buffer_index %= p->buffer_size;
114 for (; p->pad && len; --p->pad, --len)
115 *obuf++ = 0;
116 return SOX_SUCCESS;
119 sox_effect_handler_t const * lsx_delay_effect_fn(void)
121 static sox_effect_handler_t handler = {
122 "delay", "{length}", SOX_EFF_LENGTH | SOX_EFF_MODIFY,
123 create, start, flow, drain, stop, lsx_kill, sizeof(priv_t)
125 return &handler;