You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

165 lines
6.6 KiB

#include "app.h"
#include "blob.h"
#include "instr.h"
#include "rt.h"
#include "sampler.h"
#include "sampler_prg.h"
/////////////////////////////////////////////////////////////////////////////////
static void add_layers(struct sampler_rll *rll, GSList **layers_by_range, struct sampler_layer *l, uint32_t lokey, uint32_t hikey)
{
if (lokey >= 0 && lokey <= 127 &&
hikey >= 0 && hikey <= 127)
{
int start = rll->ranges_by_key[lokey];
int end = rll->ranges_by_key[hikey];
for (int i = start; i <= end; ++i)
{
if (!layers_by_range[i] || layers_by_range[i]->data != l)
layers_by_range[i] = g_slist_prepend(layers_by_range[i], l);
}
}
}
struct sampler_rll *sampler_rll_new_from_program(struct sampler_program *prg)
{
struct sampler_rll *rll = g_new(struct sampler_rll, 1);
rll->layers_oncc = NULL;
for (int i = 0; i < 4; i++)
rll->cc_trigger_bitmask[i] = 0;
GHashTable *keyswitch_groups = g_hash_table_new(g_direct_hash, g_direct_equal);
uint32_t keyswitch_group_count = 0, keyswitch_key_count = 0;
GPtrArray *keyswitch_group_array = g_ptr_array_new();
memset(rll->ranges_by_key, 255, sizeof(rll->ranges_by_key));
rll->has_release_layers = FALSE;
for (GSList *p = prg->all_layers; p; p = g_slist_next(p))
{
struct sampler_layer *l = p->data;
if (l->data.trigger == stm_release)
rll->has_release_layers = TRUE;
if (l->data.sw_last >= 0 && l->data.sw_last <= 127 &&
l->data.sw_lokey >= 0 && l->data.sw_lokey <= 127 &&
l->data.sw_hikey >= 0 && l->data.sw_hikey <= 127 &&
l->data.sw_last >= l->data.sw_lokey && l->data.sw_last <= l->data.sw_hikey)
{
int width = l->data.sw_hikey - l->data.sw_lokey + 1;
gpointer key = GINT_TO_POINTER(l->data.sw_lokey + (l->data.sw_hikey << 8));
uint8_t value = l->data.sw_last - l->data.sw_lokey;
struct sampler_keyswitch_group *ks = g_hash_table_lookup(keyswitch_groups, key);
if (!ks)
{
ks = g_malloc(sizeof(struct sampler_keyswitch_group) + width);
ks->lo = l->data.sw_lokey;
ks->hi = l->data.sw_hikey;
ks->num_used = 0;
ks->def_value = 255;
memset(ks->key_offsets, 255, width);
g_hash_table_insert(keyswitch_groups, (gpointer)key, ks);
g_ptr_array_add(keyswitch_group_array, ks);
keyswitch_group_count++;
}
if (l->data.sw_default >= ks->lo && l->data.sw_default <= ks->hi && ks->def_value == 255)
ks->def_value = l->data.sw_default - ks->lo;
if (ks->key_offsets[value] == 255)
{
ks->key_offsets[value] = ks->num_used;
ks->num_used++;
keyswitch_key_count++;
assert(ks->num_used <= width);
}
}
}
rll->keyswitch_groups = (gpointer)g_ptr_array_free(keyswitch_group_array, FALSE);
rll->keyswitch_group_count = keyswitch_group_count;
rll->keyswitch_key_count = keyswitch_key_count;
uint32_t offset = 0;
for (uint32_t i = 0; i < keyswitch_group_count; ++i)
{
rll->keyswitch_groups[i]->group_offset = 1 + offset;
offset += rll->keyswitch_groups[i]->num_used;
}
assert(offset == keyswitch_key_count);
uint16_t lo_count[129], hi_count[128], low = 127, high = 0;
for (int i = 0; i < 128; i++)
lo_count[i] = hi_count[i] = 0;
// XXXKF handle 'key' field without relying on the existing ugly hack
for (GSList *p = prg->all_layers; p; p = g_slist_next(p))
{
struct sampler_layer *l = p->data;
if (l->data.lokey >= 0 && l->data.lokey <= 127 &&
l->data.hikey >= 0 && l->data.hikey <= 127)
{
lo_count[l->data.lokey]++;
hi_count[l->data.hikey]++;
if (l->data.lokey < low)
low = l->data.lokey;
if (l->data.hikey > high)
high = l->data.hikey;
}
}
rll->lokey = low;
rll->hikey = high;
uint32_t range_count = 1;
for (int i = low + 1; i <= high; ++i)
{
rll->ranges_by_key[i - 1] = range_count - 1;
if (hi_count[i - 1] || lo_count[i])
range_count++;
}
rll->ranges_by_key[high] = range_count - 1;
rll->layers_by_range = g_malloc0_n(range_count * (1 + keyswitch_key_count), sizeof(GSList *));
rll->release_layers_by_range = rll->has_release_layers ? g_malloc0_n(range_count * (1 + keyswitch_key_count), sizeof(GSList *)) : NULL;
rll->layers_by_range_count = range_count;
for (GSList *p = prg->all_layers; p; p = g_slist_next(p))
{
struct sampler_layer *l = p->data;
uint32_t ks_offset = 0;
if (l->data.sw_last >= 0 && l->data.sw_last <= 127 &&
l->data.sw_lokey >= 0 && l->data.sw_lokey <= 127 &&
l->data.sw_hikey >= 0 && l->data.sw_hikey <= 127 &&
l->data.sw_last >= l->data.sw_lokey && l->data.sw_last <= l->data.sw_hikey)
{
gpointer key = GINT_TO_POINTER(l->data.sw_lokey + (l->data.sw_hikey << 8));
struct sampler_keyswitch_group *ks = g_hash_table_lookup(keyswitch_groups, key);
assert(ks);
int rel_offset = ks->key_offsets[l->data.sw_last - l->data.sw_lokey];
assert(rel_offset != -1);
ks_offset = ks->group_offset + rel_offset;
}
if (l->data.on_cc.is_active)
{
int cc = l->data.on_cc.cc_number;
rll->layers_oncc = g_slist_prepend(rll->layers_oncc, l);
rll->cc_trigger_bitmask[cc >> 5] |= 1 << (cc & 31);
}
if (l->data.trigger == stm_release)
add_layers(rll, rll->release_layers_by_range + ks_offset * range_count, l, l->data.lokey, l->data.hikey);
else
add_layers(rll, rll->layers_by_range + ks_offset * range_count, l, l->data.lokey, l->data.hikey);
}
g_hash_table_unref(keyswitch_groups);
return rll;
}
void sampler_rll_destroy(struct sampler_rll *rll)
{
g_slist_free(rll->layers_oncc);
for (uint32_t i = 0; i < rll->layers_by_range_count * (1 + rll->keyswitch_key_count); ++i)
{
if (rll->has_release_layers)
g_slist_free(rll->release_layers_by_range[i]);
g_slist_free(rll->layers_by_range[i]);
}
for (uint32_t i = 0; i < rll->keyswitch_group_count; ++i)
g_free(rll->keyswitch_groups[i]);
g_free(rll->keyswitch_groups);
g_free(rll->release_layers_by_range);
g_free(rll->layers_by_range);
g_free(rll);
}