Пример #1
0
static bool is_proc_filtered(
        const Processor* proc, const Au_expressions* ae, const char* expr_name)
{
    rassert(proc != NULL);
    rassert(ae != NULL);
    rassert(expr_name != NULL);

    if (expr_name[0] == '\0')
        return false;

    const Param_proc_filter* proc_filter = Au_expressions_get_proc_filter(ae, expr_name);
    if (proc_filter == NULL)
        return false;

    return !Param_proc_filter_is_proc_allowed(proc_filter, proc->index);
}
Пример #2
0
bool Event_channel_hit_process(
        Channel* ch,
        Device_states* dstates,
        const Master_params* master_params,
        const Event_params* params)
{
    rassert(ch != NULL);
    rassert(ch->audio_rate > 0);
    rassert(ch->tempo > 0);
    rassert(dstates != NULL);
    rassert(master_params != NULL);
    rassert(params != NULL);
    rassert(params->arg != NULL);
    rassert(params->arg->type == VALUE_TYPE_INT);

    // Move the old Voices to the background
    Event_channel_note_off_process(ch, dstates, master_params, NULL);

    // Find our audio unit
    Audio_unit* au = Module_get_au_from_input(ch->parent.module, ch->au_input);
    if (au == NULL)
        return true;

    init_force_controls(ch, master_params);

    // Don't attempt to hit effects
    if (Audio_unit_get_type(au) != AU_TYPE_INSTRUMENT)
        return true;

    const int hit_index = (int)params->arg->value.int_type;

    if (!Audio_unit_get_hit_existence(au, hit_index))
        return true;

    const Param_proc_filter* hpf = Audio_unit_get_hit_proc_filter(au, hit_index);

    // Generate our next note random seed here so that random generation
    // is consistent even if we run out of voices
    const uint64_t note_rand_seed = Random_get_uint64(&ch->rand);

    // Find reserved voices
    Voice_group* vgroup = VOICE_GROUP_AUTO;

    if (!Voice_group_reservations_get_clear_entry(
                ch->voice_group_res, ch->num, &ch->fg_group_id) ||
            (Voice_pool_get_group(ch->pool, ch->fg_group_id, vgroup) == NULL))
    {
        reset_channel_voices(ch);
        return true;
    }

    int voice_index = 0;

    for (int i = 0; i < KQT_PROCESSORS_MAX; ++i)
    {
        const Processor* proc = Audio_unit_get_proc(au, i);
        if (proc == NULL ||
                !Device_is_existent((const Device*)proc) ||
                !Processor_get_voice_signals(proc))
            continue;

        // Skip processors that are filtered out for this hit index
        if ((hpf != NULL) && !Param_proc_filter_is_proc_allowed(hpf, i))
            continue;

        const Proc_state* proc_state = (Proc_state*)Device_states_get_state(
                dstates, Device_get_id((const Device*)proc));

        Voice_state_get_size_func* get_vstate_size =
            proc_state->parent.device->dimpl->get_vstate_size;
        if ((get_vstate_size != NULL) && (get_vstate_size() == 0))
            continue;

        char context_str[16] = "";
        snprintf(context_str, 16, "np%hd", (short)i);
        Random* random = Random_init(RANDOM_AUTO, context_str);
        Random_set_seed(random, note_rand_seed);
        const uint64_t voice_rand_seed = Random_get_uint64(random);

        Voice* voice = Voice_group_get_voice(vgroup, voice_index);

        const bool voice_allocated = init_voice(
                ch, voice, au, ch->fg_group_id, proc_state, i, voice_rand_seed);
        if (!voice_allocated)
        {
            // Some of our voices were reallocated
            reset_channel_voices(ch);
            return true;
        }

        ++voice_index;

        Voice_state* vs = voice->state;
        vs->hit_index = hit_index;

        if (vs->proc_type == Proc_type_force)
        {
            Force_controls* fc = Force_vstate_get_force_controls_mut(vs);
            Force_controls_copy(fc, &ch->force_controls);
        }
    }

    Channel_reset_test_output(ch);

    init_streams(ch, au);

    return true;
}