コード例 #1
0
ファイル: Input_map.c プロジェクト: kagu/kunquat
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;
}
コード例 #2
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;
}
コード例 #3
0
ファイル: Order_list.c プロジェクト: kagu/kunquat
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;
}
コード例 #4
0
ファイル: Note_map.c プロジェクト: cyberixae/kunquat
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;
}
コード例 #5
0
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;
}
コード例 #6
0
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;
}
コード例 #7
0
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;
}
コード例 #8
0
ファイル: Environment.c プロジェクト: cyberixae/kunquat
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;
}
コード例 #9
0
ファイル: Environment.c プロジェクト: cyberixae/kunquat
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;
}
コード例 #10
0
ファイル: Tuning_table.c プロジェクト: kagu/kunquat
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;
}
コード例 #11
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, ']');
}