/* FluidSynth - A Software Synthesizer * * Copyright (C) 2003 Peter Hanappe and others. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307, USA */ #include "fluid.h" #include "sfont.h" #include "gen.h" namespace FluidS { //--------------------------------------------------------- // Channel //--------------------------------------------------------- Channel::Channel(Fluid* s, int num) { synth = s; channum = num; _preset = 0; banknum = 0; prognum = 0; reset(); } //--------------------------------------------------------- // reset //--------------------------------------------------------- void Channel::reset() { init(); initCtrl(); } //--------------------------------------------------------- // init //--------------------------------------------------------- void Channel::init() { sfontnum = 0; setPreset(synth->find_preset(banknum, prognum)); interp_method = FLUID_INTERP_DEFAULT; nrpn_select = 0; } //--------------------------------------------------------- // initCtrl //--------------------------------------------------------- void Channel::initCtrl() { key_pressure = 0; channel_pressure = 0; pitch_bend = 0x2000; // Range is 0x4000, pitch bend wheel starts in centered position pitch_wheel_sensitivity = 2; /* two semi-tones */ bank_msb = 0; for (int i = 0; i < GEN_LAST; i++) { gen[i] = 0.0f; gen_abs[i] = 0; } for (int i = 0; i < 128; i++) setCC(i, 0); /* Volume / initial attenuation (MSB & LSB) */ setCC(VOLUME_MSB, 127); setCC(VOLUME_LSB, 0); /* Pan (MSB & LSB) */ setCC(PAN_MSB, 64); setCC(PAN_LSB, 64); /* Expression (MSB & LSB) */ setCC(EXPRESSION_MSB, 127); setCC(EXPRESSION_LSB, 127); } //--------------------------------------------------------- // setcc //--------------------------------------------------------- void Channel::setcc(int num, int value) { cc[num] = value; // printf("setcc %d %d\n", num, value); switch (num) { case SUSTAIN_SWITCH: if (value < 64) synth->damp_voices(channum); break; case BANK_SELECT_MSB: { bank_msb = value & 0x7f; setBanknum(bank_msb << 7); } break; case BANK_SELECT_LSB: /* FIXME: according to the Downloadable Sounds II specification, bit 31 should be set when we receive the message on channel 10 (drum channel) */ setBanknum((value & 0x7f) + (bank_msb << 7)); break; case ALL_NOTES_OFF: synth->all_notes_off(channum); break; case ALL_SOUND_OFF: synth->all_sounds_off(channum); break; case ALL_CTRL_OFF: initCtrl(); synth->modulate_voices_all(channum); break; case DATA_ENTRY_MSB: { int data = (value << 7) + cc[DATA_ENTRY_LSB]; /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */ if ((cc[NRPN_MSB] == 120) && (cc[NRPN_LSB] < 100)) { float val = fluid_gen_scale_nrpn(nrpn_select, data); synth->log("%s: %d: Data = %d, value = %f", __FILE__, __LINE__, data, val); synth->set_gen(channum, nrpn_select, val); } break; } case NRPN_MSB: cc[NRPN_LSB] = 0; nrpn_select = 0; break; case NRPN_LSB: /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */ if (cc[NRPN_MSB] == 120) { if (value == 100) nrpn_select += 100; else if (value == 101) nrpn_select += 1000; else if (value == 102) nrpn_select += 10000; else if (value < 100) { nrpn_select += value; synth->log("%s: %d: NRPN Select = %d", __FILE__, __LINE__, nrpn_select); } } break; case RPN_MSB: break; case RPN_LSB: /* erase any previously received NRPN message */ cc[NRPN_MSB] = 0; cc[NRPN_LSB] = 0; nrpn_select = 0; break; default: synth->modulate_voices(channum, true, num); } } //--------------------------------------------------------- // getCC //--------------------------------------------------------- int Channel::getCC(int num) { return ((num >= 0) && (num < 128))? cc[num] : 0; } //--------------------------------------------------------- // pitchBend //--------------------------------------------------------- void Channel::pitchBend(int val) { pitch_bend = val; synth->modulate_voices(channum, false, FLUID_MOD_PITCHWHEEL); } //--------------------------------------------------------- // pitchWheelSens //--------------------------------------------------------- void Channel::pitchWheelSens(int val) { pitch_wheel_sensitivity = val; synth->modulate_voices(channum, false, FLUID_MOD_PITCHWHEELSENS); } //--------------------------------------------------------- // setPreset //--------------------------------------------------------- void Channel::setPreset(Preset* p) { if (_preset != p) { if (p) p->loadSamples(); _preset = p; } } }