commit 604c9ef7ee3f8f2c5a2093a97b75e090bcc494c8
parent d44dc9b66d503405cac29b73cdd15c962f0098b2
Author: fundamental <mark.d.mccurry@gmail.com>
Date: Tue, 13 Sep 2011 17:02:12 -0400
Rand: Replacing rand() for portable tests
In order to keep tests simple with respect to signal processing code, a portable
Pseudo Random Number Generator was built.
This will ensure that the sequence of random numbers from a given seed are
identical from platform to platform.
As this is not a cryptographic application, this behavior should not be an
issue.
Basic statistics of random source verified.
For source of magic numbers, see glibc.
Diffstat:
16 files changed, 75 insertions(+), 47 deletions(-)
diff --git a/src/DSP/Unison.h b/src/DSP/Unison.h
@@ -22,7 +22,7 @@
#ifndef UNISON_H
#define UNISON_H
#include <stdlib.h>
-#include "../globals.h"
+#include "../Misc/Util.h"
#define UNISON_FREQ_SPAN 2.0f
//how much the unison frequencies varies (always >= 1.0f)
diff --git a/src/Effects/EffectLFO.cpp b/src/Effects/EffectLFO.cpp
@@ -20,11 +20,11 @@
*/
-#include <cstdlib>
-#include <cmath>
-
#include "EffectLFO.h"
+#include "../Misc/Util.h"
+#include <cstdlib>
+#include <cmath>
EffectLFO::EffectLFO()
{
diff --git a/src/Misc/Util.cpp b/src/Misc/Util.cpp
@@ -35,9 +35,10 @@
#include <sched.h>
-int SAMPLE_RATE = 44100;
+int SAMPLE_RATE = 44100;
int SOUND_BUFFER_SIZE = 256;
-int OSCIL_SIZE = 1024;
+int OSCIL_SIZE = 1024;
+prng_t prng_state = 0x1234;
Config config;
float *denormalkillbuf;
diff --git a/src/Misc/Util.h b/src/Misc/Util.h
@@ -25,6 +25,7 @@
#include <string>
#include <sstream>
+#include <stdint.h>
#include "Config.h"
#include "../globals.h"
@@ -86,6 +87,33 @@ T limit(T val, T min, T max)
return (val < min ? min : (val > max ? max : val));
}
+//Random number generator
+
+typedef uint32_t prng_t;
+extern prng_t prng_state;
+
+// Portable Pseudo-Random Number Generator
+inline prng_t prng_r(prng_t &p)
+{
+ return (p = p * 1103515245 + 12345);
+}
+
+inline prng_t prng(void)
+{
+ return prng_r(prng_state)&0x7fffffff;
+}
+
+inline void sprng(prng_t p)
+{
+ prng_state = p;
+}
+
+/*
+ * The random generator (0.0f..1.0f)
+ */
+# define INT32_MAX (2147483647)
+#define RND (prng() / (INT32_MAX * 1.0f))
+
#endif
diff --git a/src/Output/DSSIaudiooutput.cpp b/src/Output/DSSIaudiooutput.cpp
@@ -27,10 +27,11 @@
//this file contains code used from trivial_synth.c from
//the DSSI (published by Steve Harris under public domain) as a template.
-#include <string.h>
#include "DSSIaudiooutput.h"
#include "../Misc/Config.h"
#include "../Misc/Bank.h"
+#include "../Misc/Util.h"
+#include <string.h>
#include <limits.h>
using std::string;
@@ -603,7 +604,7 @@ DSSIaudiooutput::DSSIaudiooutput(unsigned long sampleRate)
config.init();
- srand(time(NULL));
+ sprng(time(NULL));
denormalkillbuf=new float [SOUND_BUFFER_SIZE];
for (int i=0;i<SOUND_BUFFER_SIZE;i++) denormalkillbuf[i]=(RND-0.5f)*1e-16;
diff --git a/src/Params/FilterParams.cpp b/src/Params/FilterParams.cpp
@@ -20,10 +20,11 @@
*/
+#include "FilterParams.h"
+#include "../Misc/Util.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
-#include "FilterParams.h"
FilterParams::FilterParams(unsigned char Ptype_,
unsigned char Pfreq_,
diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp
@@ -93,7 +93,7 @@ ADnote::ADnote(ADnoteParameters *pars,
NoteGlobalPar.Punch.Enabled = 0;
for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
- pars->VoicePar[nvoice].OscilSmp->newrandseed(rand());
+ pars->VoicePar[nvoice].OscilSmp->newrandseed(prng());
NoteVoicePar[nvoice].OscilSmp = NULL;
NoteVoicePar[nvoice].FMSmp = NULL;
NoteVoicePar[nvoice].VoiceOut = NULL;
@@ -275,7 +275,7 @@ ADnote::ADnote(ADnoteParameters *pars,
if(pars->VoicePar[nvoice].Pextoscil != -1)
vc = pars->VoicePar[nvoice].Pextoscil;
if(!pars->GlobalPar.Hrandgrouping)
- pars->VoicePar[vc].OscilSmp->newrandseed(rand());
+ pars->VoicePar[vc].OscilSmp->newrandseed(prng());
int oscposhi_start =
pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,
getvoicebasefreq(nvoice),
@@ -478,7 +478,7 @@ void ADnote::legatonote(float freq, float velocity, int portamento_,
if(pars->VoicePar[nvoice].Pextoscil != -1)
vc = pars->VoicePar[nvoice].Pextoscil;
if(!pars->GlobalPar.Hrandgrouping)
- pars->VoicePar[vc].OscilSmp->newrandseed(rand());
+ pars->VoicePar[vc].OscilSmp->newrandseed(prng());
pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,
getvoicebasefreq(nvoice),
@@ -605,7 +605,7 @@ void ADnote::legatonote(float freq, float velocity, int portamento_,
/* Voice Modulation Parameters Init */
if((NoteVoicePar[nvoice].FMEnabled != NONE)
&& (NoteVoicePar[nvoice].FMVoice < 0)) {
- partparams->VoicePar[nvoice].FMSmp->newrandseed(rand());
+ partparams->VoicePar[nvoice].FMSmp->newrandseed(prng());
//Perform Anti-aliasing only on MORPH or RING MODULATION
@@ -614,7 +614,7 @@ void ADnote::legatonote(float freq, float velocity, int portamento_,
vc = partparams->VoicePar[nvoice].PextFMoscil;
if(!partparams->GlobalPar.Hrandgrouping)
- partparams->VoicePar[vc].FMSmp->newrandseed(rand());
+ partparams->VoicePar[vc].FMSmp->newrandseed(prng());
for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i)
NoteVoicePar[nvoice].FMSmp[OSCIL_SIZE + i] =
@@ -777,7 +777,7 @@ void ADnote::initparameters()
/* Voice Modulation Parameters Init */
if((vce.FMEnabled != NONE) && (vce.FMVoice < 0)) {
- param.FMSmp->newrandseed(rand());
+ param.FMSmp->newrandseed(prng());
vce.FMSmp = new float[OSCIL_SIZE + OSCIL_SMP_EXTRA_SAMPLES];
//Perform Anti-aliasing only on MORPH or RING MODULATION
@@ -793,7 +793,7 @@ void ADnote::initparameters()
tmp = getFMvoicebasefreq(nvoice);
if(!partparams->GlobalPar.Hrandgrouping)
- partparams->VoicePar[vc].FMSmp->newrandseed(rand());
+ partparams->VoicePar[vc].FMSmp->newrandseed(prng());
for(int k = 0; k < unison_size[nvoice]; ++k)
oscposhiFM[nvoice][k] = (oscposhi[nvoice][k]
diff --git a/src/Synth/LFO.cpp b/src/Synth/LFO.cpp
@@ -20,13 +20,13 @@
*/
+#include "LFO.h"
+#include "../Misc/Util.h"
+
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
-#include "LFO.h"
-
-
LFO::LFO(LFOParams *lfopars, float basefreq)
{
if(lfopars->Pstretch == 0)
diff --git a/src/Synth/OscilGen.cpp b/src/Synth/OscilGen.cpp
@@ -852,8 +852,8 @@ short int OscilGen::get(float *smps, float freqHz, int resonance)
//Harmonic Amplitude Randomness
if((freqHz > 0.1f) && (!ADvsPAD)) {
- unsigned int realrnd = rand();
- srand(randseed);
+ unsigned int realrnd = prng();
+ sprng(randseed);
float power = Pamprandpower / 127.0f;
float normalize = 1.0f / (1.2f - power);
switch(Pamprandtype) {
@@ -872,7 +872,7 @@ short int OscilGen::get(float *smps, float freqHz, int resonance)
* normalize;
break;
}
- srand(realrnd + 1);
+ sprng(realrnd + 1);
}
if((freqHz > 0.1f) && (resonance != 0))
diff --git a/src/Tests/AdNoteTest.h b/src/Tests/AdNoteTest.h
@@ -118,26 +118,26 @@ class AdNoteTest:public CxxTest::TestSuite
#endif
sampleCount += SOUND_BUFFER_SIZE;
- TS_ASSERT_DELTA(outL[255], 0.3019f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], 0.254609f, 0.0001f);
note->relasekey();
note->noteout(outL, outR);
sampleCount += SOUND_BUFFER_SIZE;
- TS_ASSERT_DELTA(outL[255], -0.1382f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], -0.102197f, 0.0001f);
note->noteout(outL, outR);
sampleCount += SOUND_BUFFER_SIZE;
- TS_ASSERT_DELTA(outL[255], -0.0334f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], -0.111422f, 0.0001f);
note->noteout(outL, outR);
sampleCount += SOUND_BUFFER_SIZE;
- TS_ASSERT_DELTA(outL[255], -0.1329f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], -0.021375f, 0.0001f);
note->noteout(outL, outR);
sampleCount += SOUND_BUFFER_SIZE;
- TS_ASSERT_DELTA(outL[255], 0.2690f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], 0.149882f, 0.0001f);
while(!note->finished()) {
note->noteout(outL, outR);
diff --git a/src/Tests/CMakeLists.txt b/src/Tests/CMakeLists.txt
@@ -21,3 +21,4 @@ target_link_libraries(EchoTest ${test_lib})
target_link_libraries(MicrotonalTest ${test_lib})
target_link_libraries(OscilGenTest ${test_lib})
target_link_libraries(XMLwrapperTest ${test_lib})
+target_link_libraries(RandTest ${test_lib})
diff --git a/src/Tests/OscilGenTest.h b/src/Tests/OscilGenTest.h
@@ -74,10 +74,10 @@ class OscilGenTest:public CxxTest::TestSuite
void testOutput(void)
{
oscil->get(outL, freq);
- TS_ASSERT_DELTA(outL[23], -0.014717f, 0.0001f);
- TS_ASSERT_DELTA(outL[129], -0.567502f, 0.0001f);
- TS_ASSERT_DELTA(outL[586], -0.030894f, 0.0001f);
- TS_ASSERT_DELTA(outL[1023], -0.080001f, 0.0001f);
+ TS_ASSERT_DELTA(outL[23], -0.044547f, 0.0001f);
+ TS_ASSERT_DELTA(outL[129], -0.018169f, 0.0001f);
+ TS_ASSERT_DELTA(outL[586], 0.045647f, 0.0001f);
+ TS_ASSERT_DELTA(outL[1023], -0.038334f, 0.0001f);
}
void testSpectrum(void)
diff --git a/src/Tests/RandTest.h b/src/Tests/RandTest.h
@@ -20,7 +20,7 @@
*/
-#include "../globals.h"
+#include "../Misc/Util.h"
#include <cstdlib>
#include <cstdio>
@@ -31,11 +31,11 @@ class RandTest:public CxxTest::TestSuite
public:
void testPRNG(void) {
//verify RND returns expected pattern when unseeded
- TS_ASSERT_DELTA(RND, 0.840188f, 0.00001f);
- TS_ASSERT_DELTA(RND, 0.394383f, 0.00001f);
- TS_ASSERT_DELTA(RND, 0.783099f, 0.00001f);
- TS_ASSERT_DELTA(RND, 0.798440f, 0.00001f);
- TS_ASSERT_DELTA(RND, 0.911647f, 0.00001f);
+ TS_ASSERT_DELTA(RND, 0.607781, 0.00001);
+ TS_ASSERT_DELTA(RND, 0.591761, 0.00001);
+ TS_ASSERT_DELTA(RND, 0.186133, 0.00001);
+ TS_ASSERT_DELTA(RND, 0.286319, 0.00001);
+ TS_ASSERT_DELTA(RND, 0.511766, 0.00001);
}
};
diff --git a/src/Tests/SubNoteTest.h b/src/Tests/SubNoteTest.h
@@ -111,19 +111,19 @@ class SubNoteTest:public CxxTest::TestSuite
note->noteout(outL, outR);
sampleCount += SOUND_BUFFER_SIZE;
- TS_ASSERT_DELTA(outL[255], 0.0022f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], 0.0016f, 0.0001f);
note->noteout(outL, outR);
sampleCount += SOUND_BUFFER_SIZE;
- TS_ASSERT_DELTA(outL[255], -0.0020f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], -0.0000f, 0.0001f);
note->noteout(outL, outR);
sampleCount += SOUND_BUFFER_SIZE;
- TS_ASSERT_DELTA(outL[255], 0.0010f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], -0.0013f, 0.0001f);
note->noteout(outL, outR);
sampleCount += SOUND_BUFFER_SIZE;
- TS_ASSERT_DELTA(outL[255], 0.0005f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], -0.0002f, 0.0001f);
while(!note->finished()) {
note->noteout(outL, outR);
diff --git a/src/globals.h b/src/globals.h
@@ -24,6 +24,7 @@
#ifndef GLOBALS_H
#define GLOBALS_H
+#include <stdint.h>
/**Sampling rate*/
extern int SAMPLE_RATE;
@@ -171,11 +172,6 @@ extern int OSCIL_SIZE;
#define dB2rap(dB) ((expf((dB) * LOG_10 / 20.0f)))
#define rap2dB(rap) ((20 * logf(rap) / LOG_10))
-/*
- * The random generator (0.0f..1.0f)
- */
-#define RND (rand() / (RAND_MAX * 1.0f))
-
#define ZERO(data, size) {char *data_ = (char *) data; for(int i = 0; \
i < size; \
i++) \
diff --git a/src/main.cpp b/src/main.cpp
@@ -194,7 +194,7 @@ int main(int argc, char *argv[])
OSCIL_SIZE = config.cfg.OscilSize;
swaplr = config.cfg.SwapStereo;
- srand(time(NULL));
+ sprng(time(NULL));
//produce denormal buf
denormalkillbuf = new float [SOUND_BUFFER_SIZE];
for(int i = 0; i < SOUND_BUFFER_SIZE; ++i)