Updated libADLMIDI to version 1.5.1

Changelog
 * Added an ability to disable the automatical arpeggio
 * Added an ability to set the count of loops (how many times to play the song)
 * Added an ability to disable/enable playing of selected MIDI channels
 * Fixed memory damages and crashes while playing XMI files
 * Added bank-specific MT32 defaults (to don't confuse XMI playback between different games, works for AIL and IBK only, and for WOPL if set at the header)
 * Added the chip channels allocation mode option
 * Fixed the playback of multi-song XMI files
 * Added an ability to switch the XMI song on the fly

ALSO (future updates)
 * Fixed the work on big endian processors
 * Fixed ARM64 build on some platforms
 * Improved support of the EA-MUS files (Thanks to [dashodanger](https://github.com/dashodanger))
 * Fixed crash on attempt to change the volume of a blank note
This commit is contained in:
Wohlstand 2023-01-02 01:17:44 +03:00 committed by Christoph Oelckers
parent 36a5308de1
commit 5bd573478b
32 changed files with 594 additions and 6603 deletions

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html
@ -551,6 +551,24 @@ ADLMIDI_EXPORT void adl_setFullRangeBrightness(struct ADL_MIDIPlayer *device, in
play->m_setup.fullRangeBrightnessCC74 = (fr_brightness != 0);
}
ADLMIDI_EXPORT void adl_setAutoArpeggio(ADL_MIDIPlayer *device, int aaEn)
{
if(!device)
return;
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
play->m_setup.enableAutoArpeggio = (aaEn != 0);
}
ADLMIDI_EXPORT int adl_getAutoArpeggio(ADL_MIDIPlayer *device)
{
if(!device)
return 0;
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
return play->m_setup.enableAutoArpeggio ? 1 : 0;
}
ADLMIDI_EXPORT void adl_setLoopEnabled(ADL_MIDIPlayer *device, int loopEn)
{
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
@ -565,6 +583,34 @@ ADLMIDI_EXPORT void adl_setLoopEnabled(ADL_MIDIPlayer *device, int loopEn)
#endif
}
ADLMIDI_EXPORT void adl_setLoopCount(ADL_MIDIPlayer *device, int loopCount)
{
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
if(!device)
return;
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
play->m_sequencer->setLoopsCount(loopCount);
#else
ADL_UNUSED(device);
ADL_UNUSED(loopCount);
#endif
}
ADLMIDI_EXPORT void adl_setLoopHooksOnly(ADL_MIDIPlayer *device, int loopHooksOnly)
{
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
if(!device)
return;
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
play->m_sequencer->setLoopHooksOnly(loopHooksOnly);
#else
ADL_UNUSED(device);
ADL_UNUSED(loopHooksOnly);
#endif
}
ADLMIDI_EXPORT void adl_setSoftPanEnabled(ADL_MIDIPlayer *device, int softPanEn)
{
if(!device)
@ -618,6 +664,29 @@ ADLMIDI_EXPORT int adl_getVolumeRangeModel(struct ADL_MIDIPlayer *device)
return play->m_synth->getVolumeScaleModel();
}
ADLMIDI_EXPORT void adl_setChannelAllocMode(struct ADL_MIDIPlayer *device, int chanalloc)
{
if(!device)
return;
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
Synth &synth = *play->m_synth;
if(chanalloc < -1 || chanalloc >= ADLMIDI_ChanAlloc_Count)
chanalloc = ADLMIDI_ChanAlloc_AUTO;
synth.m_channelAlloc = static_cast<ADLMIDI_ChannelAlloc>(chanalloc);
}
ADLMIDI_EXPORT int adl_getChannelAllocMode(struct ADL_MIDIPlayer *device)
{
if(!device)
return -1;
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
return static_cast<int>(play->m_synth->m_channelAlloc);
}
ADLMIDI_EXPORT int adl_openBankFile(struct ADL_MIDIPlayer *device, const char *filePath)
{
if(device)
@ -716,6 +785,35 @@ ADLMIDI_EXPORT int adl_openData(ADL_MIDIPlayer *device, const void *mem, unsigne
return -1;
}
ADLMIDI_EXPORT void adl_selectSongNum(struct ADL_MIDIPlayer *device, int songNumber)
{
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
if(!device)
return;
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
play->m_sequencer->setSongNum(songNumber);
#else
ADL_UNUSED(device);
ADL_UNUSED(songNumber);
#endif
}
ADLMIDI_EXPORT int adl_getSongsCount(struct ADL_MIDIPlayer *device)
{
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
if(!device)
return 0;
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
return play->m_sequencer->getSongsCount();
#else
ADL_UNUSED(device);
return 0;
#endif
}
ADLMIDI_EXPORT const char *adl_emulatorName()
{
@ -1083,6 +1181,36 @@ ADLMIDI_EXPORT void adl_setDebugMessageHook(struct ADL_MIDIPlayer *device, ADL_D
#endif
}
/* Set loop start hook */
ADLMIDI_EXPORT void adl_setLoopStartHook(struct ADL_MIDIPlayer *device, ADL_LoopPointHook loopStartHook, void *userData)
{
if(!device)
return;
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
play->hooks.onLoopStart = loopStartHook;
play->hooks.onLoopStart_userData = userData;
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
play->m_sequencerInterface->onloopStart = loopStartHook;
play->m_sequencerInterface->onloopStart_userData = userData;
#endif
}
/* Set loop end hook */
ADLMIDI_EXPORT void adl_setLoopEndHook(struct ADL_MIDIPlayer *device, ADL_LoopPointHook loopEndHook, void *userData)
{
if(!device)
return;
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
play->hooks.onLoopEnd = loopEndHook;
play->hooks.onLoopEnd_userData = userData;
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
play->m_sequencerInterface->onloopEnd = loopEndHook;
play->m_sequencerInterface->onloopEnd_userData = userData;
#endif
}
#ifndef ADLMIDI_HW_OPL
# ifndef __WATCOMC__
@ -1310,74 +1438,69 @@ ADLMIDI_EXPORT int adl_playFormat(ADL_MIDIPlayer *device, int sampleCount,
while(left > 0)
{
{//...
if(setup.delay <= 0.0)
setup.delay = double(left / 2) / double(setup.PCM_RATE);
const double eat_delay = setup.delay < setup.maxdelay ? setup.delay : setup.maxdelay;
if(hasSkipped)
const double eat_delay = setup.delay < setup.maxdelay ? setup.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
{
setup.delay -= eat_delay;
setup.carry += double(setup.PCM_RATE) * eat_delay;
n_periodCountStereo = static_cast<ssize_t>(setup.carry);
setup.carry -= double(n_periodCountStereo);
}
//if(setup.SkipForward > 0)
// setup.SkipForward -= 1;
//else
{
if((player->m_sequencer->positionAtEnd()) && (setup.delay <= 0.0))
break;//Stop to fetch samples at reaching the song end with disabled loop
ssize_t leftSamples = left / 2;
if(n_periodCountStereo > leftSamples)
{
size_t samples = setup.tick_skip_samples_delay > sampleCount ? sampleCount : setup.tick_skip_samples_delay;
n_periodCountStereo = samples / 2;
setup.tick_skip_samples_delay = (n_periodCountStereo - leftSamples) * 2;
n_periodCountStereo = leftSamples;
}
else
//! 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
int32_t *out_buf = player->m_outBuf;
std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
Synth &synth = *player->m_synth;
unsigned int chips = synth.m_numChips;
if(chips == 1)
{
setup.delay -= eat_delay;
setup.carry += double(setup.PCM_RATE) * eat_delay;
n_periodCountStereo = static_cast<ssize_t>(setup.carry);
setup.carry -= double(n_periodCountStereo);
synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
}
else if(n_periodCountStereo > 0)
{
/* Generate data from every chip and mix result */
for(size_t card = 0; card < chips; ++card)
synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
}
//if(setup.SkipForward > 0)
// setup.SkipForward -= 1;
//else
{
if((player->m_sequencer->positionAtEnd()) && (setup.delay <= 0.0))
break;//Stop to fetch samples at reaching the song end with disabled loop
/* Process it */
if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
return 0;
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
int32_t *out_buf = player->m_outBuf;
std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
Synth &synth = *player->m_synth;
unsigned int chips = synth.m_numChips;
if(chips == 1)
{
synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
}
else if(n_periodCountStereo > 0)
{
/* Generate data from every chip and mix result */
for(size_t card = 0; card < chips; ++card)
synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
}
left -= (int)in_generatedPhys;
gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
}
/* Process it */
if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
return 0;
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
setup.delay = player->Tick(eat_delay, setup.mindelay);
}//...
if(hasSkipped)
{
setup.tick_skip_samples_delay -= n_periodCountStereo * 2;
hasSkipped = setup.tick_skip_samples_delay > 0;
}
else
setup.delay = player->Tick(eat_delay, setup.mindelay);
}
return static_cast<int>(gotten_len);
@ -1420,47 +1543,45 @@ ADLMIDI_EXPORT int adl_generateFormat(struct ADL_MIDIPlayer *device, int sampleC
while(left > 0)
{
{//...
if(delay <= 0.0)
delay = double(left / 2) / double(setup.PCM_RATE);
const double eat_delay = delay < setup.maxdelay ? delay : setup.maxdelay;
delay -= eat_delay;
setup.carry += double(setup.PCM_RATE) * eat_delay;
n_periodCountStereo = static_cast<ssize_t>(setup.carry);
setup.carry -= double(n_periodCountStereo);
if(delay <= 0.0)
delay = double(left / 2) / double(setup.PCM_RATE);
const double eat_delay = delay < setup.maxdelay ? delay : setup.maxdelay;
delay -= eat_delay;
setup.carry += double(setup.PCM_RATE) * eat_delay;
n_periodCountStereo = static_cast<ssize_t>(setup.carry);
setup.carry -= double(n_periodCountStereo);
{
ssize_t leftSamples = left / 2;
if(n_periodCountStereo > leftSamples)
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
int32_t *out_buf = player->m_outBuf;
std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
Synth &synth = *player->m_synth;
unsigned int chips = synth.m_numChips;
if(chips == 1)
synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
else if(n_periodCountStereo > 0)
{
ssize_t leftSamples = left / 2;
if(n_periodCountStereo > leftSamples)
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
int32_t *out_buf = player->m_outBuf;
std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
Synth &synth = *player->m_synth;
unsigned int chips = synth.m_numChips;
if(chips == 1)
synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
else if(n_periodCountStereo > 0)
{
/* Generate data from every chip and mix result */
for(unsigned card = 0; card < chips; ++card)
synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
}
/* Process it */
if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
return 0;
left -= (int)in_generatedPhys;
gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
/* Generate data from every chip and mix result */
for(unsigned card = 0; card < chips; ++card)
synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
}
/* Process it */
if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
return 0;
player->TickIterators(eat_delay);
}//...
left -= (int)in_generatedPhys;
gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
}
player->TickIterators(eat_delay);
}
return static_cast<int>(gotten_len);
@ -1552,6 +1673,27 @@ ADLMIDI_EXPORT int adl_setTrackOptions(struct ADL_MIDIPlayer *device, size_t tra
#endif
}
ADLMIDI_EXPORT int adl_setChannelEnabled(struct ADL_MIDIPlayer *device, size_t channelNumber, int enabled)
{
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
if(!device)
return -1;
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
MidiSequencer &seq = *play->m_sequencer;
if(!seq.setChannelEnabled(channelNumber, (bool)enabled))
return -1;
return 0;
#else
ADL_UNUSED(device);
ADL_UNUSED(channelNumber);
ADL_UNUSED(enabled);
return -1;
#endif
}
ADLMIDI_EXPORT int adl_setTriggerHandler(struct ADL_MIDIPlayer *device, ADL_TriggerHandler handler, void *userData)
{
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html
@ -30,7 +30,7 @@ extern "C" {
#define ADLMIDI_VERSION_MAJOR 1
#define ADLMIDI_VERSION_MINOR 5
#define ADLMIDI_VERSION_PATCHLEVEL 0
#define ADLMIDI_VERSION_PATCHLEVEL 1
#define ADLMIDI_TOSTR_I(s) #s
#define ADLMIDI_TOSTR(s) ADLMIDI_TOSTR_I(s)
@ -125,7 +125,26 @@ enum ADLMIDI_VolumeModels
/*! HMI Sound Operating System volume scaling model */
ADLMIDI_VolumeModel_HMI = 10,
/*! HMI Sound Operating System volume scaling model, older variant with bugs */
ADLMIDI_VolumeModel_HMI_OLD = 11
ADLMIDI_VolumeModel_HMI_OLD = 11,
/*! Count of available volume model modes */
ADLMIDI_VolumeModel_Count
};
/*!
* \brief Algorithms of channel allocation for new notes
*/
enum ADLMIDI_ChannelAlloc
{
/*! Automatical choise of the method according to the volume model and internal preferrences */
ADLMIDI_ChanAlloc_AUTO = -1,
/*! Take only channels that has expired sounding delay */
ADLMIDI_ChanAlloc_OffDelay,
/*! Take any first released channel with the same instrument */
ADLMIDI_ChanAlloc_SameInst,
/*! Take any first released channel */
ADLMIDI_ChanAlloc_AnyReleased,
/*! Count of available channel allocation modes */
ADLMIDI_ChanAlloc_Count
};
/**
@ -548,6 +567,21 @@ extern ADLMIDI_DECLSPEC void adl_setScaleModulators(struct ADL_MIDIPlayer *devic
*/
extern ADLMIDI_DECLSPEC void adl_setFullRangeBrightness(struct ADL_MIDIPlayer *device, int fr_brightness);
/**
* @brief Enable(1) or Disable(0) the automatical arpeggio system
*
* @param device Instance of the library
* @param aaEn 0 - disabled, 1 - enabled
*/
extern ADLMIDI_DECLSPEC void adl_setAutoArpeggio(struct ADL_MIDIPlayer *device, int aaEn);
/**
* @brief Get the state of the automatical arpeggio system enable state
* @param device Instalce of the library
* @return 0 - disabled, 1 - enabled
*/
extern ADLMIDI_DECLSPEC int adl_getAutoArpeggio(struct ADL_MIDIPlayer *device);
/**
* @brief Enable or disable built-in loop (built-in loop supports 'loopStart' and 'loopEnd' tags to loop specific part)
* @param device Instance of the library
@ -555,6 +589,23 @@ extern ADLMIDI_DECLSPEC void adl_setFullRangeBrightness(struct ADL_MIDIPlayer *d
*/
extern ADLMIDI_DECLSPEC void adl_setLoopEnabled(struct ADL_MIDIPlayer *device, int loopEn);
/**
* @brief Set how many times loop will be played
*
* Note: The song will be played once if loop has been disabled with no matter which value of loop count was set
*
* @param device Instance of the library
* @param loopCount Number of loops or -1 to loop infinitely
*/
extern ADLMIDI_DECLSPEC void adl_setLoopCount(struct ADL_MIDIPlayer *device, int loopCount);
/**
* @brief Make song immediately stop on reaching a loop end point
* @param device Instance of the library
* @param loopHooksOnly 0 - disabled, 1 - enabled
*/
extern ADLMIDI_DECLSPEC void adl_setLoopHooksOnly(struct ADL_MIDIPlayer *device, int loopHooksOnly);
/**
* @brief Enable or disable soft panning with chip emulators
* @param device Instance of the library
@ -584,6 +635,20 @@ extern ADLMIDI_DECLSPEC void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *devi
*/
extern ADLMIDI_DECLSPEC int adl_getVolumeRangeModel(struct ADL_MIDIPlayer *device);
/**
* @brief Set the channel allocation mode
* @param device Instance of the library
* @param chanalloc Channel allocation mode (#ADLMIDI_ChannelAlloc)
*/
extern ADLMIDI_DECLSPEC void adl_setChannelAllocMode(struct ADL_MIDIPlayer *device, int chanalloc);
/**
* @brief Get the current channel allocation mode
* @param device Instance of the library
* @return Channel allocation mode (#ADLMIDI_ChannelAlloc)
*/
extern ADLMIDI_DECLSPEC int adl_getChannelAllocMode(struct ADL_MIDIPlayer *device);
/**
* @brief Load WOPL bank file from File System
*
@ -766,6 +831,27 @@ extern ADLMIDI_DECLSPEC int adl_openFile(struct ADL_MIDIPlayer *device, const ch
*/
extern ADLMIDI_DECLSPEC int adl_openData(struct ADL_MIDIPlayer *device, const void *mem, unsigned long size);
/**
* @brief Switch another song if multi-song file is playing (for example, XMI)
*
* Note: to set the initial song to load, you should call this function
* BBEFORE calling `adl_openFile` or `adl_openData`. When loaded file has more than
* one built-in songs (Usually XMIformat), it will be started from the selected number.
* You may call this function to switch another song.
*
* @param device Instance of the library
* @param songNumber Identifier of the track to load (or -1 to mix all tracks as one song)
* @return
*/
extern ADLMIDI_DECLSPEC void adl_selectSongNum(struct ADL_MIDIPlayer *device, int songNumber);
/**
* @brief Retrive the number of songs in a currently opened file
* @param device Instance of the library
* @return Number of songs in the file. If 1 or less, means, the file has only one song inside.
*/
extern ADLMIDI_DECLSPEC int adl_getSongsCount(struct ADL_MIDIPlayer *device);
/**
* @brief Resets MIDI player (per-channel setup) into initial state
* @param device Instance of the library
@ -876,6 +962,15 @@ enum ADLMIDI_TrackOptions
*/
extern ADLMIDI_DECLSPEC int adl_setTrackOptions(struct ADL_MIDIPlayer *device, size_t trackNumber, unsigned trackOptions);
/**
* @brief Sets the channel of the current sequence enable state
* @param device Instance of the library
* @param channelNumber Number of the channel (from 0 to 15)
* @param enabled 1 to enable and 0 to disable
* @return 0 on success, <0 when any error has occurred
*/
extern ADLMIDI_DECLSPEC int adl_setChannelEnabled(struct ADL_MIDIPlayer *device, size_t channelNumber, int enabled);
/**
* @brief Handler of callback trigger events
* @param userData Pointer to user data (usually, context of something)
@ -1210,8 +1305,19 @@ typedef void (*ADL_NoteHook)(void *userdata, int adlchn, int note, int ins, int
*/
typedef void (*ADL_DebugMessageHook)(void *userdata, const char *fmt, ...);
/**
* @brief Loop start/end point reach hook
* @param userdata Pointer to user data (usually, context of someting)
*/
typedef void (*ADL_LoopPointHook)(void *userdata);
/**
* @brief Set raw MIDI event hook
*
* CAUTION: Don't call any libADLMIDI API functions from off this hook directly!
* Suggestion: Use boolean variables to mark the fact this hook got been called, and then,
* apply your action outside of this hook, for example, in the next after audio output call.
*
* @param device Instance of the library
* @param rawEventHook Pointer to the callback function which will be called on every MIDI event
* @param userData Pointer to user data which will be passed through the callback.
@ -1220,6 +1326,11 @@ extern ADLMIDI_DECLSPEC void adl_setRawEventHook(struct ADL_MIDIPlayer *device,
/**
* @brief Set note hook
*
* CAUTION: Don't call any libADLMIDI API functions from off this hook directly!
* Suggestion: Use boolean variables to mark the fact this hook got been called, and then,
* apply your action outside of this hook, for example, in the next after audio output call.
*
* @param device Instance of the library
* @param noteHook Pointer to the callback function which will be called on every noteOn MIDI event
* @param userData Pointer to user data which will be passed through the callback.
@ -1228,12 +1339,46 @@ extern ADLMIDI_DECLSPEC void adl_setNoteHook(struct ADL_MIDIPlayer *device, ADL_
/**
* @brief Set debug message hook
*
* CAUTION: Don't call any libADLMIDI API functions from off this hook directly!
* Suggestion: Use boolean variables to mark the fact this hook got been called, and then,
* apply your action outside of this hook, for example, in the next after audio output call.
*
* @param device Instance of the library
* @param debugMessageHook Pointer to the callback function which will be called on every debug message
* @param userData Pointer to user data which will be passed through the callback.
*/
extern ADLMIDI_DECLSPEC void adl_setDebugMessageHook(struct ADL_MIDIPlayer *device, ADL_DebugMessageHook debugMessageHook, void *userData);
/**
* @brief Set the look start point hook
*
* CAUTION: Don't call any libADLMIDI API functions from off this hook directly!
* Suggestion: Use boolean variables to mark the fact this hook got been called, and then,
* apply your action outside of this hook, for example, in the next after audio output call.
*
* @param device Instance of the library
* @param loopStartHook Pointer to the callback function which will be called on every loop start point passing
* @param userData Pointer to user data which will be passed through the callback.
*/
extern ADLMIDI_DECLSPEC void adl_setLoopStartHook(struct ADL_MIDIPlayer *device, ADL_LoopPointHook loopStartHook, void *userData);
/**
* @brief Set the look start point hook
*
* CAUTION: Don't call any libADLMIDI API functions from off this hook directly!
* Suggestion: Use boolean variables to mark the fact this hook got been called, and then,
* apply your action outside of this hook, for example, in the next after audio output call.
*
* If you want to switch the song after calling this hook, suggested to call the function
* adl_setLoopHooksOnly(device, 1) to immediately stop the song on reaching the loop point
*
* @param device Instance of the library
* @param loopStartHook Pointer to the callback function which will be called on every loop start point passing
* @param userData Pointer to user data which will be passed through the callback.
*/
extern ADLMIDI_DECLSPEC void adl_setLoopEndHook(struct ADL_MIDIPlayer *device, ADL_LoopPointHook loopEndHook, void *userData);
/**
* @brief Get a textual description of the channel state. For display only.
* @param device Instance of the library

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html
@ -31,7 +31,7 @@
#include <stddef.h>
#include <vector>
#ifndef _MSC_VER
#if !defined(_MSC_VER) && !defined(__aarch64__) && !defined(__3DS__)
#define ATTRIB_PACKED __attribute__((__packed__))
#else
#define ATTRIB_PACKED

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html
@ -117,6 +117,7 @@ bool MIDIplay::LoadBank(FileAndMemReader &fr)
synth.m_insBankSetup.scaleModulators = false;
synth.m_insBankSetup.deepTremolo = (wopl->opl_flags & WOPL_FLAG_DEEP_TREMOLO) != 0;
synth.m_insBankSetup.deepVibrato = (wopl->opl_flags & WOPL_FLAG_DEEP_VIBRATO) != 0;
synth.m_insBankSetup.mt32defaults = (wopl->opl_flags & WOPL_FLAG_MT32) != 0;
synth.m_insBankSetup.volumeModel = wopl->volume_model;
m_setup.deepTremoloMode = -1;
m_setup.deepVibratoMode = -1;

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html
@ -36,7 +36,8 @@ enum { MasterVolumeDefault = 127 };
inline bool isXgPercChannel(uint8_t msb, uint8_t lsb)
{
return (msb == 0x7E || msb == 0x7F) && (lsb == 0);
ADL_UNUSED(lsb);
return (msb == 0x7E || msb == 0x7F);
}
void MIDIplay::AdlChannel::addAge(int64_t us)
@ -90,6 +91,7 @@ MIDIplay::MIDIplay(unsigned long sampleRate):
//m_setup.SkipForward = 0;
m_setup.scaleModulators = -1;
m_setup.fullRangeBrightnessCC74 = false;
m_setup.enableAutoArpeggio = false;
m_setup.delay = 0.0;
m_setup.carry = 0.0;
m_setup.tick_skip_samples_delay = 0;
@ -126,6 +128,7 @@ void MIDIplay::applySetup()
synth.m_insBankSetup.volumeModel = (b.bankSetup & 0x00FF);
synth.m_insBankSetup.deepTremolo = (b.bankSetup >> 8 & 0x0001) != 0;
synth.m_insBankSetup.deepVibrato = (b.bankSetup >> 8 & 0x0002) != 0;
synth.m_insBankSetup.mt32defaults = (b.bankSetup >> 8 & 0x0004) != 0;
}
#endif
@ -200,15 +203,15 @@ void MIDIplay::resetMIDIDefaults(int offset)
for(size_t c = offset, n = m_midiChannels.size(); c < n; ++c)
{
MIDIchannel &ch = m_midiChannels[c];
if(synth.m_musicMode == Synth::MODE_XMIDI)
if(synth.m_musicMode == Synth::MODE_RSXX)
ch.def_volume = 127;
else if(synth.m_insBankSetup.mt32defaults)
{
ch.def_volume = 127;
ch.def_bendsense_lsb = 0;
ch.def_bendsense_msb = 12;
}
else
if(synth.m_musicMode == Synth::MODE_RSXX)
ch.def_volume = 127;
}
}
@ -290,10 +293,11 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
if(!i.is_end())
{
MIDIchannel::NoteInfo &ni = i->value;
const int veloffset = ni.ains->midiVelocityOffset;
const int veloffset = ni.ains ? ni.ains->midiVelocityOffset : 0;
velocity = (uint8_t)std::min(127, std::max(1, (int)velocity + veloffset));
ni.vol = velocity;
noteUpdate(channel, i, Upd_Volume);
if(ni.ains)
noteUpdate(channel, i, Upd_Volume);
return false;
}
}
@ -329,7 +333,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
// Let XG Percussion bank will use (0...127 LSB range in WOPN file)
// Choose: SFX or Drum Kits
bank = midiins + ((bank == 0x7E00) ? 128 : 0);
bank = midiins + ((midiChan.bank_msb == 0x7E) ? 128 : 0);
}
else
{
@ -357,8 +361,8 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
caughtMissingBank = true;
}
//Or fall back to bank ignoring LSB (GS)
if((ains->flags & OplInstMeta::Flag_NoSound) && ((m_synthMode & Mode_GS) != 0))
//Or fall back to bank ignoring LSB (GS/XG)
if(ains->flags & OplInstMeta::Flag_NoSound)
{
size_t fallback = bank & ~(size_t)0x7F;
if(fallback != bank)
@ -1345,6 +1349,17 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note
const AdlChannel &chan = m_chipChannels[c];
int64_t koff_ms = chan.koff_time_until_neglible_us / 1000;
int64_t s = -koff_ms;
ADLMIDI_ChannelAlloc allocType = synth.m_channelAlloc;
if(allocType == ADLMIDI_ChanAlloc_AUTO)
{
if(synth.m_musicMode == Synth::MODE_CMF)
allocType = ADLMIDI_ChanAlloc_SameInst;
else if(synth.m_volumeScale == Synth::VOLUME_HMI)
allocType = ADLMIDI_ChanAlloc_AnyReleased; // HMI doesn't care about the same instrument
else
allocType = ADLMIDI_ChanAlloc_OffDelay;
}
// Rate channel with a releasing note
if(s < 0 && chan.users.empty())
@ -1353,19 +1368,22 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note
s -= 40000;
// If it's same instrument, better chance to get it when no free channels
if(synth.m_musicMode == Synth::MODE_CMF)
switch(allocType)
{
case ADLMIDI_ChanAlloc_SameInst:
if(isSame)
s = 0; // Re-use releasing channel with the same instrument
}
else if(synth.m_volumeScale == Synth::VOLUME_HMI)
{
s = 0; // HMI doesn't care about the same instrument
}
else
{
break;
case ADLMIDI_ChanAlloc_AnyReleased:
s = 0; // Re-use any releasing channel
break;
default:
case ADLMIDI_ChanAlloc_OffDelay:
if(isSame)
s = -koff_ms; // Wait until releasing sound will complete
break;
}
return s;
@ -1502,6 +1520,9 @@ void MIDIplay::killOrEvacuate(size_t from_channel,
{
uint16_t cs = static_cast<uint16_t>(c);
if(!m_setup.enableAutoArpeggio)
break; // Arpeggio disabled completely
if(c >= maxChannels)
break;
if(c == from_channel)
@ -1725,6 +1746,13 @@ void MIDIplay::updateArpeggio(double) // amount = amount of time passed
Synth &synth = *m_synth;
if(!m_setup.enableAutoArpeggio) // Arpeggio was disabled
{
if(m_arpeggioCounter != 0)
m_arpeggioCounter = 0;
return;
}
#if 0
const unsigned desired_arpeggio_rate = 40; // Hz (upper limit)
# if 1

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html
@ -37,6 +37,10 @@ struct MIDIEventHooks
MIDIEventHooks() :
onNote(NULL),
onNote_userData(NULL),
onLoopStart(NULL),
onLoopStart_userData(NULL),
onLoopEnd(NULL),
onLoopEnd_userData(NULL),
onDebugMessage(NULL),
onDebugMessage_userData(NULL)
{}
@ -46,6 +50,13 @@ struct MIDIEventHooks
NoteHook onNote;
void *onNote_userData;
// Loop start/end hooks
ADL_LoopPointHook onLoopStart;
void *onLoopStart_userData;
ADL_LoopPointHook onLoopEnd;
void *onLoopEnd_userData;
//! Library internal debug messages
typedef void (*DebugMessageHook)(void *userdata, const char *fmt, ...);
DebugMessageHook onDebugMessage;
@ -526,6 +537,7 @@ public:
//unsigned int SkipForward;
int scaleModulators;
bool fullRangeBrightnessCC74;
bool enableAutoArpeggio;
double delay;
double carry;

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html
@ -868,12 +868,14 @@ OPL3::OPL3() :
m_softPanning(false),
m_masterVolume(MasterVolumeDefault),
m_musicMode(MODE_MIDI),
m_volumeScale(VOLUME_Generic)
m_volumeScale(VOLUME_Generic),
m_channelAlloc(ADLMIDI_ChanAlloc_AUTO)
{
m_insBankSetup.volumeModel = OPL3::VOLUME_Generic;
m_insBankSetup.deepTremolo = false;
m_insBankSetup.deepVibrato = false;
m_insBankSetup.scaleModulators = false;
m_insBankSetup.mt32defaults = false;
#ifdef DISABLE_EMBEDDED_BANKS
m_embeddedBank = CustomBankTag;
@ -913,6 +915,7 @@ void OPL3::setEmbeddedBank(uint32_t bank)
const BanksDump::BankEntry &bankEntry = g_embeddedBanks[m_embeddedBank];
m_insBankSetup.deepTremolo = ((bankEntry.bankSetup >> 8) & 0x01) != 0;
m_insBankSetup.deepVibrato = ((bankEntry.bankSetup >> 8) & 0x02) != 0;
m_insBankSetup.mt32defaults = ((bankEntry.bankSetup >> 8) & 0x04) != 0;
m_insBankSetup.volumeModel = (bankEntry.bankSetup & 0xFF);
m_insBankSetup.scaleModulators = false;
@ -1628,6 +1631,7 @@ void OPL3::setVolumeScaleModel(ADLMIDI_VolumeModels volumeModel)
{
switch(volumeModel)
{
default:
case ADLMIDI_VolumeModel_AUTO://Do nothing until restart playing
break;

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html
@ -162,6 +162,9 @@ public:
VOLUME_HMI_OLD
} m_volumeScale;
//! Channel allocation algorithm
ADLMIDI_ChannelAlloc m_channelAlloc;
//! Reserved
char _padding3[8];

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html
@ -21,14 +21,26 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(_WIN32)
#include <pthread.h>
#ifndef DOSBOX_NO_MUTEX
# if defined(USE_LIBOGC_MUTEX)
# include <ogc/mutex.h>
typedef mutex_t MutexNativeObject;
# elif defined(USE_WUT_MUTEX)
# if __cplusplus < 201103L || (defined(_MSC_VER) && _MSC_VER < 1900)
# define static_assert(x, y)
# endif
# include <coreinit/mutex.h>
typedef OSMutex MutexNativeObject;
# elif !defined(_WIN32)
# include <pthread.h>
typedef pthread_mutex_t MutexNativeObject;
#else
#include <windows.h>
# else
# include <windows.h>
typedef CRITICAL_SECTION MutexNativeObject;
# endif
#endif
class Mutex
{
public:
@ -37,7 +49,9 @@ public:
void lock();
void unlock();
private:
#if !defined(DOSBOX_NO_MUTEX)
MutexNativeObject m;
#endif
Mutex(const Mutex &);
Mutex &operator=(const Mutex &);
};
@ -53,7 +67,65 @@ private:
MutexHolder &operator=(const MutexHolder &);
};
#if !defined(_WIN32)
#if defined(DOSBOX_NO_MUTEX) // No mutex, just a dummy
inline Mutex::Mutex()
{}
inline Mutex::~Mutex()
{}
inline void Mutex::lock()
{}
inline void Mutex::unlock()
{}
#elif defined(USE_WUT_MUTEX)
inline Mutex::Mutex()
{
OSInitMutex(&m);
}
inline Mutex::~Mutex()
{}
inline void Mutex::lock()
{
OSLockMutex(&m);
}
inline void Mutex::unlock()
{
OSUnlockMutex(&m);
}
#elif defined(USE_LIBOGC_MUTEX)
inline Mutex::Mutex()
{
m = LWP_MUTEX_NULL;
LWP_MutexInit(&m, 0);
}
inline Mutex::~Mutex()
{
LWP_MutexDestroy(m);
}
inline void Mutex::lock()
{
LWP_MutexLock(m);
}
inline void Mutex::unlock()
{
LWP_MutexUnlock(m);
}
#elif !defined(_WIN32) // pthread
inline Mutex::Mutex()
{
pthread_mutex_init(&m, NULL);
@ -73,7 +145,9 @@ inline void Mutex::unlock()
{
pthread_mutex_unlock(&m);
}
#else
#else // Win32
inline Mutex::Mutex()
{
InitializeCriticalSection(&m);

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html

View file

@ -1,7 +1,7 @@
/*
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
*
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -1,7 +1,7 @@
/*
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
*
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -1,7 +1,7 @@
/*
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
*
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -1,7 +1,7 @@
/*
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
*
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -1,7 +1,7 @@
/*
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
*
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -1,7 +1,7 @@
/*
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
*
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -1,7 +1,7 @@
/*
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
*
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -1,7 +1,7 @@
/*
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
*
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -1,7 +1,7 @@
/*
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
*
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -1,7 +1,7 @@
/*
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
*
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View file

@ -1,7 +1,7 @@
/*
* FileAndMemoryReader - a tiny helper to utify file reading from a disk and memory block
*
* Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),

File diff suppressed because one or more lines are too long

View file

@ -2,7 +2,7 @@
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
*
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
* http://iki.fi/bisqwit/source/adlmidi.html
@ -106,6 +106,7 @@ struct OplBankSetup
bool deepTremolo;
bool deepVibrato;
bool scaleModulators;
bool mt32defaults;
};
/**

View file

@ -1,7 +1,7 @@
/*
* Wohlstand's OPL3 Bank File - a bank format to store OPL3 timbre data and setup
*
* Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),

View file

@ -1,7 +1,7 @@
/*
* Wohlstand's OPL3 Bank File - a bank format to store OPL3 timbre data and setup
*
* Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
* Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
@ -32,8 +32,22 @@
extern "C" {
#endif
#if !defined(__STDC_VERSION__) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ < 199901L)) \
|| defined(__STRICT_ANSI__) || !defined(__cplusplus)
/* Solaris defines the integer types regardless of what C/C++ standard is actually available,
* so avoid defining them at all by ourselves. */
#if !defined(WOPL_STDINT_TYPEDEFS_NOT_NEEDED) && defined(__sun)
# define WOPL_STDINT_TYPEDEFS_NOT_NEEDED
#endif
#if !defined(WOPL_STDINT_TYPEDEFS_NEEDED) && !defined(WOPL_STDINT_TYPEDEFS_NOT_NEEDED)
# if !defined(__STDC_VERSION__) || \
(defined(__STDC_VERSION__) && (__STDC_VERSION__ < 199901L)) || \
defined(__STRICT_ANSI__) || \
!defined(__cplusplus)
# define WOPL_STDINT_TYPEDEFS_NEEDED
# endif
#endif
#ifdef WOPL_STDINT_TYPEDEFS_NEEDED
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int int16_t;
@ -46,7 +60,9 @@ typedef enum WOPLFileFlags
/* Enable Deep-Tremolo flag */
WOPL_FLAG_DEEP_TREMOLO = 0x01,
/* Enable Deep-Vibrato flag */
WOPL_FLAG_DEEP_VIBRATO = 0x02
WOPL_FLAG_DEEP_VIBRATO = 0x02,
/* Enable MT32 defaults (127 initials and octave-wide pitch bend by default, etc.) */
WOPL_FLAG_MT32 = 0x04
} WOPLFileFlags;
/* Volume scaling model implemented in the libADLMIDI */