|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- /* nekobee DSSI software synthesizer plugin
- *
- * Copyright (C) 2004 Sean Bolton and others.
- *
- * Portions of this file may have come from Steve Brookes'
- * nekobee, copyright (C) 1999 S. J. Brookes.
- * Portions of this file may have come from Peter Hanappe's
- * Fluidsynth, copyright (C) 2003 Peter Hanappe and others.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
- #define _BSD_SOURCE 1
- #define _SVID_SOURCE 1
- #define _ISOC99_SOURCE 1
-
- #include <stdlib.h>
-
- #include "nekobee_types.h"
- #include "nekobee.h"
- #include "nekobee_synth.h"
- #include "nekobee_voice.h"
-
- /*
- * nekobee_voice_new
- */
- nekobee_voice_t *
- nekobee_voice_new()
- {
- nekobee_voice_t *voice;
-
- voice = (nekobee_voice_t *)calloc(sizeof(nekobee_voice_t), 1);
- if (voice) {
- voice->status = XSYNTH_VOICE_OFF;
- }
- return voice;
- }
-
- /*
- * nekobee_voice_note_on
- */
- void
- nekobee_voice_note_on(nekobee_synth_t *synth, nekobee_voice_t *voice,
- unsigned char key, unsigned char velocity)
- {
- int i;
-
- voice->key = key;
- voice->velocity = velocity;
-
-
- if (!synth->monophonic || !(_ON(voice) || _SUSTAINED(voice))) {
-
- // brand-new voice, or monophonic voice in release phase; set everything up
- XDB_MESSAGE(XDB_NOTE, " nekobee_voice_note_on in polyphonic/new section: key %d, mono %d, old status %d\n", key, synth->monophonic, voice->status);
-
- voice->target_pitch = nekobee_pitch[key];
-
-
- if (synth->held_keys[0] >= 0) {
- voice->prev_pitch = nekobee_pitch[synth->held_keys[0]];
- } else {
- voice->prev_pitch = voice->target_pitch;
- }
-
- if (!_PLAYING(voice)) {
- voice->lfo_pos = 0.0f;
- voice->vca_eg = 0.0f;
- voice->vcf_eg = 0.0f;
- voice->delay1 = 0.0f;
- voice->delay2 = 0.0f;
- voice->delay3 = 0.0f;
- voice->delay4 = 0.0f;
- voice->c5 = 0.0f;
- voice->osc_index = 0;
- voice->osc1.last_waveform = -1;
- voice->osc1.pos = 0.0f;
-
- }
- voice->vca_eg_phase = 0;
- voice->vcf_eg_phase = 0;
- // nekobee_voice_update_pressure_mod(synth, voice);
-
- } else {
-
- /* synth is monophonic, and we're modifying a playing voice */
- XDB_MESSAGE(XDB_NOTE, " nekobee_voice_note_on in monophonic section: old key %d => new key %d\n", synth->held_keys[0], key);
-
- /* set new pitch */
- voice->target_pitch = nekobee_pitch[key];
- if (synth->glide == XSYNTH_GLIDE_MODE_INITIAL ||
- synth->glide == XSYNTH_GLIDE_MODE_OFF)
- voice->prev_pitch = voice->target_pitch;
-
- /* if in 'on' or 'both' modes, and key has changed, then re-trigger EGs */
- if ((synth->monophonic == XSYNTH_MONO_MODE_ON ||
- synth->monophonic == XSYNTH_MONO_MODE_BOTH) &&
- (synth->held_keys[0] < 0 || synth->held_keys[0] != key)) {
- voice->vca_eg_phase = 0;
- voice->vcf_eg_phase = 0;
- }
-
- /* all other variables stay what they are */
-
- }
- synth->last_noteon_pitch = voice->target_pitch;
-
- /* add new key to the list of held keys */
-
- /* check if new key is already in the list; if so, move it to the
- * top of the list, otherwise shift the other keys down and add it
- * to the top of the list. */
- for (i = 0; i < 7; i++) {
- if (synth->held_keys[i] == key)
- break;
- }
- for (; i > 0; i--) {
- synth->held_keys[i] = synth->held_keys[i - 1];
- }
- synth->held_keys[0] = key;
-
- if (!_PLAYING(voice)) {
-
- nekobee_voice_start_voice(voice);
-
- } else if (!_ON(voice)) { /* must be XSYNTH_VOICE_SUSTAINED or XSYNTH_VOICE_RELEASED */
-
- voice->status = XSYNTH_VOICE_ON;
-
- }
- }
-
- /*
- * nekobee_voice_set_release_phase
- */
- static inline void
- nekobee_voice_set_release_phase(nekobee_voice_t *voice)
- {
- voice->vca_eg_phase = 2;
- voice->vcf_eg_phase = 2;
- }
-
- /*
- * nekobee_voice_remove_held_key
- */
- inline void
- nekobee_voice_remove_held_key(nekobee_synth_t *synth, unsigned char key)
- {
- int i;
-
- /* check if this key is in list of held keys; if so, remove it and
- * shift the other keys up */
- for (i = 7; i >= 0; i--) {
- if (synth->held_keys[i] == key)
- break;
- }
- if (i >= 0) {
- for (; i < 7; i++) {
- synth->held_keys[i] = synth->held_keys[i + 1];
- }
- synth->held_keys[7] = -1;
- }
- }
-
- /*
- * nekobee_voice_note_off
- */
- void
- nekobee_voice_note_off(nekobee_synth_t *synth, nekobee_voice_t *voice,
- unsigned char key, unsigned char rvelocity)
- {
- unsigned char previous_top_key;
-
- XDB_MESSAGE(XDB_NOTE, " nekobee_set_note_off: called for voice %p, key %d\n", voice, key);
-
- /* save release velocity */
- voice->velocity = rvelocity;
-
- previous_top_key = synth->held_keys[0];
-
- /* remove this key from list of held keys */
- nekobee_voice_remove_held_key(synth, key);
-
- if (synth->held_keys[0] >= 0) {
-
- /* still some keys held */
-
- if (synth->held_keys[0] != previous_top_key) {
-
- /* most-recently-played key has changed */
- voice->key = synth->held_keys[0];
- XDB_MESSAGE(XDB_NOTE, " note-off in monophonic section: changing pitch to %d\n", voice->key);
- voice->target_pitch = nekobee_pitch[voice->key];
- if (synth->glide == XSYNTH_GLIDE_MODE_INITIAL ||
- synth->glide == XSYNTH_GLIDE_MODE_OFF)
- voice->prev_pitch = voice->target_pitch;
-
- /* if mono mode is 'both', re-trigger EGs */
- if (synth->monophonic == XSYNTH_MONO_MODE_BOTH && !_RELEASED(voice)) {
- voice->vca_eg_phase = 0;
- voice->vcf_eg_phase = 0;
- }
-
- }
-
- } else { /* no keys still held */
-
- if (XSYNTH_SYNTH_SUSTAINED(synth)) {
-
- /* no more keys in list, but we're sustained */
- XDB_MESSAGE(XDB_NOTE, " note-off in monophonic section: sustained with no held keys\n");
- if (!_RELEASED(voice))
- voice->status = XSYNTH_VOICE_SUSTAINED;
-
- } else { /* not sustained */
-
- /* no more keys in list, so turn off note */
- XDB_MESSAGE(XDB_NOTE, " note-off in monophonic section: turning off voice %p\n", voice);
- nekobee_voice_set_release_phase(voice);
- voice->status = XSYNTH_VOICE_RELEASED;
-
- }
- }
-
- }
-
- /*
- * nekobee_voice_release_note
- */
- void
- nekobee_voice_release_note(nekobee_synth_t *synth, nekobee_voice_t *voice)
- {
- XDB_MESSAGE(XDB_NOTE, " nekobee_voice_release_note: turning off voice %p\n", voice);
- if (_ON(voice)) {
- /* dummy up a release velocity */
- voice->rvelocity = 64;
- }
- nekobee_voice_set_release_phase(voice);
- voice->status = XSYNTH_VOICE_RELEASED;
-
- return;
- (void)synth;
- }
|