合唱音效

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 */
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值