From: James Trammell <james.trammell@gmail.com>
To: sox-devel@lists.sourceforge.net
Subject: Updating synth.c with a Gaussian white noise effect?
Date: Mon, 8 Oct 2018 17:59:50 -0400 [thread overview]
Message-ID: <CAB0xix69qrJ0ZKbx6XHWuJu9yHWuZvoMbqhNPpHJ8xOk0TBfSw@mail.gmail.com> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 1274 bytes --]
Hi,
I have tried to write my own SoX effect to generate Gaussian white noise as
an alternative to the uniform white noise that it generates currently. Even
though I have a copy of "Numerical Recipes in C", a fair amount of C
experience, and the internet at my disposal, I'm still stuck.
Would anyone mind looking at the code I have come up with so far, and
hopefully tell me where I am screwing up?
A patch file for synth.c is attached; patch your v14.4.2 synth.c file with
my changes using:
cd sox-14.4.2/src
patch -p1 <synth.diff
(If you would like me to send you my modified synth.c itself, let me know.)
I tried a number of ways to accomplish this; that is why there are so many
commented out blocks. The last block of code is where I left off.
The new effect is invoked like this:
sox -V -b 24 -r 96000 -n gaussianwhite.wav synth 60 gaussianwhitenoise
gaussianwhitenoise gain -12
Thanks,
James
case synth_gaussianwhitenoise: {
static double V1, V2, S;
static int phase = 0;
double X;
do {
if(phase == 0) {
do {
V1 = DRANQD1;
V2 = DRANQD1;
S = V1 * V1 + V2 * V2;
} while (S >= 1 || S == 0);
X = V1 * sqrt(-2 * log(S) / S);
} else {
X = V2 * sqrt(-2 * log(S) / S);
}
phase = 1 - phase;
} while (X < -1 || X > 1);
synth_out = X;
//printf("%lf\n", synth_out);
}
[-- Attachment #1.2: Type: text/html, Size: 3692 bytes --]
[-- Attachment #2: synth.diff --]
[-- Type: application/octet-stream, Size: 11320 bytes --]
--- /Users/jtrammel/Developer/sox/sox-14.4.2-virgin/src/synth.c 2014-10-05 22:02:30.000000000 -0400
+++ /Users/jtrammel/Developer/sox/sox-14.4.2/src/synth.c 2018-10-05 13:13:26.000000000 -0400
@@ -46,7 +46,8 @@
synth_tpdfnoise,
synth_pinknoise,
synth_brownnoise,
- synth_pluck
+ synth_pluck,
+ synth_gaussianwhitenoise
} type_t;
static lsx_enum_item const synth_type[] = {
@@ -63,6 +64,7 @@
LSX_ENUM_ITEM(synth_, pinknoise)
LSX_ENUM_ITEM(synth_, brownnoise)
LSX_ENUM_ITEM(synth_, pluck)
+ LSX_ENUM_ITEM(synth_, gaussianwhitenoise)
{0, 0}
};
@@ -468,7 +470,7 @@
elapsed_time_s;
break;
case Square:
- phase = (chan->freq + sign(chan->mult) *
+ phase = (chan->freq + sign(chan->mult) *
sqr(p->samples_done * chan->mult)) * elapsed_time_s;
break;
case Exp:
@@ -571,9 +573,622 @@
default: synth_out = 0;
}
} else switch (chan->type) {
- case synth_whitenoise:
+
+
+/*
+ *
+ *
+ * ATTEMPT #1
+ *
+ *
+ *
+ // http://c-faq.com/lib/gaussian.html
+
+ case synth_gaussianwhitenoise: {
+ static double V1, V2, S;
+ static int phase = 0;
+ double X;
+
+ if(phase == 0) {
+ do {
+ double U1 = DRANQD1 / RAND_MAX;
+ double U2 = DRANQD1 / RAND_MAX;
+
+ V1 = 2 * U1 - 1;
+ V2 = 2 * U2 - 1;
+ S = V1 * V1 + V2 * V2;
+ } while(S >= 1 || S == 0);
+
+ X = V1 * sqrt(-2 * log(S) / S);
+ } else {
+ X = V2 * sqrt(-2 * log(S) / S);
+ }
+
+ phase = 1 - phase;
+
+ synth_out = X;
+ break;
+
+ }
+
+*/
+
+
+
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #2
+ *
+ *
+ *
+
+ // http://c-faq.com/lib/gaussian.html
+
+ case synth_gaussianwhitenoise: {
+ static double V1, V2, S;
+ static int phase = 0;
+
+ if(phase == 0) {
+ do {
+
+ V1 = 2 * DRANQD1 - 1;
+ V2 = 2 * DRANQD1 - 1;
+ S = V1 * V1 + V2 * V2;
+ } while(S >= 1 || S == 0);
+
+ synth_out = V1 * sqrt(-2 * log(S) / S);
+ } else {
+ synth_out = V2 * sqrt(-2 * log(S) / S);
+ }
+
+ phase = 1 - phase;
+
+ break;
+
+ }
+
+*/
+
+
+
+
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #3
+ *
+ *
+ *
+
+ // http://c-faq.com/lib/gaussian.html
+
+ case synth_gaussianwhitenoise: {
+ static double V1, V2, S;
+ static int phase = 0;
+
+ if(phase == 0) {
+ do {
+
+ double U1 = (double)DRANQD1 / RAND_MAX;
+ double U2 = (double)DRANQD1 / RAND_MAX;
+
+ V1 = 2 * U1 - 1;
+ V2 = 2 * U2 - 1;
+ S = V1 * V1 + V2 * V2;
+ } while(S >= 1 || S == 0);
+
+ synth_out = V1 * sqrt(-2 * log(S) / S);
+
+ } else {
+
+ synth_out = V2 * sqrt(-2 * log(S) / S);
+
+ }
+
+ phase = 1 - phase;
+
+ break;
+
+ }
+
+*/
+
+
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #4
+ *
+ *
+ *
+
+ case synth_gaussianwhitenoise: {
+ static double V1, V2, S;
+ static int phase = 0;
+ double X;
+
+ if(phase == 0) {
+ do {
+
+ double U1 = DRANQD1;
+ double U2 = DRANQD1;
+
+ V1 = 2 * U1 - 1;
+ V2 = 2 * U2 - 1;
+
+ S = V1 * V1 + V2 * V2;
+
+ } while(S >= 1 || S <= -1);
+
+ X = V1 * sqrt(-2 * log(S) / S);
+
+ } else {
+
+ X = V2 * sqrt(-2 * log(S) / S);
+
+ }
+
+ phase = 1 - phase;
+
+ synth_out = X;
+ printf("%lf\n", synth_out);
+
+ break;
+
+ }
+
+*/
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #5
+ *
+ *
+ *
+ case synth_gaussianwhitenoise: {
+
+ static double V1, V2, S;
+ static int phase = 0;
+ double X;
+
+ if (phase == 0) {
+
+ do {
+
+ double U1 = DRANQD1;
+ double U2 = DRANQD1;
+
+ S = U1 * U1 + U2 * U2;
+
+ } while (S >= 1 || S == 0);
+
+ V1 = U1 * sqrt((-2.0 * log(S)) / S);
+ double ln1 = exp(V1);
+ synth_out = ln1;
+
+ } else {
+
+ V2 = U2 * sqrt((-2.0 * log(S)) / S);
+ double ln2 = exp(V2);
+ synth_out = ln2;
+ }
+
+ phase = 1 - phase;
+ printf("%lf\n", synth_out);
+
+
+ break;
+
+ }
+
+*/
+
+
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #6
+ *
+ *
+ *
+
+ case synth_gaussianwhitenoise: {
+
+ static double V1, V2, S;
+ static int phase = 0;
+ double X;
+ double U1, U2;
+
+
+ do {
+
+ U1 = DRANQD1;
+ U2 = DRANQD1;
+
+ S = U1 * U1 + U2 * U2;
+
+ } while (S >= 1 || S == 0);
+
+ V1 = U1 * sqrt((-2.0 * log(S)) / S);
+ V2 = U2 * sqrt((-2.0 * log(S)) / S);
+
+ if (phase == 0) {
+ synth_out = exp(V1);
+
+ } else {
+
+ synth_out = exp(V2);
+ }
+
+ phase = 1 - phase;
+
+ printf("%lf\n", synth_out);
+
+ break;
+
+ }
+*/
+
+
+
+
+
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #7
+ *
+ *
+ *
+ * seems close?
+
+
+ case synth_gaussianwhitenoise: {
+ static double U1, U2, S;
+ static int phase = 0;
+ double X;
+
+ if(phase == 0) {
+ do {
+
+ U1 = DRANQD1;
+ U2 = DRANQD1;
+
+ //V1 = 2 * U1 - 1;
+ //V2 = 2 * U2 - 1;
+ S = U1 * U1 + U2 * U2;
+
+ } while (S >= 1 || S == 0);
+
+ X = U1 * sqrt(-2 * log(S) / S);
+ synth_out = exp(X);
+ printf("%lf\n", synth_out);
+
+ } else {
+
+ X = U2 * sqrt(-2 * log(S) / S);
+ synth_out = exp(X);
+ printf("%lf\n", synth_out);
+ }
+
+ phase = 1 - phase;
+
+ }
+
+*/
+
+
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #8
+ *
+ *
+ *
+
+
+case synth_gaussianwhitenoise: {
+ double x1, x2, w, y1;
+ static double y2;
+ static int use_last = 0;
+ static double mean = 0;
+ static double stdev = 4;
+
+ if (use_last) /* use value from previous call
+ {
+ y1 = y2;
+ use_last = 0;
+ } else {
+ do {
+ x1 = DRANQD1;
+ x2 = DRANQD1;
+ w = x1 * x1 + x2 * x2;
+ } while ( w >= 1.0 || w == 0);
+
+ w = sqrt( (-2.0 * log( w ) ) / w );
+ y1 = x1 * w;
+ y2 = x2 * w;
+ use_last = 1;
+ }
+
+ synth_out = mean + y1 * stdev;
+ printf("%lf\n", synth_out);
+
+}
+
+*/
+
+
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #9
+ *
+ *
+ *
+ case synth_gaussianwhitenoise: {
+ static double V1, V2, S;
+ static int phase = 0;
+ double X;
+ static int mean = 0;
+ static int stddev = 1;
+
+ if(phase == 0) {
+ do {
+ double U1 = (double)rand() / RAND_MAX;
+ double U2 = (double)rand() / RAND_MAX;
+
+ V1 = 2 * U1 - 1;
+ V2 = 2 * U2 - 1;
+ S = V1 * V1 + V2 * V2;
+
+ } while (S >= 1 || S == 0);
+
+ X = V1 * sqrt(-2 * log(S) / S);
+
+ } else {
+
+ X = V2 * sqrt(-2 * log(S) / S);
+
+ }
+
+ phase = 1 - phase;
+
+ synth_out = X; //i.e. mean = 0 and stddev = 1
+
+ printf("%lf %lf\n", synth_out, exp(mean + stddev * X));
+ }
+*/
+
+
+
+
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #10
+ *
+ *
+ *
+
+// this one works? kind of?
+// figured out where should the phase switch should be?
+
+ case synth_gaussianwhitenoise: {
+ static double V1, V2, S;
+ static int phase = 0;
+ double X = 1;
+
+ do {
+ if(phase == 0) {
+ do {
+ double U1 = (double)rand() / RAND_MAX;
+ double U2 = (double)rand() / RAND_MAX;
+
+ V1 = 2 * U1 - 1;
+ V2 = 2 * U2 - 1;
+ S = V1 * V1 + V2 * V2;
+
+ } while (S >= 1 || S == 0);
+
+ X = V1 * sqrt(-2 * log(S) / S);
+
+ } else {
+
+ X = V2 * sqrt(-2 * log(S) / S);
+
+ }
+
+ phase = 1 - phase;
+
+ } while (X < -1 || X > 1);
+
+ //phase = 1 - phase; //loops infinitely
+
+ synth_out = X;
+ printf("%lf\n", synth_out);
+
+ }
+*/
+
+
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #11
+ *
+ *
+ *
+
+//this should be the best one too, reuses existing code, and has options
+//but the exp output gives numbers that are not anything like the X numbers: 0.367881 to 2.71828
+//i am officially confused
+
+ case synth_gaussianwhitenoise: {
+ static double V1, V2, S;
+ static int phase = 0;
+ double X;
+ static int mean = 0;
+ static int stddev = 1;
+
+ do {
+ if(phase == 0) {
+ do {
+ V1 = DRANQD1;
+ V2 = DRANQD1;
+
+ S = V1 * V1 + V2 * V2;
+
+ } while (S >= 1 || S == 0);
+
+ X = V1 * sqrt(-2 * log(S) / S);
+
+ } else {
+
+ X = V2 * sqrt(-2 * log(S) / S);
+
+ }
+
+ phase = 1 - phase;
+
+ } while (X < -1 || X > 1);
+
+ //phase = 1 - phase; // causes infinite loop
+
+ synth_out = X;
+
+ printf("%lf %lf\n", synth_out, exp(mean + stddev * X));
+
+ }
+
+*/
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #12
+ *
+ *
+ *
+
+// https://stackoverflow.com/questions/2325472/generate-random-numbers-following-a-normal-distribution-in-c-c
+ case synth_gaussianwhitenoise: {
+ static double y1, y2;
+ static double sigma = 82.;
+ static double Mi = 40.;
+
+ y1 = (DRANQD1 + 1.) / ((double)(RAND_MAX) + 1.);
+ y2 = (DRANQD1 + 1.) / ((double)(RAND_MAX) + 1.);
+ synth_out = (cos(2*3.14*y2)*sqrt(-2.*log(y1))) * sigma + Mi;
+
+ break;
+
+ }
+
+
+*/
+
+
+
+
+
+
+
+/*
+ *
+ *
+ * ATTEMPT #13
+ *
+ *
+ *
+ */
+
+//this should be the best one, reuses existing code
+
+ case synth_gaussianwhitenoise: {
+ static double V1, V2, S;
+ static int phase = 0;
+ double X;
+
+ do {
+ if(phase == 0) {
+ do {
+ V1 = DRANQD1;
+ V2 = DRANQD1;
+
+ S = V1 * V1 + V2 * V2;
+
+ } while (S >= 1 || S == 0);
+
+ X = V1 * sqrt(-2 * log(S) / S);
+
+ } else {
+
+ X = V2 * sqrt(-2 * log(S) / S);
+
+ }
+
+ phase = 1 - phase;
+
+ } while (X < -1 || X > 1);
+
+ synth_out = X;
+ printf("%lf\n", synth_out);
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ case synth_whitenoise: {
synth_out = DRANQD1;
+ printf("%lf\n", synth_out);
break;
+ }
+
+
case synth_tpdfnoise:
synth_out = .5 * (DRANQD1 + DRANQD1);
@@ -582,15 +1197,15 @@
case synth_pinknoise: { /* "Paul Kellet's refined method" */
#define _ .125 / (65536. * 32768.)
double d = RANQD1;
- chan->c0 = .99886 * chan->c0 + d * (.0555179*_);
- chan->c1 = .99332 * chan->c1 + d * (.0750759*_);
- chan->c2 = .96900 * chan->c2 + d * (.1538520*_);
- chan->c3 = .86650 * chan->c3 + d * (.3104856*_);
- chan->c4 = .55000 * chan->c4 + d * (.5329522*_);
- chan->c5 = -.7616 * chan->c5 - d * (.0168980*_);
+ chan->c0 = .99886 * chan->c0 + d * (.0555179*_);
+ chan->c1 = .99332 * chan->c1 + d * (.0750759*_);
+ chan->c2 = .96900 * chan->c2 + d * (.1538520*_);
+ chan->c3 = .86650 * chan->c3 + d * (.3104856*_);
+ chan->c4 = .55000 * chan->c4 + d * (.5329522*_);
+ chan->c5 = -.7616 * chan->c5 - d * (.0168980*_);
synth_out = chan->c0 + chan->c1 + chan->c2 + chan->c3
- + chan->c4 + chan->c5 + chan->c6 + d * (.5362*_);
- chan->c6 = d * (.115926*_);
+ + chan->c4 + chan->c5 + chan->c6 + d * (.5362*_);
+ chan->c6 = d * (.115926*_);
break;
#undef _
}
@@ -604,10 +1219,10 @@
case synth_pluck: {
double d = chan->buffer[chan->pos];
- chan->hp_last_out =
+ chan->hp_last_out =
(d - chan->hp_last_in) * chan->c3 + chan->hp_last_out * chan->c2;
chan->hp_last_in = d;
-
+
synth_out = range_limit(chan->hp_last_out, -1, 1);
chan->lp_last_out = d = d * chan->c1 + chan->lp_last_out * chan->c0;
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
[-- Attachment #4: Type: text/plain, Size: 158 bytes --]
_______________________________________________
SoX-devel mailing list
SoX-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sox-devel
reply other threads:[~2018-10-08 22:00 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://lists.sourceforge.net/lists/listinfo/sox-devel
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAB0xix69qrJ0ZKbx6XHWuJu9yHWuZvoMbqhNPpHJ8xOk0TBfSw@mail.gmail.com \
--to=sox-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/sox.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).