done bw_{buf,common,math,note_queue,rand,voice_alloc} + related changes
This commit is contained in:
parent
41f56ec91c
commit
55a78a5ab4
3
TODO
3
TODO
@ -33,7 +33,7 @@ code:
|
||||
* update state ctrl -> process ctrl?
|
||||
* mem req -> return value of set sample rate?
|
||||
* peak gain + Q ???
|
||||
* bwpp -> bwxx
|
||||
* merge c++ code into c headers
|
||||
* sr_reduce reset_coeffs? update_coeffs? process_multi?
|
||||
* fix definitions leading to X ** -> const X ** error https://isocpp.org/wiki/faq/const-correctness#constptrptr-conversion, fix fx_balance, fx_pan, synth_poly
|
||||
* drywet -> dry_wet, ringmod -> ring_mod, etc?
|
||||
@ -43,7 +43,6 @@ code:
|
||||
* c++ get coeffs/state? or public? src nIn/OutSamples case (array vs single value), delay read/write, process1? process single?
|
||||
* bw_buf invert src dest order?
|
||||
* check unititialized warnings
|
||||
* voice alloc mode -> voice alloc priority
|
||||
* clearly specify that state is tied to a particular set of coeffs (1:N)
|
||||
* modulation vs process (multi) no update (post 1.0.0)???
|
||||
* check assumptions w.r.t. usage of math functions
|
||||
|
@ -149,12 +149,12 @@ static void note_off(void *BW_RESTRICT voice, float velocity) {
|
||||
v->gate = 0;
|
||||
}
|
||||
|
||||
static unsigned char get_note(void *BW_RESTRICT voice) {
|
||||
static unsigned char get_note(const void *BW_RESTRICT voice) {
|
||||
bw_example_synth_poly_voice *v = (bw_example_synth_poly_voice *)voice;
|
||||
return v->note;
|
||||
}
|
||||
|
||||
static char is_free(void *BW_RESTRICT voice) {
|
||||
static char is_free(const void *BW_RESTRICT voice) {
|
||||
bw_example_synth_poly_voice *v = (bw_example_synth_poly_voice *)voice;
|
||||
bw_env_gen_phase phase = bw_env_gen_get_phase(&v->vca_env_gen_state);
|
||||
return !v->gate && phase == bw_env_gen_phase_off;
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "bw_example_synthpp_poly.h"
|
||||
|
||||
#include <bw_math.h>
|
||||
#include <bwpp_buf.h>
|
||||
#include <bw_buf.h>
|
||||
#include <bw_voice_alloc.h>
|
||||
|
||||
void bw_example_synthpp_poly_init(bw_example_synthpp_poly *instance) {
|
||||
@ -121,12 +121,12 @@ static void note_off(void *BW_RESTRICT voice, float velocity) {
|
||||
v->gate = 0;
|
||||
}
|
||||
|
||||
static unsigned char get_note(void *BW_RESTRICT voice) {
|
||||
static unsigned char get_note(const void *BW_RESTRICT voice) {
|
||||
bw_example_synthpp_poly_voice *v = (bw_example_synthpp_poly_voice *)voice;
|
||||
return v->note;
|
||||
}
|
||||
|
||||
static char is_free(void *BW_RESTRICT voice) {
|
||||
static char is_free(const void *BW_RESTRICT voice) {
|
||||
bw_example_synthpp_poly_voice *v = (bw_example_synthpp_poly_voice *)voice;
|
||||
bw_env_gen_phase phase = v->instance->vcaEnvGen.getPhase(v->index);
|
||||
return !v->gate && phase == bw_env_gen_phase_off;
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include <bwpp_note_queue.h>
|
||||
#include <bw_note_queue.h>
|
||||
#include <bwpp_phase_gen.h>
|
||||
#include <bwpp_osc_saw.h>
|
||||
#include <bwpp_osc_pulse.h>
|
||||
|
136
include/bw_buf.h
136
include/bw_buf.h
@ -31,6 +31,8 @@
|
||||
* <ul>
|
||||
* <li>Now using <code>size_t</code> instead of
|
||||
* <code>BW_SIZE_T</code>.</li>
|
||||
* <li>Moved C++ code to C header.</li>
|
||||
* <li>Removed usage of reserved identifiers.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Version <strong>0.6.0</strong>:
|
||||
@ -61,8 +63,8 @@
|
||||
* }}}
|
||||
*/
|
||||
|
||||
#ifndef _BW_BUF_H
|
||||
#define _BW_BUF_H
|
||||
#ifndef BW_BUF_H
|
||||
#define BW_BUF_H
|
||||
|
||||
#include <bw_common.h>
|
||||
|
||||
@ -160,11 +162,85 @@ static inline void bw_buf_mul_multi(float **dest, const float **src1, const floa
|
||||
* `n_channels` buffers `dest`.
|
||||
* }}} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace Brickworks {
|
||||
|
||||
/*! api_cpp {{{
|
||||
* ##### Brickworks::bufFill
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufFill(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
float k,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
*
|
||||
* ##### Brickworks::bufNeg
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufNeg(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
*
|
||||
* ##### Brickworks::bufAdd
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufAdd(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
float k,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
*
|
||||
* ##### Brickworks::bufScale
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufScale(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
float k,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
*
|
||||
* ##### Brickworks::bufMix
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufMix(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src1,
|
||||
std::array<const float *, N_CHANNELS> src2,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
*
|
||||
* ##### Brickworks::bufMul
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufMul(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src1,
|
||||
std::array<const float *, N_CHANNELS> src2,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
* }}} */
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** 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. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void bw_buf_fill(float *dest, float k, size_t n_elems) {
|
||||
BW_ASSERT(!(dest == NULL && n_elems != 0));
|
||||
BW_ASSERT(!bw_is_nan(k));
|
||||
@ -272,6 +348,62 @@ static inline void bw_buf_mul_multi(float **dest, const float **src1, const floa
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
namespace Brickworks {
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufFill(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
float k,
|
||||
int nSamples) {
|
||||
bw_buf_fill_multi(dest.data(), k, N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufNeg(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
int nSamples) {
|
||||
bw_buf_neg_multi(dest.data(), src.data(), N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufAdd(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
float k,
|
||||
int nSamples) {
|
||||
bw_buf_add_multi(dest.data(), src.data(), k, N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufScale(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
float k,
|
||||
int nSamples) {
|
||||
bw_buf_scale_multi(dest.data(), src.data(), k, N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufMix(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src1,
|
||||
std::array<const float *, N_CHANNELS> src2,
|
||||
int nSamples) {
|
||||
bw_buf_mix_multi(dest.data(), src1.data(), src2.data(), N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufMul(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src1,
|
||||
std::array<const float *, N_CHANNELS> src2,
|
||||
int nSamples) {
|
||||
bw_buf_mul_multi(dest.data(), src1.data(), src2.data(), N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -38,7 +38,8 @@
|
||||
* <li>Introduced <code>BW_NO_DEBUG</code> to replace
|
||||
* <code>NDEBUG</code> and prevented useless inclusion of
|
||||
* <code>assert.h</code>.</li>
|
||||
* <li>Avoided using reserved identifiers.</li>
|
||||
* <li>Removed usage of reserved identifiers.</li>
|
||||
* <li>Added <code>extern "C"</code> to functions.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Version <strong>0.6.0</strong>:
|
||||
@ -194,6 +195,11 @@
|
||||
# define BW_ASSERT_DEEP(ignore) ((void)0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! ...
|
||||
*
|
||||
* #### bw_is_inf()
|
||||
@ -244,11 +250,19 @@ static inline uint32_t bw_hash_sdbm(const char *string);
|
||||
* Returns the sdbm hash of the given `string`.
|
||||
* }}} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** 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. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline char bw_is_inf(float x) {
|
||||
union { uint32_t u; float f; } v;
|
||||
v.f = x;
|
||||
@ -295,4 +309,8 @@ static inline uint32_t bw_hash_sdbm(const char *string) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -62,6 +62,7 @@
|
||||
* <code>bw_acoshf()</code>.</li>
|
||||
* <li>Removed usage of reserved identifiers and designated
|
||||
* initializers.</li>
|
||||
* <li>Added <code>extern "C"</code> to functions.</li>
|
||||
* <li>Improved documentation w.r.t. validity of input values and
|
||||
* approximation errors.</li>
|
||||
* </ul>
|
||||
@ -110,12 +111,12 @@
|
||||
#ifndef BW_MATH_H
|
||||
#define BW_MATH_H
|
||||
|
||||
#include <bw_common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <bw_common.h>
|
||||
|
||||
/*! api {{{
|
||||
* #### bw_signfilli32()
|
||||
* ```>>> */
|
||||
@ -482,11 +483,19 @@ static inline float bw_acoshf(float x);
|
||||
* Absolute error < 0.004 or relative error < 0.8%, whatever is worse.
|
||||
* }}} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** 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. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// I hope the target architecture and compiler will use conditional ops here
|
||||
|
||||
static inline int32_t bw_signfilli32(int32_t x) {
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
/*!
|
||||
* module_type {{{ utility }}}
|
||||
* version {{{ 0.6.0 }}}
|
||||
* version {{{ 1.0.0 }}}
|
||||
* requires {{{ bw_common }}}
|
||||
* description {{{
|
||||
* Simple data structure that helps keeping track of note on/off events and
|
||||
@ -30,6 +30,19 @@
|
||||
* }}}
|
||||
* changelog {{{
|
||||
* <ul>
|
||||
* <li>Version <strong>1.0.0</strong>:
|
||||
* <ul>
|
||||
* <li>Removed redundant <code>status</code> member from
|
||||
* <code>bw_note_queue_event</code>.</li>
|
||||
* <li>Possibly improved memeory layout of
|
||||
* <code>bw_note_queue</code>.</li>
|
||||
* <li>Moved C++ code to C header.</li>
|
||||
* <li>Removed usage of reserved identifiers and designated
|
||||
* initializers.</li>
|
||||
* <li>Clarified ambiguity in the documentation of
|
||||
* <code>bw_note_queue_status</code>.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Version <strong>0.6.0</strong>:
|
||||
* <ul>
|
||||
* <li>Added debugging code.</li>
|
||||
@ -45,38 +58,37 @@
|
||||
* }}}
|
||||
*/
|
||||
|
||||
#ifndef _BW_NOTE_QUEUE_H
|
||||
#define _BW_NOTE_QUEUE_H
|
||||
#ifndef BW_NOTE_QUEUE_H
|
||||
#define BW_NOTE_QUEUE_H
|
||||
|
||||
#include <bw_common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <bw_common.h>
|
||||
|
||||
/*! api {{{
|
||||
* #### bw_note_queue_status
|
||||
* ```>>> */
|
||||
typedef struct {
|
||||
char pressed;
|
||||
float velocity; // negative = unknown / not available
|
||||
float velocity;
|
||||
} bw_note_queue_status;
|
||||
/*! <<<```
|
||||
* Note status:
|
||||
* * `pressed`: whether the note is pressed (non-`0`) or not (`0`);
|
||||
* * `velocity`: velocity in [`0.f`, `1.f`].
|
||||
* * `velocity`: velocity in [`0.f`, `1.f`], otherwise negative to indicate
|
||||
* unknown / not available.
|
||||
*
|
||||
* #### bw_note_queue_event
|
||||
* ```>>> */
|
||||
typedef struct {
|
||||
unsigned char note;
|
||||
bw_note_queue_status status;
|
||||
char went_off;
|
||||
} bw_note_queue_event;
|
||||
/*! <<<```
|
||||
* Note on/off event:
|
||||
* * `note`: note number in [`0`, `127`];
|
||||
* * `status`: note status;
|
||||
* * `went_off`: whether a note off event fired on the same note (non-`0`)
|
||||
* or not (`0`) -- see `bw_note_queue`.
|
||||
*
|
||||
@ -84,8 +96,8 @@ typedef struct {
|
||||
* ```>>> */
|
||||
typedef struct {
|
||||
bw_note_queue_event events[128];
|
||||
unsigned char n_events;
|
||||
bw_note_queue_status status[128];
|
||||
unsigned char n_events;
|
||||
unsigned char n_pressed;
|
||||
} bw_note_queue;
|
||||
/*! <<<```
|
||||
@ -95,8 +107,8 @@ typedef struct {
|
||||
* event added for a given note overwrites the previous if it exists;
|
||||
* `went_off` is set to non-`0` in case of a note off event or when
|
||||
* overwriting an event whose `went_off` was already non-`0`;
|
||||
* * `n_events`: number of elements in `events`;
|
||||
* * `status`: current status of all notes;
|
||||
* * `n_events`: number of elements in `events`;
|
||||
* * `n_pressed`: number of currently pressed keys.
|
||||
*
|
||||
* #### bw_note_queue_reset()
|
||||
@ -135,17 +147,46 @@ static inline char bw_note_queue_is_valid(const bw_note_queue *BW_RESTRICT queue
|
||||
* than or equal to that of `bw_note_queue`.
|
||||
* }}} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
namespace Brickworks {
|
||||
|
||||
/*! api_cpp {{{
|
||||
* ##### Brickworks::NoteQueue
|
||||
* ```>>> */
|
||||
class NoteQueue {
|
||||
public:
|
||||
NoteQueue();
|
||||
|
||||
void clear();
|
||||
void add(unsigned char note, bool pressed, float velocity, bool force_went_off);
|
||||
|
||||
bw_note_queue queue;
|
||||
};
|
||||
/*! <<<```
|
||||
* }}} */
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** 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. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void bw_note_queue_reset(bw_note_queue *BW_RESTRICT queue) {
|
||||
BW_ASSERT(queue != NULL);
|
||||
for (int i = 0; i < 128; i++)
|
||||
queue->status[i] = (bw_note_queue_status){ .pressed = 0, .velocity = 0.f };
|
||||
queue->n_pressed = 0;
|
||||
for (int i = 0; i < 128; i++) {
|
||||
queue->status[i].pressed = 0;
|
||||
queue->status[i].velocity = 0.f;
|
||||
}
|
||||
queue->n_events = 0;
|
||||
queue->n_pressed = 0;
|
||||
BW_ASSERT_DEEP(bw_note_queue_is_valid(queue));
|
||||
}
|
||||
|
||||
@ -172,14 +213,16 @@ static inline void bw_note_queue_add(bw_note_queue *BW_RESTRICT queue, unsigned
|
||||
if (i == queue->n_events)
|
||||
queue->n_events++;
|
||||
else
|
||||
went_off = queue->events[i].went_off || !queue->events[i].status.pressed;
|
||||
went_off = queue->events[i].went_off || !queue->status[note].pressed;
|
||||
|
||||
queue->events[i] = (bw_note_queue_event){ .note = note, .status = { pressed, velocity }, .went_off = went_off || force_went_off };
|
||||
queue->events[i].note = note;
|
||||
queue->events[i].went_off = went_off || force_went_off;
|
||||
if (pressed && !queue->status[note].pressed)
|
||||
queue->n_pressed++;
|
||||
else if (!pressed && queue->status[note].pressed)
|
||||
queue->n_pressed--;
|
||||
queue->status[note] = (bw_note_queue_status){ .pressed = pressed, .velocity = velocity };
|
||||
queue->status[note].pressed = pressed;
|
||||
queue->status[note].velocity = velocity;
|
||||
|
||||
BW_ASSERT_DEEP(bw_note_queue_is_valid(queue));
|
||||
}
|
||||
@ -190,19 +233,19 @@ static inline char bw_note_queue_is_valid(const bw_note_queue *BW_RESTRICT queue
|
||||
if (queue->n_events >= 128 || queue->n_pressed >= 128)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < (int)queue->n_events; i++) {
|
||||
for (unsigned char i = 0; i < queue->n_events; i++) {
|
||||
const bw_note_queue_event *ev = queue->events + i;
|
||||
if (ev->note >= 128 || !bw_is_finite(ev->status.velocity) || ev->status.velocity > 1.f)
|
||||
if (ev->note >= 128)
|
||||
return 0;
|
||||
for (int j = 0; j < i; j++) {
|
||||
for (unsigned char j = 0; j < i; j++) {
|
||||
const bw_note_queue_event *ev2 = queue->events + j;
|
||||
if (ev2->note == ev->note)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
for (int i = 0; i < 128; i++) {
|
||||
unsigned char cnt = 0;
|
||||
for (unsigned char i = 0; i < 128; i++) {
|
||||
const bw_note_queue_status *st = queue->status + i;
|
||||
if (st->pressed)
|
||||
cnt++;
|
||||
@ -214,6 +257,22 @@ static inline char bw_note_queue_is_valid(const bw_note_queue *BW_RESTRICT queue
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
namespace Brickworks {
|
||||
|
||||
inline NoteQueue::NoteQueue() {
|
||||
bw_note_queue_reset(&queue);
|
||||
}
|
||||
|
||||
inline void NoteQueue::clear() {
|
||||
bw_note_queue_clear(&queue);
|
||||
}
|
||||
|
||||
inline void NoteQueue::add(unsigned char note, bool pressed, float velocity, bool force_went_off) {
|
||||
bw_note_queue_add(&queue, note, pressed, velocity, force_went_off);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
/*!
|
||||
* module_type {{{ utility }}}
|
||||
* version {{{ 0.6.0 }}}
|
||||
* version {{{ 1.0.0 }}}
|
||||
* requires {{{ bw_common }}}
|
||||
* description {{{
|
||||
* Pseudo-random number generators.
|
||||
@ -34,6 +34,12 @@
|
||||
* }}}
|
||||
* changelog {{{
|
||||
* <ul>
|
||||
* <li>Version <strong>1.0.0</strong>:
|
||||
* <ul>
|
||||
* <li>Added one more assertion in <code>bw_randf()</code>.</li>
|
||||
* <li>Removed usage of reserved identifiers.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Version <strong>0.6.0</strong>:
|
||||
* <ul>
|
||||
* <li>Added debugging code.</li>
|
||||
@ -55,8 +61,8 @@
|
||||
* }}}
|
||||
*/
|
||||
|
||||
#ifndef _BW_RAND_H
|
||||
#define _BW_RAND_H
|
||||
#ifndef BW_RAND_H
|
||||
#define BW_RAND_H
|
||||
|
||||
#include <bw_common.h>
|
||||
|
||||
@ -86,8 +92,16 @@ static inline float bw_randf(uint64_t *BW_RESTRICT state);
|
||||
* between calls and which gets updated by this function.
|
||||
* }}} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** Implementation ***/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
|
||||
@ -101,7 +115,9 @@ static inline uint32_t bw_randu32(uint64_t *BW_RESTRICT state) {
|
||||
|
||||
static inline float bw_randf(uint64_t *BW_RESTRICT state) {
|
||||
BW_ASSERT(state != NULL);
|
||||
return (2.f / (float)UINT32_MAX) * (float)bw_randu32(state) - 1.f;
|
||||
const float y = (2.f / (float)UINT32_MAX) * (float)bw_randu32(state) - 1.f;
|
||||
BW_ASSERT(bw_is_finite(y));
|
||||
return y;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -31,6 +31,10 @@
|
||||
* <ul>
|
||||
* <li>Now using <code>size_t</code> instead of
|
||||
* <code>BW_SIZE_T</code>.</li>
|
||||
* <li>Added <code>const</code> where needed to callback types in
|
||||
* <code>bw_voice_alloc_opts</code> and to
|
||||
* <code>bw_voice_alloc()</code>.</li>
|
||||
* <li>Removed usage of reserved identifiers.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Version <strong>0.6.0</strong>:
|
||||
@ -50,8 +54,8 @@
|
||||
* }}}
|
||||
*/
|
||||
|
||||
#ifndef _BW_VOICE_ALLOC_H
|
||||
#define _BW_VOICE_ALLOC_H
|
||||
#ifndef BW_VOICE_ALLOC_H
|
||||
#define BW_VOICE_ALLOC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -79,8 +83,8 @@ typedef struct {
|
||||
|
||||
void (*note_on)(void *BW_RESTRICT voice, unsigned char note, float velocity);
|
||||
void (*note_off)(void *BW_RESTRICT voice, float velocity);
|
||||
unsigned char (*get_note)(void *BW_RESTRICT voice);
|
||||
char (*is_free)(void *BW_RESTRICT voice);
|
||||
unsigned char (*get_note)(const void *BW_RESTRICT voice);
|
||||
char (*is_free)(const void *BW_RESTRICT voice);
|
||||
} bw_voice_alloc_opts;
|
||||
/*! <<<```
|
||||
* Voice allocation options:
|
||||
@ -97,7 +101,7 @@ typedef struct {
|
||||
*
|
||||
* #### bw_voice_alloc()
|
||||
* ```>>> */
|
||||
void bw_voice_alloc(const bw_voice_alloc_opts *BW_RESTRICT opts, bw_note_queue *BW_RESTRICT queue, void **BW_RESTRICT voices, size_t n_voices);
|
||||
void bw_voice_alloc(const bw_voice_alloc_opts *BW_RESTRICT opts, bw_note_queue *BW_RESTRICT queue, void * const *BW_RESTRICT voices, size_t n_voices);
|
||||
/*! <<<```
|
||||
* It performs voice allocation according to `opts` and using the events in
|
||||
* `queue`.
|
||||
@ -111,7 +115,7 @@ void bw_voice_alloc(const bw_voice_alloc_opts *BW_RESTRICT opts, bw_note_queue *
|
||||
/* 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. */
|
||||
|
||||
void bw_voice_alloc(const bw_voice_alloc_opts *BW_RESTRICT opts, bw_note_queue *BW_RESTRICT queue, void **BW_RESTRICT voices, size_t n_voices) {
|
||||
void bw_voice_alloc(const bw_voice_alloc_opts *BW_RESTRICT opts, bw_note_queue *BW_RESTRICT queue, void * const *BW_RESTRICT voices, size_t n_voices) {
|
||||
BW_ASSERT(opts != NULL);
|
||||
BW_ASSERT(opts->priority == bw_voice_alloc_priority_low || opts->priority == bw_voice_alloc_priority_high);
|
||||
BW_ASSERT(n_voices == 0 || opts->note_on != NULL);
|
||||
@ -124,45 +128,43 @@ void bw_voice_alloc(const bw_voice_alloc_opts *BW_RESTRICT opts, bw_note_queue *
|
||||
|
||||
for (unsigned char i = 0; i < queue->n_events; i++) {
|
||||
bw_note_queue_event *ev = queue->events + i;
|
||||
bw_note_queue_status *st = queue->status + ev->note;
|
||||
|
||||
for (size_t j = 0; j < n_voices; j++)
|
||||
if (!opts->is_free(voices[j]) && opts->get_note(voices[j]) == ev->note) {
|
||||
if (!ev->status.pressed || ev->went_off)
|
||||
opts->note_off(voices[j], ev->status.velocity);
|
||||
if (ev->status.pressed)
|
||||
opts->note_on(voices[j], ev->note, ev->status.velocity);
|
||||
if (!st->pressed || ev->went_off)
|
||||
opts->note_off(voices[j], st->velocity);
|
||||
if (st->pressed)
|
||||
opts->note_on(voices[j], ev->note, st->velocity);
|
||||
goto next_event;
|
||||
}
|
||||
|
||||
if (ev->status.pressed) {
|
||||
if (st->pressed) {
|
||||
for (size_t j = 0; j < n_voices; j++)
|
||||
if (opts->is_free(voices[j])) {
|
||||
opts->note_on(voices[j], ev->note, ev->status.velocity);
|
||||
opts->note_on(voices[j], ev->note, st->velocity);
|
||||
goto next_event;
|
||||
}
|
||||
|
||||
size_t k = n_voices;
|
||||
int v = ev->note;
|
||||
unsigned char v = ev->note;
|
||||
for (size_t j = 0; j < n_voices; j++) {
|
||||
int n = opts->get_note(voices[j]);
|
||||
unsigned char n = opts->get_note(voices[j]);
|
||||
if (!queue->status[n].pressed && (k == n_voices || (opts->priority == bw_voice_alloc_priority_low ? n > v : n < v))) {
|
||||
v = n;
|
||||
k = j;
|
||||
}
|
||||
}
|
||||
if (k != n_voices) {
|
||||
opts->note_on(voices[k], ev->note, ev->status.velocity);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k == n_voices)
|
||||
for (size_t j = 0; j < n_voices; j++) {
|
||||
int n = opts->get_note(voices[j]);
|
||||
unsigned char n = opts->get_note(voices[j]);
|
||||
if (opts->priority == bw_voice_alloc_priority_low ? n > v : n < v) {
|
||||
v = n;
|
||||
k = j;
|
||||
}
|
||||
}
|
||||
if (k != n_voices)
|
||||
opts->note_on(voices[k], ev->note, ev->status.velocity);
|
||||
opts->note_on(voices[k], ev->note, st->velocity);
|
||||
}
|
||||
|
||||
next_event:;
|
||||
|
@ -1,148 +0,0 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can reosc_sinribute 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 osc_sinributed 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
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#ifndef BWPP_BUF_H
|
||||
#define BWPP_BUF_H
|
||||
|
||||
#include <bw_buf.h>
|
||||
#include <array>
|
||||
|
||||
namespace Brickworks {
|
||||
|
||||
/*! api {{{
|
||||
* ##### Brickworks::bufFill
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufFill(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
float k,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
*
|
||||
* ##### Brickworks::bufNeg
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufNeg(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
*
|
||||
* ##### Brickworks::bufAdd
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufAdd(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
float k,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
*
|
||||
* ##### Brickworks::bufScale
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufScale(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
float k,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
*
|
||||
* ##### Brickworks::bufMix
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufMix(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src1,
|
||||
std::array<const float *, N_CHANNELS> src2,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
*
|
||||
* ##### Brickworks::bufMul
|
||||
* ```>>> */
|
||||
template<size_t N_CHANNELS>
|
||||
void bufMul(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src1,
|
||||
std::array<const float *, N_CHANNELS> src2,
|
||||
int nSamples);
|
||||
/*! <<<```
|
||||
* }}} */
|
||||
|
||||
/*** 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. */
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufFill(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
float k,
|
||||
int nSamples) {
|
||||
bw_buf_fill_multi(dest.data(), k, N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufNeg(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
int nSamples) {
|
||||
bw_buf_neg_multi(dest.data(), src.data(), N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufAdd(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
float k,
|
||||
int nSamples) {
|
||||
bw_buf_add_multi(dest.data(), src.data(), k, N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufScale(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src,
|
||||
float k,
|
||||
int nSamples) {
|
||||
bw_buf_scale_multi(dest.data(), src.data(), k, N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufMix(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src1,
|
||||
std::array<const float *, N_CHANNELS> src2,
|
||||
int nSamples) {
|
||||
bw_buf_mix_multi(dest.data(), src1.data(), src2.data(), N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void bufMul(
|
||||
std::array<float *, N_CHANNELS> dest,
|
||||
std::array<const float *, N_CHANNELS> src1,
|
||||
std::array<const float *, N_CHANNELS> src2,
|
||||
int nSamples) {
|
||||
bw_buf_mul_multi(dest.data(), src1.data(), src2.data(), N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user