1 /* June 1, 1992
2  * Copyright 1992 Guido van Rossum And Sundry Contributors
3  * This source code is freely redistributable and may be used for
4  * any purpose.  This copyright notice must be maintained.
5  * Guido van Rossum And Sundry Contributors are not responsible for
6  * the consequences of using this software.
7  */
8 
9 /*
10  * "reverse" effect, uses a temporary file created by lsx_tmpfile().
11  */
12 
13 #include "sox_i.h"
14 #include <string.h>
15 
16 typedef struct {
17   off_t         pos;
18   FILE          * tmp_file;
19 } priv_t;
20 
start(sox_effect_t * effp)21 static int start(sox_effect_t * effp)
22 {
23   priv_t * p = (priv_t *)effp->priv;
24   p->pos = 0;
25   p->tmp_file = lsx_tmpfile();
26   if (p->tmp_file == NULL) {
27     lsx_fail("can't create temporary file: %s", strerror(errno));
28     return SOX_EOF;
29   }
30   return SOX_SUCCESS;
31 }
32 
flow(sox_effect_t * effp,const sox_sample_t * ibuf,sox_sample_t * obuf,size_t * isamp,size_t * osamp)33 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
34     sox_sample_t * obuf, size_t * isamp, size_t * osamp)
35 {
36   priv_t * p = (priv_t *)effp->priv;
37   if (fwrite(ibuf, sizeof(*ibuf), *isamp, p->tmp_file) != *isamp) {
38     lsx_fail("error writing temporary file: %s", strerror(errno));
39     return SOX_EOF;
40   }
41   (void)obuf, *osamp = 0; /* samples not output until drain */
42   return SOX_SUCCESS;
43 }
44 
drain(sox_effect_t * effp,sox_sample_t * obuf,size_t * osamp)45 static int drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
46 {
47   priv_t * p = (priv_t *)effp->priv;
48   int i, j;
49 
50   if (p->pos == 0) {
51     fflush(p->tmp_file);
52     p->pos = ftello(p->tmp_file);
53     if (p->pos % sizeof(sox_sample_t) != 0) {
54       lsx_fail("temporary file has incorrect size");
55       return SOX_EOF;
56     }
57     p->pos /= sizeof(sox_sample_t);
58   }
59   p->pos -= *osamp = min((off_t)*osamp, p->pos);
60   fseeko(p->tmp_file, (off_t)(p->pos * sizeof(sox_sample_t)), SEEK_SET);
61   if (fread(obuf, sizeof(sox_sample_t), *osamp, p->tmp_file) != *osamp) {
62     lsx_fail("error reading temporary file: %s", strerror(errno));
63     return SOX_EOF;
64   }
65   for (i = 0, j = *osamp - 1; i < j; ++i, --j) { /* reverse the samples */
66     sox_sample_t temp = obuf[i];
67     obuf[i] = obuf[j];
68     obuf[j] = temp;
69   }
70   return p->pos? SOX_SUCCESS : SOX_EOF;
71 }
72 
stop(sox_effect_t * effp)73 static int stop(sox_effect_t * effp)
74 {
75   priv_t * p = (priv_t *)effp->priv;
76   fclose(p->tmp_file); /* auto-deleted by lsx_tmpfile */
77   return SOX_SUCCESS;
78 }
79 
lsx_reverse_effect_fn(void)80 sox_effect_handler_t const * lsx_reverse_effect_fn(void)
81 {
82   static sox_effect_handler_t handler = {
83     "reverse", NULL, SOX_EFF_MODIFY, NULL, start, flow, drain, stop, NULL, sizeof(priv_t)
84   };
85   return &handler;
86 }
87