Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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],", &cents, &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, ']');
}
Beispiel #12
0
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, ']');
}