Input_map* new_Input_map(Streader* sr, int32_t num_inputs, int32_t num_outputs) { rassert(sr != NULL); rassert(num_inputs > 0); rassert(num_outputs > 0); Input_map* im = memory_alloc_item(Input_map); if (im == NULL) return NULL; im->map = NULL; im->num_inputs = num_inputs; im->num_outputs = num_outputs; im->map = new_AAtree( (AAtree_item_cmp*)Entry_cmp, (AAtree_item_destroy*)memory_free); if (im->map == NULL) { del_Input_map(im); return NULL; } if (!Streader_read_list(sr, read_entry, im)) { del_Input_map(im); return NULL; } return im; }
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; }
Order_list* new_Order_list(Streader* sr) { rassert(sr != NULL); if (Streader_is_error_set(sr)) return NULL; // Create the base structure Order_list* ol = memory_alloc_item(Order_list); if (ol == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for order list"); return NULL; } ol->pat_insts = NULL; ol->index_map = NULL; // Create Pattern instance reference vector ol->pat_insts = new_Vector(sizeof(Pat_inst_ref)); if (ol->pat_insts == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for order list"); del_Order_list(ol); return NULL; } // Create reverse index of ol->pat_insts ol->index_map = new_AAtree( (AAtree_item_cmp*)Pat_inst_ref_cmp, (AAtree_item_destroy*)memory_free); if (ol->index_map == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for order list"); del_Order_list(ol); return NULL; } // List is empty by default if (!Streader_has_data(sr)) return ol; // Read the list of Pattern instance references if (!Streader_read_list(sr, read_piref, ol)) { del_Order_list(ol); return NULL; } return ol; }
Note_map* new_Note_map_from_string(Streader* sr) { assert(sr != NULL); if (Streader_is_error_set(sr)) return NULL; Note_map* map = memory_alloc_item(Note_map); if (map == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for note map"); return NULL; } map->map = NULL; map->iter = NULL; map->map = new_AAtree( (int (*)(const void*, const void*))Random_list_cmp, (void (*)(void*))del_Random_list); if (map->map == NULL) { del_Note_map(map); Streader_set_memory_error( sr, "Could not allocate memory for note map"); return NULL; } map->iter = new_AAiter(map->map); if (map->iter == NULL) { del_Note_map(map); Streader_set_memory_error( sr, "Could not allocate memory for note map"); return NULL; } if (!Streader_has_data(sr)) return map; if (!Streader_read_list(sr, read_mapping, map)) { del_Note_map(map); return NULL; } return map; }
Event_cache* new_Event_cache(void) { Event_cache* cache = memory_alloc_item(Event_cache); if (cache == NULL) return NULL; cache->cache = new_AAtree( (AAtree_item_cmp*)strcmp, (AAtree_item_destroy*)del_Event_state); if (cache->cache == NULL) { del_Event_cache(cache); return NULL; } return cache; }
Au_expressions* new_Au_expressions(Streader* sr) { rassert(sr != NULL); if (Streader_is_error_set(sr)) return NULL; Au_expressions* ae = memory_alloc_item(Au_expressions); if (ae == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for audio unit expressions"); return NULL; } memset(ae->default_note_expr, '\0', KQT_VAR_NAME_MAX); ae->entries = new_AAtree( (AAtree_item_cmp*)strcmp, (AAtree_item_destroy*)del_Entry); if (ae->entries == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for audio unit expressions"); del_Au_expressions(ae); return NULL; } if (!Streader_read_dict(sr, read_expressions_def, ae)) { rassert(Streader_is_error_set(sr)); del_Au_expressions(ae); return NULL; } if (ae->default_note_expr[0] != '\0' && !Au_expressions_get_proc_filter(ae, ae->default_note_expr)) { Streader_set_error( sr, "Audio unit expressions do not contain the default expression %s", ae->default_note_expr); del_Au_expressions(ae); return NULL; } return ae; }
Channel_cv_state* new_Channel_cv_state(void) { Channel_cv_state* state = memory_alloc_item(Channel_cv_state); if (state == NULL) return NULL; state->tree = NULL; state->tree = new_AAtree( (AAtree_item_cmp*)strcmp, (AAtree_item_destroy*)memory_free); if (state->tree == NULL) { del_Channel_cv_state(state); return NULL; } return state; }
Environment* new_Environment(void) { Environment* env = memory_alloc_item(Environment); if (env == NULL) return NULL; env->vars = NULL; env->iter = NULL; env->vars = new_AAtree( (int (*)(const void*, const void*))strcmp, (void (*)(void*))del_Env_var); env->iter = new_AAiter(env->vars); if (env->vars == NULL || env->iter == NULL) { del_Environment(env); return NULL; } return env; }
bool Environment_parse(Environment* env, Streader* sr) { assert(env != NULL); assert(sr != NULL); if (Streader_is_error_set(sr)) return false; if (!Streader_has_data(sr)) { AAtree_clear(env->vars); AAiter_change_tree(env->iter, env->vars); return true; } AAtree* new_vars = new_AAtree( (int (*)(const void*, const void*))strcmp, (void (*)(void*))del_Env_var); if (new_vars == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for environment"); return false; } if (!Streader_read_list(sr, read_env_var, new_vars)) { del_AAtree(new_vars); return false; } AAiter_change_tree(env->iter, new_vars); AAtree* old_vars = env->vars; env->vars = new_vars; del_AAtree(old_vars); 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_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, ']'); }