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; }
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; }
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_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) { 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, ']'); }
static bool read_mapping(Streader* sr, int32_t index, void* userdata) { assert(sr != NULL); ignore(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_contains(map->map, list)) { Streader_set_error( sr, "Duplicate note map entry with pitch %.2f, force %.2f", list->cents, list->force); memory_free(list); return false; } 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; return Streader_match_char(sr, ']'); }