Updating synth.c with a Gaussian white noise effect?

James Trammell <[email protected]>
Newsgroups gmane.comp.audio.sox
Message-ID <CAB0xix5Xst80G0+Ee_Jz6oQ1ff72W0rvkkfeKTLDhJTQs1UmWA@mail.gmail.com>
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);
}

_______________________________________________
Sox-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sox-users
synth.diff (application/octet-stream, 11.1 KB)
--- /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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.