1 /*
2 * libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
3 *
4 * Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
5 * ADLMIDI Library API: Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru>
6 *
7 * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
8 * http://iki.fi/bisqwit/source/adlmidi.html
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
25
26 // Rename class to avoid ABI collisions
27 #define BW_MidiSequencer AdlMidiSequencer
28 // Inlucde MIDI sequencer class implementation
29 #include "midi_sequencer_impl.hpp"
30
31 #include "adlmidi_private.hpp"
32
33 /****************************************************
34 * Real-Time MIDI calls proxies *
35 ****************************************************/
36
rtNoteOn(void * userdata,uint8_t channel,uint8_t note,uint8_t velocity)37 static void rtNoteOn(void *userdata, uint8_t channel, uint8_t note, uint8_t velocity)
38 {
39 MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
40 context->realTime_NoteOn(channel, note, velocity);
41 }
42
rtNoteOff(void * userdata,uint8_t channel,uint8_t note)43 static void rtNoteOff(void *userdata, uint8_t channel, uint8_t note)
44 {
45 MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
46 context->realTime_NoteOff(channel, note);
47 }
48
rtNoteAfterTouch(void * userdata,uint8_t channel,uint8_t note,uint8_t atVal)49 static void rtNoteAfterTouch(void *userdata, uint8_t channel, uint8_t note, uint8_t atVal)
50 {
51 MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
52 context->realTime_NoteAfterTouch(channel, note, atVal);
53 }
54
rtChannelAfterTouch(void * userdata,uint8_t channel,uint8_t atVal)55 static void rtChannelAfterTouch(void *userdata, uint8_t channel, uint8_t atVal)
56 {
57 MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
58 context->realTime_ChannelAfterTouch(channel, atVal);
59 }
60
rtControllerChange(void * userdata,uint8_t channel,uint8_t type,uint8_t value)61 static void rtControllerChange(void *userdata, uint8_t channel, uint8_t type, uint8_t value)
62 {
63 MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
64 context->realTime_Controller(channel, type, value);
65 }
66
rtPatchChange(void * userdata,uint8_t channel,uint8_t patch)67 static void rtPatchChange(void *userdata, uint8_t channel, uint8_t patch)
68 {
69 MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
70 context->realTime_PatchChange(channel, patch);
71 }
72
rtPitchBend(void * userdata,uint8_t channel,uint8_t msb,uint8_t lsb)73 static void rtPitchBend(void *userdata, uint8_t channel, uint8_t msb, uint8_t lsb)
74 {
75 MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
76 context->realTime_PitchBend(channel, msb, lsb);
77 }
78
rtSysEx(void * userdata,const uint8_t * msg,size_t size)79 static void rtSysEx(void *userdata, const uint8_t *msg, size_t size)
80 {
81 MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
82 context->realTime_SysEx(msg, size);
83 }
84
85
86 /* NonStandard calls */
rtRawOPL(void * userdata,uint8_t reg,uint8_t value)87 static void rtRawOPL(void *userdata, uint8_t reg, uint8_t value)
88 {
89 MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
90 return context->realTime_rawOPL(reg, value);
91 }
92
rtDeviceSwitch(void * userdata,size_t track,const char * data,size_t length)93 static void rtDeviceSwitch(void *userdata, size_t track, const char *data, size_t length)
94 {
95 MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
96 context->realTime_deviceSwitch(track, data, length);
97 }
98
rtCurrentDevice(void * userdata,size_t track)99 static size_t rtCurrentDevice(void *userdata, size_t track)
100 {
101 MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
102 return context->realTime_currentDevice(track);
103 }
104 /* NonStandard calls End */
105
106
initSequencerInterface()107 void MIDIplay::initSequencerInterface()
108 {
109 std::memset(&m_sequencerInterface, 0, sizeof(BW_MidiRtInterface));
110
111 m_sequencerInterface.onDebugMessage = hooks.onDebugMessage;
112 m_sequencerInterface.onDebugMessage_userData = hooks.onDebugMessage_userData;
113
114 /* MIDI Real-Time calls */
115 m_sequencerInterface.rtUserData = this;
116 m_sequencerInterface.rt_noteOn = rtNoteOn;
117 m_sequencerInterface.rt_noteOff = rtNoteOff;
118 m_sequencerInterface.rt_noteAfterTouch = rtNoteAfterTouch;
119 m_sequencerInterface.rt_channelAfterTouch = rtChannelAfterTouch;
120 m_sequencerInterface.rt_controllerChange = rtControllerChange;
121 m_sequencerInterface.rt_patchChange = rtPatchChange;
122 m_sequencerInterface.rt_pitchBend = rtPitchBend;
123 m_sequencerInterface.rt_systemExclusive = rtSysEx;
124
125 /* NonStandard calls */
126 m_sequencerInterface.rt_rawOPL = rtRawOPL;
127 m_sequencerInterface.rt_deviceSwitch = rtDeviceSwitch;
128 m_sequencerInterface.rt_currentDevice = rtCurrentDevice;
129 /* NonStandard calls End */
130
131 m_sequencer.setInterface(&m_sequencerInterface);
132 }
133
Tick(double s,double granularity)134 double MIDIplay::Tick(double s, double granularity)
135 {
136 double ret = m_sequencer.Tick(s, granularity);
137
138 s *= m_sequencer.getTempoMultiplier();
139 for(uint16_t c = 0; c < m_synth.m_numChannels; ++c)
140 m_chipChannels[c].addAge(static_cast<int64_t>(s * 1000.0));
141
142 updateVibrato(s);
143 updateArpeggio(s);
144 #if !defined(ADLMIDI_AUDIO_TICK_HANDLER)
145 updateGlide(s);
146 #endif
147
148 return ret;
149 }
150
151 #endif /* ADLMIDI_DISABLE_MIDI_SEQUENCER */
152