示例#1
0
static int32_t Padsynth_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 buf_start,
        int32_t buf_stop,
        double tempo)
{
    rassert(vstate != NULL);
    rassert(proc_state != NULL);
    rassert(proc_ts != NULL);
    rassert(au_state != NULL);
    rassert(wbs != NULL);
    rassert(tempo > 0);

    if (buf_start == buf_stop)
        return buf_start;

    const Device_state* dstate = &proc_state->parent;

    Padsynth_vstate* ps_vstate = (Padsynth_vstate*)vstate;

    const Proc_padsynth* ps = (const Proc_padsynth*)dstate->device->dimpl;
    if (ps->sample_map == NULL)
    {
        vstate->active = false;
        return buf_start;
    }

    // Get frequencies
    Work_buffer* freqs_wb = Device_thread_state_get_voice_buffer(
            proc_ts, DEVICE_PORT_TYPE_RECV, PORT_IN_PITCH);
    Work_buffer* pitches_wb = freqs_wb;

    if (isnan(ps_vstate->init_pitch))
        ps_vstate->init_pitch =
            (pitches_wb != NULL) ? Work_buffer_get_contents(pitches_wb)[buf_start] : 0;

    if (freqs_wb == NULL)
        freqs_wb = Work_buffers_get_buffer_mut(wbs, PADSYNTH_WB_FIXED_PITCH);
    Proc_fill_freq_buffer(freqs_wb, pitches_wb, buf_start, buf_stop);
    const float* freqs = Work_buffer_get_contents(freqs_wb);

    // Get volume scales
    Work_buffer* scales_wb = Device_thread_state_get_voice_buffer(
            proc_ts, DEVICE_PORT_TYPE_RECV, PORT_IN_FORCE);
    Work_buffer* dBs_wb = scales_wb;
    if (scales_wb == NULL)
        scales_wb = Work_buffers_get_buffer_mut(wbs, PADSYNTH_WB_FIXED_FORCE);
    Proc_fill_scale_buffer(scales_wb, dBs_wb, buf_start, buf_stop);
    const float* scales = Work_buffer_get_contents(scales_wb);

    // Get output buffer for writing
    float* out_bufs[2] = { NULL };
    Proc_state_get_voice_audio_out_buffers(
            proc_ts, PORT_OUT_AUDIO_L, PORT_OUT_COUNT, out_bufs);

    // Choose our sample
    const Padsynth_sample_entry* entry =
        Padsynth_sample_map_get_entry(ps->sample_map, ps_vstate->init_pitch);
    if (entry == NULL)
    {
        vstate->active = false;
        return buf_start;
    }

    // Render audio
    const float* sample_buf = Sample_get_buffer(entry->sample, 0);
    const int32_t length = Padsynth_sample_map_get_sample_length(ps->sample_map);
    const int32_t sample_rate = PADSYNTH_DEFAULT_AUDIO_RATE;
    const double sample_freq = cents_to_Hz(entry->center_pitch);

    const double audio_rate = dstate->audio_rate;

    const double init_pos = fmod(ps_vstate->pos, length); // the length may have changed
    bool is_state_pos_updated = false;

    for (int32_t ch = 0; ch < 2; ++ch)
    {
        float* out_buf = out_bufs[ch];
        if (out_buf == NULL)
            continue;

        double pos = init_pos;
        if (ps->is_stereo_enabled && is_state_pos_updated)
        {
            pos += (length / 2);
            if (pos >= length)
                pos -= length;
        }

        for (int32_t i = buf_start; i < buf_stop; ++i)
        {
            const float freq = freqs[i];
            const float scale = scales[i];

            const int32_t pos1 = (int32_t)pos;
            const int32_t pos2 = pos1 + 1;
            const double lerp_val = pos - floor(pos);

            const float item1 = sample_buf[pos1];
            const float item2 = sample_buf[pos2];
            const float value = (float)lerp(item1, item2, lerp_val);

            out_buf[i] = value * scale;

            pos += (freq / sample_freq) * (sample_rate / audio_rate);

            while (pos >= length)
                pos -= length;
        }

        if (!ps->is_stereo_enabled || !is_state_pos_updated)
        {
            ps_vstate->pos = pos;
            is_state_pos_updated = true;
        }
    }


    if (ps->is_ramp_attack_enabled)
        Proc_ramp_attack(vstate, 2, out_bufs, buf_start, buf_stop, dstate->audio_rate);

    return buf_stop;
}
示例#2
0
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;
}
示例#3
0
static 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 buf_start,
        int32_t buf_stop,
        double tempo)
{
    rassert(vstate != NULL);
    rassert(proc_state != NULL);
    rassert(proc_ts != NULL);
    rassert(au_state != NULL);
    rassert(wbs != NULL);
    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),
            0);

    // Get output buffers for writing
    float* out_buffers[2] = { NULL };
    Proc_state_get_voice_audio_out_buffers(proc_ts, 0, 2, out_buffers);

    Proc_debug* debug = (Proc_debug*)proc->parent.dimpl;
    if (debug->single_pulse)
    {
        if (buf_start < buf_stop)
        {
            const float val = 1.0;
            if (out_buffers[0] != NULL)
                out_buffers[0][buf_start] = val;
            if (out_buffers[1] != NULL)
                out_buffers[1][buf_start] = val;
            Voice_state_set_finished(vstate);

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

            return buf_start + 1;
        }
        return buf_start;
    }

    const int32_t audio_rate = proc_state->parent.audio_rate;

    for (int32_t i = buf_start; i < buf_stop; ++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];

            Voice_state_mark_release_data(vstate, i + 1);
        }

        if (out_buffers[0] != NULL)
            out_buffers[0][i] = (float)vals[0];
        if (out_buffers[1] != NULL)
            out_buffers[1][i] = (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_finished(vstate);
                return i + 1;
            }
        }

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

    return buf_stop;
}