int32_t Rangemap_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(isfinite(tempo)); rassert(tempo > 0); const Proc_rangemap* rangemap = (const Proc_rangemap*)proc_state->parent.device->dimpl; float mul = 0; float add = 0; get_scalars( &mul, &add, rangemap->from_min, rangemap->from_max, rangemap->min_to, rangemap->max_to); const double range_min = min(rangemap->min_to, rangemap->max_to); const double range_max = max(rangemap->min_to, rangemap->max_to); const float min_val = (float)(rangemap->clamp_dest_min ? range_min : -INFINITY); const float max_val = (float)(rangemap->clamp_dest_max ? range_max : INFINITY); Work_buffer* in_wb = Proc_get_voice_input_2ch(proc_ts, 0, frame_count); if (in_wb == NULL) { in_wb = Work_buffers_get_buffer_mut(wbs, RANGEMAP_WB_FIXED_INPUT, 2); Work_buffer_clear_all(in_wb, 0, frame_count); } Work_buffer* out_wb = Proc_get_voice_output_2ch(proc_ts, 0); rassert(out_wb != NULL); apply_range(in_wb, out_wb, frame_count, mul, add, min_val, max_val); return frame_count; }
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; }
static int32_t Add_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 Device_state* dstate = &proc_state->parent; const Proc_add* add = (Proc_add*)proc_state->parent.device->dimpl; Add_vstate* add_state = (Add_vstate*)vstate; rassert(is_p2(ADD_BASE_FUNC_SIZE)); // 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 (freqs_wb == NULL) freqs_wb = Work_buffers_get_buffer_mut(wbs, ADD_WORK_BUFFER_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, ADD_WORK_BUFFER_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); // Get phase modulation signal const Work_buffer* mod_wbs[] = { Device_thread_state_get_voice_buffer( proc_ts, DEVICE_PORT_TYPE_RECV, PORT_IN_PHASE_MOD_L), Device_thread_state_get_voice_buffer( proc_ts, DEVICE_PORT_TYPE_RECV, PORT_IN_PHASE_MOD_R), }; for (int ch = 0; ch < 2; ++ch) { if (mod_wbs[ch] == NULL) { Work_buffer* zero_buf = Work_buffers_get_buffer_mut( wbs, (Work_buffer_type)(ADD_WORK_BUFFER_MOD_L + ch)); Work_buffer_clear(zero_buf, buf_start, buf_stop); mod_wbs[ch] = zero_buf; } } // Add base waveform tones const double inv_audio_rate = 1.0 / dstate->audio_rate; const float* base = Sample_get_buffer(add->base, 0); for (int h = 0; h < add_state->tone_limit; ++h) { const Add_tone* tone = &add->tones[h]; const double pitch_factor = tone->pitch_factor; const double volume_factor = tone->volume_factor; if ((pitch_factor <= 0) || (volume_factor <= 0)) continue; const double pannings[] = { -tone->panning, tone->panning, }; const double pitch_factor_inv_audio_rate = pitch_factor * inv_audio_rate; Add_tone_state* tone_state = &add_state->tones[h]; for (int32_t ch = 0; ch < 2; ++ch) { float* out_buf_ch = out_bufs[ch]; if (out_buf_ch == NULL) continue; const double panning_factor = 1 + pannings[ch]; const float* mod_values_ch = Work_buffer_get_contents(mod_wbs[ch]); double phase = tone_state->phase[ch]; int32_t res_slice_start = buf_start; while (res_slice_start < buf_stop) { int32_t res_slice_stop = buf_stop; // Get current pitch range const float first_mod_shift = mod_values_ch[res_slice_start] - add_state->prev_mod[ch]; const float first_phase_shift_abs = (float)fabs( first_mod_shift + (freqs[res_slice_start] * pitch_factor_inv_audio_rate)); int shift_exp = 0; const float shift_norm = frexpf(first_phase_shift_abs, &shift_exp); const float min_phase_shift_abs = ldexpf(0.5f, shift_exp); const float max_phase_shift_abs = min_phase_shift_abs * 2.0f; // Choose appropriate waveform resolution for current pitch range int32_t cur_size = ADD_BASE_FUNC_SIZE; if (isfinite(shift_norm) && (shift_norm > 0.0f)) { cur_size = (int32_t)ipowi(2, max(-shift_exp + 1, 3)); cur_size = min(cur_size, ADD_BASE_FUNC_SIZE * 2); rassert(is_p2(cur_size)); } const uint32_t cur_size_mask = (uint32_t)cur_size - 1; const int base_offset = (ADD_BASE_FUNC_SIZE * 4 - cur_size * 2); rassert(base_offset >= 0); rassert(base_offset < (ADD_BASE_FUNC_SIZE * 4) - 1); const float* cur_base = base + base_offset; // Get length of input compatible with current waveform resolution const int32_t res_check_stop = min(res_slice_stop, max(Work_buffer_get_const_start(freqs_wb), Work_buffer_get_const_start(mod_wbs[ch])) + 1); for (int32_t i = res_slice_start + 1; i < res_check_stop; ++i) { const float cur_mod_shift = mod_values_ch[i] - mod_values_ch[i - 1]; const float cur_phase_shift_abs = (float)fabs( cur_mod_shift + (freqs[i] * pitch_factor_inv_audio_rate)); if (cur_phase_shift_abs < min_phase_shift_abs || cur_phase_shift_abs > max_phase_shift_abs) { res_slice_stop = i; break; } } for (int32_t i = res_slice_start; i < res_slice_stop; ++i) { const float freq = freqs[i]; const float vol_scale = scales[i]; const float mod_val = mod_values_ch[i]; // Note: + mod_val is specific to phase modulation const double actual_phase = phase + mod_val; const double pos = actual_phase * cur_size; // Note: direct cast of negative doubles to uint32_t is undefined const uint32_t pos1 = (uint32_t)(int32_t)floor(pos) & cur_size_mask; const uint32_t pos2 = (pos1 + 1) & cur_size_mask; const float item1 = cur_base[pos1]; const float item_diff = cur_base[pos2] - item1; const double lerp_val = pos - floor(pos); const double value = (item1 + (lerp_val * item_diff)) * volume_factor * panning_factor; out_buf_ch[i] += (float)value * vol_scale; phase += freq * pitch_factor_inv_audio_rate; // Normalise to range [0, 1) if (phase >= 1) { phase -= 1; // Don't bother updating the phase if our frequency is too high if (phase >= 1) phase = tone_state->phase[ch]; } } rassert(res_slice_start < res_slice_stop); add_state->prev_mod[ch] = mod_values_ch[res_slice_stop - 1]; res_slice_start = res_slice_stop; } tone_state->phase[ch] = phase; } } if (add->is_ramp_attack_enabled) Proc_ramp_attack(vstate, 2, out_bufs, buf_start, buf_stop, dstate->audio_rate); return buf_stop; }
static int32_t Compress_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(buf_start >= 0); rassert(buf_stop >= 0); rassert(isfinite(tempo)); rassert(tempo > 0); const Device_state* dstate = &proc_state->parent; const Proc_compress* compress = (const Proc_compress*)proc_state->parent.device->dimpl; Compress_vstate* cvstate = (Compress_vstate*)vstate; // Get audio input buffers const Work_buffer* in_wbs[2] = { Device_thread_state_get_voice_buffer( proc_ts, DEVICE_PORT_TYPE_RECV, PORT_IN_AUDIO_L), Device_thread_state_get_voice_buffer( proc_ts, DEVICE_PORT_TYPE_RECV, PORT_IN_AUDIO_R), }; // Get audio output buffers Work_buffer* out_wbs[2] = { Device_thread_state_get_voice_buffer( proc_ts, DEVICE_PORT_TYPE_SEND, PORT_OUT_AUDIO_L), Device_thread_state_get_voice_buffer( proc_ts, DEVICE_PORT_TYPE_SEND, PORT_OUT_AUDIO_R), }; // Get level buffers Work_buffer* level_wbs[2] = { Work_buffers_get_buffer_mut(wbs, COMPRESS_WB_LEVEL_L), Work_buffers_get_buffer_mut(wbs, COMPRESS_WB_LEVEL_R), }; // Get gain buffer Work_buffer* gain_wb = Device_thread_state_get_voice_buffer( proc_ts, DEVICE_PORT_TYPE_SEND, PORT_OUT_GAIN); if (gain_wb == NULL) gain_wb = Work_buffers_get_buffer_mut(wbs, COMPRESS_WB_GAIN); Compress_states_update( cvstate->cstates, compress, gain_wb, level_wbs, in_wbs, buf_start, buf_stop, dstate->audio_rate); write_audio(out_wbs, gain_wb, in_wbs, buf_start, buf_stop); return buf_stop; }
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; }