mirror of
https://github.com/DrBeef/QuestZDoom.git
synced 2025-03-05 17:10:55 +00:00
120 lines
4.6 KiB
C
120 lines
4.6 KiB
C
/* FluidSynth - A Software Synthesizer
|
|
*
|
|
* Copyright (C) 2003 Peter Hanappe and others.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public License
|
|
* as published by the Free Software Foundation; either version 2 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the Free
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
* 02111-1307, USA
|
|
*/
|
|
|
|
|
|
/* Purpose:
|
|
* Low-level voice processing:
|
|
*
|
|
* - interpolates (obtains values between the samples of the original waveform data)
|
|
* - filters (applies a lowpass filter with variable cutoff frequency and quality factor)
|
|
* - mixes the processed sample to left and right output using the pan setting
|
|
* - sends the processed sample to chorus and reverb
|
|
*
|
|
*
|
|
* This file does -not- generate an object file.
|
|
* Instead, it is #included in several places in fluid_voice.c.
|
|
* The motivation for this is
|
|
* - Calling it as a subroutine may be time consuming, especially with optimization off
|
|
* - The previous implementation as a macro was clumsy to handle
|
|
*
|
|
*
|
|
* Fluid_voice.c sets a couple of variables before #including this:
|
|
* - dsp_data: Pointer to the original waveform data
|
|
* - dsp_left_buf: The generated signal goes here, left channel
|
|
* - dsp_right_buf: right channel
|
|
* - dsp_reverb_buf: Send to reverb unit
|
|
* - dsp_chorus_buf: Send to chorus unit
|
|
* - dsp_start: Start processing at this output buffer index
|
|
* - dsp_end: End processing just before this output buffer index
|
|
* - dsp_a1: Coefficient for the filter
|
|
* - dsp_a2: same
|
|
* - dsp_b0: same
|
|
* - dsp_b1: same
|
|
* - dsp_b2: same
|
|
* - dsp_filter_flag: Set, the filter is needed (many sound fonts don't use
|
|
* the filter at all. If it is left at its default setting
|
|
* of roughly 20 kHz, there is no need to apply filterling.)
|
|
* - dsp_interp_method: Which interpolation method to use.
|
|
* - voice holds the voice structure
|
|
*
|
|
* Some variables are set and modified:
|
|
* - dsp_phase: The position in the original waveform data.
|
|
* This has an integer and a fractional part (between samples).
|
|
* - dsp_phase_incr: For each output sample, the position in the original
|
|
* waveform advances by dsp_phase_incr. This also has an integer
|
|
* part and a fractional part.
|
|
* If a sample is played at root pitch (no pitch change),
|
|
* dsp_phase_incr is integer=1 and fractional=0.
|
|
* - dsp_amp: The current amplitude envelope value.
|
|
* - dsp_amp_incr: The changing rate of the amplitude envelope.
|
|
*
|
|
* A couple of variables are used internally, their results are discarded:
|
|
* - dsp_i: Index through the output buffer
|
|
* - dsp_phase_fractional: The fractional part of dsp_phase
|
|
* - dsp_coeff: A table of four coefficients, depending on the fractional phase.
|
|
* Used to interpolate between samples.
|
|
* - dsp_process_buffer: Holds the processed signal between stages
|
|
* - dsp_centernode: delay line for the IIR filter
|
|
* - dsp_hist1: same
|
|
* - dsp_hist2: same
|
|
*
|
|
*/
|
|
|
|
|
|
/* Nonoptimized DSP loop */
|
|
#warning "This code is meant for experiments only.";
|
|
|
|
/* wave table interpolation */
|
|
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
|
|
|
dsp_coeff = &interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];
|
|
dsp_phase_index = fluid_phase_index(dsp_phase);
|
|
dsp_sample = (dsp_amp *
|
|
(dsp_coeff->a0 * dsp_data[dsp_phase_index]
|
|
+ dsp_coeff->a1 * dsp_data[dsp_phase_index+1]
|
|
+ dsp_coeff->a2 * dsp_data[dsp_phase_index+2]
|
|
+ dsp_coeff->a3 * dsp_data[dsp_phase_index+3]));
|
|
|
|
/* increment phase and amplitude */
|
|
fluid_phase_incr(dsp_phase, dsp_phase_incr);
|
|
dsp_amp += dsp_amp_incr;
|
|
|
|
/* filter */
|
|
/* The filter is implemented in Direct-II form. */
|
|
dsp_centernode = dsp_sample - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
|
|
dsp_sample = dsp_b0 * dsp_centernode + dsp_b1 * dsp_hist1 + dsp_b2 * dsp_hist2;
|
|
dsp_hist2 = dsp_hist1;
|
|
dsp_hist1 = dsp_centernode;
|
|
|
|
/* pan */
|
|
dsp_left_buf[dsp_i] += voice->amp_left * dsp_sample;
|
|
dsp_right_buf[dsp_i] += voice->amp_right * dsp_sample;
|
|
|
|
/* reverb */
|
|
if (dsp_reverb_buf){
|
|
dsp_reverb_buf[dsp_i] += voice->amp_reverb * dsp_sample;
|
|
}
|
|
|
|
/* chorus */
|
|
if (dsp_chorus_buf){
|
|
dsp_chorus_buf[dsp_i] += voice->amp_chorus * dsp_sample;
|
|
}
|
|
}
|
|
|