#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; } struct sampler_cc_range *oncc = l->data.on_cc; if (oncc) { rll->layers_oncc = g_slist_prepend(rll->layers_oncc, l); while(oncc) { int cc = oncc->key.cc_number; rll->cc_trigger_bitmask[cc >> 5] |= 1 << (cc & 31); oncc = oncc->next; } } 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); }