You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
FFmpegAndroid/app/src/main/cpp/sox/phaser.c

147 lines
4.5 KiB

/* Effect: phaser Copyright (C) 1998 Juergen Mueller And Sundry Contributors
*
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Juergen Mueller And Sundry Contributors are not responsible for
* the consequences of using this software.
*
* Flow diagram scheme: August 24, 1998
*
* * gain-in +---+ * gain-out
* ibuff ----------->| |----------------------------------> obuff
* | + | * decay
* | |<------------+
* +---+ _______ |
* | | | |
* +---| delay |---+
* |_______|
* /|\
* |
* +---------------+ +------------------+
* | Delay control |<-----| modulation speed |
* +---------------+ +------------------+
*
* The delay is controled by a sine or triangle modulation.
*
* Usage:
* phaser gain-in gain-out delay decay speed [ -s | -t ]
*
* Where:
* gain-in, decay : 0.0 .. 1.0 volume
* gain-out : 0.0 .. volume
* delay : 0.0 .. 5.0 msec
* speed : 0.1 .. 2.0 Hz modulation speed
* -s : modulation by sine (default)
* -t : modulation by triangle
*
* Note:
* When decay is close to 1.0, the samples may begin clipping or the output
* can saturate! Hint:
* in-gain < (1 - decay * decay)
* 1 / out-gain > gain-in / (1 - decay)
*/
#include "sox_i.h"
#include <string.h>
typedef struct {
double in_gain, out_gain, delay_ms, decay, mod_speed;
lsx_wave_t mod_type;
int * mod_buf;
size_t mod_buf_len;
int mod_pos;
double * delay_buf;
size_t delay_buf_len;
int delay_pos;
} priv_t;
static int getopts(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *) effp->priv;
char chars[2];
/* Set non-zero defaults: */
p->in_gain = .4;
p->out_gain = .74;
p->delay_ms = 3.;
p->decay = .4;
p->mod_speed = .5;
--argc, ++argv;
do { /* break-able block */
NUMERIC_PARAMETER(in_gain , .0, 1)
NUMERIC_PARAMETER(out_gain , .0, 1e9)
NUMERIC_PARAMETER(delay_ms , .0, 5)
NUMERIC_PARAMETER(decay , .0, .99)
NUMERIC_PARAMETER(mod_speed, .1, 2)
} while (0);
if (argc && sscanf(*argv, "-%1[st]%c", chars, chars + 1) == 1) {
p->mod_type = *chars == 's'? SOX_WAVE_SINE : SOX_WAVE_TRIANGLE;
--argc, ++argv;
}
if (p->in_gain > (1 - p->decay * p->decay))
lsx_warn("warning: gain-in might cause clipping");
if (p->in_gain / (1 - p->decay) > 1 / p->out_gain)
lsx_warn("warning: gain-out might cause clipping");
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
p->delay_buf_len = p->delay_ms * .001 * effp->in_signal.rate + .5;
p->delay_buf = lsx_calloc(p->delay_buf_len, sizeof(*p->delay_buf));
p->mod_buf_len = effp->in_signal.rate / p->mod_speed + .5;
p->mod_buf = lsx_malloc(p->mod_buf_len * sizeof(*p->mod_buf));
lsx_generate_wave_table(p->mod_type, SOX_INT, p->mod_buf, p->mod_buf_len,
1., (double)p->delay_buf_len, M_PI_2);
p->delay_pos = p->mod_pos = 0;
effp->out_signal.length = SOX_UNKNOWN_LEN; /* TODO: calculate actual length */
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;
size_t len = *isamp = *osamp = min(*isamp, *osamp);
while (len--) {
double d = *ibuf++ * p->in_gain + p->delay_buf[
(p->delay_pos + p->mod_buf[p->mod_pos]) % p->delay_buf_len] * p->decay;
p->mod_pos = (p->mod_pos + 1) % p->mod_buf_len;
p->delay_pos = (p->delay_pos + 1) % p->delay_buf_len;
p->delay_buf[p->delay_pos] = d;
*obuf++ = SOX_ROUND_CLIP_COUNT(d * p->out_gain, effp->clips);
}
return SOX_SUCCESS;
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
free(p->delay_buf);
free(p->mod_buf);
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_phaser_effect_fn(void)
{
static sox_effect_handler_t handler = {
"phaser", "gain-in gain-out delay decay speed [ -s | -t ]",
SOX_EFF_LENGTH | SOX_EFF_GAIN, getopts, start, flow, NULL, stop, NULL, sizeof(priv_t)
};
return &handler;
}