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; }
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]); }
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); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }