diff --git a/Makefile b/Makefile index b303b5a..0863760 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ tests: $(TESTS) .SECONDEXPANSION: adpcm-decode_SRCS=adpcm.c adpcm-encode_SRCS=adpcm.c -mdx2midi_SRCS=mdx.c tools.c cmdline.c +mdx2midi_SRCS=mdx.c tools.c cmdline.c adpcm_driver.c adpcm_midi_driver.c midi_timer_driver.c fm_driver.c fm_midi_driver.c mdx_driver.c timer_driver.c mdx2mml_SRCS=mdx.c mdx_decompiler.c tools.c cmdline.c x68ksjis/sjis.c x68ksjis/sjis_unicode.c x68ksjis/utf8.c mdx2opm_SRCS=mdx2opm.c tools.c mdx.c mdx2vgm_SRCS=mdx.c mdx_driver.c adpcm_driver.c adpcm.c speex_resampler.c timer.c tools.c x68ksjis/sjis_unicode.c x68ksjis/sjis.c ym2151.c okim6258.c vgm.c diff --git a/adpcm_driver.c b/adpcm_driver.c index bf3e560..c47e966 100644 --- a/adpcm_driver.c +++ b/adpcm_driver.c @@ -39,4 +39,3 @@ int adpcm_driver_set_pan(struct adpcm_driver *d, uint8_t pan) { d->set_pan(d, pan); return 0; } - diff --git a/adpcm_midi_driver.c b/adpcm_midi_driver.c new file mode 100644 index 0000000..852ae8d --- /dev/null +++ b/adpcm_midi_driver.c @@ -0,0 +1,49 @@ +#include "adpcm_midi_driver.h" + +int adpcm_midi_driver_play(struct adpcm_driver *d, uint8_t channel, uint8_t *data, int len, uint8_t freq, uint8_t vol) { + return 0; +} + +int adpcm_midi_driver_stop(struct adpcm_driver *d, uint8_t channel) { + return 0; +} + +int adpcm_midi_driver_set_volume(struct adpcm_driver *d, uint8_t channel, uint8_t vol) { + return 0; +} + +int adpcm_midi_driver_set_freq(struct adpcm_driver *d, uint8_t channel, uint8_t freq) { + return 0; +} + +int adpcm_midi_driver_set_pan(struct adpcm_driver *d, uint8_t pan) { + return 0; +} + +int adpcm_midi_driver_init(struct adpcm_midi_driver *driver, struct midi_file *midi_file) { + adpcm_driver_init(&driver->adpcm_driver); + driver->adpcm_driver.play = adpcm_midi_driver_play; + driver->adpcm_driver.stop = adpcm_midi_driver_stop; + driver->adpcm_driver.set_freq = adpcm_midi_driver_set_freq; + driver->adpcm_driver.set_volume = adpcm_midi_driver_set_volume; + driver->adpcm_driver.set_pan = adpcm_midi_driver_set_pan; + + driver->midi_file = midi_file; + for(int i = 0; i < 8; i++) + driver->channels[i].ticks = 0; + + return 0; +} + +void adpcm_midi_driver_end(struct adpcm_midi_driver *driver) { + for(int i = 0; i < 8; i++) { + midi_track_write_track_end(&driver->midi_file->tracks[i + 9], driver->channels[i].ticks); + driver->channels[i].ticks = 0; + } +} + +int adpcm_midi_driver_tick(struct adpcm_midi_driver *driver) { + for(int i = 0; i < 8; i++) + driver->channels[i].ticks++; + return 0; +} diff --git a/adpcm_midi_driver.h b/adpcm_midi_driver.h new file mode 100644 index 0000000..b0ef8bc --- /dev/null +++ b/adpcm_midi_driver.h @@ -0,0 +1,20 @@ +#ifndef ADPCM_MIDI_DRIVER_H_ +#define ADPCM_MIDI_DRIVER_H_ + +#include "adpcm_driver.h" +#include "midilib/midi_file.h" + +struct adpcm_midi_driver_channel { + int ticks; +}; + +struct adpcm_midi_driver { + struct adpcm_driver adpcm_driver; // parent + struct midi_file *midi_file; + struct adpcm_midi_driver_channel channels[8]; +}; +int adpcm_midi_driver_init(struct adpcm_midi_driver *driver, struct midi_file *midi_file); +int adpcm_midi_driver_tick(struct adpcm_midi_driver *driver); +void adpcm_midi_driver_end(struct adpcm_midi_driver *driver); + +#endif /* ADPCM_MIDI_DRIVER_H_ */ diff --git a/fm_midi_driver.c b/fm_midi_driver.c new file mode 100644 index 0000000..de1cce7 --- /dev/null +++ b/fm_midi_driver.c @@ -0,0 +1,112 @@ +#include "fm_midi_driver.h" + +void fm_midi_driver_reset_key_sync(struct fm_driver *driver, int channel) { + struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; + (void)mididrv; +} + +void fm_midi_driver_set_pms_ams(struct fm_driver *driver, int channel, uint8_t pms_ams) { + struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; + (void)mididrv; +} + +void fm_midi_driver_set_pitch(struct fm_driver *driver, int channel, int pitch) { + struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; + if(mididrv->channels[channel].on && pitch != mididrv->channels[channel].pitch) { + pitch >>= 8; + pitch -= 5; + int detune = pitch & 0x3f; + int note = pitch >> 6; + printf("pitch bend channel=%d pitch=%d note=%d detune=%d ticks=%d\n", channel, pitch, note, detune, mididrv->channels[channel].ticks); + mididrv->channels[channel].ticks = 0; + } + mididrv->channels[channel].pitch = pitch; +} + +void fm_midi_driver_set_tl(struct fm_driver *driver, int channel, uint8_t tl, uint8_t *v) { + struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; + mididrv->channels[channel].tl = tl; +} + +void fm_midi_driver_note_on(struct fm_driver *driver, int channel, uint8_t op_mask, uint8_t *v) { + struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; + printf("note on channel=%d op_mask=%01x\n"); + mididrv->channels[channel].on = 1; + int pitch = (mididrv->channels[channel].pitch >> 8) - 5; + int detune = pitch & 0x3f; + int note = pitch >> 6; + printf("set pitch channel=%d pitch=%d note=%d detune=%d ticks=%d\n", channel, pitch, note, detune, mididrv->channels[channel].ticks); + midi_track_write_note_on(&mididrv->midi_file->tracks[channel + 1], mididrv->channels[channel].ticks, channel, note, 127); + mididrv->channels[channel].ticks = 0; +} + +void fm_midi_driver_note_off(struct fm_driver *driver, int channel) { + struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; + (void)mididrv; + mididrv->channels[channel].on = 0; + int pitch = (mididrv->channels[channel].pitch >> 8) - 5; + int detune = pitch & 0x3f; + int note = pitch >> 6; + printf("note off channel=%d ticks=%d\n", channel, mididrv->channels[channel].ticks); + midi_track_write_note_off(&mididrv->midi_file->tracks[channel + 1], mididrv->channels[channel].ticks, channel, note, 127); + mididrv->channels[channel].ticks = 0; +} + +void fm_midi_driver_write_opm_reg(struct fm_driver *driver, uint8_t reg, uint8_t data) { + struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; + (void)mididrv; +} + +void fm_midi_driver_set_pan(struct fm_driver *driver, int channel, uint8_t pan, uint8_t *v) { + struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; + (void)mididrv; +} + +void fm_midi_driver_set_noise_freq(struct fm_driver *driver, int channel, int freq) { + struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; + (void)mididrv; +} + +void fm_midi_driver_load_voice(struct fm_driver *driver, int channel, uint8_t *v, int volume, int pan) { + struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; + (void)mididrv; +} + +void fm_midi_driver_load_lfo(struct fm_driver *driver, int channel, uint8_t wave, uint8_t freq, uint8_t pmd, uint8_t amd) { + struct fm_midi_driver *mididrv = (struct fm_midi_driver *)driver; + (void)mididrv; +} + +void fm_midi_driver_init(struct fm_midi_driver *driver, struct midi_file *midi_file) { + fm_driver_init(&driver->fm_driver); + driver->fm_driver.reset_key_sync = fm_midi_driver_reset_key_sync; + driver->fm_driver.set_pms_ams = fm_midi_driver_set_pms_ams; + driver->fm_driver.set_pitch = fm_midi_driver_set_pitch; + driver->fm_driver.set_tl = fm_midi_driver_set_tl; + driver->fm_driver.note_on = fm_midi_driver_note_on; + driver->fm_driver.note_off = fm_midi_driver_note_off; + driver->fm_driver.write_opm_reg = fm_midi_driver_write_opm_reg; + driver->fm_driver.set_pan = fm_midi_driver_set_pan; + driver->fm_driver.set_noise_freq = fm_midi_driver_set_noise_freq; + driver->fm_driver.load_voice = fm_midi_driver_load_voice; + driver->fm_driver.load_lfo = fm_midi_driver_load_lfo; + + driver->midi_file = midi_file; + for(int i = 0; i < 8; i++) { + driver->channels[i].on = 0; + driver->channels[i].pitch = 0; + driver->channels[i].ticks = 0; + } +} + +void fm_midi_driver_end(struct fm_midi_driver *driver) { + for(int i = 0; i < 8; i++) { + midi_track_write_track_end(&driver->midi_file->tracks[i + 1], driver->channels[i].ticks); + driver->channels[i].ticks = 0; + } +} + +void fm_midi_driver_tick(struct fm_midi_driver *driver) { + for(int i = 0; i < 8; i++) + driver->channels[i].ticks++; +} diff --git a/fm_midi_driver.h b/fm_midi_driver.h new file mode 100644 index 0000000..5c3002a --- /dev/null +++ b/fm_midi_driver.h @@ -0,0 +1,21 @@ +#ifndef FM_MIDI_DRIVER_H_ +#define FM_MIDI_DRIVER_H_ + +#include "fm_driver.h" +#include "midilib/midi_file.h" + +struct fm_midi_driver_channel { + int on, pitch, tl, ticks; +}; + +/* MIDI driver */ +struct fm_midi_driver { + struct fm_driver fm_driver; + struct midi_file *midi_file; + struct fm_midi_driver_channel channels[8]; +}; +void fm_midi_driver_init(struct fm_midi_driver *driver, struct midi_file *midi_file); +void fm_midi_driver_deinit(struct fm_midi_driver *driver); +void fm_midi_driver_tick(struct fm_midi_driver *driver); + +#endif /* FM_MIDI_DRIVER_H_ */ diff --git a/fm_opm_emu_driver.h b/fm_opm_emu_driver.h index 5538658..e0a9fb9 100644 --- a/fm_opm_emu_driver.h +++ b/fm_opm_emu_driver.h @@ -7,7 +7,6 @@ /* OPM emulation driver */ struct fm_opm_emu_driver { struct fm_opm_driver fm_opm_driver; - int sample_rate; struct ym2151 opm; }; diff --git a/fm_opm_midi_driver.c b/fm_opm_midi_driver.c deleted file mode 100644 index b4bacc7..0000000 --- a/fm_opm_midi_driver.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "fm_opm_midi_driver.h" - -void fm_opm_midi_driver_reset_key_sync(struct fm_driver *driver, int channel) { - struct fm_opm_midi_driver *mididrv = (struct fm_opm_midi_driver *)driver; - (void)mididrv; -} - -void fm_opm_midi_driver_set_pms_ams(struct fm_driver *driver, int channel, uint8_t pms_ams) { - struct fm_opm_midi_driver *mididrv = (struct fm_opm_midi_driver *)driver; - (void)mididrv; -} - -void fm_opm_midi_driver_set_pitch(struct fm_driver *driver, int channel, int pitch) { - struct fm_opm_midi_driver *mididrv = (struct fm_opm_midi_driver *)driver; - (void)mididrv; -} - -void fm_opm_midi_driver_set_tl(struct fm_driver *driver, int channel, uint8_t tl, uint8_t *v) { - struct fm_opm_midi_driver *mididrv = (struct fm_opm_midi_driver *)driver; - (void)mididrv; -} - -void fm_opm_midi_driver_note_on(struct fm_driver *driver, int channel, uint8_t op_mask, uint8_t *v) { - struct fm_opm_midi_driver *mididrv = (struct fm_opm_midi_driver *)driver; - (void)mididrv; -} - -void fm_opm_midi_driver_note_off(struct fm_driver *driver, int channel) { - struct fm_opm_midi_driver *mididrv = (struct fm_opm_midi_driver *)driver; - (void)mididrv; -} - -void fm_opm_midi_driver_write_opm_reg(struct fm_driver *driver, uint8_t reg, uint8_t data) { - struct fm_opm_midi_driver *mididrv = (struct fm_opm_midi_driver *)driver; - (void)mididrv; -} - -void fm_opm_midi_driver_set_pan(struct fm_driver *driver, int channel, uint8_t pan, uint8_t *v) { - struct fm_opm_midi_driver *mididrv = (struct fm_opm_midi_driver *)driver; - (void)mididrv; -} - -void fm_opm_midi_driver_set_noise_freq(struct fm_driver *driver, int channel, int freq) { - struct fm_opm_midi_driver *mididrv = (struct fm_opm_midi_driver *)driver; - (void)mididrv; -} - -void fm_opm_midi_driver_load_voice(struct fm_driver *driver, int channel, uint8_t *v, int opm_volume, int pan) { - struct fm_opm_midi_driver *mididrv = (struct fm_opm_midi_driver *)driver; - (void)mididrv; -} - -void fm_opm_midi_driver_load_lfo(struct fm_driver *driver, int channel, uint8_t wave, uint8_t freq, uint8_t pmd, uint8_t amd) { - struct fm_opm_midi_driver *mididrv = (struct fm_opm_midi_driver *)driver; - (void)mididrv; -} - -void fm_opm_midi_driver_init(struct fm_opm_midi_driver *driver) { - driver->fm_driver.reset_key_sync = fm_opm_midi_driver_reset_key_sync; - driver->fm_driver.set_pms_ams = fm_opm_midi_driver_set_pms_ams; - driver->fm_driver.set_pitch = fm_opm_midi_driver_set_pitch; - driver->fm_driver.set_tl = fm_opm_midi_driver_set_tl; - driver->fm_driver.note_on = fm_opm_midi_driver_note_on; - driver->fm_driver.note_off = fm_opm_midi_driver_note_off; - driver->fm_driver.write_opm_reg = fm_opm_midi_driver_write_opm_reg; - driver->fm_driver.set_pan = fm_opm_midi_driver_set_pan; - driver->fm_driver.set_noise_freq = fm_opm_midi_driver_set_noise_freq; - driver->fm_driver.load_voice = fm_opm_midi_driver_load_voice; - driver->fm_driver.load_lfo = fm_opm_midi_driver_load_lfo; - - fm_opm_driver_init(&driver->fm_opm_driver); -} - -void fm_opm_midi_driver_deinit(struct fm_opm_midi_driver *driver) { - -} diff --git a/fm_opm_midi_driver.h b/fm_opm_midi_driver.h deleted file mode 100644 index 747d414..0000000 --- a/fm_opm_midi_driver.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef FM_OPM_MIDI_DRIVER_H_ -#define FM_OPM_MIDI_DRIVER_H_ - -#include "fm_opm_driver.h" - -/* MIDI driver */ -struct fm_opm_midi_driver { - struct fm_opm_driver fm_opm_driver; -}; -void fm_opm_midi_driver_init(struct fm_opm_midi_driver *driver); -void fm_opm_midi_driver_deinit(struct fm_opm_midi_driver *driver); - -#endif /* FM_OPM_MIDI_DRIVER_H_ */ diff --git a/mdx2midi.c b/mdx2midi.c index 1e6b9df..7d38a3a 100644 --- a/mdx2midi.c +++ b/mdx2midi.c @@ -10,341 +10,19 @@ #include "cmdline.h" #include "mdx.h" #include "tools.h" +#include "midi_timer_driver.h" +#include "adpcm_midi_driver.h" +#include "fm_midi_driver.h" +#include "mdx_driver.h" #include "midilib/midi.h" #include "midilib/midi_file.h" #include "midilib/midi_track.h" #include "midilib/stream.h" char *opt_output = 0; -int opt_utf8 = 0; - -struct midi_file midi_file; -struct midi_track midi_track; - -uint32_t deltaTime, restTime; -uint8_t lastCmd; -uint8_t volume, pan; -uint8_t firstTempo; -uint32_t totalTicks; -uint8_t kTicks, qTicks; -int nextKeyOff; -int nextPortamento; -int lastNote; -int detune; -int channel = 0; - -int loopCount = 1; -int midiTracks = 1; -uint32_t totalTicks = 0; - -void handleChannelStart(struct mdx_file *f, struct mdx_track *mdx_track, int i) { - channel = i; - volume = 127; - pan = 3; - firstTempo = 0; - totalTicks = 0; - kTicks = 0; - qTicks = 8; - nextKeyOff = 0; - nextPortamento = 0; - lastNote = -1; - detune = 0; - - midi_track_init(&midi_track); -} - -void handleChannelEnd(struct mdx_file *f, struct mdx_track *mdx_track, int channelNum) { - if(midi_track.buffer.data_len == 0) - return; - - struct midi_track *track = midi_file_append_empty_track(&midi_file); - - char buf[256]; - snprintf(buf, sizeof(buf), "Channel %c (%s)", mdx_track_name(channelNum), channelNum < 8 ? "FM" : "ADPCM"); - midi_track_write_track_name(track, 0, buf, -1); - midi_track_write_bank_select(track, 0, channelNum, 0); - - midi_track_write_control_change(track, 0, channelNum, 126, 127); // Monophonic mode - if(channelNum >= 8) { // OPM only - midi_track_write_nrpn_msb(track, 0, channelNum, 0, 112); // OPM Clock = 4MHz - } - midi_track_write_control_change(track, 0, channelNum, 12, 0); // Amplitude LFO level - midi_track_write_control_change(track, 0, channelNum, 13, 0); // Pitch LFO level - - midi_track_write_rpn_msb(track, 0, channelNum, 0, 32); // Pitch Bend Sensitivity - midi_track_write_pitch_bend(track, 0, channelNum, 0x2000); - - midi_track_write_track(track, &midi_track); - - midi_track_write_track_end(track, 0); -} - -void handleNote(uint8_t n, uint8_t duration) { - int add = channel >= 8 ? 36 : 3; - uint8_t d; - if(qTicks <= 8) d = duration * qTicks / 8; - else d = MIN(duration, 255 - qTicks); - if(kTicks < d) { - if(nextPortamento) { - int nextNote = n + (nextPortamento * duration + (nextPortamento < 0 ? -16383 : 16383)) / 16384; - if(lastNote >= 0) { - midi_track_write_note_on(&midi_track, restTime, channel, lastNote + add, 0); - } - midi_track_write_control_change(&midi_track, 0, channel, 5, MIN(duration - kTicks, 127)); // Portamento time - midi_track_write_note_on(&midi_track, kTicks, channel, n + add, volume); - midi_track_write_note_on(&midi_track, 1, channel, nextNote + add, volume); - midi_track_write_note_on(&midi_track, d - kTicks - 1, channel, n + add, 0); - midi_track_write_note_on(&midi_track, 0, channel, nextNote + add, 0); - nextPortamento = 0; - } else if(nextKeyOff) { - midi_track_write_control_change(&midi_track, 0, channel, 5, 0); // Portamento time - if(lastNote >= 0) { - if(lastNote != n) { - midi_track_write_note_on(&midi_track, restTime + kTicks, channel, n + add, volume); - midi_track_write_note_on(&midi_track, d - kTicks, channel, lastNote + add, 0); - restTime = 0; - } else restTime += duration; - } else { - midi_track_write_note_on(&midi_track, restTime + kTicks, channel, n + add, volume); - restTime = duration; - } - lastNote = n; - } else { - if(lastNote >= 0) { - if(lastNote != n) { - midi_track_write_note_on(&midi_track, restTime + kTicks, channel, n + add, volume); - midi_track_write_note_on(&midi_track, d - kTicks, channel, n + add, 0); - midi_track_write_note_on(&midi_track, 0, channel, lastNote + add, 0); - } else { - midi_track_write_note_on(&midi_track, restTime + d, channel, n + add, 0); - } - } else { - midi_track_write_note_on(&midi_track, restTime + kTicks, channel, n + add, volume); - midi_track_write_note_on(&midi_track, d - kTicks, channel, n + add, 0); - } - restTime = duration - d; - lastNote = -1; - } - } else { - restTime += duration; - } - totalTicks += duration; - nextPortamento = 0; - nextKeyOff = 0; -} - -void handleRest(uint8_t duration) { - restTime += duration; - totalTicks += duration; -} - -void handlePortamento(int16_t p) { - nextPortamento = p; -} - -void handleDisableKeyOff() { - nextKeyOff = 1; -} - -void handleDataEnd() { -} - -void handleSetVoiceNum(uint8_t voice) { - midi_track_write_program_change(&midi_track, restTime, channel, voice); - restTime = 0; -} - -static uint32_t calcTempo(uint32_t tempo) { - uint32_t mdxTempo = 1250000 / (256*(256-tempo)); - return 60000000 / mdxTempo; -} - -void handleSetTempo(uint8_t tempo) { - midi_track_write_tempo(&midi_track, restTime, calcTempo(tempo)); - restTime = 0; - if(firstTempo == 0) firstTempo = tempo; -} - -void handleDetune(int16_t det) { - midi_track_write_rpn_msb(&midi_track, restTime, channel, 0, 32); // Pitch Bend Sensitivity - midi_track_write_pitch_bend(&midi_track, 0, channel, 0x2000 + det * 4); - detune = det; - restTime = 0; -} - -static int volumeVal(uint8_t v) { - int vol_conv[] = { - 85, 87, 90, 93, 95, 98, 101, 103, - 106, 109, 111, 114, 117, 119, 122, 125 - }; - - if(v < 16) return vol_conv[v]; - return 255 - v; -} - -void handleSetVolume(uint8_t vol) { - volume = volumeVal(vol) & 0x7f; - midi_track_write_control_change(&midi_track, restTime, channel, 7, pan ? volumeVal(vol) & 0x7f : 0); - restTime = 0; -} - -void handlePan(uint8_t p) { - pan = p; - if(pan == 0) { - midi_track_write_control_change(&midi_track, restTime, channel, 7, 0); - restTime = 0; - } - uint8_t pans[] = { 64, 127, 0, 64 }; - midi_track_write_control_change(&midi_track, restTime, channel, 10, pans[pan & 0x03]); - restTime = 0; -} - -void handleSoundLength(uint8_t q) { - qTicks = q; -} - -void handleKeyOnDelay(uint8_t k) { - kTicks = k; -} - -void handleVolumeInc() { - int v = (volume * 16 + 15) / 127; - volume = (v + 1) * 127 / 15; -} - -void handleVolumeDec() { - int v = (volume * 16 + 15) / 127; - volume = (v - 1) * 127 / 15; -} - -void handlePerformanceEnd(uint16_t loopOffset) {} -void handleSyncSend(uint8_t channel) {} -void handleSyncWait() {} -void handleADPCMNoiseFreq(uint8_t freq) {} -void handleOPMLFO(uint8_t sync_wave, uint8_t lfrq, uint8_t pmd, uint8_t amd, uint8_t pms_ams) {} -void handleOPMLFOMHON() {} -void handleOPMLFOMHOF() {} -void handlePCM8Enable() {} -void handleFadeOut(uint8_t f) {} -void handleUndefinedCommand(uint8_t b) {} -void handleSetOPMRegister(uint8_t reg, uint8_t val) {} -void handleSetNoteLength(uint8_t ticks) {} -void handleLFOPitch(uint8_t b, uint16_t period, uint16_t change) {} -void handleLFOPitchMPON() {} -void handleLFOPitchMPOF() {} -void handleLFOVolume(uint8_t b, uint16_t period, uint16_t change) {} -void handleLFOVolumeMAON() {} -void handleLFOVolumeMAOF() {} -void handleLFODelaySetting(uint8_t d) {} - -static void run_through_file(struct mdx_file *f, int *num_cmds_out, int *pcm8_out, int *pcm_notes_out) { - *pcm8_out = 0; - memset(num_cmds_out, 0, 16 * sizeof(int)); - if(pcm_notes_out) memset(pcm_notes_out, 0, 96 * sizeof(int)); - - for(int i = 0; i < f->num_tracks; i++) { - struct mdx_track *track = &f->tracks[i]; - - handleChannelStart(f, track, i); - - for(int j = 0; j < track->data_len; /* nothing */) { - int l = mdx_cmd_len(track->data, j, track->data_len - j); - if(l < 0) break; - - uint8_t *p = &track->data[j]; - - // stop on performance end command - num_cmds_out[i]++; - if(*p == 0xf1 && j < track->data_len - 1 && p[1] == 0) { - break; - } - if(*p == 0xe8) *pcm8_out = 1; - if(pcm_notes_out && i >= 8 && *p >= 0x80 && *p <= 0xdf) { - pcm_notes_out[*p - 0x80]++; - } - - // printf("channel=%d file_offset=0x%08x channel_offset=0x%08x length=%d ", i, j + (track->data - f->data), j, l); - - if(*p <= 0x7f) { - handleRest(*p); - } else if(*p <= 0xdf) { - handleNote(*p - 0x80, p[1] + 1); - } else switch(*p) { - case 0xff: handleSetTempo(p[1]); break; - case 0xfe: handleSetOPMRegister(p[1], p[2]); break; - case 0xfd: handleSetVoiceNum(p[1]); break; - case 0xfc: handlePan(p[1]); break; - case 0xfb: handleSetVolume(p[1]); break; - case 0xfa: handleVolumeDec(); break; - case 0xf9: handleVolumeInc(); break; - case 0xf8: handleSetNoteLength(p[1]); break; - case 0xf7: handleDisableKeyOff(); break; - case 0xf6: - { - p[2] = p[1]; - p += 3; - } - break; - case 0xf5: - { - int16_t ofs = p[1] << 8 | p[2]; - p += 3; - if(p[ofs - 1] > 1) { - p[ofs - 1]--; - p += ofs; - } - } - break; - case 0xf4: - { - int16_t ofs = (p[1] << 8) | p[2]; - p += 3; - int16_t start_ofs = (p[ofs] << 8) | p[ofs + 1]; - if(p[ofs + start_ofs + 1] <= 1) { - p += ofs + 2; - } - } - break; - case 0xf3: handleDetune(p[1] << 8 | p[2]); break; - case 0xf2: handlePortamento(p[1] << 8 | p[2]); break; - case 0xf1: handlePerformanceEnd(p[1] == 0 ? 0 : (p[1] << 8 | p[2])); break; - case 0xf0: handleKeyOnDelay(p[1]); break; - case 0xef: handleSyncSend(p[1]); break; - case 0xee: handleSyncWait(); break; - case 0xed: handleADPCMNoiseFreq(p[1]); break; - case 0xec: - { - if(p[1] == 0x80) handleLFOPitchMPOF(); - else if(p[1] == 0x81) handleLFOPitchMPON(); - else handleLFOPitch(p[1], p[2] << 8 | p[3], p[4] << 8 | p[5]); - } - break; - case 0xeb: - { - if(p[1] == 0x80) handleLFOVolumeMAOF(); - else if(p[1] == 0x81) handleLFOVolumeMAON(); - else handleLFOVolume(p[1], p[2] << 8 | p[3], p[4] << 8 | p[5]); - } - break; - case 0xea: - { - if(p[1] == 0x80) handleOPMLFOMHOF(); - else if(p[1] == 0x81) handleOPMLFOMHON(); - else handleOPMLFO(p[1], p[2], p[3], p[4], p[5]); - } - break; - case 0xe9: handleLFODelaySetting(p[1]); break; - case 0xe8: handlePCM8Enable(); break; - case 0xe7: handleFadeOut(p[2]); break; - default: - handleUndefinedCommand(*p); - break; - } - j += l; - } - handleChannelEnd(f, track, i); - } -} +int opt_channel_mask = 0xffff; +int opt_loops = 1; +int opt_fadeout_rate = 4; static int write_cb(void *buf, size_t len, void *data_ptr) { return fwrite(buf, 1, len, (FILE *)data_ptr); @@ -353,11 +31,25 @@ static int write_cb(void *buf, size_t len, void *data_ptr) { int main(int argc, char **argv) { int optind = cmdline_parse_args(argc, argv, (struct cmdline_option[]){ { - 'u', "utf8", - "Convert strings to UTF-8", - 0, - TYPE_SWITCH, - TYPE_INT, &opt_utf8 + 'm', "mask", + "Channel mask", + "mask", + TYPE_REQUIRED, + TYPE_INT, &opt_channel_mask + }, + { + 'l', "loops", + "Loop times. Default 1.", + "n", + TYPE_REQUIRED, + TYPE_INT, &opt_loops + }, + { + 'f', "fadeout-rate", + "Fade-out rate. Default 4.", + "n", + TYPE_REQUIRED, + TYPE_INT, &opt_fadeout_rate }, { 'o', "output", @@ -371,43 +63,67 @@ int main(int argc, char **argv) { if(optind < 0) exit(-optind); - size_t data_len = 0; - uint8_t *data = load_file(argv[optind], &data_len); - if(!data) { - fprintf(stderr, "Could not load %s\n", argv[optind]); - return 1; - } - - struct mdx_file f; - mdx_file_load(&f, data, data_len); - - midi_file_init( &midi_file, MIDI_FORMAT_MULTI_TRACKS, 0, 48); - - int num_cmds_out[16], pcm8_out; - run_through_file(&f, num_cmds_out, &pcm8_out, 0); + for(int i = optind; i < argc; i++) { + struct midi_file midi_file; + midi_file_init(&midi_file, MIDI_FORMAT_MULTI_TRACKS, 16, 48); + + struct midi_track *first_track = midi_file_prepend_empty_track(&midi_file); + midi_track_write_time_signature(first_track, 0, 4, 2, 0, 0); + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), "Converted from %s", argv[optind]); + midi_track_write_text(first_track, 0, buf, -1); + + struct mdx_driver mdx_driver; + struct midi_timer_driver timer_driver; + struct adpcm_midi_driver adpcm_driver; + struct fm_midi_driver fm_driver; + + midi_timer_driver_init(&timer_driver); + adpcm_midi_driver_init(&adpcm_driver, &midi_file); + fm_midi_driver_init(&fm_driver, &midi_file); + mdx_driver_init( + &mdx_driver, + (struct timer_driver *)&timer_driver, + (struct fm_driver *)&fm_driver, + (struct adpcm_driver *)&adpcm_driver + ); + mdx_driver.max_loops = opt_loops; + + struct mdx_file mdx_file; + struct pdx_file pdx_file; + + size_t mdx_file_size; + uint8_t *mdx_file_data = load_file(argv[i], &mdx_file_size); + if(!mdx_file_data) + continue; + mdx_file_load(&mdx_file, mdx_file_data, mdx_file_size); + printf("Loaded MDX file \"%s\"\n", argv[i]); + + mdx_driver_load(&mdx_driver, &mdx_file, &pdx_file); + + while(!mdx_driver.ended) { + adpcm_midi_driver_tick(&adpcm_driver); + fm_midi_driver_tick(&fm_driver); + midi_timer_driver_tick(&timer_driver); + } - free(data); + adpcm_midi_driver_end(&adpcm_driver); + fm_midi_driver_end(&fm_driver); - struct midi_track *first_track = midi_file_prepend_empty_track(&midi_file); - midi_track_write_tempo(first_track, 0, calcTempo(firstTempo ? firstTempo : 200)); - midi_track_write_time_signature(first_track, 0, 4, 2, 0, 0); - char buf[PATH_MAX]; - snprintf(buf, sizeof(buf), "Converted from %s", argv[optind]); - midi_track_write_text(first_track, 0, buf, -1); - midi_track_write_track_end(first_track, totalTicks); - if(!opt_output || !opt_output[0]) { - char midbuf[PATH_MAX]; - replace_ext(midbuf, sizeof(midbuf), argv[optind], "mid"); - opt_output = midbuf; - } - FILE *o = fopen(opt_output, "wb"); - if(!o) { - fprintf(stderr, "Could not open %s: %s (%d)\n", opt_output, strerror(errno), errno); - return -1; + if(!opt_output || !opt_output[0]) { + char midbuf[PATH_MAX]; + replace_ext(midbuf, sizeof(midbuf), argv[optind], "mid"); + opt_output = midbuf; + } + FILE *o = fopen(opt_output, "wb"); + if(!o) { + fprintf(stderr, "Could not open %s: %s (%d)\n", opt_output, strerror(errno), errno); + return -1; + } + midi_file_write(&midi_file, write_cb, o); + fclose(o); + midi_file_clear(&midi_file); } - midi_file_write(&midi_file, write_cb, o); - fclose(o); - midi_file_clear(&midi_file); return 0; } diff --git a/mdx2pcm.c b/mdx2pcm.c index 2cd0dc0..4b73588 100644 --- a/mdx2pcm.c +++ b/mdx2pcm.c @@ -140,7 +140,6 @@ int main(int argc, char **argv) { mdx_driver_load(&mdx_driver, &mdx_file, &pdx_file); while(!mdx_driver.ended) { - fflush(stdout); int samples_remaining = BUFFER_SIZE; memset(mixBuf, 0, sizeof(mixBuf)); int16_t *mixBufp = mixBuf; diff --git a/midi_timer_driver.c b/midi_timer_driver.c new file mode 100644 index 0000000..f8d7f41 --- /dev/null +++ b/midi_timer_driver.c @@ -0,0 +1,19 @@ +#include "midi_timer_driver.h" + +static void midi_timer_driver_set_opm_tempo(struct timer_driver *driver, int opm_tempo) { + printf("midi_timer_driver_set_opm_tempo opm_tempo=%d\n", opm_tempo); +} +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; +} + +void midi_timer_driver_deinit(struct midi_timer_driver *driver) { +} + +int midi_timer_driver_tick(struct midi_timer_driver *driver) { + if(!driver->timer_driver.tick) return -1; + driver->timer_driver.tick((struct timer_driver *)&driver, driver->timer_driver.data_ptr); + return 0; +} diff --git a/midi_timer_driver.h b/midi_timer_driver.h new file mode 100644 index 0000000..a96b091 --- /dev/null +++ b/midi_timer_driver.h @@ -0,0 +1,14 @@ +#ifndef MIDI_TIMER_DRIVER_H_ +#define MIDI_TIMER_DRIVER_H_ + +#include "timer_driver.h" + +struct midi_timer_driver { + struct timer_driver timer_driver; + int ticks_per_quarter_note; +}; +int midi_timer_driver_init(struct midi_timer_driver *driver); +void midi_timer_driver_deinit(struct midi_timer_driver *driver); +int midi_timer_driver_tick(struct midi_timer_driver *driver); + +#endif /* MIDI_TIMER_DRIVER_H_ */