blob: 8ec48e674b9693cbb9f9085d594624764660fd53 [file] [log] [blame]
/* June 1, 1992
* Copyright 1992 Guido van Rossum And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Guido van Rossum And Sundry Contributors are not responsible for
* the consequences of using this software.
*/
/*
* "reverse" effect, uses a temporary file created by lsx_tmpfile().
*/
#include "third_party/sox/src/src/sox_i.h"
#include <string.h>
typedef struct {
off_t pos;
FILE * tmp_file;
} priv_t;
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
p->pos = 0;
p->tmp_file = lsx_tmpfile();
if (p->tmp_file == NULL) {
lsx_fail("can't create temporary file: %s", strerror(errno));
return SOX_EOF;
}
return SOX_SUCCESS;
}
static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
sox_sample_t * obuf, size_t * isamp, size_t * osamp)
{
priv_t * p = (priv_t *)effp->priv;
if (fwrite(ibuf, sizeof(*ibuf), *isamp, p->tmp_file) != *isamp) {
lsx_fail("error writing temporary file: %s", strerror(errno));
return SOX_EOF;
}
(void)obuf, *osamp = 0; /* samples not output until drain */
return SOX_SUCCESS;
}
static int drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
priv_t * p = (priv_t *)effp->priv;
int i, j;
if (p->pos == 0) {
fflush(p->tmp_file);
p->pos = ftello(p->tmp_file);
if (p->pos % sizeof(sox_sample_t) != 0) {
lsx_fail("temporary file has incorrect size");
return SOX_EOF;
}
p->pos /= sizeof(sox_sample_t);
}
p->pos -= *osamp = min((off_t)*osamp, p->pos);
fseeko(p->tmp_file, (off_t)(p->pos * sizeof(sox_sample_t)), SEEK_SET);
if (fread(obuf, sizeof(sox_sample_t), *osamp, p->tmp_file) != *osamp) {
lsx_fail("error reading temporary file: %s", strerror(errno));
return SOX_EOF;
}
for (i = 0, j = *osamp - 1; i < j; ++i, --j) { /* reverse the samples */
sox_sample_t temp = obuf[i];
obuf[i] = obuf[j];
obuf[j] = temp;
}
return p->pos? SOX_SUCCESS : SOX_EOF;
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
fclose(p->tmp_file); /* auto-deleted by lsx_tmpfile */
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_reverse_effect_fn(void)
{
static sox_effect_handler_t handler = {
"reverse", NULL, SOX_EFF_MODIFY, NULL, start, flow, drain, stop, NULL, sizeof(priv_t)
};
return &handler;
}