Feature: bend playback

This commit is contained in:
igevorse 2015-06-01 22:49:48 +05:00
parent 59250c675c
commit ed6fe07d61
4 changed files with 65 additions and 3 deletions

View file

@ -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++) {

View file

@ -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()));

View file

@ -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();

View file

@ -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);
}