230 lines
6.7 KiB
C++
230 lines
6.7 KiB
C++
/* 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->allNotesOff(channum);
|
|
break;
|
|
|
|
case ALL_SOUND_OFF:
|
|
synth->allSoundsOff(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);
|
|
qDebug("%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;
|
|
qDebug("%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;
|
|
}
|
|
}
|
|
|
|
}
|
|
|