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 */}
posted on 2012-06-26 08:03 阅读( ...) 评论( ...)