int main (int argc, char **argv) { float outbuf[BUFSIZE]; float del, att, spd, shape, mod, op; int nsamples, s, i; program_name = argv[0]; if (argc != 7) { usage(); } nsamples = parse_int(argv[1], "nsamples"); del = parse_float(argv[2], "del"); att = parse_float(argv[3], "att"); spd = parse_float(argv[4], "spd"); shape = parse_shape(argv[5], "shape"); mod = parse_float(argv[6], "mod"); op = 0.0f; if (!nsamples) { fprintf(stderr, "%s: nsamples must be nonzero\n", program_name); usage(); } // Seconds * samples/second = samples LfoParams p = {20.0f * 48000.0f, &del, &att, &spd, &shape, &mod, &op}; Lfo *lfo = lfo_create(&p); lfo_trigger(lfo); for (s = 0; s < nsamples;) { // Blank buffer for (i=0; i<BUFSIZE; ++i) outbuf[i] = 0.0f; // Run lfo_run(lfo, outbuf, BUFSIZE); // Write for (i = 0; i < BUFSIZE && s < nsamples; ++i, ++s) printf("%d %f\n", s, outbuf[i]); } lfo_destroy(lfo); return EXIT_SUCCESS; }
int sample_default(Sample* sample, int rate) { int frames = rate / 8; float* tmp; LFO* lfo; LFOParams lfopar; int i; double v; float const* lfo_out; debug("Creating default sample\n"); if (!(tmp = malloc(frames * 2 * sizeof(*tmp)))) { pf_error(PF_ERR_SAMPLE_DEFAULT_ALLOC); return -1; } sample->frames = frames; sample->sp = tmp; lfo = lfo_new(); lfo_init(lfo); lfo_params_init(&lfopar, 523.251, LFO_SHAPE_SAW); lfo_trigger(lfo, &lfopar); lfo_out = lfo_output(lfo); for (i = 0; i < frames; ++i) { lfo_tick(lfo); v = *lfo_out * 0.9; *tmp++ = v; *tmp++ = v; } lfo_free(lfo); sample->filename = strdup("Default"); sample->default_sample = true; return 0; }
/* a helper function to activate a voice for a patch */ inline static void patch_trigger_patch (Patch* p, int note, float vel, Tick ticks) { int i; PatchVoice* v; int index; /* the index we ended up settling on */ float key_track; bool legato; if (p->sample->sp == NULL) return; if (p->upper_note == p->lower_note) key_track = 1.0; else key_track = (float)(note - p->lower_note) / (p->upper_note - p->lower_note); legato = patch_bool_get(&p->legato, p); if (p->mono && legato) { /* half of the previous logic operating here was ignored. * removing it left only logic which could be simplified * to the following: */ v = p->voices[0]; index = 0; if (!v->active || v->released) v->vel = vel; else { /* don't trigger voice, do legato instead: */ v->ticks = ticks; v->note = note; v->vel = vel; v->relset = -1; /* cancel any pending release */ v->relmode = RELEASE_NONE; v->released = false; v->to_end = false; v->xfade = false; v->loop = p->play_mode & PATCH_PLAY_LOOP; v->key_track = key_track; v->portamento = patch_bool_get(&p->porta, p); v->porta_secs = patch_float_get(&p->porta_secs, p); prepare_pitch(p, v, note); return; } } else /* mono w/o legato, or poly */ { int oldest = 0; Tick oldestticks = ticks; /* find a free voice slot and determine the oldest running voice */ for (i = 0; i < PATCH_VOICE_COUNT; ++i) { if (p->voices[i]->ticks <= oldestticks) { oldestticks = p->voices[i]->ticks; oldest = i; } if (!p->voices[i]->active) break; } /* take the oldest running voice's slot if we couldn't find an * empty one */ index = (i == PATCH_VOICE_COUNT) ? oldest : i; } v = p->voices[index]; /* shutdown any running voices if monophonic */ if (p->mono) patch_release_patch(p, -69, RELEASE_CUTOFF); /* fill in our voice */ v->ticks = ticks; v->relset = -1; /* N/A at this time */ v->relmode = RELEASE_NONE; v->released = false; v->to_end = false; /* TRUE after loop */ v->xfade = false; v->loop = p->play_mode & PATCH_PLAY_LOOP; v->note = note; v->key_track = key_track; v->legato = legato; v->portamento = patch_bool_get(&p->porta, p); v->porta_secs = patch_float_get(&p->porta_secs, p); if (!(p->mono && v->legato)) v->vel = vel; if (!p->mono) v->fll = v->fbl = v->flr = v->fbr = 0; for (i = 0; i < MAX_MOD_SLOTS; ++i) { v->amp_mod[i] = patch_mod_id_to_pointer(p->amp.mod_id[i], p, v); v->pan_mod[i] = patch_mod_id_to_pointer(p->pan.mod_id[i], p, v); v->ffreq_mod[i] = patch_mod_id_to_pointer(p->ffreq.mod_id[i], p, v); v->freso_mod[i] = patch_mod_id_to_pointer(p->freso.mod_id[i], p, v); v->pitch_mod[i] = patch_mod_id_to_pointer(p->pitch.mod_id[i], p, v); } if (!(p->mono && v->legato && v->active)) playstate_init_fade_in(p, v); prepare_pitch(p, v, note); for (i = 0; i < VOICE_MAX_ENVS; i++) { if (p->env_params[i].active) { adsr_set_params(v->env[i], &p->env_params[i]); adsr_trigger(v->env[i], key_track, vel); } } for (i = 0; i < VOICE_MAX_LFOS; i++) { if (p->vlfo_params[i].active) { float const* src; src = patch_mod_id_to_pointer(p->vlfo_params[i].fm1_id, p, v); lfo_set_fm1(v->lfo[i], src); src = patch_mod_id_to_pointer(p->vlfo_params[i].fm2_id, p, v); lfo_set_fm2(v->lfo[i], src); src = patch_mod_id_to_pointer(p->vlfo_params[i].am1_id, p, v); lfo_set_am1(v->lfo[i], src); src = patch_mod_id_to_pointer(p->vlfo_params[i].am2_id, p, v); lfo_set_am2(v->lfo[i], src); lfo_trigger(v->lfo[i], &p->vlfo_params[i]); } } /* mark our territory */ v->active = true; }