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:
parent
5eb5b0dc83
commit
59aed37d3e
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue