ref: 0a384c4b91402a6133424548551b90293c1f8ea9
parent: a2fec7d4c67b8b7cea4604c449b413cc124e6ba8
author: robs <robs>
date: Sat Nov 15 14:44:16 EST 2008
tpdf and pluck enhancements
--- a/src/synth.c
+++ b/src/synth.c
@@ -27,6 +27,7 @@
/* Tones above, noises below */
synth_whitenoise,
synth_noise = synth_whitenoise, /* Just a handy alias */
+ synth_tpdfnoise,
synth_pinknoise,
synth_brownnoise,
synth_pluck
@@ -42,6 +43,7 @@
LSX_ENUM_ITEM(synth_, exp)
LSX_ENUM_ITEM(synth_, whitenoise)
LSX_ENUM_ITEM(synth_, noise)
+ LSX_ENUM_ITEM(synth_, tpdfnoise)
LSX_ENUM_ITEM(synth_, pinknoise)
LSX_ENUM_ITEM(synth_, brownnoise)
LSX_ENUM_ITEM(synth_, pluck)
@@ -159,7 +161,7 @@
PinkNoise pink_noise;
float *buffer;
size_t buffer_len;
-} * channel_t;
+} channel_t;
@@ -166,18 +168,18 @@
/* Private data for the synthesizer */
typedef struct {
char * length_str;
- channel_t getopts_channels;
+ channel_t * getopts_channels;
size_t getopts_nchannels;
sox_sample_t max;
size_t samples_done;
size_t samples_to_do;
- channel_t channels;
+ channel_t * channels;
size_t number_of_channels;
} priv_t;
-static void create_channel(channel_t chan)
+static void create_channel(channel_t * chan)
{
memset(chan, 0, sizeof(*chan));
chan->freq2 = chan->freq = 440;
@@ -186,7 +188,7 @@
-static void set_default_parameters(channel_t chan, size_t c)
+static void set_default_parameters(channel_t * chan, size_t c)
{
switch (chan->type) {
case synth_square: /* p1 is pulse width */
@@ -235,9 +237,9 @@
case synth_pluck:
if (chan->p1 < 0)
- chan->p1 = 0.995 * .5;
+ chan->p1 = .4;
if (chan->p2 < 0)
- chan->p2 = 16;
+ chan->p2 = 0;
default: break;
}
@@ -245,9 +247,27 @@
+#undef NUMERIC_PARAMETER
+#define NUMERIC_PARAMETER(p, min, max) { \
+char * end_ptr; \
+double d = strtod(argv[argn], &end_ptr); \
+if (end_ptr == argv[argn]) \
+ break; \
+if (d < min || d > max || *end_ptr != '\0') { \
+ lsx_fail("parameter error"); \
+ return SOX_EOF; \
+} \
+chan->p = d / 100; /* adjust so abs(parameter) <= 1 */\
+if (++argn == argc) \
+ break; \
+}
+
+
+
static int getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * synth = (priv_t *) effp->priv;
+ channel_t master, * chan = &master;
int argn = 0;
/* Get duration if given (if first arg starts with digit) */
@@ -255,13 +275,23 @@
synth->length_str = lsx_malloc(strlen(argv[argn]) + 1);
strcpy(synth->length_str, argv[argn]);
/* Do a dummy parse of to see if it will fail */
- if (lsx_parsesamples(9e9, synth->length_str, &synth->samples_to_do, 't') == NULL || !synth->samples_to_do)
+ if (lsx_parsesamples(9e9, synth->length_str, &synth->samples_to_do, 't') == NULL)
return lsx_usage(effp);
argn++;
}
+ if (argn < argc) { /* [off [ph [p1 [p2 [p3]]]]]] */
+ create_channel(chan);
+ do { /* break-able block */
+ NUMERIC_PARAMETER(offset,-100, 100)
+ NUMERIC_PARAMETER(phase , 0, 100)
+ NUMERIC_PARAMETER(p1, 0, 100)
+ NUMERIC_PARAMETER(p2, 0, 100)
+ NUMERIC_PARAMETER(p3, 0, 100)
+ } while (0);
+ }
+
while (argn < argc) { /* type [combine] [f1[-f2] [off [ph [p1 [p2 [p3]]]]]] */
- channel_t chan;
char * end_ptr;
lsx_enum_item const *p = lsx_find_enum_text(argv[argn], synth_type);
@@ -271,7 +301,7 @@
}
synth->getopts_channels = lsx_realloc(synth->getopts_channels, sizeof(*synth->getopts_channels) * (synth->getopts_nchannels + 1));
chan = &synth->getopts_channels[synth->getopts_nchannels++];
- create_channel(chan);
+ memcpy(chan, &master, sizeof(*chan));
chan->type = p->value;
if (++argn == argc)
break;
@@ -320,20 +350,6 @@
}
/* read rest of parameters */
-#undef NUMERIC_PARAMETER
-#define NUMERIC_PARAMETER(p, min, max) { \
- char * end_ptr; \
- double d = strtod(argv[argn], &end_ptr); \
- if (end_ptr == argv[argn]) \
- break; \
- if (d < min || d > max || *end_ptr != '\0') { \
- lsx_fail("parameter error"); \
- return SOX_EOF; \
- } \
- chan->p = d / 100; /* adjust so abs(parameter) <= 1 */\
- if (++argn == argc) \
- break; \
- }
do { /* break-able block */
NUMERIC_PARAMETER(offset,-100, 100)
NUMERIC_PARAMETER(phase , 0, 100)
@@ -341,19 +357,13 @@
NUMERIC_PARAMETER(p2, 0, 100)
NUMERIC_PARAMETER(p3, 0, 100)
} while (0);
-
- if (chan->type == synth_pluck) {
- if (chan->p1 >= 0)
- chan->p1 = .4 + (.1 / 3) * log10(1 + 999 * chan->p1);
- if (chan->p2 >= 0)
- chan->p2 *= 100;
- }
}
/* If no channel parameters were given, create one default channel: */
if (!synth->getopts_nchannels) {
synth->getopts_channels = lsx_malloc(sizeof(*synth->getopts_channels));
- create_channel(&synth->getopts_channels[synth->getopts_nchannels++]);
+ memcpy(&synth->getopts_channels[0], &master, sizeof(channel_t));
+ ++synth->getopts_nchannels;
}
if (!effp->in_signal.channels)
@@ -373,27 +383,30 @@
synth->samples_done = 0;
if (synth->length_str)
- if (lsx_parsesamples(effp->in_signal.rate, synth->length_str, &synth->samples_to_do, 't') == NULL || !synth->samples_to_do)
+ if (lsx_parsesamples(effp->in_signal.rate, synth->length_str, &synth->samples_to_do, 't') == NULL)
return lsx_usage(effp);
synth->number_of_channels = effp->in_signal.channels;
synth->channels = lsx_calloc(synth->number_of_channels, sizeof(*synth->channels));
for (i = 0; i < synth->number_of_channels; ++i) {
- channel_t chan = &synth->channels[i];
+ channel_t * chan = &synth->channels[i];
*chan = synth->getopts_channels[i % synth->getopts_nchannels];
set_default_parameters(chan, i);
if (chan->type == synth_pluck) {
int32_t r = 0;
- float dc = 0;
+ float colour = pow(2., 4 * (chan->p2 - 1));
+ float dc = 0, a = 6.9 / (chan->p2 < .25? chan->p2 / .25 * 11 + 7 :
+ chan->p2 <= .55? 18 : (1-chan->p2) / .45 * 3 + 15);
chan->buffer_len = effp->in_signal.rate / chan->freq + .5;
chan->buffer = malloc(chan->buffer_len * sizeof(*chan->buffer));
chan->buffer[0] = 0;
for (j = 1; j < chan->buffer_len; dc += chan->buffer[j++])
- do chan->buffer[j] = chan->buffer[j - 1] + RAND_ * (1. / chan->p2);
+ do chan->buffer[j] = chan->buffer[j - 1] + RAND_ * colour;
while (fabs(chan->buffer[j]) > 1);
for (dc /= chan->buffer_len, j = 0; j < chan->buffer_len; ++j)
- chan->buffer[j] = range_limit(chan->buffer[j] - dc, -1, 1);
- chan->p1 /= cos(M_PI * chan->freq / effp->in_signal.rate);
+ chan->buffer[j] = range_limit(chan->buffer[j] - dc, -1, 1) * a;
+ chan->p3 = .5 * exp(log(.6) / chan->freq / chan->p1);
+ lsx_debug("a=%g colour=%g", a, 1/colour);
}
switch (chan->sweep) {
case Linear: chan->mult = synth->samples_to_do?
@@ -438,7 +451,7 @@
for (done = 0; done < len && result == SOX_SUCCESS; ++done) {
for (c = 0; c < effp->in_signal.channels; c++) {
sox_sample_t synth_input = *ibuf++;
- channel_t chan = &synth->channels[c];
+ channel_t * chan = &synth->channels[c];
double synth_out; /* [-1, 1] */
if (chan->type < synth_noise) { /* Need to calculate phase: */
@@ -556,6 +569,10 @@
synth_out = RAND;
break;
+ case synth_tpdfnoise:
+ synth_out = .5 * (RAND + RAND);
+ break;
+
case synth_pinknoise:
synth_out = GeneratePinkNoise(&(chan->pink_noise));
break;
@@ -569,7 +586,7 @@
case synth_pluck: {
size_t j = synth->samples_done % chan->buffer_len;
synth_out = chan->buffer[j];
- chan->buffer[j] = chan->p1 * (synth_out + chan->last_out);
+ chan->buffer[j] = chan->p3 * (synth_out + chan->last_out);
chan->last_out = synth_out;
break;
}