frac32 modulation inlet for attack parameter
frac32 modulation inlet for decay parameter
frac32 modulation inlet for density parameter
frac32 modulation inlet for playback parameter
frac32 modulation inlet for pos parameter
bool32 hard retrig for a new grain
int32 number of active grains (use for debug)
frac32buffer audio out
frac32.s.map.klineartime.exp set the attack length for a grain
frac32.s.map.klineartime.exp set the decay length for a grain
frac32.u.map how many grains per second are played (not in natural units)
frac32.u.map position in the table from where to read audio
frac32.s.map.ratio playback speed for grains.0=stop; +64 = normal speed; -64 reverse playback. For faster tempos use mod inlet
int32 useful in case many grains are played
spinner maximum number of allocated grains
objref name of the table object to granulize
bool grain_active[attr_grains];
uint32_t grain_amp[attr_grains];
uint32_t grain_phase[attr_grains];
uint32_t global_phase;
uint32_t global_phase_old;
uint32_t grain_num = 0;
uint32_t temp_32;
uint32_t freq;
uint32_t global_attack;
uint32_t global_decay;
uint32_t pitchmul =
66000 *
((1 << 27) / attr_table.LENGTH); // this coefficient should be adjusted
// (const*48000*2^27 / LENGTH)
bool rtrig;
bool dostuff = 0;
if (inlet_reset && !rtrig) {
global_phase_old = 0;
global_phase = 0;
dostuff = 1;
rtrig = 1;
} else {
if (!inlet_reset)
rtrig = 0;
global_phase += param_density + inlet_density;
if (global_phase < global_phase_old) // time to activate another grain
dostuff = 1;
global_phase_old = global_phase;
}
MTOF(-param_attack - inlet_attack, global_attack);
MTOF(-param_decay - inlet_decay, global_decay);
freq = ___SMMUL(param_playback + inlet_playback >> 11, pitchmul);
if (dostuff) {
grain_num++;
if (grain_num >= attr_grains)
grain_num = 0;
grain_amp[grain_num] = 0;
grain_active[grain_num] = 1;
grain_phase[grain_num] = param_pos + inlet_pos;
}
int32_t accum = 0;
int voicealloc = 0;
for (int i = 0; i < attr_grains; i++) {
if (grain_active[i]) // if in attack phase (active)
{
temp_32 = grain_amp[i] + (global_attack >> 5);
if (temp_32 > grain_amp[i])
grain_amp[i] = temp_32;
else
grain_active[i] = 0;
accum += ___SMMUL(attr_table.array[__USAT(grain_phase[i], 27) >>
(27 - attr_table.LENGTHPOW)]
<< attr_table.GAIN,
grain_amp[i] >> 1) >>
param_gainreduction;
grain_phase[i] += freq;
voicealloc++;
} else if (grain_amp[i]) // not active but in decay phase
{
temp_32 = grain_amp[i] - (global_decay >> 5);
if (temp_32 < grain_amp[i])
grain_amp[i] = temp_32;
else
grain_amp[i] = 0;
accum += ___SMMUL(attr_table.array[__USAT(grain_phase[i], 27) >>
(27 - attr_table.LENGTHPOW)]
<< attr_table.GAIN,
grain_amp[i] >> 1) >>
param_gainreduction;
grain_phase[i] += freq;
voicealloc++;
}
}
outlet_o = accum;
outlet_alloc = voicealloc;