modulator[] mod; /* sinus/triangle modulator */ /*----------------------------------------------------------------------------- * API * ------------------------------------------------------------------------------*/ /** * Create the chorus unit. * @sample_rate audio sample rate in Hz. * @return pointer on chorus unit. */ public fluid_chorus(float psample_rate, int bufsize) { FLUID_BUFSIZE = bufsize; sample_rate = psample_rate; mod = new modulator[MAX_CHORUS]; for (int i = 0; i < MAX_CHORUS; i++) { mod[i] = new modulator(); } //# ifdef DEBUG_PRINT // printf("fluid_chorus_t:{0} bytes\n", sizeof(fluid_chorus_t)); // printf("float:{0} bytes\n", sizeof(float)); //#endif //# ifdef DEBUG_PRINT // printf("NEW_MOD\n"); //#endif new_mod_delay_line(MAX_SAMPLES); }
/*----------------------------------------------------------------------------- * Reads the sample value out of the modulated delay line. * @param mdl, pointer on modulated delay line. * @return the sample value. * -----------------------------------------------------------------------------*/ float get_mod_delay(modulator mod) { float out_index; /* new modulated index position */ int int_out_index; /* integer part of out_index */ float outp; /* value to return */ /* Checks if the modulator must be updated (every mod_rate samples). */ /* Important: center_pos_mod must be used immediately for the * first sample. So, mdl.index_rate must be initialized * to mdl.mod_rate (new_mod_delay_line()) */ if (index_rate >= mod_rate) { /* out_index = center position (center_pos_mod) + sinus waweform */ if (type == fluid_chorus_mod.FLUID_CHORUS_MOD_SINE) { out_index = center_pos_mod + get_mod_sinus(mod.sinus) * mod_depth; } else { out_index = center_pos_mod + get_mod_triang(mod.triang) * mod_depth; } /* extracts integer part in int_out_index */ if (out_index >= 0f) { int_out_index = (int)out_index; /* current integer part */ /* forces read index (line_out) with integer modulation value */ /* Boundary check and circular motion as needed */ if ((mod.line_out = int_out_index) >= size) { mod.line_out -= size; } } else /* negative */ { int_out_index = (int)(out_index - 1); /* previous integer part */ /* forces read index (line_out) with integer modulation value */ /* circular motion as needed */ mod.line_out = int_out_index + size; } /* extracts fractionnal part. (it will be used when interpolating * between line_out and line_out +1) and memorize it. * Memorizing is necessary for modulation rate above 1 */ mod.frac_pos_mod = out_index - int_out_index; } /* First order all-pass interpolation ----------------------------------*/ /* https://ccrma.stanford.edu/~jos/pasp/First_Order_Allpass_Interpolation.html */ /* begins interpolation: read current sample */ outp = line[mod.line_out]; /* updates line_out to the next sample. * Boundary check and circular motion as needed */ if (++mod.line_out >= size) { mod.line_out -= size; } /* Fractional interpolation between next sample (at next position) and * previous output added to current sample. */ outp += mod.frac_pos_mod * (line[mod.line_out] - mod.buffer); mod.buffer = outp; /* memorizes current output */ return(outp); }