ref: 60a2c7aa5849c3a1743fbbe80393cfe20d42b9ec
parent: bf5457c6dd2d1e5b70ada7931b509a5159b00e25
author: robs <robs>
date: Wed Nov 12 03:22:46 EST 2008
synth pluck
--- a/src/synth.c
+++ b/src/synth.c
@@ -13,6 +13,9 @@
#include <string.h>
#include <ctype.h>
+#define RAND (2. * rand() * (1. / RAND_MAX) - 1)
+#define RAND_ ranqd1(r) * (1. / (65536. * 32768.)) /* [-1,1) */
+
typedef enum {
synth_sine,
synth_square,
@@ -25,7 +28,8 @@
synth_whitenoise,
synth_noise = synth_whitenoise, /* Just a handy alias */
synth_pinknoise,
- synth_brownnoise
+ synth_brownnoise,
+ synth_pluck
} type_t;
static lsx_enum_item const synth_type[] = {
@@ -40,6 +44,7 @@
LSX_ENUM_ITEM(synth_, noise)
LSX_ENUM_ITEM(synth_, pinknoise)
LSX_ENUM_ITEM(synth_, brownnoise)
+ LSX_ENUM_ITEM(synth_, pluck)
{0, 0}
};
@@ -61,15 +66,6 @@
* Author: Phil Burk, http://www.softsynth.com
*/
-/* Calculate pseudo-random 32 bit number based on linear congruential method. */
-static unsigned long GenerateRandomNumber(void)
-{
- static unsigned long randSeed = 22222; /* Change this for different random sequences. */
-
- randSeed = (randSeed * 196314165) + 907633515;
- return randSeed;
-}
-
#define PINK_MAX_RANDOM_ROWS (30)
#define PINK_RANDOM_BITS (24)
#define PINK_RANDOM_SHIFT ((sizeof(long)*8)-PINK_RANDOM_BITS)
@@ -105,6 +101,7 @@
long newRandom;
long sum;
float output;
+ static int32_t r;
/* Increment and mask index. */
pink->pink_Index = (pink->pink_Index + 1) & pink->pink_IndexMask;
@@ -126,13 +123,13 @@
* values together. Only one changes each time.
*/
pink->pink_RunningSum -= pink->pink_Rows[numZeros];
- newRandom = ((long) GenerateRandomNumber()) >> PINK_RANDOM_SHIFT;
+ newRandom = ranqd1(r) >> PINK_RANDOM_SHIFT;
pink->pink_RunningSum += newRandom;
pink->pink_Rows[numZeros] = newRandom;
}
/* Add extra white noise value. */
- newRandom = ((long) GenerateRandomNumber()) >> PINK_RANDOM_SHIFT;
+ newRandom = ranqd1(r) >> PINK_RANDOM_SHIFT;
sum = pink->pink_RunningSum + newRandom;
/* Scale to range of -1 to 0.9999. */
@@ -158,8 +155,10 @@
/* internal stuff */
double cycle_start_time_s;
- double brown_noise;
+ double last_out;
PinkNoise pink_noise;
+ float *buffer;
+ size_t buffer_len;
} * channel_t;
@@ -234,6 +233,12 @@
chan->p2 = 1;
break;
+ case synth_pluck:
+ if (chan->p1 < 0)
+ chan->p1 = 0.995 * .5;
+ if (chan->p2 < 0)
+ chan->p2 = 16;
+
default: break;
}
}
@@ -255,7 +260,7 @@
argn++;
}
- while (argn < argc) { /* type [combine] [f1[-f2] [p1 [p2 [p3 [p3 [p4]]]]]] */
+ 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);
@@ -334,8 +339,15 @@
NUMERIC_PARAMETER(phase , 0, 100)
NUMERIC_PARAMETER(p1, 0, 100)
NUMERIC_PARAMETER(p2, 0, 100)
- NUMERIC_PARAMETER(p1, 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: */
@@ -355,7 +367,7 @@
static int start(sox_effect_t * effp)
{
priv_t * synth = (priv_t *) effp->priv;
- size_t i;
+ size_t i, j;
synth->max = lsx_sample_max(effp->out_encoding);
synth->samples_done = 0;
@@ -370,6 +382,19 @@
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;
+ 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);
+ 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);
+ }
switch (chan->sweep) {
case Linear: chan->mult = synth->samples_to_do?
(chan->freq2 - chan->freq) / synth->samples_to_do / 2 : 0;
@@ -527,7 +552,6 @@
default: synth_out = 0;
}
} else switch (chan->type) {
-#define RAND (2. * rand() * (1. / RAND_MAX) - 1)
case synth_whitenoise:
synth_out = RAND;
break;
@@ -537,11 +561,19 @@
break;
case synth_brownnoise:
- do synth_out = chan->brown_noise + RAND * (1. / 16);
+ do synth_out = chan->last_out + RAND * (1. / 16);
while (fabs(synth_out) > 1);
- chan->brown_noise = synth_out;
+ chan->last_out = synth_out;
break;
+ 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->last_out = synth_out;
+ break;
+ }
+
default: synth_out = 0;
}
@@ -567,6 +599,10 @@
static int stop(sox_effect_t * effp)
{
priv_t * synth = (priv_t *) effp->priv;
+ size_t i;
+
+ for (i = 0; i < synth->number_of_channels; ++i)
+ free(synth->channels[i].buffer);
free(synth->channels);
return SOX_SUCCESS;
}