From 1aed75e0c7f4da07cd603c8cb82a8f57cabde8e0 Mon Sep 17 00:00:00 2001 From: vampi Date: Thu, 21 Nov 2024 15:18:40 +0200 Subject: [PATCH] mdx2midi: preliminary pitch bend support --- fm_driver.c | 4 ++-- fm_driver.h | 4 ++-- fm_midi_driver.c | 26 +++++++++++++++++++++----- fm_midi_driver.h | 2 +- fm_opm_driver.c | 2 +- mdx_driver.c | 2 +- midi_timer_driver.c | 1 + 7 files changed, 29 insertions(+), 12 deletions(-) diff --git a/fm_driver.c b/fm_driver.c index 266b0d9..c4992f3 100644 --- a/fm_driver.c +++ b/fm_driver.c @@ -60,9 +60,9 @@ void fm_driver_set_noise_freq(struct fm_driver *driver, int channel, int freq) { driver->set_noise_freq(driver, channel, freq); } -void fm_driver_load_voice(struct fm_driver *driver, int channel, uint8_t *v, int opm_volume, int pan) { +void fm_driver_load_voice(struct fm_driver *driver, int channel, uint8_t *v, int voice_num, int opm_volume, int pan) { if(driver->load_voice) - driver->load_voice(driver, channel, v, opm_volume, pan); + driver->load_voice(driver, channel, v, voice_num, opm_volume, pan); } void fm_driver_load_lfo(struct fm_driver *driver, int channel, uint8_t wave, uint8_t freq, uint8_t pmd, uint8_t amd) { diff --git a/fm_driver.h b/fm_driver.h index 81b86fc..e182b6c 100644 --- a/fm_driver.h +++ b/fm_driver.h @@ -15,7 +15,7 @@ struct fm_driver { void (*write_opm_reg)(struct fm_driver *driver, uint8_t reg, uint8_t data); void (*set_pan)(struct fm_driver *driver, int channel, uint8_t pan, uint8_t *v); void (*set_noise_freq)(struct fm_driver *driver, int channel, int freq); - void (*load_voice)(struct fm_driver *driver, int channel, uint8_t *v, int opm_volume, int pan); + void (*load_voice)(struct fm_driver *driver, int channel, uint8_t *v, int voice_num, int opm_volume, int pan); void (*load_lfo)(struct fm_driver *driver, int channel, uint8_t wave, uint8_t freq, uint8_t pmd, uint8_t amd); }; void fm_driver_init(struct fm_driver *driver); @@ -29,7 +29,7 @@ void fm_driver_note_off(struct fm_driver *driver, int channel); void fm_driver_write_opm_reg(struct fm_driver *driver, uint8_t reg, uint8_t val); void fm_driver_set_pan(struct fm_driver *driver, int channel, uint8_t pan, uint8_t *v); void fm_driver_set_noise_freq(struct fm_driver *driver, int channel, int freq); -void fm_driver_load_voice(struct fm_driver *driver, int channel, uint8_t *v, int opm_volume, int pan); +void fm_driver_load_voice(struct fm_driver *driver, int channel, uint8_t *v, int voice_num, int opm_volume, int pan); void fm_driver_load_lfo(struct fm_driver *driver, int channel, uint8_t wave, uint8_t freq, uint8_t pmd, uint8_t amd); #endif /* FM_DRIVER_H_ */ diff --git a/fm_midi_driver.c b/fm_midi_driver.c index 8554075..489ae0d 100644 --- a/fm_midi_driver.c +++ b/fm_midi_driver.c @@ -15,9 +15,14 @@ void fm_midi_driver_set_pitch(struct fm_driver *driver, int channel, int pitch) if(mididrv->channels[channel].on && pitch != mididrv->channels[channel].pitch) { pitch >>= 8; pitch -= 5; - int detune = pitch & 0x3f; - int note = pitch >> 6; - mididrv->channels[channel].ticks = 0; + int root_pitch = mididrv->channels[channel].note << 6; + int detune = (pitch - root_pitch); + + if(detune != mididrv->channels[channel].detune) { + midi_track_write_pitch_bend(&mididrv->midi_file->tracks[channel + 1], mididrv->channels[channel].ticks, channel, detune); + mididrv->channels[channel].detune = detune; + mididrv->channels[channel].ticks = 0; + } } mididrv->channels[channel].pitch = pitch; } @@ -33,6 +38,11 @@ void fm_midi_driver_note_on(struct fm_driver *driver, int channel, uint8_t op_ma int pitch = (mididrv->channels[channel].pitch >> 8) - 5; int detune = pitch & 0x3f; int note = pitch >> 6; + mididrv->channels[channel].note = note; + if(detune != mididrv->channels[channel].detune) { + midi_track_write_pitch_bend(&mididrv->midi_file->tracks[channel + 1], mididrv->channels[channel].ticks, channel, detune); + mididrv->channels[channel].ticks = 0; + } midi_track_write_note_on(&mididrv->midi_file->tracks[channel + 1], mididrv->channels[channel].ticks, channel, note, 127); mididrv->channels[channel].ticks = 0; } @@ -44,6 +54,8 @@ void fm_midi_driver_note_off(struct fm_driver *driver, int channel) { int pitch = (mididrv->channels[channel].pitch >> 8) - 5; int detune = pitch & 0x3f; int note = pitch >> 6; + + mididrv->channels[channel].detune = detune; midi_track_write_note_off(&mididrv->midi_file->tracks[channel + 1], mididrv->channels[channel].ticks, channel, note, 127); mididrv->channels[channel].ticks = 0; } @@ -63,9 +75,10 @@ void fm_midi_driver_set_noise_freq(struct fm_driver *driver, int channel, int fr (void)mididrv; } -void fm_midi_driver_load_voice(struct fm_driver *driver, int channel, uint8_t *v, int volume, int pan) { +void fm_midi_driver_load_voice(struct fm_driver *driver, int channel, uint8_t *v, int voice_num, int volume, int pan) { struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; - (void)mididrv; + midi_track_write_program_change(&mididrv->midi_file->tracks[channel + 1], mididrv->channels[channel].ticks, channel, voice_num); + mididrv->channels[channel].ticks = 0; } void fm_midi_driver_load_lfo(struct fm_driver *driver, int channel, uint8_t wave, uint8_t freq, uint8_t pmd, uint8_t amd) { @@ -91,6 +104,9 @@ void fm_midi_driver_init(struct fm_midi_driver *driver, struct midi_file *midi_f for(int i = 0; i < 8; i++) { driver->channels[i].on = 0; driver->channels[i].pitch = 0; + driver->channels[i].note = 0; + driver->channels[i].detune = 0; + driver->channels[i].tl = 0; driver->channels[i].ticks = 0; } } diff --git a/fm_midi_driver.h b/fm_midi_driver.h index c397ccc..cdc6c24 100644 --- a/fm_midi_driver.h +++ b/fm_midi_driver.h @@ -5,7 +5,7 @@ #include "midilib/midi_file.h" struct fm_midi_driver_channel { - int on, pitch, tl, ticks; + int on, pitch, note, detune, tl, ticks; }; /* MIDI driver */ diff --git a/fm_opm_driver.c b/fm_opm_driver.c index e000c7f..609745d 100644 --- a/fm_opm_driver.c +++ b/fm_opm_driver.c @@ -85,7 +85,7 @@ static void fm_opm_driver_set_noise_freq(struct fm_driver *driver, int channel, fm_opm_driver_write(fmdrv, 0x0F, freq & 0x1f); } -static void fm_opm_driver_load_voice(struct fm_driver *driver, int channel, uint8_t *v, int opm_volume, int pan) { +static void fm_opm_driver_load_voice(struct fm_driver *driver, int channel, uint8_t *v, int voice_num, int opm_volume, int pan) { struct fm_opm_driver *fmdrv = (struct fm_opm_driver *)driver; for(int i = 0; i < 4; i++) diff --git a/mdx_driver.c b/mdx_driver.c index 0e2a6a5..66377c6 100644 --- a/mdx_driver.c +++ b/mdx_driver.c @@ -249,7 +249,7 @@ static int mdx_driver_track_advance(struct mdx_driver *driver, int track_num) { case 0xfd: // Set voice if(track_num < 8) { track->voice_num = track->data[track->pos + 1]; - fm_driver_load_voice(driver->fm_driver, track_num, driver->mdx_file->voices[track->voice_num], track->opm_volume, track->pan); + fm_driver_load_voice(driver->fm_driver, track_num, driver->mdx_file->voices[track->voice_num], track->voice_num, track->opm_volume, track->pan); } track->pos += 2; break; diff --git a/midi_timer_driver.c b/midi_timer_driver.c index f5357e9..3417378 100644 --- a/midi_timer_driver.c +++ b/midi_timer_driver.c @@ -8,6 +8,7 @@ int midi_timer_driver_init(struct midi_timer_driver *driver) { timer_driver_init(&driver->timer_driver); driver->ticks_per_quarter_note = 48; driver->timer_driver.set_opm_tempo = midi_timer_driver_set_opm_tempo; + return 0; } void midi_timer_driver_deinit(struct midi_timer_driver *driver) {