Feature: bend playback
This commit is contained in:
parent
59250c675c
commit
ed6fe07d61
4 changed files with 65 additions and 3 deletions
|
@ -69,7 +69,7 @@ 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 */
|
||||
pitch_wheel_sensitivity = 12; /* twelve semi-tones */
|
||||
bank_msb = 0;
|
||||
|
||||
for (int i = 0; i < GEN_LAST; i++) {
|
||||
|
|
|
@ -179,7 +179,7 @@ void Fluid::play(const PlayEvent& event)
|
|||
err = !cp->preset()->noteon(this, noteid++, ch, key, vel, event.tuning());
|
||||
}
|
||||
}
|
||||
else if (type == ME_CONTROLLER) {
|
||||
else if (type == ME_CONTROLLER) {
|
||||
switch(event.dataA()) {
|
||||
case CTRL_PROGRAM:
|
||||
program_change(ch, event.dataB());
|
||||
|
@ -194,6 +194,10 @@ void Fluid::play(const PlayEvent& event)
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if (type == ME_PITCHBEND){
|
||||
int midiPitch = event.dataB() * 128 + event.dataA(); // msb * 128 + lsb
|
||||
cp->pitchBend(midiPitch);
|
||||
}
|
||||
if (err)
|
||||
qWarning("FluidSynth error: event 0x%2x channel %d: %s",
|
||||
type, ch, qPrintable(error()));
|
||||
|
|
|
@ -239,6 +239,64 @@ static void collectNote(EventMap* events, int channel, const Note* note, int vel
|
|||
off += tieLen;
|
||||
playNote(events, note, channel, p, velo, on, off);
|
||||
}
|
||||
|
||||
// Bends
|
||||
for (Element* e: note->el()) {
|
||||
if (e == 0 || e->type() != Element::Type::BEND)
|
||||
continue;
|
||||
Bend* bend = static_cast<Bend*>(e);
|
||||
const QList<PitchValue>& points = bend->points();
|
||||
int pitchSize = points.size();
|
||||
|
||||
double noteLen = note->playTicks();
|
||||
int lastPointTick = tick1;
|
||||
for(int pitchIndex = 0; pitchIndex < pitchSize-1; pitchIndex++) {
|
||||
PitchValue pitchValue = points[pitchIndex];
|
||||
PitchValue nextPitch = points[pitchIndex+1];
|
||||
int nextPointTick = tick1 + nextPitch.time / 60.0 * noteLen;
|
||||
int pitch = pitchValue.pitch;
|
||||
|
||||
if (pitchIndex == 0 && (pitch == nextPitch.pitch)) {
|
||||
int midiPitch = (pitch * 16384) / 1200 + 8192;
|
||||
qDebug()<<"p: "<<midiPitch;
|
||||
int msb = midiPitch / 128;
|
||||
int lsb = midiPitch % 128;
|
||||
NPlayEvent ev(ME_PITCHBEND, channel, lsb, msb);
|
||||
events->insert(std::pair<int, NPlayEvent>(lastPointTick, ev));
|
||||
lastPointTick = nextPointTick;
|
||||
continue;
|
||||
}
|
||||
if (pitch == nextPitch.pitch && !(pitchIndex == 0 && pitch != 0)) {
|
||||
lastPointTick = nextPointTick;
|
||||
continue;
|
||||
}
|
||||
|
||||
double pitchDelta = nextPitch.pitch - pitch;
|
||||
double tickDelta = nextPitch.time - pitchValue.time;
|
||||
/* B
|
||||
/. pitch is 1/100 semitones
|
||||
bend / . pitchDelta time is in noteDuration/60
|
||||
/ . midi pitch is 12/16384 semitones
|
||||
A....
|
||||
tickDelta */
|
||||
for (int i = lastPointTick; i <= nextPointTick; i += 16) {
|
||||
double dx = ((i-lastPointTick) * 60) / noteLen;
|
||||
int p = pitch + dx * pitchDelta / tickDelta;
|
||||
|
||||
// We don't support negative pitch, but Midi does. Let's center by adding 8192.
|
||||
int midiPitch = (p * 16384) / 1200 + 8192;
|
||||
qDebug()<<"p: "<<midiPitch;
|
||||
// Representing pitch as two bytes
|
||||
int msb = midiPitch / 128;
|
||||
int lsb = midiPitch % 128;
|
||||
NPlayEvent ev(ME_PITCHBEND, channel, lsb, msb);
|
||||
events->insert(std::pair<int, NPlayEvent>(i, ev));
|
||||
}
|
||||
lastPointTick = nextPointTick;
|
||||
}
|
||||
NPlayEvent ev(ME_PITCHBEND, channel, 0, 64); // 0:64 is 8192 - no pitch bend
|
||||
events->insert(std::pair<int, NPlayEvent>(tick1+noteLen, ev));
|
||||
}
|
||||
#if 0
|
||||
if (note->bend()) {
|
||||
Bend* bend = note->bend();
|
||||
|
|
|
@ -513,7 +513,7 @@ void Seq::playEvent(const NPlayEvent& event, unsigned framePos)
|
|||
if (!mute)
|
||||
putEvent(event, framePos);
|
||||
}
|
||||
else if (type == ME_CONTROLLER)
|
||||
else if (type == ME_CONTROLLER || type == ME_PITCHBEND)
|
||||
putEvent(event, framePos);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue