ref: 34252aa3466fb2f84621822448703154073ef84a
parent: 4cca3b10be7b4bc6f3f420d55877bc00ab8f288b
author: Rob Sykes <robs@users.sourceforge.net>
date: Wed Jan 23 12:35:59 EST 2013
improved pink noise freq. response
--- a/src/synth.c
+++ b/src/synth.c
@@ -7,10 +7,10 @@
* This copyright notice must be maintained. The authors are not responsible
* for the consequences of using this software.
*
- * Except for synth types: pluck, tpdf, & brownnoise, and sweep types: linear
- * square & exp, which are:
+ * Except for synth types: pluck, tpdf, pinknoise, & brownnoise, and
+ * sweep types: linear, square & exp, which are:
*
- * Copyright (c) 2006-2009 robs@users.sourceforge.net
+ * Copyright (c) 2006-2013 robs@users.sourceforge.net
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -78,87 +78,6 @@
-/******************************************************************************
- * start of pink noise generator stuff
- * algorithm stolen from:
- * Author: Phil Burk, http://www.softsynth.com
- */
-
-#define PINK_MAX_RANDOM_ROWS (30)
-#define PINK_RANDOM_BITS (24)
-#define PINK_RANDOM_SHIFT ((sizeof(int32_t)*8)-PINK_RANDOM_BITS)
-
-typedef struct {
- long pink_Rows[PINK_MAX_RANDOM_ROWS];
- long pink_RunningSum; /* Used to optimize summing of generators. */
- int pink_Index; /* Incremented each sample. */
- int pink_IndexMask; /* Index wrapped by ANDing with this mask. */
- float pink_Scalar; /* Used to scale within range of -1 to +1 */
-} PinkNoise;
-
-/* Setup PinkNoise structure for N rows of generators. */
-static void InitializePinkNoise(PinkNoise * pink, size_t numRows)
-{
- size_t i;
- long pmax;
-
- pink->pink_Index = 0;
- pink->pink_IndexMask = (1 << numRows) - 1;
- /* Calculate maximum possible signed random value. Extra 1 for white noise always added. */
- pmax = (numRows + 1) * (1 << (PINK_RANDOM_BITS - 1));
- pink->pink_Scalar = 1.0f / pmax;
- /* Initialize rows. */
- for (i = 0; i < numRows; i++)
- pink->pink_Rows[i] = 0;
- pink->pink_RunningSum = 0;
-}
-
-/* Generate Pink noise values between -1 and +1 */
-static float GeneratePinkNoise(PinkNoise * pink)
-{
- long newRandom;
- long sum;
- float output;
-
- /* Increment and mask index. */
- pink->pink_Index = (pink->pink_Index + 1) & pink->pink_IndexMask;
-
- /* If index is zero, don't update any random values. */
- if (pink->pink_Index != 0) {
- /* Determine how many trailing zeros in PinkIndex. */
- /* This algorithm will hang if n==0 so test first. */
- int numZeros = 0;
- int n = pink->pink_Index;
-
- while ((n & 1) == 0) {
- n = n >> 1;
- numZeros++;
- }
-
- /* Replace the indexed ROWS random value.
- * Subtract and add back to RunningSum instead of adding all the random
- * values together. Only one changes each time.
- */
- pink->pink_RunningSum -= pink->pink_Rows[numZeros];
- newRandom = RANQD1 >> PINK_RANDOM_SHIFT;
- pink->pink_RunningSum += newRandom;
- pink->pink_Rows[numZeros] = newRandom;
- }
-
- /* Add extra white noise value. */
- newRandom = RANQD1 >> PINK_RANDOM_SHIFT;
- sum = pink->pink_RunningSum + newRandom;
-
- /* Scale to range of -1 to 0.9999. */
- output = pink->pink_Scalar * sum;
-
- return output;
-}
-
-/**************** end of pink noise stuff */
-
-
-
typedef enum {Linear, Square, Exp, Exp_cycle} sweep_t;
typedef struct {
@@ -172,8 +91,7 @@
/* internal stuff */
double lp_last_out, hp_last_out, hp_last_in, ap_last_out, ap_last_in;
- double cycle_start_time_s, c0, c1, c2, c3, c4;
- PinkNoise pink_noise;
+ double cycle_start_time_s, c0, c1, c2, c3, c4, c5, c6;
double * buffer;
size_t buffer_len, pos;
@@ -205,7 +123,7 @@
-static void set_default_parameters(channel_t * chan, size_t c)
+static void set_default_parameters(channel_t * chan)
{
switch (chan->type) {
case synth_square: /* p1 is pulse width */
@@ -240,11 +158,6 @@
chan->p3 = 1; /* simple falling slope to the end */
break;
- case synth_pinknoise:
- /* Initialize pink noise signals with different numbers of rows. */
- InitializePinkNoise(&(chan->pink_noise), 10 + 2 * c);
- break;
-
case synth_exp:
if (chan->p1 < 0) /* p1 is position of maximum */
chan->p1 = 0.5;
@@ -427,7 +340,7 @@
for (i = 0; i < p->number_of_channels; ++i) {
channel_t * chan = &p->channels[i];
*chan = p->getopts_channels[i % p->getopts_nchannels];
- set_default_parameters(chan, i);
+ set_default_parameters(chan);
if (chan->type == synth_pluck) {
double min, max, frac, p2;
@@ -666,9 +579,21 @@
synth_out = .5 * (DRANQD1 + DRANQD1);
break;
- case synth_pinknoise:
- synth_out = GeneratePinkNoise(&(chan->pink_noise));
+ 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*_);
+ synth_out = chan->c0 + chan->c1 + chan->c2 + chan->c3
+ + chan->c4 + chan->c5 + chan->c6 + d * (.5362*_);
+ chan->c6 = d * (.115926*_);
break;
+#undef _
+ }
case synth_brownnoise:
do synth_out = chan->lp_last_out + DRANQD1 * (1. / 16);