bw_note_queue and bw_voice_alloc progress

This commit is contained in:
Stefano D'Angelo 2023-06-05 18:41:14 +02:00
parent ee4fa3c9f2
commit 5c2030bf97
3 changed files with 73 additions and 32 deletions

1
TODO
View File

@ -46,6 +46,7 @@ code:
* remove union value = {.f = v};? (std c++ latest)
* make gain of distortions homogeneous?
* max_delay -> set sample rate? see reverb
* revise typedef style (see https://stackoverflow.com/questions/54752861/using-an-anonymous-struct-vs-a-named-struct-with-typedef)
build system:
* make makefiles handle paths with spaces etc

View File

@ -21,7 +21,7 @@
/*!
* module_type {{{ utility }}}
* version {{{ 0.5.0 }}}
* requires {{{ }}}
* requires {{{ bw_common bw_config }}}
* description {{{
* Note queue.
*
@ -45,62 +45,61 @@
extern "C" {
#endif
#include <bw_common.h>
/*! api {{{
* #### bw_note_queue_status
* ```>>> */
struct _bw_note_queue_status {
typedef struct {
char pressed;
float velocity;
};
typedef struct _bw_note_queue_status bw_note_queue_status;
float velocity; // negative = unknown / not available
} bw_note_queue_status;
/*! <<<```
* #### bw_note_queue_event
* ```>>> */
struct _bw_note_queue_event {
typedef struct {
unsigned char note;
bw_note_queue_status status;
char went_off;
};
typedef struct _bw_note_queue_event bw_note_queue_event;
} bw_note_queue_event;
/*! <<<```
* #### bw_note_queue
* ```>>> */
struct _bw_note_queue {
typedef struct {
bw_note_queue_event events[128];
unsigned char n_events;
bw_note_queue_status status[128];
unsigned char n_pressed;
};
typedef struct _bw_note_queue bw_note_queue;
} bw_note_queue;
/*! <<<```
* #### bw_note_queue_reset()
* ```>>> */
static inline void bw_note_queue_reset(bw_note_queue *queue);
static inline void bw_note_queue_reset(bw_note_queue *BW_RESTRICT queue);
/*! <<<```
* #### bw_note_queue_clear()
* ```>>> */
static inline void bw_note_queue_clear(bw_note_queue *queue);
static inline void bw_note_queue_clear(bw_note_queue *BW_RESTRICT queue);
/*! <<<```
* #### bw_note_queue_add()
* ```>>> */
static inline void bw_note_queue_add(bw_note_queue *queue, unsigned char note, char pressed, float velocity, char force_went_off);
static inline void bw_note_queue_add(bw_note_queue *BW_RESTRICT queue, unsigned char note, char pressed, float velocity, char force_went_off);
/*** 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 void bw_note_queue_reset(bw_note_queue *queue) {
static inline void bw_note_queue_reset(bw_note_queue *BW_RESTRICT queue) {
for (char i = 0; i < 128; i++)
queue->status[i] = { 0, 0.f };
queue->n_pressed = 0;
}
static inline void bw_note_queue_clear(bw_note_queue *queue) {
static inline void bw_note_queue_clear(bw_note_queue *BW_RESTRICT queue) {
queue->n_events = 0;
}
static inline void bw_note_queue_add(bw_note_queue *queue, unsigned char note, char pressed, float velocity, char force_went_off) {
static inline void bw_note_queue_add(bw_note_queue *BW_RESTRICT queue, unsigned char note, char pressed, float velocity, char force_went_off) {
if (!pressed && !queue->status[note].pressed)
return;

View File

@ -18,30 +18,71 @@
* File author: Stefano D'Angelo
*/
#ifndef _BW_VOICE_ALLOC_H
#define _BW_VOICE_ALLOC_H
#ifdef __cplusplus
extern "C" {
#endif
#include <bw_common.h>
#include <bw_note_queue.h>
#include <bw_voice.h>
typedef struct _bw_voice_alloc bw_voice_alloc;
typedef enum
bw_voice_alloc_mode_low,
bw_voice_alloc_mode_high
} bw_voice_alloc_mode;
void bw_voice_alloc_reset(bw_voice_alloc *voice_alloc);
typedef struct {
bw_voice_alloc_mode mode;
char unison;
void bw_voice_alloc_process(bw_voice_alloc *voice_alloc, bw_note_queue *queue);
void (*note_on)(const void *BW_RESTRICT voice, unsigned char note, float velocity);
void (*note_off)(const void *BW_RESTRICT voice, float velocity);
unsigned char (*get_note)(const void *BW_RESTRICT voice);
char (*is_free)(const void *BW_RESTRICT voice);
} bw_voice_alloc_opts;
void bw_voice_alloc_set_unison(bw_voice_alloc *voice_alloc, char value);
void bw_voice_alloc(const bw_voice_alloc_opts *BW_RESTRICT opts, bw_note_queue *BW_RESTRICT queue, const void **BW_RESTRICT voices, int n_voices);
struct _bw_voice_alloc {
bw_voice *voices;
int n_voices;
void bw_voice_alloc(const bw_voice_alloc_opts *BW_RESTRICT opts, bw_note_queue *BW_RESTRICT queue, const void **BW_RESTRICT voices, int n_voices) {
for (unsigned char i = 0; i < queue->n_events; i++) {
bw_note_queue_event *ev = queue->events + i;
for (int 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);
goto next_event;
}
char unison;
};
if (ev->status.pressed) {
for (j = 0; j < n_voices; j++)
if (opt->is_free(voices[j])) {
opts->note_on(voices[j], ev->note, ev->status.velocity);
goto next_event;
}
void bw_voice_alloc_reset(bw_voice_alloc *voice_alloc) {
int k = -1;
int v = ev->note;
for (j = 0; j < n_voices; j++) {
int n = opts->get_note(voices[j]);
if (opts->mode == bw_voice_alloc_mode_low ? n > v : n < v) {
v = n;
k = j;
}
}
if (k >= 0)
opts->note_on(voices[k], ev->note, ev->status.velocity);
}
next_event:;
}
}
void bw_voice_alloc_process(bw_voice_alloc *voice_alloc, bw_note_queue *queue) {
#ifdef __cplusplus
}
#endif
void bw_voice_alloc_set_unison(bw_voice_alloc *voice_alloc, char value) {
voice_alloc->unison = value;
}
#endif