diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fcbc9f..0738550 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,7 @@ -cmake_minimum_required (VERSION 3.0) +cmake_minimum_required (VERSION 3.0) + +# This is used for code completion in vim +set(CMAKE_EXPORT_COMPILE_COMMANDS=ON) project(LASP) # Whether we want to use blas yes or no diff --git a/lasp/c/lasp_siggen.c b/lasp/c/lasp_siggen.c index a2e8de1..b75114a 100644 --- a/lasp/c/lasp_siggen.c +++ b/lasp/c/lasp_siggen.c @@ -10,20 +10,19 @@ #include "lasp_assert.h" #include "lasp_mat.h" -#define PRIVATE_SIZE 32 +#define PRIVATE_SIZE 64 typedef enum { SINEWAVE = 0, WHITENOISE, - PINKNOISE, SWEEP, } SignalType; - typedef struct { SignalType signaltype; d fs; // Sampling frequency [Hz] + d level_amp; void* private; char private_data[PRIVATE_SIZE]; @@ -35,31 +34,58 @@ typedef struct { d omg; } SinewaveSpecific; +typedef struct { + d V1, V2, S; + int phase; +} WhitenoiseSpecific; + +static d level_amp(d level_dB){ + return pow(10, level_dB/20); +} + +Siggen* Siggen_create(SignalType type, const d fs,const d level_dB) { -Siggen* Siggen_Sinewave_create(const d fs, const d freq) { fsTRACE(15); - Siggen* sinesiggen = a_malloc(sizeof(Siggen)); - sinesiggen->signaltype = SINEWAVE; - sinesiggen->fs = fs; + Siggen* siggen = a_malloc(sizeof(Siggen)); + siggen->signaltype = type; + siggen->fs = fs; + siggen->private = NULL; + siggen->level_amp = level_amp(level_dB); + + feTRACE(15); + return siggen; +} + +Siggen* Siggen_Sinewave_create(const d fs, const d freq,const d level_dB) { + fsTRACE(15); + + Siggen* sinesiggen = Siggen_create(SINEWAVE, fs, level_dB); sinesiggen->private = sinesiggen->private_data; SinewaveSpecific* sp = (SinewaveSpecific*) sinesiggen->private; sp->curtime = 0; sp->omg = 2*number_pi*freq; - feTRACE(15); return sinesiggen; } -Siggen* Siggen_Whitenoise_create() { + +Siggen* Siggen_Whitenoise_create(const d fs, const d level_dB) { fsTRACE(15); - Siggen* whitenoise = a_malloc(sizeof(Siggen)); - whitenoise->signaltype = WHITENOISE; - + Siggen* whitenoise = Siggen_create(WHITENOISE, fs, level_dB); + whitenoise->private = whitenoise->private_data; + dbgassert(sizeof(WhitenoiseSpecific) <= sizeof(whitenoise->private_data), "Allocated memory too small"); + WhitenoiseSpecific* wn = whitenoise->private; + wn->phase = 0; + wn->V1 = 0; + wn->V2 = 0; + wn->S = 0; + feTRACE(15); return whitenoise; } + void Siggen_free(Siggen* siggen) { fsTRACE(15); assertvalidptr(siggen); @@ -67,10 +93,11 @@ void Siggen_free(Siggen* siggen) { if(siggen->signaltype == SWEEP) { /* Sweep specific stuff here */ } - + a_free(siggen); feTRACE(15); } + static void Sinewave_genSignal(Siggen* siggen, SinewaveSpecific* sine, vd* samples) { fsTRACE(15); assertvalidptr(sine); @@ -79,44 +106,51 @@ static void Sinewave_genSignal(Siggen* siggen, SinewaveSpecific* sine, vd* sampl d curtime = sine->curtime; for(us i =0; i< samples->n_rows; i++) { - setvecval(samples, i, sin(omg*curtime)); + setvecval(samples, i, siggen->level_amp*sin(omg*curtime)); curtime = curtime + ts; } sine->curtime = curtime; feTRACE(15); } -static d gaussrand() { - static d V1, V2, S; - static int phase = 0; - d X; +static void Whitenoise_genSignal(Siggen* siggen, WhitenoiseSpecific* wn, vd* samples) { + fsTRACE(15); + d X; + d S = wn->S; + d V1 = wn->V1; + d V2 = wn->V2; + int phase = wn->phase; - if(phase == 0) { - do { - d U1 = (d)rand() / RAND_MAX; - d U2 = (d)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; - - return X; -} -static void Whitenoise_genSignal(Siggen* siggen, vd* samples) { for(us i =0; i< samples->n_rows; i++) { - d rn = gaussrand(); - setvecval(samples, i, rn); + + if(wn->phase == 0) { + do { + d U1 = (d)rand() / RAND_MAX; + d U2 = (d)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; + + setvecval(samples, i, siggen->level_amp*X); } + wn->S = S; + wn->V1 = V1; + wn->V2 = V2; + wn->phase = phase; + feTRACE(15); } + void Siggen_genSignal(Siggen* siggen,vd* samples) { + fsTRACE(15); assertvalidptr(siggen); assert_vx(samples); @@ -129,10 +163,16 @@ void Siggen_genSignal(Siggen* siggen,vd* samples) { break; case WHITENOISE: - Whitenoise_genSignal(siggen, samples); + Whitenoise_genSignal(siggen, (WhitenoiseSpecific*) siggen->private, + samples); + break; + case SWEEP: + break; + default: + dbgassert(false, "Not implementend signal type"); } - + feTRACE(15); } diff --git a/lasp/c/lasp_siggen.h b/lasp/c/lasp_siggen.h index ab210a8..757f7b7 100644 --- a/lasp/c/lasp_siggen.h +++ b/lasp/c/lasp_siggen.h @@ -17,16 +17,17 @@ typedef struct {} Siggen; * Create a sine wave signal generator * * @param[in] fs: Sampling frequency [Hz] + * @param[in] level: Relative level in [dB], should be between -inf and 0 * @param[freq] Sine wave frequency [Hz] */ -Siggen* Siggen_Sinewave_create(const d fs,const d freq); +Siggen* Siggen_Sinewave_create(const d fs,const d freq,const d level_dB); /** * Create a white noise signal generator * * @return Siggen* handle */ -Siggen* Siggen_Whitenoise_create(); +Siggen* Siggen_Whitenoise_create(const d fs, const d level_dB); /** * Create a pink (1/f) noise signal generator @@ -34,7 +35,7 @@ Siggen* Siggen_Whitenoise_create(); * @param[in] fs: Sampling frequency [Hz] * @return Siggen* handle */ -Siggen* Siggen_Pinknoise_create(const us fs); +Siggen* Siggen_Pinknoise_create(const us fs,const d level_dB); /* Siggen* Siggen_ForwardSweep_create(const d fs,; */ /* Siggen* Siggen_(const d fs,; */ diff --git a/lasp/wrappers.pyx b/lasp/wrappers.pyx index 0e2bd42..6e18f05 100644 --- a/lasp/wrappers.pyx +++ b/lasp/wrappers.pyx @@ -471,8 +471,8 @@ cdef class SPLowpass: cdef extern from "lasp_siggen.h": ctypedef struct c_Siggen "Siggen" - c_Siggen* Siggen_Whitenoise_create() - c_Siggen* Siggen_Sinewave_create(d fs, d freq) + c_Siggen* Siggen_Whitenoise_create(d fs, d level_dB) + c_Siggen* Siggen_Sinewave_create(d fs, d freq, d level_dB) void Siggen_genSignal(c_Siggen*, vd* samples) nogil void Siggen_free(c_Siggen*) @@ -505,16 +505,16 @@ cdef class Siggen: @staticmethod - def sineWave(fs, freq): - cdef c_Siggen* c_siggen = Siggen_Sinewave_create(fs, freq) + def sineWave(d fs,d freq,d level_dB): + cdef c_Siggen* c_siggen = Siggen_Sinewave_create(fs, freq, level_dB) siggen = Siggen() siggen._siggen = c_siggen return siggen @staticmethod - def whiteNoise(): - cdef c_Siggen* c_siggen = Siggen_Whitenoise_create() + def whiteNoise(d fs, d level_dB): + cdef c_Siggen* c_siggen = Siggen_Whitenoise_create(fs, level_dB) siggen = Siggen() siggen._siggen = c_siggen return siggen