static void mix_interface_connection( Device_state* ds, const Device_state* in_ds, uint32_t start, uint32_t stop) { assert(ds != NULL); assert(in_ds != NULL); for (int port = 0; port < KQT_DEVICE_PORTS_MAX; ++port) { Audio_buffer* out = Device_state_get_audio_buffer( ds, DEVICE_PORT_TYPE_SEND, port); const Audio_buffer* in = Device_state_get_audio_buffer( in_ds, DEVICE_PORT_TYPE_RECEIVE, port); if (in != NULL && out != NULL) Audio_buffer_mix(out, in, start, stop); } return; }
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; }