CSL 5.2

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

Noise.cpp
Go to the documentation of this file.
1 //
2 // Noise.cpp
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5
6 #include "Noise.h"
7 #include <time.h>
8
9 using namespace csl;
10
11 ///
12 /// Abstract Noise class
13 ///
14
15 /// Constructors call UnitGenerator & Scalable constructors
16 /// Noise defaults to expansion copy policy (i.e. distinct noise per channel)
17 /// if no seed is specified, current clock time is used
18
19 Noise::Noise() :
20 UnitGenerator(),
21 Scalable(1.f, 0.f),
22 //mCopyPolicy(kExpand),
23 mSeed(time(NULL)),
24 mDivisor(1.0f / (float) 0x7fffffff) {
25 setCopyPolicy(kExpand);
26 }
27
28 Noise::Noise(double ampl, double offset) :
29 UnitGenerator(),
30 Scalable((float)ampl, (float)offset),
31 //mCopyPolicy(kExpand),
32 mSeed(time(NULL)),
33 mDivisor(1.0f / (float) 0x7fffffff) {
34 setCopyPolicy(kExpand);
35 }
36
37 Noise::Noise(int seed, double ampl, double offset) :
38 UnitGenerator(),
39 Scalable((float)ampl, (float)offset),
40 //mCopyPolicy(kExpand),
41 mSeed(seed),
42 mDivisor(1.0f / (float) 0x7fffffff) {
43 setCopyPolicy(kExpand);
44 }
45
46 void Noise::dump() {
47 logMsg("a Noise generator");
48 Scalable::dump();
49 UnitGenerator::dump();
50 }
51
52 ///
53 /// White noise -- equal power per frequency
54 ///
55
56 void WhiteNoise::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
57 sample* out = outputBuffer.monoBuffer(outBufNum); // get ptr to output channel
58 unsigned numFrames = outputBuffer.mNumFrames; // get buffer length
59
60 DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values
61 LOAD_SCALABLE_CONTROLS;
62 #ifdef CSL_DEBUG
63 logMsg("WhiteNoise nextBuffer");
64 #endif
65 for (unsigned i = 0; i < numFrames; i++) { // sample loop
66 // call generate_random_number and do the division myself
67 *out++ = ((((float) generateRandomNumber()) * mDivisor) * scaleValue) + offsetValue;
68 UPDATE_SCALABLE_CONTROLS; // update the dynamic scale/offset
69 }
70 }
71
72 /// Most of this code was taken from an public domain C implementation written by Phil Burk.
73 /// The code and the webpage explaining it is at
74 /// http://www.firstpr.com.au/dsp/pink-noise/phil_burk_19990905mPatestmPink.c
75 /// and
76 /// http://www.firstpr.com.au/dsp/pink-noise/
77
78 PinkNoise::PinkNoise() : Noise() {
79 setCopyPolicy(kExpand);
80 initialize(32);
81 }
82
83 PinkNoise::PinkNoise(double ampl, double offset) : Noise(ampl, offset) {
84 setCopyPolicy(kExpand);
85 initialize(32);
86 }
87
88 PinkNoise::PinkNoise(int seed, double ampl, double offset) : Noise(seed, ampl, offset) {
89 setCopyPolicy(kExpand);
90 initialize(32);
91 }
92
93 /// Setup PinkNoise structure for N rows of generators.
94 void PinkNoise::initialize(int numRows) {
95 int i;
96 int pmax;
97 mPinkIndex = 0;
98 mPinkIndexMask = (1<<numRows) - 1;
99 // Calculate maximum possible signed random value. Extra 1 for white noise always added.
100 pmax = (numRows + 1) * (1<<(PINK_RANDOM_BITS-1));
101 mPinkScalar = 1.0f / pmax;
102 // Initialize rows.
103 for (i=0; i<numRows; i++ ) mPinkRows[i] = 0;
104 mPinkRunningSum = 0;
105 }
106
107 // Generate Pink noise values between -1.0 and +1.0
108 sample PinkNoise::nextPink() {
109 int newRandom;
110 int sum;
111 sample output;
112 // Increment and mask index.
113 mPinkIndex = (mPinkIndex + 1) & mPinkIndexMask;
114 // If index is zero, don't update any random values.
115 if (mPinkIndex != 0 ) {
116 // Determine how many trailing zeros in PinkIndex.
117 // This algorithm will hang if n==0 so test first.
118 int numZeros = 0;
119 int n = mPinkIndex;
120 while((n & 1) == 0 ) {
121 n = n >> 1;
122 numZeros++;
123 }
124 // Replace the indexed ROWS random value.
125 // Subtract and add back to RunningSum instead of adding all the random values together. Only one changes each time.
126 mPinkRunningSum -= mPinkRows[numZeros];
127 newRandom = ((int)generateRandomNumber()) >> PINK_RANDOM_SHIFT;
128 mPinkRunningSum += newRandom;
129 mPinkRows[numZeros] = newRandom;
130 }
131 // Add extra white noise value.
132 newRandom = ((int)generateRandomNumber()) >> PINK_RANDOM_SHIFT;
133 sum = mPinkRunningSum + newRandom;
134 // Scale to range of -1.0 to 0.9999.
135 output = mPinkScalar * sum;
136 //#define PINK_MEASURE
137 #ifdef PINK_MEASURE
138 // Check Min/Max
139 static float pinkMax = 0, pinkMin = 0;
140 if (output > pinkMax ) pinkMax = output;
141 else if (output < pinkMin ) pinkMin = output;
142 // printf("max: %g\t min: %g", pinkMax, pinkMin);
143 #endif
144 return output;
145 }
146
147 void PinkNoise::nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException) {
148 SampleBuffer out = outputBuffer.monoBuffer(outBufNum);
149 unsigned numFrames = outputBuffer.mNumFrames;
150
151 DECLARE_SCALABLE_CONTROLS; // declare the scale/offset buffers and values as above
152 #ifdef CSL_DEBUG
153 logMsg("SineAsScaled nextBuffer");
154 #endif
155 LOAD_SCALABLE_CONTROLS;
156 for (unsigned i = 0; i < numFrames; i++ ) {
157 *out++ = (nextPink() * scaleValue) + offsetValue; // get a sample
158 UPDATE_SCALABLE_CONTROLS;
159 }
160 }
161