MidiSource: Improve pitch shifting accuracy

Also drop note events whose keys are shifted out of range
instead of clamping them.
This commit is contained in:
Jonas Kulla 2014-08-02 16:15:11 +02:00
parent 5eb5b0dc83
commit 59aed37d3e
2 changed files with 20 additions and 22 deletions

View File

@ -83,7 +83,6 @@ mkxp doesn't come with a soundfont by default, so you will have to supply it you
Known issues with midi playback: Known issues with midi playback:
* Some songs' instruments become mute after looping * Some songs' instruments become mute after looping
* Pitch shifting is implemented poorly
## Fonts ## Fonts

View File

@ -75,12 +75,7 @@ struct ChannelEvent
uint8_t chan; uint8_t chan;
}; };
struct NoteOffEvent : ChannelEvent struct NoteEvent : ChannelEvent
{
uint8_t key;
};
struct NoteOnEvent : ChannelEvent
{ {
uint8_t key; uint8_t key;
uint8_t vel; uint8_t vel;
@ -119,8 +114,7 @@ struct MidiEvent
union union
{ {
ChannelEvent chan; ChannelEvent chan;
NoteOnEvent noteOn; NoteEvent note;
NoteOffEvent noteOff;
NoteTouchEvent chanTouch; NoteTouchEvent chanTouch;
PitchBendEvent pitchBend; PitchBendEvent pitchBend;
CCEvent cc; CCEvent cc;
@ -226,14 +220,14 @@ readVoiceEvent(MidiEvent &e, MemChunk &chunk,
{ {
case 0x8 : case 0x8 :
e.type = NoteOff; e.type = NoteOff;
e.e.noteOff.key = data1; e.e.note.key = data1;
chunk.readByte(); /* We don't care about velocity */ chunk.readByte(); /* We don't care about velocity */
break; break;
case 0x9 : case 0x9 :
e.type = NoteOn; e.type = NoteOn;
e.e.noteOn.key = data1; e.e.note.key = data1;
e.e.noteOn.vel = chunk.readByte(); e.e.note.vel = chunk.readByte();
break; break;
case 0xA : case 0xA :
@ -639,20 +633,25 @@ struct MidiSource : ALDataSource, MidiReadHandler
void activateEvent(MidiEvent &e) void activateEvent(MidiEvent &e)
{ {
// FIXME: This is not a good solution for very high/low int16_t key = e.e.note.key;
// keys, but I'm not sure what else would be.
int8_t shift = (e.e.chan.chan != 9) ? pitchShift : 0; /* Apply pitch shift if necessary */
int16_t key; if ((e.type == NoteOn || e.type == NoteOff) && e.e.chan.chan != 9)
{
key += pitchShift;
/* Drop events whose keys are out of bounds */
if (key < 0 || key > 127)
return;
}
switch (e.type) switch (e.type)
{ {
case NoteOn: case NoteOn:
key = clamp<int16_t>(e.e.noteOn.key+shift, 0, 127); fluid_synth_noteon(synth, e.e.note.chan, key, e.e.note.vel);
fluid_synth_noteon(synth, e.e.noteOn.chan, key, e.e.noteOn.vel);
break; break;
case NoteOff: case NoteOff:
key = clamp<int16_t>(e.e.noteOn.key+shift, 0, 127); fluid_synth_noteoff(synth, e.e.note.chan, key);
fluid_synth_noteoff(synth, e.e.noteOff.chan, key);
break; break;
case ChanTouch: case ChanTouch:
fluid_synth_channel_pressure(synth, e.e.chanTouch.chan, e.e.chanTouch.val); fluid_synth_channel_pressure(synth, e.e.chanTouch.chan, e.e.chanTouch.val);
@ -833,8 +832,8 @@ struct MidiSource : ALDataSource, MidiReadHandler
bool setPitch(float value) bool setPitch(float value)
{ {
// 1.0 = one octave, not sure about this yet // not completely correct, but close
pitchShift = 12 * (value - 1.0); pitchShift = round((value > 1.0 ? 14 : 24) * (value - 1.0));
return true; return true;
} }