diff --git a/TODO b/TODO index 18dbb3f..cac07a6 100644 --- a/TODO +++ b/TODO @@ -4,7 +4,6 @@ code: * audio rate optional pulse width/slope inputs? * one pole process const input? (return also if const out) * optimize triangle generation for constant pulse width -* naming type suffixes math.h vs random.h * API for buffer fill, scale, offset, zero, copy...? * web examples construction/destruction * web effect multichannel in? diff --git a/examples/synth/src/bw_example_synth.c b/examples/synth/src/bw_example_synth.c index 224ed91..ceb7987 100644 --- a/examples/synth/src/bw_example_synth.c +++ b/examples/synth/src/bw_example_synth.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include #include @@ -60,6 +61,7 @@ struct _bw_example_synth { // Sub-components bw_phase_gen_coeffs phase_gen_coeffs; bw_phase_gen_state phase_gen_state; + bw_noise_gen_coeffs noise_gen_coeffs; bw_phase_gen_coeffs a440_phase_gen_coeffs; bw_phase_gen_state a440_phase_gen_state; bw_vol_coeffs vol_coeffs; @@ -76,6 +78,7 @@ struct _bw_example_synth { float params[p_n]; // States + uint64_t rand_state; int note; float level; @@ -89,10 +92,14 @@ bw_example_synth bw_example_synth_new() { return NULL; bw_phase_gen_init(&instance->phase_gen_coeffs); + bw_noise_gen_init(&instance->noise_gen_coeffs, &instance->rand_state); bw_phase_gen_init(&instance->a440_phase_gen_coeffs); bw_vol_init(&instance->vol_coeffs); bw_phase_gen_set_frequency(&instance->a440_phase_gen_coeffs, 440.f); + bw_noise_gen_set_sample_rate_scaling(&instance->noise_gen_coeffs, 1); + + instance->rand_state = 0xbaddecaf600dfeed; /* bw_osc_pulse_init(&instance->osc_pulse); bw_osc_filt_init(&instance->osc_filt); @@ -114,6 +121,7 @@ void bw_example_synth_free(bw_example_synth instance) { void bw_example_synth_set_sample_rate(bw_example_synth instance, float sample_rate) { bw_phase_gen_set_sample_rate(&instance->phase_gen_coeffs, sample_rate); + bw_noise_gen_set_sample_rate(&instance->noise_gen_coeffs, sample_rate); bw_phase_gen_set_sample_rate(&instance->a440_phase_gen_coeffs, sample_rate); bw_vol_set_sample_rate(&instance->vol_coeffs, sample_rate); /* @@ -155,6 +163,10 @@ void bw_example_synth_process(bw_example_synth instance, const float** x, float* //bw_phase_gen_process(&instance->phase_gen_coeffs, &instance->phase_gen_state, NULL, y[0], instance->buf, n_samples); for (int i = 0; i < n_samples; i++) y[0][i] = 0.f; + + if (instance->note != -1) + bw_noise_gen_process(&instance->noise_gen_coeffs, y[0], n_samples); + /* for (int i = 0; i < n_samples; i += BUFFER_SIZE) { float *out = y[0] + i; diff --git a/include/bw_noise_gen.h b/include/bw_noise_gen.h index 3f6a86b..2a7ccef 100644 --- a/include/bw_noise_gen.h +++ b/include/bw_noise_gen.h @@ -28,7 +28,7 @@ *
    *
  • Version 0.2.0: *
      - *
    • Refactored API to avoid dynamic memory allocation.
    • + *
    • Refactored API.
    • *
    *
  • *
  • Version 0.1.0: @@ -50,40 +50,33 @@ extern "C" { #endif /*! api {{{ - * #### bw_noise_gen + * #### bw_noise_gen_coeffs * ```>>> */ -typedef struct _bw_noise_gen bw_noise_gen; +typedef struct _bw_noise_gen_coeffs bw_noise_gen_coeffs; /*! <<<``` - * Instance object. - * >>> */ - -/*! ... + * Coefficients. + * * #### bw_noise_gen_init() * ```>>> */ -void bw_noise_gen_init(bw_noise_gen *instance, uint64_t *state); +static inline void bw_noise_gen_init(bw_noise_gen_coeffs *BW_RESTRICT coeffs, uint64_t *BW_RESTRICT state); /*! <<<``` - * Initializes the `instance` object and lets it use the given `state` - * pointer to obtain pseudo-random numbers. - * >>> */ - -/*! ... + * Initializes `coeffs` and lets it use the given `state` pointer to obtain + * pseudo-random numbers. + * * #### bw_noise_gen_set_sample_rate() * ```>>> */ -void bw_noise_gen_set_sample_rate(bw_noise_gen *instance, float sample_rate); +static inline void bw_noise_gen_set_sample_rate(bw_noise_gen_coeffs *BW_RESTRICT coeffs, float sample_rate); /*! <<<``` - * Sets the `sample_rate` value for the given `instance`. + * Sets the `sample_rate` (Hz) value for the given `coeffs`. * >>> */ -/*! ... - * #### bw_noise_gen_reset() - * - * There is none (not needed). - * >>> */ +static inline float bw_noise_gen_process1(const bw_noise_gen_coeffs *BW_RESTRICT coeffs); +static inline float bw_noise_gen_process1_scaling(const bw_noise_gen_coeffs *BW_RESTRICT coeffs); /*! ... * #### bw_noise_gen_process() * ```>>> */ -void bw_noise_gen_process(bw_noise_gen *instance, float* y, int n_samples); +static inline void bw_noise_gen_process(bw_noise_gen_coeffs *BW_RESTRICT coeffs, float *BW_RESTRICT y, int n_samples); /*! <<<``` * Lets the given `instance` generate `n_samples` samples and puts them in * the output buffer `y`. @@ -92,7 +85,7 @@ void bw_noise_gen_process(bw_noise_gen *instance, float* y, int n_samples); /*! ... * #### bw_noise_gen_set_sample_rate_scaling() * ```>>> */ -void bw_noise_gen_set_sample_rate_scaling(bw_noise_gen *instance, char value); +static inline void bw_noise_gen_set_sample_rate_scaling(bw_noise_gen_coeffs *BW_RESTRICT coeffs, char value); /*! <<<``` * Sets whether the output should be scaled (`value` non-`0`) or not (`0`) * according to the sample rate by the given `instance`. @@ -105,20 +98,53 @@ void bw_noise_gen_set_sample_rate_scaling(bw_noise_gen *instance, char value); * Default value: `0`. * }}} */ -/* WARNING: the internal definition of this struct is not part of the public - * API. Its content may change at any time in future versions. Please, do not - * access its members directly. */ -struct _bw_noise_gen { +/*** Implementation ***/ + +/* WARNING: This part of the file is not part of the public API. Its content may + * change at any time in future versions. Please, do not use it directly. */ + +#include +#include + +struct _bw_noise_gen_coeffs { // Coefficients float scaling_k; // Parameters - char sample_rate_scaling; - - // State uint64_t *state; + char sample_rate_scaling; }; +static inline void bw_noise_gen_init(bw_noise_gen_coeffs *BW_RESTRICT coeffs, uint64_t *BW_RESTRICT state) { + coeffs->state = state; + coeffs->sample_rate_scaling = 0; +} + +static inline void bw_noise_gen_set_sample_rate(bw_noise_gen_coeffs *BW_RESTRICT coeffs, float sample_rate) { + coeffs->scaling_k = 0.004761904761904762f * bw_sqrtf_2(sample_rate); +} + +static inline float bw_noise_gen_process1(const bw_noise_gen_coeffs *BW_RESTRICT coeffs) { + return bw_randf(coeffs->state); +} + +static inline float bw_noise_gen_process1_scaling(const bw_noise_gen_coeffs *BW_RESTRICT coeffs) { + return coeffs->scaling_k * bw_randf(coeffs->state); +} + +static inline void bw_noise_gen_process(bw_noise_gen_coeffs *BW_RESTRICT coeffs, float *BW_RESTRICT y, int n_samples) { + if (coeffs->sample_rate_scaling) + for (int i = 0; i < n_samples; i++) + y[i] = bw_noise_gen_process1(coeffs); + else + for (int i = 0; i < n_samples; i++) + y[i] = bw_noise_gen_process1_scaling(coeffs); +} + +static inline void bw_noise_gen_set_sample_rate_scaling(bw_noise_gen_coeffs *BW_RESTRICT coeffs, char value) { + coeffs->sample_rate_scaling = value; +} + #ifdef __cplusplus } #endif diff --git a/include/bw_rand.h b/include/bw_rand.h index b8452da..da73c43 100644 --- a/include/bw_rand.h +++ b/include/bw_rand.h @@ -33,6 +33,11 @@ * }}} * changelog {{{ *
      + *
    • Version 0.2.0: + *
        + *
      • Refactored API.
      • + *
      + *
    • *
    • Version 0.1.0: *
        *
      • First release.
      • @@ -52,9 +57,9 @@ extern "C" { #endif /*! api {{{ - * #### bw_rand_u32() + * #### bw_randu32() * ```>>> */ -uint32_t bw_rand_u32(uint64_t *state); +static inline uint32_t bw_randu32(uint64_t *BW_RESTRICT state); /*! <<<``` * Returns a pseudo-random unsigned 32-bit integer in the range * [`0`, `UINT32_MAX`]. @@ -64,9 +69,9 @@ uint32_t bw_rand_u32(uint64_t *state); * >>> */ /*! ... - * #### bw_rand_f() + * #### bw_randf() * ```>>> */ -float bw_rand_f(uint64_t *state); +static inline float bw_randf(uint64_t *BW_RESTRICT state); /*! <<<``` * Returns a pseudo-random unsigned 32-bit floating point number in the range * [`-1.f`, `1.f`]. @@ -75,6 +80,22 @@ float bw_rand_f(uint64_t *state); * between calls, and which gets updated by calls to this function. * }}} */ +/*** Implementation ***/ + +/* WARNING: This part of the file is not part of the public API. Its content may + * change at any time in future versions. Please, do not use it directly. */ + +static inline uint32_t bw_randu32(uint64_t *BW_RESTRICT state) { + // Permuted Congruential Generator, + // taken from https://nullprogram.com/blog/2017/09/21/ + *state = *state * 0x9b60933458e17d7d + 0xd737232eeccdf7ed; + return *state >> (29 - (*state >> 61)); +} + +static inline float bw_randf(uint64_t *BW_RESTRICT state) { + return (2.f / (float)UINT32_MAX) * (float)bw_randu32(state) - 1.f; +} + #ifdef __cplusplus } #endif diff --git a/src/bw_noise_gen.c b/src/bw_noise_gen.c deleted file mode 100644 index 6b13237..0000000 --- a/src/bw_noise_gen.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Brickworks - * - * Copyright (C) 2022 Orastron Srl unipersonale - * - * Brickworks is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * Brickworks is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * - * File author: Stefano D'Angelo - */ - -#include - -#include -#include - -void bw_noise_gen_init(bw_noise_gen *instance, uint64_t *state) { - instance->state = state; - instance->sample_rate_scaling = 0; -} - -void bw_noise_gen_set_sample_rate(bw_noise_gen *instance, float sample_rate) { - instance->scaling_k = 0.004761904761904762f * bw_sqrtf_2(sample_rate); -} - -void bw_noise_gen_process(bw_noise_gen *instance, float* y, int n_samples) { - for (int i = 0; i < n_samples; i++) - y[i] = bw_rand_f(instance->state); - - if (instance->sample_rate_scaling) - for (int i = 0; i < n_samples; i++) - y[i] *= instance->scaling_k; -} - -void bw_noise_gen_set_sample_rate_scaling(bw_noise_gen *instance, char value) { - instance->sample_rate_scaling = value; -} diff --git a/src/bw_rand.c b/src/bw_rand.c deleted file mode 100644 index 0e31255..0000000 --- a/src/bw_rand.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Brickworks - * - * Copyright (C) 2022 Orastron Srl unipersonale - * - * Brickworks is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * Brickworks is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * - * File author: Stefano D'Angelo - */ - -#include - -uint32_t bw_rand_u32(uint64_t *state) { - // Permuted Congruential Generator, - // taken from https://nullprogram.com/blog/2017/09/21/ - *state = *state * 0x9b60933458e17d7d + 0xd737232eeccdf7ed; - return *state >> (29 - (*state >> 61)); -} - -float bw_rand_f(uint64_t *state) { - return (2.f / (float)UINT32_MAX) * (float)bw_random_u32(state) - 1.f; -}