bool Channel_cv_state_add_entry(Channel_cv_state* state, const char* var_name) { rassert(state != NULL); rassert(var_name != NULL); rassert(strlen(var_name) < KQT_VAR_NAME_MAX); const Entry* entry = Entry_init(ENTRY_AUTO, var_name); if (!AAtree_contains(state->tree, entry)) { Entry* new_entry = memory_alloc_item(Entry); if (new_entry == NULL) return false; *new_entry = *entry; if (!AAtree_ins(state->tree, new_entry)) { memory_free(new_entry); return false; } } return true; }
static bool read_env_var(Streader* sr, int32_t index, void* userdata) { assert(sr != NULL); (void)index; assert(userdata != NULL); AAtree* new_vars = userdata; Env_var* var = new_Env_var_from_string(sr); if (var == NULL) return false; if (AAtree_contains(new_vars, Env_var_get_name(var))) { Streader_set_error( sr, "Variable name %s is not unique", Env_var_get_name(var)); del_Env_var(var); return false; } if (!AAtree_ins(new_vars, var)) { Streader_set_memory_error( sr, "Could not allocate memory for environment"); del_Env_var(var); return false; } return true; }
Connections* new_Connections_from_string( Streader* sr, Connection_level level, Au_table* au_table, Device* master) { rassert(sr != NULL); rassert(au_table != NULL); rassert(master != NULL); if (Streader_is_error_set(sr)) return NULL; Connections* graph = memory_alloc_item(Connections); if (graph == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for connections"); return NULL; } graph->nodes = NULL; graph->nodes = new_AAtree( (int (*)(const void*, const void*))Device_node_cmp, (void (*)(void*))del_Device_node); mem_error_if(graph->nodes == NULL, graph, NULL, sr); Device_node* master_node = NULL; if (level == CONNECTION_LEVEL_AU) { const Device* iface = Audio_unit_get_output_interface((Audio_unit*)master); master_node = new_Device_node("", au_table, iface); } else { master_node = new_Device_node("", au_table, master); } mem_error_if(master_node == NULL, graph, NULL, sr); mem_error_if(!AAtree_ins(graph->nodes, master_node), graph, master_node, sr); if (!Streader_has_data(sr)) return graph; read_conn_data rcdata = { graph, level, au_table, master }; if (!Streader_read_list(sr, read_connection, &rcdata)) { del_Connections(graph); return NULL; } if (Connections_is_cyclic(graph)) { Streader_set_error(sr, "The connection graph contains a cycle"); del_Connections(graph); return NULL; } return graph; }
bool Event_cache_add_event(Event_cache* cache, char* event_name) { rassert(cache != NULL); rassert(event_name != NULL); if (AAtree_get_exact(cache->cache, event_name) != NULL) return true; Event_state* es = new_Event_state(event_name); if (es == NULL || !AAtree_ins(cache->cache, es)) { del_Event_state(es); return false; } return true; }
static bool read_piref(Streader* sr, int32_t index, void* userdata) { rassert(sr != NULL); rassert(userdata != NULL); Order_list* ol = userdata; // Read the Pattern instance reference Pat_inst_ref* p = PAT_INST_REF_AUTO; if (!Streader_read_piref(sr, p)) return false; // Check if the Pattern instance is already used Index_mapping* key = INDEX_MAPPING_AUTO; key->p = *p; key->ol_index = index; if (AAtree_contains(ol->index_map, key)) { Streader_set_error( sr, "Duplicate occurrence of pattern instance" " [%" PRId16 ", %" PRId16 "]", p->pat, p->inst); return false; } // Add the reference to our containers if (!Vector_append(ol->pat_insts, p)) { Streader_set_memory_error( sr, "Could not allocate memory for order list"); return false; } Index_mapping* im = new_Index_mapping(key); if (im == NULL || !AAtree_ins(ol->index_map, im)) { memory_free(im); Streader_set_memory_error( sr, "Could not allocate memory for order list"); return false; } return true; }
bool Note_map_add_entry( Note_map* map, double cents, double force, Sample_entry* entry) { assert(map != NULL); assert(isfinite(cents)); assert(isfinite(force)); assert(entry != NULL); Random_list* key = &(Random_list){ .force = force, .cents = cents }; Random_list* list = AAtree_get_exact(map->map, key); if (list == NULL) { Random_list* list = memory_alloc_item(Random_list); if (list == NULL || !AAtree_ins(map->map, list)) { memory_free(list); return false; } list->freq = exp2(cents / 1200) * 440; list->cents = cents; list->force = force; list->entry_count = 0; } if (list->entry_count >= NOTE_MAP_RANDOMS_MAX) { assert(list->entry_count == NOTE_MAP_RANDOMS_MAX); return false; } list->entries[list->entry_count].ref_freq = list->freq; list->entries[list->entry_count].cents = entry->cents; list->entries[list->entry_count].vol_scale = entry->vol_scale; list->entries[list->entry_count].sample = entry->sample; ++list->entry_count; return true; }
static bool read_expressions(Streader* sr, const char* key, void* userdata) { rassert(sr != NULL); rassert(key != NULL); rassert(userdata != NULL); Au_expressions* ae = userdata; if (!is_valid_var_name(key)) { Streader_set_error(sr, "Invalid expression name: %s", key); return false; } Entry* entry = memory_alloc_item(Entry); if (entry == NULL) return false; strcpy(entry->name, key); Param_proc_filter* filter = new_Param_proc_filter(sr); if (filter == NULL) { memory_free(entry); return false; } entry->filter = filter; if (!AAtree_ins(ae->entries, entry)) { del_Param_proc_filter(filter); memory_free(entry); return false; } return true; }
static bool Tuning_table_build_pitch_map(Tuning_table* tt) { rassert(tt != NULL); AAtree* pitch_map = new_AAtree( (AAtree_item_cmp*)pitch_index_cmp, (AAtree_item_destroy*)memory_free); if (pitch_map == NULL) return false; for (int octave = 0; octave < KQT_TUNING_TABLE_OCTAVES; ++octave) { for (int note = 0; note < tt->note_count; ++note) { pitch_index* pi = &(pitch_index){ .cents = 0 }; pi->cents = tt->ref_pitch + tt->note_offsets[note] + tt->octave_offsets[octave]; pi->note = note; pi->octave = octave; if (!AAtree_contains(pitch_map, pi)) { pitch_index* pi_entry = memory_alloc_item(pitch_index); if (pi_entry == NULL) { del_AAtree(pitch_map); return false; } *pi_entry = *pi; if (!AAtree_ins(pitch_map, pi_entry)) { del_AAtree(pitch_map); return false; } } } } if (tt->pitch_map != NULL) del_AAtree(tt->pitch_map); tt->pitch_map = pitch_map; return true; } /** * Set a new note in the Tuning table using cents. * * Any existing note at the target index will be replaced. * The note will be set at no further than the first unoccupied index. * * \param tt The Tuning table -- must not be \c NULL. * \param index The index of the note to be set -- must be >= \c 0 and * less than the current note count. * \param cents The pitch ratio between the new note and reference pitch * in cents -- must be a finite value. */ static void Tuning_table_set_note_cents(Tuning_table* tt, int index, double cents); void Tuning_table_set_octave_width(Tuning_table* tt, double octave_width); static Tuning_table* new_Tuning_table(double ref_pitch, double octave_width) { rassert(ref_pitch > 0); rassert(isfinite(octave_width)); rassert(octave_width > 0); Tuning_table* tt = memory_alloc_item(Tuning_table); if (tt == NULL) return NULL; tt->pitch_map = NULL; tt->note_count = 0; tt->ref_note = 0; tt->ref_pitch = ref_pitch; tt->global_offset = 0; tt->centre_octave = 4; Tuning_table_set_octave_width(tt, octave_width); for (int i = 0; i < KQT_TUNING_TABLE_NOTES_MAX; ++i) tt->note_offsets[i] = 0; if (!Tuning_table_build_pitch_map(tt)) { memory_free(tt); return NULL; } return tt; }
static bool read_connection(Streader* sr, int32_t index, void* userdata) { rassert(sr != NULL); rassert(userdata != NULL); ignore(index); read_conn_data* rcdata = userdata; char src_name[KQT_DEVICE_NODE_NAME_MAX] = ""; char dest_name[KQT_DEVICE_NODE_NAME_MAX] = ""; if (!Streader_readf( sr, "[%s,%s]", READF_STR(KQT_DEVICE_NODE_NAME_MAX, src_name), READF_STR(KQT_DEVICE_NODE_NAME_MAX, dest_name))) return false; int src_port = validate_connection_path( sr, src_name, rcdata->level, DEVICE_PORT_TYPE_SEND); int dest_port = validate_connection_path( sr, dest_name, rcdata->level, DEVICE_PORT_TYPE_RECV); if (Streader_is_error_set(sr)) return false; if (rcdata->level == CONNECTION_LEVEL_AU) { if (string_eq(src_name, "")) strcpy(src_name, "Iin"); } if (AAtree_get_exact(rcdata->graph->nodes, src_name) == NULL) { const Device* actual_master = rcdata->master; if ((rcdata->level == CONNECTION_LEVEL_AU) && string_eq(src_name, "Iin")) actual_master = Audio_unit_get_input_interface((Audio_unit*)rcdata->master); Device_node* new_src = new_Device_node( src_name, rcdata->au_table, actual_master); mem_error_if(new_src == NULL, rcdata->graph, NULL, sr); mem_error_if( !AAtree_ins(rcdata->graph->nodes, new_src), rcdata->graph, new_src, sr); } Device_node* src_node = AAtree_get_exact(rcdata->graph->nodes, src_name); if (AAtree_get_exact(rcdata->graph->nodes, dest_name) == NULL) { Device_node* new_dest = new_Device_node( dest_name, rcdata->au_table, rcdata->master); mem_error_if(new_dest == NULL, rcdata->graph, NULL, sr); mem_error_if( !AAtree_ins(rcdata->graph->nodes, new_dest), rcdata->graph, new_dest, sr); } Device_node* dest_node = AAtree_get_exact(rcdata->graph->nodes, dest_name); rassert(src_node != NULL); rassert(dest_node != NULL); mem_error_if( !Device_node_connect(dest_node, dest_port, src_node, src_port), rcdata->graph, NULL, sr); return true; }
static bool read_entry(Streader* sr, int32_t index, void* userdata) { rassert(sr != NULL); rassert(userdata != NULL); ignore(index); Input_map* im = userdata; int64_t in = 0; int64_t out = 0; if (!Streader_readf(sr, "[%i, %i]", &in, &out)) return false; if (in < 0 || in >= im->num_inputs) { Streader_set_error( sr, "Input ID %" PRId64 " out of range [0, %" PRId32 ")", in, im->num_inputs); return false; } if (out < 0 || out >= im->num_outputs) { Streader_set_error( sr, "Output ID %" PRId64 " out of range [0, %" PRId32 ")", out, im->num_outputs); return false; } const Entry* key = ENTRY_KEY((int32_t)in); if (AAtree_contains(im->map, key)) { Streader_set_error(sr, "Duplicate entry for input %" PRId64, in); return false; } Entry* entry = memory_alloc_item(Entry); if (entry == NULL) { Error_set( &sr->error, ERROR_MEMORY, "Could not allocate memory for input map"); return false; } entry->input = (int32_t)in; entry->output = (int32_t)out; if (!AAtree_ins(im->map, entry)) { memory_free(entry); Error_set( &sr->error, ERROR_MEMORY, "Could not allocate memory for input map"); return false; } return true; }
static bool read_mapping(Streader* sr, int32_t index, void* userdata) { assert(sr != NULL); (void)index; assert(userdata != NULL); Note_map* map = userdata; Random_list* list = memory_alloc_item(Random_list); if (list == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for note map entry"); return false; } double cents = NAN; double force = NAN; if (!Streader_readf(sr, "[[%f,%f],", ¢s, &force)) { memory_free(list); return false; } if (!isfinite(cents)) { Streader_set_error(sr, "Mapping cents is not finite"); memory_free(list); return false; } if (!isfinite(force)) { Streader_set_error(sr, "Mapping force is not finite"); memory_free(list); return false; } list->freq = exp2(cents / 1200) * 440; list->cents = cents; list->force = force; list->entry_count = 0; if (!AAtree_ins(map->map, list)) { Streader_set_memory_error( sr, "Couldn't allocate memory for note map entry"); memory_free(list); return false; } if (!Streader_read_list(sr, read_random_list_entry, list)) return false; if (list->entry_count == 0) { Streader_set_error(sr, "Empty note mapping random list"); return false; } return Streader_match_char(sr, ']'); }
static bool read_mapping(Streader* sr, int32_t index, void* userdata) { rassert(sr != NULL); ignore(index); rassert(userdata != NULL); Hit_map* map = userdata; Random_list* list = memory_alloc_item(Random_list); if (list == NULL) { del_Hit_map(map); Streader_set_memory_error( sr, "Could not allocate memory for hit map random list"); return false; } int64_t hit_index = -1; double force = NAN; if (!Streader_readf(sr, "[[%i,%f],", &hit_index, &force)) { memory_free(list); return false; } if (hit_index < 0 || hit_index >= KQT_HITS_MAX) { Streader_set_error( sr, "Mapping hit index is outside range [0, %d)", KQT_HITS_MAX); memory_free(list); return false; } if (!isfinite(force)) { Streader_set_error( sr, "Mapping force is not finite", KQT_HITS_MAX); memory_free(list); return false; } if (map->hits[hit_index] == NULL) { map->hits[hit_index] = new_AAtree( (AAtree_item_cmp*)Random_list_cmp, (AAtree_item_destroy*)memory_free); if (map->hits[hit_index] == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for hit map"); memory_free(list); return false; } } list->force = force; list->entry_count = 0; if (AAtree_contains(map->hits[hit_index], list)) { Streader_set_error( sr, "Duplicate hit map entry with hit index %" PRId64 ", force %.2f", hit_index, force); memory_free(list); return false; } if (!AAtree_ins(map->hits[hit_index], list)) { Streader_set_memory_error( sr, "Could not allocate memory for hit map random list"); memory_free(list); return false; } if (!Streader_read_list(sr, read_random_list_entry, list)) return false; return Streader_match_char(sr, ']'); }