aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/adlmidi.h53
-rw-r--r--src/adlmidi.cpp237
-rw-r--r--src/adlmidi_load.cpp17
-rw-r--r--src/adlmidi_midiplay.cpp32
-rw-r--r--src/adlmidi_opl3.cpp10
-rw-r--r--src/adlmidi_private.hpp12
6 files changed, 298 insertions, 63 deletions
diff --git a/include/adlmidi.h b/include/adlmidi.h
index c67952f..bc1b2d3 100644
--- a/include/adlmidi.h
+++ b/include/adlmidi.h
@@ -33,14 +33,14 @@ extern "C" {
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#include <stdint.h>
typedef uint8_t ADL_UInt8;
-typedef uint16_t ADL_Uint16;
-typedef int8_t ADL_Sint8;
+typedef uint16_t ADL_UInt16;
+typedef int8_t ADL_SInt8;
typedef int16_t ADL_Sint16;
#else
typedef unsigned char ADL_UInt8;
-typedef unsigned short ADL_Uint16;
-typedef char ADL_Sint8;
-typedef short ADL_Sint16;
+typedef unsigned short ADL_UInt16;
+typedef char ADL_SInt8;
+typedef short ADL_SInt16;
#endif
enum ADLMIDI_VolumeModels
@@ -67,7 +67,7 @@ extern int adl_setNumChips(struct ADL_MIDIPlayer *device, int numCards);
/* Get current number of emulated chips */
extern int adl_getNumChips(struct ADL_MIDIPlayer *device);
-/* Sets a number of the patches bank from 0 to N banks */
+/* Sets a number of the patches bank from 0 to N banks. Is recommended to call adl_reset() to apply changes to already-loaded file player or real-time. */
extern int adl_setBank(struct ADL_MIDIPlayer *device, int bank);
/* Returns total number of available banks */
@@ -107,7 +107,7 @@ extern void adl_setLogarithmicVolumes(struct ADL_MIDIPlayer *device, int logvol)
/*Set different volume range model */
extern void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *device, int volumeModel);
-/*Load WOPL bank file from File System*/
+/*Load WOPL bank file from File System. Is recommended to call adl_reset() to apply changes to already-loaded file player or real-time.*/
extern int adl_openBankFile(struct ADL_MIDIPlayer *device, const char *filePath);
/*Load WOPL bank file from memory data*/
@@ -192,12 +192,10 @@ extern size_t adl_metaMarkerCount(struct ADL_MIDIPlayer *device);
extern const struct Adl_MarkerEntry adl_metaMarker(struct ADL_MIDIPlayer *device, size_t index);
-
-
/*Take a sample buffer and iterate MIDI timers */
extern int adl_play(struct ADL_MIDIPlayer *device, int sampleCount, short out[]);
-/*Generate audio output from chip emulators without iteration of MIDI timers. 512 samples per channel is a maximum*/
+/*Generate audio output from chip emulators without iteration of MIDI timers.*/
extern int adl_generate(struct ADL_MIDIPlayer *device, int sampleCount, short *out);
/**
@@ -215,9 +213,44 @@ extern double adl_tickEvents(struct ADL_MIDIPlayer *device, double seconds, doub
/*Returns 1 if music position has reached end*/
extern int adl_atEnd(struct ADL_MIDIPlayer *device);
+/**RealTime**/
+
/*Force Off all notes on all channels*/
extern void adl_panic(struct ADL_MIDIPlayer *device);
+/*Reset states of all controllers on all MIDI channels*/
+extern void adl_rt_resetState(struct ADL_MIDIPlayer *device);
+
+/*Turn specific MIDI note ON*/
+extern bool adl_rt_noteOn(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 note, ADL_UInt8 velocity);
+
+/*Turn specific MIDI note OFF*/
+extern void adl_rt_noteOff(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 note);
+
+/*Set note after-touch*/
+extern void adl_rt_noteAfterTouch(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 note, ADL_UInt8 atVal);
+/*Set channel after-touch*/
+extern void adl_rt_channelAfterTouch(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 atVal);
+
+/*Apply controller change*/
+extern void adl_rt_controllerChange(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 type, ADL_UInt8 value);
+
+/*Apply patch change*/
+extern void adl_rt_patchChange(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 patch);
+
+/*Apply pitch bend change*/
+extern void adl_rt_pitchBend(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 pitch);
+/*Apply pitch bend change*/
+extern void adl_rt_pitchBendML(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 msb, ADL_UInt8 lsb);
+
+/*Change LSB of the bank*/
+extern void adl_rt_bankChangeLSB(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 lsb);
+/*Change MSB of the bank*/
+extern void adl_rt_bankChangeMSB(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 msb);
+/*Change bank by absolute signed value*/
+extern void adl_rt_bankChange(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_SInt16 bank);
+
+
/**Hooks**/
typedef void (*ADL_RawEventHook)(void *userdata, ADL_UInt8 type, ADL_UInt8 subtype, ADL_UInt8 channel, const ADL_UInt8 *data, size_t len);
diff --git a/src/adlmidi.cpp b/src/adlmidi.cpp
index 380630a..dd4a3e1 100644
--- a/src/adlmidi.cpp
+++ b/src/adlmidi.cpp
@@ -75,6 +75,7 @@ ADLMIDI_EXPORT int adl_setNumChips(ADL_MIDIPlayer *device, int numCards)
}
play->opl.NumCards = play->m_setup.NumCards;
+ adl_reset(device);
return adlRefreshNumCards(device);
}
@@ -173,6 +174,7 @@ ADLMIDI_EXPORT void adl_setPercMode(ADL_MIDIPlayer *device, int percmod)
MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
play->m_setup.AdlPercussionMode = percmod;
play->opl.AdlPercussionMode = play->m_setup.AdlPercussionMode;
+ play->opl.updateFlags();
}
ADLMIDI_EXPORT void adl_setHVibrato(ADL_MIDIPlayer *device, int hvibro)
@@ -181,6 +183,7 @@ ADLMIDI_EXPORT void adl_setHVibrato(ADL_MIDIPlayer *device, int hvibro)
MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
play->m_setup.HighVibratoMode = hvibro;
play->opl.HighVibratoMode = play->m_setup.HighVibratoMode;
+ play->opl.updateDeepFlags();
}
ADLMIDI_EXPORT void adl_setHTremolo(ADL_MIDIPlayer *device, int htremo)
@@ -189,6 +192,7 @@ ADLMIDI_EXPORT void adl_setHTremolo(ADL_MIDIPlayer *device, int htremo)
MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
play->m_setup.HighTremoloMode = htremo;
play->opl.HighTremoloMode = play->m_setup.HighTremoloMode;
+ play->opl.updateDeepFlags();
}
ADLMIDI_EXPORT void adl_setScaleModulators(ADL_MIDIPlayer *device, int smod)
@@ -358,6 +362,8 @@ ADLMIDI_EXPORT void adl_reset(struct ADL_MIDIPlayer *device)
MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
play->m_setup.tick_skip_samples_delay = 0;
play->opl.Reset(play->m_setup.PCM_RATE);
+ play->ch.clear();
+ play->ch.resize(play->opl.NumChannels);
}
ADLMIDI_EXPORT double adl_totalTimeLength(struct ADL_MIDIPlayer *device)
@@ -640,45 +646,90 @@ ADLMIDI_EXPORT int adl_generate(struct ADL_MIDIPlayer *device, int sampleCount,
if(!device)
return 0;
- /*
- * TODO: Implement the processing of vibrato and arpeggio here.
- * Otherwise, in realtime playing there are will not be processed
- * and chip channel management will work incorrectly!
- */
-
MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
- sampleCount = (sampleCount > 1024) ? 1024 : sampleCount;
+ MIDIplay::Setup &setup = player->m_setup;
- //! Count of stereo samples
- ssize_t in_generatedStereo = sampleCount / 2;
- //! Unsigned total sample count
- //fill buffer with zeros
- std::memset(out, 0, static_cast<size_t>(sampleCount) * sizeof(int16_t));
+ ssize_t gotten_len = 0;
+ ssize_t n_periodCountStereo = 512;
- if(player->m_setup.NumCards == 1)
- {
- #ifdef ADLMIDI_USE_DOSBOX_OPL
- player->opl.cards[0].GenerateArr(out, &in_generatedStereo);
- sampleCount = in_generatedStereo * 2;
- #else
- OPL3_GenerateStream(&player->opl.cards[0], out, static_cast<Bit32u>(in_generatedStereo));
- #endif
- }
- else
+ int left = sampleCount;
+ bool hasSkipped = setup.tick_skip_samples_delay > 0;
+
+ double delay = double(sampleCount) / double(setup.PCM_RATE);
+
+ while(left > 0)
{
- /* Generate data from every chip and mix result */
- for(unsigned card = 0; card < player->m_setup.NumCards; ++card)
- {
- #ifdef ADLMIDI_USE_DOSBOX_OPL
- player->opl.cards[card].GenerateArrMix(out, &in_generatedStereo);
- sampleCount = in_generatedStereo * 2;
- #else
- OPL3_GenerateStreamMix(&player->opl.cards[card], out, static_cast<Bit32u>(in_generatedStereo));
- #endif
- }
+ {//...
+ const double eat_delay = delay < setup.maxdelay ? delay : setup.maxdelay;
+ if(hasSkipped)
+ {
+ size_t samples = setup.tick_skip_samples_delay > sampleCount ? sampleCount : setup.tick_skip_samples_delay;
+ n_periodCountStereo = samples / 2;
+ }
+ else
+ {
+ delay -= eat_delay;
+ setup.carry += setup.PCM_RATE * eat_delay;
+ n_periodCountStereo = static_cast<ssize_t>(setup.carry);
+ setup.carry -= n_periodCountStereo;
+ }
+
+ {
+ ssize_t leftSamples = left / 2;
+ if(n_periodCountStereo > leftSamples)
+ {
+ setup.tick_skip_samples_delay = (n_periodCountStereo - leftSamples) * 2;
+ n_periodCountStereo = leftSamples;
+ }
+ //! Count of stereo samples
+ ssize_t in_generatedStereo = (n_periodCountStereo > 512) ? 512 : n_periodCountStereo;
+ //! Total count of samples
+ ssize_t in_generatedPhys = in_generatedStereo * 2;
+ //! Unsigned total sample count
+ //fill buffer with zeros
+ int16_t *out_buf = player->outBuf;
+ std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(int16_t));
+ unsigned int chips = player->opl.NumCards;
+ if(chips == 1)
+ {
+ #ifdef ADLMIDI_USE_DOSBOX_OPL
+ player->opl.cards[0].GenerateArr(out_buf, &in_generatedStereo);
+ in_generatedPhys = in_generatedStereo * 2;
+ #else
+ OPL3_GenerateStream(&player->opl.cards[0], out_buf, static_cast<Bit32u>(in_generatedStereo));
+ #endif
+ }
+ else if(n_periodCountStereo > 0)
+ {
+ /* Generate data from every chip and mix result */
+ for(unsigned card = 0; card < chips; ++card)
+ {
+ #ifdef ADLMIDI_USE_DOSBOX_OPL
+ player->opl.cards[card].GenerateArrMix(out_buf, &in_generatedStereo);
+ in_generatedPhys = in_generatedStereo * 2;
+ #else
+ OPL3_GenerateStreamMix(&player->opl.cards[card], out_buf, static_cast<Bit32u>(in_generatedStereo));
+ #endif
+ }
+ }
+ /* Process it */
+ SendStereoAudio(setup, sampleCount, in_generatedStereo, out_buf, gotten_len, out);
+
+ left -= (int)in_generatedPhys;
+ gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
+ }
+
+ if(hasSkipped)
+ {
+ setup.tick_skip_samples_delay -= n_periodCountStereo * 2;
+ hasSkipped = setup.tick_skip_samples_delay > 0;
+ }
+ else
+ player->TickIteratos(eat_delay);
+ }//...
}
- return sampleCount;
+ return static_cast<int>(gotten_len);
#endif
}
@@ -711,3 +762,123 @@ ADLMIDI_EXPORT void adl_panic(struct ADL_MIDIPlayer *device)
return;
player->realTime_panic();
}
+
+ADLMIDI_EXPORT void adl_rt_resetState(struct ADL_MIDIPlayer *device)
+{
+ if(!device)
+ return;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return;
+ player->realTime_ResetState();
+}
+
+bool adl_rt_noteOn(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 note, ADL_UInt8 velocity)
+{
+ if(!device)
+ return false;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return false;
+ return player->realTime_NoteOn(channel, note, velocity);
+}
+
+void adl_rt_noteOff(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 note)
+{
+ if(!device)
+ return;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return;
+ player->realTime_NoteOff(channel, note);
+}
+
+void adl_rt_noteAfterTouch(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 note, ADL_UInt8 atVal)
+{
+ if(!device)
+ return;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return;
+ player->realTime_NoteAfterTouch(channel, note, atVal);
+}
+
+void adl_rt_channelAfterTouch(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 atVal)
+{
+ if(!device)
+ return;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return;
+ player->realTime_ChannelAfterTouch(channel, atVal);
+}
+
+void adl_rt_controllerChange(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 type, ADL_UInt8 value)
+{
+ if(!device)
+ return;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return;
+ player->realTime_Controller(channel, type, value);
+}
+
+void adl_rt_patchChange(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 patch)
+{
+ if(!device)
+ return;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return;
+ player->realTime_PatchChange(channel, patch);
+}
+
+void adl_rt_pitchBend(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 pitch)
+{
+ if(!device)
+ return;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return;
+ player->realTime_PitchBend(channel, pitch);
+}
+
+void adl_rt_pitchBendML(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 msb, ADL_UInt8 lsb)
+{
+ if(!device)
+ return;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return;
+ player->realTime_PitchBend(channel, msb, lsb);
+}
+
+void adl_rt_bankChangeLSB(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 lsb)
+{
+ if(!device)
+ return;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return;
+ player->realTime_BankChangeLSB(channel, lsb);
+}
+
+void adl_rt_bankChangeMSB(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 msb)
+{
+ if(!device)
+ return;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return;
+ player->realTime_BankChangeMSB(channel, msb);
+}
+
+void adl_rt_bankChange(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_SInt16 bank)
+{
+ if(!device)
+ return;
+ MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
+ if(!player)
+ return;
+ player->realTime_BankChange(channel, (uint16_t)bank);
+}
diff --git a/src/adlmidi_load.cpp b/src/adlmidi_load.cpp
index 89428c9..f33c091 100644
--- a/src/adlmidi_load.cpp
+++ b/src/adlmidi_load.cpp
@@ -379,22 +379,7 @@ bool MIDIplay::LoadMIDI(MIDIplay::fileReader &fr)
}
/**** Set all properties BEFORE starting of actial file reading! ****/
- m_setup.tick_skip_samples_delay = 0;
- opl.HighTremoloMode = m_setup.HighTremoloMode == -1 ? adlbanksetup[m_setup.AdlBank].deepTremolo : (bool)m_setup.HighTremoloMode;
- opl.HighVibratoMode = m_setup.HighVibratoMode == -1 ? adlbanksetup[m_setup.AdlBank].deepVibrato : (bool)m_setup.HighVibratoMode;
- opl.AdlPercussionMode = m_setup.AdlPercussionMode == -1 ? adlbanksetup[m_setup.AdlBank].adLibPercussions : (bool)m_setup.AdlPercussionMode;
- opl.ScaleModulators = m_setup.ScaleModulators == -1 ? adlbanksetup[m_setup.AdlBank].scaleModulators : (bool)m_setup.ScaleModulators;
- opl.LogarithmicVolumes = m_setup.LogarithmicVolumes;
- //opl.CartoonersVolumes = false;
- opl.m_musicMode = OPL3::MODE_MIDI;
- opl.ChangeVolumeRangesModel(static_cast<ADLMIDI_VolumeModels>(m_setup.VolumeModel));
- if(m_setup.VolumeModel == ADLMIDI_VolumeModel_AUTO)//Use bank default volume model
- opl.m_volumeScale = (OPL3::VolumesScale)adlbanksetup[m_setup.AdlBank].volumeModel;
-
- opl.NumCards = m_setup.NumCards;
- opl.NumFourOps = m_setup.NumFourOps;
- cmf_percussion_mode = false;
- opl.Reset(m_setup.PCM_RATE);
+ applySetup();
atEnd = false;
loopStart = true;
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp
index dacb2b1..2470903 100644
--- a/src/adlmidi_midiplay.cpp
+++ b/src/adlmidi_midiplay.cpp
@@ -717,14 +717,30 @@ MIDIplay::MIDIplay():
m_setup.carry = 0.0;
m_setup.tick_skip_samples_delay = 0;
- opl.NumCards = m_setup.NumCards;
- opl.AdlBank = m_setup.AdlBank;
- opl.NumFourOps = m_setup.NumFourOps;
- opl.LogarithmicVolumes = m_setup.LogarithmicVolumes;
+ applySetup();
+}
+
+void MIDIplay::applySetup()
+{
+ m_setup.tick_skip_samples_delay = 0;
opl.HighTremoloMode = m_setup.HighTremoloMode == -1 ? adlbanksetup[m_setup.AdlBank].deepTremolo : (bool)m_setup.HighTremoloMode;
opl.HighVibratoMode = m_setup.HighVibratoMode == -1 ? adlbanksetup[m_setup.AdlBank].deepVibrato : (bool)m_setup.HighVibratoMode;
opl.AdlPercussionMode = m_setup.AdlPercussionMode == -1 ? adlbanksetup[m_setup.AdlBank].adLibPercussions : (bool)m_setup.AdlPercussionMode;
opl.ScaleModulators = m_setup.ScaleModulators == -1 ? adlbanksetup[m_setup.AdlBank].scaleModulators : (bool)m_setup.ScaleModulators;
+ opl.LogarithmicVolumes = m_setup.LogarithmicVolumes;
+ //opl.CartoonersVolumes = false;
+ opl.m_musicMode = OPL3::MODE_MIDI;
+ opl.ChangeVolumeRangesModel(static_cast<ADLMIDI_VolumeModels>(m_setup.VolumeModel));
+ if(m_setup.VolumeModel == ADLMIDI_VolumeModel_AUTO)//Use bank default volume model
+ opl.m_volumeScale = (OPL3::VolumesScale)adlbanksetup[m_setup.AdlBank].volumeModel;
+
+ opl.NumCards = m_setup.NumCards;
+ opl.NumFourOps = m_setup.NumFourOps;
+ cmf_percussion_mode = false;
+
+ opl.Reset(m_setup.PCM_RATE);
+ ch.clear();
+ ch.resize(opl.NumChannels);
}
uint64_t MIDIplay::ReadVarLen(uint8_t **ptr)
@@ -795,6 +811,14 @@ double MIDIplay::Tick(double s, double granularity)
return CurrentPositionNew.wait;
}
+void MIDIplay::TickIteratos(double s)
+{
+ for(uint16_t c = 0; c < opl.NumChannels; ++c)
+ ch[c].AddAge(static_cast<int64_t>(s * 1000.0));
+ UpdateVibrato(s);
+ UpdateArpeggio(s);
+}
+
void MIDIplay::seek(double seconds)
{
if(seconds < 0.0)
diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp
index 273f548..9813621 100644
--- a/src/adlmidi_opl3.cpp
+++ b/src/adlmidi_opl3.cpp
@@ -458,6 +458,16 @@ void OPL3::updateFlags()
}
}
+void OPL3::updateDeepFlags()
+{
+ for(unsigned card = 0; card < NumCards; ++card)
+ {
+ Poke(card, 0x0BD, regBD[card] = (HighTremoloMode * 0x80
+ + HighVibratoMode * 0x40
+ + AdlPercussionMode * 0x20));
+ }
+}
+
void OPL3::ChangeVolumeRangesModel(ADLMIDI_VolumeModels volumeModel)
{
switch(volumeModel)
diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp
index 46187bc..cb100dc 100644
--- a/src/adlmidi_private.hpp
+++ b/src/adlmidi_private.hpp
@@ -166,6 +166,7 @@ public:
};
class MIDIplay;
+struct ADL_MIDIPlayer;
class OPL3
{
public:
@@ -263,6 +264,7 @@ public:
void Pan(unsigned c, unsigned value);
void Silence();
void updateFlags();
+ void updateDeepFlags();
void ChangeVolumeRangesModel(ADLMIDI_VolumeModels volumeModel);
void Reset(unsigned long PCM_RATE);
};
@@ -300,12 +302,15 @@ struct MIDIEventHooks
class MIDIplay
{
+ friend void adl_reset(struct ADL_MIDIPlayer*);
public:
MIDIplay();
~MIDIplay()
{}
+ void applySetup();
+
/**********************Internal structures and classes**********************/
/**
@@ -852,6 +857,12 @@ public:
double Tick(double s, double granularity);
/**
+ * @brief Process extra iterators like vibrato or arpeggio
+ * @param s seconds since last call
+ */
+ void TickIteratos(double s);
+
+ /**
* @brief Change current position to specified time position in seconds
* @param seconds Absolute time position in seconds
*/
@@ -950,6 +961,7 @@ private:
//void UpdatePortamento(unsigned MidCh)
void NoteUpdate_All(uint16_t MidCh, unsigned props_mask);
void NoteOff(uint16_t MidCh, uint8_t note);
+
void UpdateVibrato(double amount);
void UpdateArpeggio(double /*amount*/);