コード例 #1
0
static void write_audio(
        Work_buffer* out_wbs[2],
        const Work_buffer* gain_wb,
        const Work_buffer* in_wbs[2],
        int32_t buf_start,
        int32_t buf_stop)
{
    rassert(out_wbs != NULL);
    rassert(gain_wb != NULL);
    rassert(in_wbs != NULL);
    rassert(buf_start >= 0);
    rassert(buf_stop > buf_start);

    const float* gains = Work_buffer_get_contents(gain_wb);

    for (int ch = 0; ch < 2; ++ch)
    {
        if (out_wbs[ch] == NULL || in_wbs[ch] == NULL)
            continue;

        float* out = Work_buffer_get_contents_mut(out_wbs[ch]);
        const float* in = Work_buffer_get_contents(in_wbs[ch]);

        for (int32_t i = buf_start; i < buf_stop; ++i)
            out[i] = in[i] * gains[i];
    }

    return;
}
コード例 #2
0
float* Work_buffers_get_buffer_contents_mut(
        const Work_buffers* buffers, Work_buffer_type type)
{
    rassert(buffers != NULL);
    rassert(type < WORK_BUFFER_COUNT_);

    return Work_buffer_get_contents_mut(buffers->buffers[type]);
}
コード例 #3
0
float* Device_thread_state_get_voice_buffer_contents(
        const Device_thread_state* ts, Device_port_type type, int port)
{
    rassert(ts != NULL);
    rassert(type < DEVICE_PORT_TYPES);
    rassert(port >= 0);
    rassert(port < KQT_DEVICE_PORTS_MAX);

    Work_buffer* wb = Device_thread_state_get_voice_buffer(ts, type, port);
    if (wb == NULL)
        return NULL;

    return Work_buffer_get_contents_mut(wb);
}
コード例 #4
0
ファイル: Rangemap_state.c プロジェクト: kagu/kunquat
static void apply_range(
        const Work_buffer* in_wb,
        Work_buffer* out_wb,
        int32_t frame_count,
        float mul,
        float add,
        float min_val,
        float max_val)
{
    rassert(in_wb != NULL);
    rassert(out_wb != NULL);
    rassert(frame_count > 0);
    rassert(isfinite(mul));
    rassert(isfinite(add));
    rassert(min_val <= max_val);

    const float* in = Work_buffer_get_contents(in_wb, 0);
    float* out = Work_buffer_get_contents_mut(out_wb, 0);

    const int32_t item_count = frame_count * 2;

    for (int32_t i = 0; i < item_count; ++i)
        out[i] = (mul * in[i]) + add;

    if (isfinite(min_val))
    {
        for (int32_t i = 0; i < item_count; ++i)
            out[i] = max(out[i], min_val);
    }

    if (isfinite(max_val))
    {
        for (int32_t i = 0; i < item_count; ++i)
            out[i] = min(out[i], max_val);
    }

    return;
}
コード例 #5
0
static void apply_range(
        const Work_buffer* in_wb,
        Work_buffer* out_wb,
        int32_t buf_start,
        int32_t buf_stop,
        float mul,
        float add,
        float min_val,
        float max_val)
{
    rassert(in_wb != NULL);
    rassert(out_wb != NULL);
    rassert(buf_start >= 0);
    rassert(buf_stop > buf_start);
    rassert(isfinite(mul));
    rassert(isfinite(add));
    rassert(min_val < max_val);

    const float* in = Work_buffer_get_contents(in_wb);
    float* out = Work_buffer_get_contents_mut(out_wb);

    for (int32_t i = buf_start; i < buf_stop; ++i)
        out[i] = (mul * in[i]) + add;

    if (isfinite(min_val))
    {
        for (int32_t i = buf_start; i < buf_stop; ++i)
            out[i] = max(out[i], min_val);
    }

    if (isfinite(max_val))
    {
        for (int32_t i = buf_start; i < buf_stop; ++i)
            out[i] = min(out[i], max_val);
    }

    return;
}
コード例 #6
0
ファイル: Debug_state.c プロジェクト: kagu/kunquat
int32_t Debug_vstate_render_voice(
        Voice_state* vstate,
        Proc_state* proc_state,
        const Device_thread_state* proc_ts,
        const Au_state* au_state,
        const Work_buffers* wbs,
        int32_t frame_count,
        double tempo)
{
    rassert(vstate != NULL);
    rassert(proc_state != NULL);
    rassert(proc_ts != NULL);
    rassert(au_state != NULL);
    rassert(wbs != NULL);
    rassert(frame_count > 0);
    rassert(tempo > 0);

    const Processor* proc = (const Processor*)proc_state->parent.device;

    // Get pitches
    const Cond_work_buffer* actual_pitches = Cond_work_buffer_init(
            COND_WORK_BUFFER_AUTO,
            Device_thread_state_get_voice_buffer(
                proc_ts, DEVICE_PORT_TYPE_RECV, 0, NULL),
            0);

    // Get output buffers for writing
    float* out_buffer = NULL;
    {
        Work_buffer* out_wb = Device_thread_state_get_voice_buffer(
                proc_ts, DEVICE_PORT_TYPE_SEND, 0, NULL);
        if (out_wb != NULL)
        {
            rassert(Work_buffer_get_sub_count(out_wb) == 2);
            rassert(Work_buffer_get_stride(out_wb) == 2);

            out_buffer = Work_buffer_get_contents_mut(out_wb, 0);
            Work_buffer_mark_valid(out_wb, 0);
            Work_buffer_mark_valid(out_wb, 1);
        }
    }

    Proc_debug* debug = (Proc_debug*)proc->parent.dimpl;
    if (debug->single_pulse)
    {
        if (vstate->pos == 1)
        {
            vstate->active = false;
            return 0;
        }

        const float val = 1.0;
        if (out_buffer != NULL)
        {
            out_buffer[0] = val;
            out_buffer[1] = val;
        }

        // We want all single pulses to be included in test buffers,
        // even if another voice replaces us in the channel foreground
        Voice_state_set_keep_alive_stop(vstate, 1);

        vstate->pos = 1;

        return 1;
    }

    if ((vstate->pos >= 10) || (!vstate->note_on && vstate->noff_pos_rem >= 2))
    {
        vstate->active = false;
        return 0;
    }

    const int32_t audio_rate = proc_state->parent.audio_rate;

    for (int32_t i = 0; i < frame_count; ++i)
    {
        const double freq = cents_to_Hz(
                Cond_work_buffer_get_value(actual_pitches, i));

        double vals[KQT_BUFFERS_MAX] = { 0 };

        if (vstate->rel_pos == 0)
        {
            vals[0] = vals[1] = 1.0;
            vstate->rel_pos = 1;
        }
        else
        {
            vals[0] = vals[1] = 0.5;
        }

        if (!vstate->note_on)
        {
            vals[0] = -vals[0];
            vals[1] = -vals[1];
        }

        if (out_buffer != NULL)
        {
            out_buffer[i * 2] = (float)vals[0];
            out_buffer[i * 2 + 1] = (float)vals[1];
        }

        vstate->rel_pos_rem += freq / audio_rate;

        if (!vstate->note_on)
        {
            vstate->noff_pos_rem += freq / audio_rate;
            if (vstate->noff_pos_rem >= 2)
            {
                Voice_state_set_keep_alive_stop(vstate, i + 1);
                return i + 1;
            }
        }

        if (vstate->rel_pos_rem >= 1)
        {
            ++vstate->pos;
            if (vstate->pos >= 10)
            {
                Voice_state_set_keep_alive_stop(vstate, i + 1);
                return i + 1;
            }
            vstate->rel_pos = 0;
            vstate->rel_pos_rem -= floor(vstate->rel_pos_rem);
        }
    }

    Voice_state_set_keep_alive_stop(vstate, frame_count);

    return frame_count;
}
コード例 #7
0
ファイル: Delay_state.c プロジェクト: EdwardBetts/kunquat
static void Delay_pstate_render_mixed(
        Device_state* dstate,
        const Work_buffers* wbs,
        int32_t buf_start,
        int32_t buf_stop,
        double tempo)
{
    assert(dstate != NULL);
    assert(wbs != NULL);
    assert(buf_start <= buf_stop);
    assert(tempo > 0);

    Delay_pstate* dpstate = (Delay_pstate*)dstate;

    const Proc_delay* delay = (const Proc_delay*)dstate->device->dimpl;

    float* in_data[2] = { NULL };
    Proc_state_get_mixed_audio_in_buffers(
            &dpstate->parent, PORT_IN_AUDIO_L, PORT_IN_AUDIO_COUNT, in_data);

    float* out_data[2] = { NULL };
    Proc_state_get_mixed_audio_out_buffers(
            &dpstate->parent, PORT_OUT_AUDIO_L, PORT_OUT_COUNT, out_data);

    float* history_data[] =
    {
        Work_buffer_get_contents_mut(dpstate->bufs[0]),
        Work_buffer_get_contents_mut(dpstate->bufs[1]),
    };

    const int32_t delay_buf_size = Work_buffer_get_size(dpstate->bufs[0]);
    assert(delay_buf_size == Work_buffer_get_size(dpstate->bufs[1]));
    const int32_t delay_max = delay_buf_size - 1;

    static const int DELAY_WORK_BUFFER_TOTAL_OFFSETS = WORK_BUFFER_IMPL_1;
    static const int DELAY_WORK_BUFFER_FIXED_DELAY = WORK_BUFFER_IMPL_2;

    float* total_offsets = Work_buffers_get_buffer_contents_mut(
            wbs, DELAY_WORK_BUFFER_TOTAL_OFFSETS);

    // Get delay stream
    float* delays = Device_state_get_audio_buffer_contents_mut(
            dstate, DEVICE_PORT_TYPE_RECEIVE, PORT_IN_DELAY);
    if (delays == NULL)
    {
        delays =
            Work_buffers_get_buffer_contents_mut(wbs, DELAY_WORK_BUFFER_FIXED_DELAY);
        const float init_delay = delay->init_delay;
        for (int32_t i = buf_start; i < buf_stop; ++i)
            delays[i] = init_delay;
    }

    int32_t cur_dpstate_buf_pos = dpstate->buf_pos;

    const int32_t audio_rate = dstate->audio_rate;

    // Get total offsets
    for (int32_t i = buf_start, chunk_offset = 0; i < buf_stop; ++i, ++chunk_offset)
    {
        const float delay = delays[i];
        float delay_frames = delay * audio_rate;
        delay_frames = clamp(delay_frames, 0, delay_max);
        total_offsets[i] = chunk_offset - delay_frames;
    }

    for (int ch = 0; ch < 2; ++ch)
    {
        const float* in = in_data[ch];
        float* out = out_data[ch];
        if ((in == NULL) || (out == NULL))
            continue;

        const float* history = history_data[ch];
        assert(history != NULL);

        for (int32_t i = buf_start; i < buf_stop; ++i)
        {
            const float total_offset = total_offsets[i];

            // Get buffer positions
            const int32_t cur_pos = (int32_t)floor(total_offset);
            const double remainder = total_offset - cur_pos;
            assert(cur_pos <= (int32_t)i);
            assert(implies(cur_pos == (int32_t)i, remainder == 0));
            const int32_t next_pos = cur_pos + 1;

            // Get audio frames
            double cur_val = 0;
            double next_val = 0;

            if (cur_pos >= 0)
            {
                const int32_t in_cur_pos = buf_start + cur_pos;
                assert(in_cur_pos < (int32_t)buf_stop);
                cur_val = in[in_cur_pos];

                const int32_t in_next_pos = min(buf_start + next_pos, i);
                assert(in_next_pos < (int32_t)buf_stop);
                next_val = in[in_next_pos];
            }
            else
            {
                const int32_t cur_delay_buf_pos =
                    (cur_dpstate_buf_pos + cur_pos + delay_buf_size) % delay_buf_size;
                assert(cur_delay_buf_pos >= 0);

                cur_val = history[cur_delay_buf_pos];

                if (next_pos < 0)
                {
                    const int32_t next_delay_buf_pos =
                        (cur_dpstate_buf_pos + next_pos + delay_buf_size) %
                        delay_buf_size;
                    assert(next_delay_buf_pos >= 0);

                    next_val = history[next_delay_buf_pos];
                }
                else
                {
                    assert(next_pos == 0);
                    next_val = in[buf_start];
                }
            }

            // Create output frame
            const double prev_scale = 1 - remainder;
            const float val =
                (prev_scale * cur_val) + (remainder * next_val);

            out[i] = val;
        }
    }

    // Update the delay state buffers
    for (int ch = 0; ch < 2; ++ch)
    {
        const float* in = in_data[ch];
        if (in == NULL)
            continue;

        float* history = history_data[ch];
        assert(history != NULL);

        cur_dpstate_buf_pos = dpstate->buf_pos;

        for (int32_t i = buf_start; i < buf_stop; ++i)
        {
            history[cur_dpstate_buf_pos] = in[i];

            ++cur_dpstate_buf_pos;
            if (cur_dpstate_buf_pos >= delay_buf_size)
            {
                assert(cur_dpstate_buf_pos == delay_buf_size);
                cur_dpstate_buf_pos = 0;
            }
        }
    }

    dpstate->buf_pos = cur_dpstate_buf_pos;

    return;
}
コード例 #8
0
static void Compress_states_update(
        Compress_state cstates[2],
        const Proc_compress* compress,
        Work_buffer* gain_wb,
        Work_buffer* level_wbs[2],
        const Work_buffer* in_wbs[2],
        int32_t buf_start,
        int32_t buf_stop,
        int32_t audio_rate)
{
    rassert(cstates != NULL);
    rassert(compress != NULL);
    rassert(gain_wb != NULL);
    rassert(level_wbs != NULL);
    rassert(level_wbs[0] != NULL);
    rassert(level_wbs[1] != NULL);
    rassert(in_wbs != NULL);
    rassert(buf_start >= 0);
    rassert(buf_stop > buf_start);

    // Get levels
    const float attack_mul =
        (float)dB_to_scale(6 / (compress->attack * 0.001 * audio_rate));
    const float release_mul =
        (float)dB_to_scale(-6 / (compress->release * 0.001 * audio_rate));

    for (int ch = 0; ch < 2; ++ch)
    {
        Compress_state* cstate = &cstates[ch];
        rassert(cstate != NULL);

        if (in_wbs[ch] == NULL)
            continue;

        float level = cstate->level;

        float* levels = Work_buffer_get_contents_mut(level_wbs[ch]);
        const float* in = Work_buffer_get_contents(in_wbs[ch]);

        for (int32_t i = buf_start; i < buf_stop; ++i)
        {
            const float in_abs = fabsf(in[i]);
            if (in_abs > level)
            {
                level *= attack_mul;
                level = min(level, in_abs);
            }
            else
            {
                level *= release_mul;
                level = max(level, max((float)MIN_LEVEL, in_abs));
            }

            levels[i] = level;
        }

        cstate->level = level;
    }

    if ((in_wbs[0] != NULL) && (in_wbs[1] != NULL))
    {
        // Get maximum levels
        for (int32_t i = buf_start; i < buf_stop; ++i)
            level_wbs[0] = max(level_wbs[0], level_wbs[1]);
    }

    const Work_buffer* applied_levels_wb =
        (in_wbs[0] == NULL) ? level_wbs[1] : level_wbs[0];
    const float* applied_levels = Work_buffer_get_contents(applied_levels_wb);

    Work_buffer_clear(gain_wb, buf_start, buf_stop);
    float* gains = Work_buffer_get_contents_mut(gain_wb);

    for (int32_t i = buf_start; i < buf_stop; ++i)
        gains[i] = 1.0f;

    if (compress->upward_enabled)
    {
        // Apply upward compression
        const double upward_threshold_dB =
            compress->downward_enabled
            ? min(compress->upward_threshold, compress->downward_threshold)
            : compress->upward_threshold;
        const float threshold = (float)dB_to_scale(upward_threshold_dB);
        const float inv_ratio = (float)(1.0 / compress->upward_ratio);
        const float max_gain = (float)dB_to_scale(compress->upward_range);

        for (int32_t i = buf_start; i < buf_stop; ++i)
        {
            const float level = applied_levels[i];
            if (level < threshold)
            {
                const float diff = threshold / level;
                const float gain = threshold / (powf(diff, inv_ratio) * level);
                gains[i] = min(gain, max_gain);
            }
        }
    }

    if (compress->downward_enabled)
    {
        // Apply downward compression
        const float threshold = (float)dB_to_scale(compress->downward_threshold);
        const float inv_ratio = (float)(1.0 / compress->downward_ratio);
        const float min_gain = (float)dB_to_scale(-compress->downward_range);

        for (int32_t i = buf_start; i < buf_stop; ++i)
        {
            const float level = applied_levels[i];
            if (level > threshold)
            {
                const float diff = level / threshold;
                const float gain = (threshold * powf(diff, inv_ratio)) / level;
                gains[i] = max(gain, min_gain);
            }
        }
    }

    return;
}
コード例 #9
0
ファイル: Noise_state.c プロジェクト: kagu/kunquat
int32_t Noise_vstate_render_voice(
        Voice_state* vstate,
        Proc_state* proc_state,
        const Device_thread_state* proc_ts,
        const Au_state* au_state,
        const Work_buffers* wbs,
        int32_t frame_count,
        double tempo)
{
    rassert(vstate != NULL);
    rassert(proc_state != NULL);
    rassert(proc_ts != NULL);
    rassert(au_state != NULL);
    rassert(wbs != NULL);
    rassert(frame_count > 0);
    rassert(tempo > 0);

//    double max_amp = 0;
//  fprintf(stderr, "bufs are %p and %p\n", ins->bufs[0], ins->bufs[1]);

    // Get volume scales
    Work_buffer* scales_wb = Device_thread_state_get_voice_buffer(
            proc_ts, DEVICE_PORT_TYPE_RECV, PORT_IN_FORCE, NULL);
    Work_buffer* dBs_wb = scales_wb;
    if ((dBs_wb != NULL) &&
            Work_buffer_is_valid(dBs_wb, 0) &&
            Work_buffer_is_final(dBs_wb, 0) &&
            (Work_buffer_get_const_start(dBs_wb, 0) == 0) &&
            (Work_buffer_get_contents(dBs_wb, 0)[0] == -INFINITY))
    {
        // We are only getting silent force from this point onwards
        vstate->active = false;
        return 0;
    }

    if ((scales_wb == NULL) || !Work_buffer_is_valid(scales_wb, 0))
        scales_wb = Work_buffers_get_buffer_mut(wbs, NOISE_WB_FIXED_FORCE, 1);
    Proc_fill_scale_buffer(scales_wb, dBs_wb, frame_count);
    const float* scales = Work_buffer_get_contents(scales_wb, 0);

    Noise_pstate* noise_state = (Noise_pstate*)proc_state;
    Noise_vstate* noise_vstate = (Noise_vstate*)vstate;

    // Get output buffer
    Work_buffer* out_wb = Proc_get_voice_output_2ch(proc_ts, PORT_OUT_AUDIO_L);
    if (out_wb == NULL)
    {
        vstate->active = false;
        return 0;
    }

    float* out_buffer = Work_buffer_get_contents_mut(out_wb, 0);

    const int order = noise_state->order;
    if (order >= 0)
    {
        float* out = out_buffer;
        for (int32_t i = 0; i < frame_count; ++i)
        {
            *out++ = scales[i] * (float)dc_zero_filter(
                    order,
                    noise_vstate->buf[0],
                    Random_get_float_signal(&noise_vstate->rands[0]));

            *out++ = scales[i] * (float)dc_zero_filter(
                    order,
                    noise_vstate->buf[1],
                    Random_get_float_signal(&noise_vstate->rands[1]));
        }
    }
    else
    {
        float* out = out_buffer;
        for (int32_t i = 0; i < frame_count; ++i)
        {
            *out++ = scales[i] * (float)dc_pole_filter(
                    -order,
                    noise_vstate->buf[0],
                    Random_get_float_signal(&noise_vstate->rands[0]));

            *out++ = scales[i] * (float)dc_pole_filter(
                    -order,
                    noise_vstate->buf[1],
                    Random_get_float_signal(&noise_vstate->rands[1]));
        }
    }

#if 0
    for (int ch = 0; ch < 2; ++ch)
    {
        float* out_buffer = out_buffers[ch];
        if (out_buffer == NULL)
            continue;

        if (noise_state->order >= 0)
        {
            for (int32_t i = 0; i < frame_count; ++i)
            {
                const double val = dc_zero_filter(
                        noise_state->order,
                        noise_vstate->buf[ch],
                        Random_get_float_signal(&noise_vstate->rands[ch]));
                out_buffer[i] = (float)val * scales[i];
            }
        }
        else
        {
            for (int32_t i = 0; i < frame_count; ++i)
            {
                const double val = dc_pole_filter(
                        -noise_state->order,
                        noise_vstate->buf[ch],
                        Random_get_float_signal(&noise_vstate->rands[ch]));
                out_buffer[i] = (float)val * scales[i];
            }
        }
    }
#endif

    const int32_t audio_rate = proc_state->parent.audio_rate;
    Proc_ramp_attack(vstate, out_wb, frame_count, audio_rate);

//  fprintf(stderr, "max_amp is %lf\n", max_amp);
    return frame_count;
}
コード例 #10
0
ファイル: Freeverb_state.c プロジェクト: EdwardBetts/kunquat
static void Freeverb_pstate_render_mixed(
        Device_state* dstate,
        const Work_buffers* wbs,
        int32_t buf_start,
        int32_t buf_stop,
        double tempo)
{
    assert(dstate != NULL);
    assert(wbs != NULL);
    assert(buf_start >= 0);
    assert(tempo > 0);

    Freeverb_pstate* fstate = (Freeverb_pstate*)dstate;

    Proc_freeverb* freeverb = (Proc_freeverb*)dstate->device->dimpl;

    // Get reflectivity parameter stream
    float* refls = Device_state_get_audio_buffer_contents_mut(
            dstate, DEVICE_PORT_TYPE_RECEIVE, PORT_IN_REFL);
    if (refls == NULL)
    {
        refls = Work_buffers_get_buffer_contents_mut(wbs, FREEVERB_WB_FIXED_REFL);
        const float fixed_refl = exp2(-5 / freeverb->reflect_setting);
        for (int32_t i = buf_start; i < buf_stop; ++i)
            refls[i] = fixed_refl;
    }
    else
    {
        // Convert reflectivity to the domain of our algorithm
        static const float max_param_inv = -5.0 / 200.0;
        static const float min_param_inv = -5.0 / 0.001;
        for (int32_t i = buf_start; i < buf_stop; ++i)
        {
            const double orig_refl = refls[i];
            const double param_inv = -5.0 / max(0, orig_refl);
            const float refl = fast_exp2(clamp(param_inv, min_param_inv, max_param_inv));
            refls[i] = refl;
        }
    }

    // Get damp parameter stream
    float* damps = Device_state_get_audio_buffer_contents_mut(
            dstate, DEVICE_PORT_TYPE_RECEIVE, PORT_IN_DAMP);
    if (damps == NULL)
    {
        damps = Work_buffers_get_buffer_contents_mut(wbs, FREEVERB_WB_FIXED_DAMP);
        const float fixed_damp = freeverb->damp_setting * 0.01;
        for (int32_t i = buf_start; i < buf_stop; ++i)
            damps[i] = fixed_damp;
    }
    else
    {
        for (int32_t i = buf_start; i < buf_stop; ++i)
        {
            const float scaled_damp = damps[i] * 0.01f;
            damps[i] = clamp(scaled_damp, 0, 1);
        }
    }

    Work_buffer* in_wbs[] =
    {
        Device_state_get_audio_buffer(dstate, DEVICE_PORT_TYPE_RECEIVE, PORT_IN_AUDIO_L),
        Device_state_get_audio_buffer(dstate, DEVICE_PORT_TYPE_RECEIVE, PORT_IN_AUDIO_R),
    };

    Work_buffer* out_wbs[] =
    {
        Device_state_get_audio_buffer(dstate, DEVICE_PORT_TYPE_SEND, PORT_OUT_AUDIO_L),
        Device_state_get_audio_buffer(dstate, DEVICE_PORT_TYPE_SEND, PORT_OUT_AUDIO_R),
    };

    // TODO: figure out a cleaner way of dealing with the buffers
    Work_buffer* workspace[] =
    {
        Work_buffers_get_buffer_mut(wbs, FREEVERB_WB_LEFT),
        Work_buffers_get_buffer_mut(wbs, FREEVERB_WB_RIGHT),
    };

    // Get input data
    if ((in_wbs[0] != NULL) && (in_wbs[1] != NULL))
    {
        Work_buffer_copy(workspace[0], in_wbs[0], buf_start, buf_stop);
        Work_buffer_copy(workspace[1], in_wbs[1], buf_start, buf_stop);
    }
    else if ((in_wbs[0] == NULL) != (in_wbs[1] == NULL))
    {
        const Work_buffer* existing = (in_wbs[0] != NULL) ? in_wbs[0] : in_wbs[1];
        Work_buffer_copy(workspace[0], existing, buf_start, buf_stop);
        Work_buffer_copy(workspace[1], existing, buf_start, buf_stop);
    }
    else
    {
        Work_buffer_clear(workspace[0], buf_start, buf_stop);
        Work_buffer_clear(workspace[1], buf_start, buf_stop);
    }

    float* ws[] =
    {
        Work_buffer_get_contents_mut(workspace[0]),
        Work_buffer_get_contents_mut(workspace[1]),
    };

    // Apply reverb
    {
        float* comb_input =
            Work_buffers_get_buffer_contents_mut(wbs, FREEVERB_WB_COMB_INPUT);
        for (int32_t i = buf_start; i < buf_stop; ++i)
            comb_input[i] = (ws[0][i] + ws[1][i]) * freeverb->gain;

        for (int ch = 0; ch < 2; ++ch)
        {
            float* ws_buf = ws[ch];
            for (int32_t i = buf_start; i < buf_stop; ++i)
                ws_buf[i] = 0;

            for (int comb = 0; comb < FREEVERB_COMBS; ++comb)
                Freeverb_comb_process(
                        fstate->combs[ch][comb],
                        ws_buf,
                        comb_input,
                        refls,
                        damps,
                        buf_start,
                        buf_stop);

            for (int allpass = 0; allpass < FREEVERB_ALLPASSES; ++allpass)
                Freeverb_allpass_process(
                        fstate->allpasses[ch][allpass], ws_buf, buf_start, buf_stop);
        }

        for (int32_t i = buf_start; i < buf_stop; ++i)
        {
            ws[0][i] = ws[0][i] * freeverb->wet1 + ws[1][i] * freeverb->wet2;
            ws[1][i] = ws[1][i] * freeverb->wet1 + ws[0][i] * freeverb->wet2;
        }
    }

    // Copy results to outputs that exist
    for (int ch = 0; ch < 2; ++ch)
    {
        if (out_wbs[ch] != NULL)
            Work_buffer_copy(out_wbs[ch], workspace[ch], buf_start, buf_stop);
    }

    return;
}
コード例 #11
0
void Linear_controls_fill_work_buffer(
        Linear_controls* lc,
        Work_buffer* wb,
        int32_t buf_start,
        int32_t buf_stop)
{
    rassert(lc != NULL);
    rassert(wb != NULL);
    rassert(buf_start < buf_stop);

    float* values = Work_buffer_get_contents_mut(wb);

    int32_t const_start = buf_start;

    // Apply slider
    {
        int32_t cur_pos = buf_start;
        while (cur_pos < buf_stop)
        {
            const int32_t estimated_steps =
                Slider_estimate_active_steps_left(&lc->slider);
            if (estimated_steps > 0)
            {
                int32_t slide_stop = buf_stop;
                if (estimated_steps < buf_stop - cur_pos)
                    slide_stop = cur_pos + estimated_steps;

                double new_value = lc->value;
                for (int32_t i = cur_pos; i < slide_stop; ++i)
                {
                    new_value = Slider_step(&lc->slider);
                    values[i] = (float)new_value;
                }
                lc->value = new_value;

                const_start = slide_stop;
                cur_pos = slide_stop;
            }
            else
            {
                const float value = (float)lc->value;
                for (int32_t i = cur_pos; i < buf_stop; ++i)
                    values[i] = value;

                cur_pos = buf_stop;
            }
        }
    }

    // Apply LFO
    {
        int32_t cur_pos = buf_start;
        int32_t final_lfo_stop = buf_start;
        while (cur_pos < buf_stop)
        {
            const int32_t estimated_steps = LFO_estimate_active_steps_left(&lc->lfo);
            if (estimated_steps > 0)
            {
                int32_t lfo_stop = buf_stop;
                if (estimated_steps < buf_stop - cur_pos)
                    lfo_stop = cur_pos + estimated_steps;

                for (int32_t i = cur_pos; i < lfo_stop; ++i)
                    values[i] += (float)LFO_step(&lc->lfo);

                final_lfo_stop = lfo_stop;
                cur_pos = lfo_stop;
            }
            else
            {
                final_lfo_stop = cur_pos;
                break;
            }
        }

        const_start = max(const_start, final_lfo_stop);
    }

    // Clamp values
    if (lc->min_value > -INFINITY)
    {
        const float min_value = (float)lc->min_value;
        for (int32_t i = buf_start; i < buf_stop; ++i)
            values[i] = max(min_value, values[i]);
    }

    if (lc->max_value < INFINITY)
    {
        const float max_value = (float)lc->max_value;
        for (int32_t i = buf_start; i < buf_stop; ++i)
            values[i] = min(max_value, values[i]);
    }

    // Mark constant region of the buffer
    Work_buffer_set_const_start(wb, const_start);

    return;
}