1. 算法原理
合唱即多人一起唱歌,以下是算法的原理图:
/* * * * gain-in ___ * ibuff -----+--------------------------------------------->| | * | _________ | | * | | | * level 1 | | * +---->| delay 1 |----------------------------->| | * | |_________| | | * | /|\ | | * : | | | * : +-----------------+ +--------------+ | + | * : | Delay control 1 |<--| mod. speed 1 | | | * : +-----------------+ +--------------+ | | * | _________ | | * | | | * level n | | * +---->| delay n |----------------------------->| | * |_________| | | * /|\ |___| * | | * +-----------------+ +--------------+ | * gain-out * | Delay control n |<--| mod. speed n | | * +-----------------+ +--------------+ +----->obuff * * */
2. 代码实现
void dsound_chorus_processmix(dsound_chorus_t* chorus, dsound_real_t *in,
dsound_real_t *left_out, dsound_real_t *right_out)
{
int sample_index;
int i;
dsound_real_t d_in, d_out;
for (sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++) {
d_in = in[sample_index];
d_out = 0.0f;
# if 0
/* Debug: Listen to the chorus signal only */
left_out[sample_index]=0;
right_out[sample_index]=0;
#endif
/* Write the current sample into the circular buffer */
chorus->chorusbuf[chorus->counter] = d_in;
for (i = 0; i < chorus->number_blocks; i++) {
int ii;
/* Calculate the delay in subsamples for the delay line of chorus block nr. */
/* The value in the lookup table is so, that this expression
* will always be positive. It will always include a number of
* full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
* remain positive at all times. */
int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
- chorus->lookup_tab[chorus->phase[i]]);
int pos_samples = pos_subsamples/INTERPOLATION_SUBSAMPLES;
/* modulo divide by INTERPOLATION_SUBSAMPLES */
pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
/* Add the delayed signal to the chorus sum d_out Note: The
* delay in the delay line moves backwards for increasing
* delay!*/
/* The & in chorusbuf[...] is equivalent to a division modulo
MAX_SAMPLES, only faster. */
d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
* chorus->sinc_table[ii][pos_subsamples];
pos_samples--;
};
/* Cycle the phase of the modulating LFO */
chorus->phase[i]++;
chorus->phase[i] %= (chorus->modulation_period_samples);
} /* foreach chorus block */
d_out *= chorus->level;
/* Add the chorus sum d_out to output */
left_out[sample_index] += d_out;
right_out[sample_index] += d_out;
/* Move forward in circular buffer */
chorus->counter++;
chorus->counter %= MAX_SAMPLES;
} /* foreach sample */
}
浙公网安备 33010602011771号