mirror of
https://github.com/ZDoom/ZMusic.git
synced 2025-03-20 01:21:03 +00:00
Update libADLMIDI up to 1.5.0
## 1.5.0 2020-09-28 * Drum note length expanding is now supported in real-time mode (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Channels manager has been improved (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Nuked OPL3 1.8 emulator got some optimizations ported from 1.7 where they are was applied previously (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Reworked rhythm-mode percussions system, WOPL banks with rhythm-mode percussions * Added Public Domain Opal OPL3 emulator made by Reality (a team who originally made the Reality Adlib Tracker) (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Added LGPL licensed JavaOPL3 emulator made by Robson Cozendey in Java and later rewritten into C++ for GZDoom (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Fully rewritten an embedded bank database format, embedded banks now supports a wider set (more than 127:127 instruments in one bank) * Improved accuracy of the DMX volume model, include the buggy AM interpretation * Improved accuracy of Apogee volume model, include the bug of AM instruments * Improved accuracy of the Win9X volume model * Removed C++ extras. C++-bounded instruments tester is useless since a real-time MIDI API can completely replace it * Added AIL volume model * Added Generic FM variant of Win9X volume model * Fixed an incorrect work of CC-121 (See https://github.com/Wohlstand/libADLMIDI/issues/227 for details) * Added HMI volume model (Thanks to [Alexey Khokholov](https://github.com/nukeykt) for help with research!) * Added frequency models, assigned to every volume model: AIL, HMI, DMX, Apogee, 9X, and the Generic formula
This commit is contained in:
parent
9461e3cc62
commit
1d4a016c41
49 changed files with 15243 additions and 13623 deletions
12
thirdparty/adlmidi/CMakeLists.txt
vendored
12
thirdparty/adlmidi/CMakeLists.txt
vendored
|
@ -6,18 +6,20 @@ use_fast_math()
|
|||
add_definitions(-DADLMIDI_DISABLE_MIDI_SEQUENCER)
|
||||
|
||||
add_library( adl STATIC
|
||||
adldata.cpp
|
||||
adlmidi.cpp
|
||||
adlmidi_load.cpp
|
||||
adlmidi_midiplay.cpp
|
||||
adlmidi_opl3.cpp
|
||||
adlmidi_private.cpp
|
||||
adlmidi.cpp
|
||||
adlmidi_load.cpp
|
||||
inst_db.cpp
|
||||
chips/opal_opl3.cpp
|
||||
chips/dosbox/dbopl.cpp
|
||||
chips/nuked_opl3_v174.cpp
|
||||
chips/java_opl3.cpp
|
||||
chips/dosbox_opl3.cpp
|
||||
chips/nuked_opl3.cpp
|
||||
chips/nuked/nukedopl3_174.c
|
||||
chips/nuked/nukedopl3.c
|
||||
chips/nuked_opl3.cpp
|
||||
chips/nuked_opl3_v174.cpp
|
||||
wopl/wopl_file.c
|
||||
)
|
||||
target_link_libraries( adl )
|
||||
|
|
10748
thirdparty/adlmidi/adldata.cpp
vendored
10748
thirdparty/adlmidi/adldata.cpp
vendored
File diff suppressed because it is too large
Load diff
138
thirdparty/adlmidi/adldata.hh
vendored
138
thirdparty/adlmidi/adldata.hh
vendored
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* 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) 2016 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
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ADLDATA_H
|
||||
#define ADLDATA_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
#define ADLDATA_BYTE_COMPARABLE(T) \
|
||||
inline bool operator==(const T &a, const T &b) \
|
||||
{ return !memcmp(&a, &b, sizeof(T)); } \
|
||||
inline bool operator!=(const T &a, const T &b) \
|
||||
{ return !operator==(a, b); }
|
||||
|
||||
struct adldata
|
||||
{
|
||||
uint32_t modulator_E862, carrier_E862; // See below
|
||||
uint8_t modulator_40, carrier_40; // KSL/attenuation settings
|
||||
uint8_t feedconn; // Feedback/connection bits for the channel
|
||||
|
||||
int8_t finetune;
|
||||
};
|
||||
ADLDATA_BYTE_COMPARABLE(struct adldata)
|
||||
|
||||
struct adlinsdata
|
||||
{
|
||||
enum { Flag_Pseudo4op = 0x01, Flag_NoSound = 0x02, Flag_Real4op = 0x04 };
|
||||
|
||||
enum { Flag_RM_BassDrum = 0x08, Flag_RM_Snare = 0x10, Flag_RM_TomTom = 0x18,
|
||||
Flag_RM_Cymbal = 0x20, Flag_RM_HiHat = 0x28, Mask_RhythmMode = 0x38 };
|
||||
|
||||
uint16_t adlno1, adlno2;
|
||||
uint8_t tone;
|
||||
uint8_t flags;
|
||||
uint16_t ms_sound_kon; // Number of milliseconds it produces sound;
|
||||
uint16_t ms_sound_koff;
|
||||
int8_t midi_velocity_offset;
|
||||
double voice2_fine_tune;
|
||||
};
|
||||
ADLDATA_BYTE_COMPARABLE(struct adlinsdata)
|
||||
|
||||
enum { adlNoteOnMaxTime = 40000 };
|
||||
|
||||
/**
|
||||
* @brief Instrument data with operators included
|
||||
*/
|
||||
struct adlinsdata2
|
||||
{
|
||||
adldata adl[2];
|
||||
uint8_t tone;
|
||||
uint8_t flags;
|
||||
uint16_t ms_sound_kon; // Number of milliseconds it produces sound;
|
||||
uint16_t ms_sound_koff;
|
||||
int8_t midi_velocity_offset;
|
||||
double voice2_fine_tune;
|
||||
static adlinsdata2 from_adldata(const adlinsdata &d);
|
||||
};
|
||||
ADLDATA_BYTE_COMPARABLE(struct adlinsdata2)
|
||||
|
||||
#undef ADLDATA_BYTE_COMPARABLE
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* @brief Bank global setup
|
||||
*/
|
||||
struct AdlBankSetup
|
||||
{
|
||||
int volumeModel;
|
||||
bool deepTremolo;
|
||||
bool deepVibrato;
|
||||
bool adLibPercussions;
|
||||
bool scaleModulators;
|
||||
};
|
||||
|
||||
#ifndef DISABLE_EMBEDDED_BANKS
|
||||
int maxAdlBanks();
|
||||
extern const adldata adl[];
|
||||
extern const adlinsdata adlins[];
|
||||
extern const unsigned short banks[][256];
|
||||
extern const char* const banknames[];
|
||||
extern const AdlBankSetup adlbanksetup[];
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Conversion of storage formats
|
||||
*/
|
||||
inline adlinsdata2 adlinsdata2::from_adldata(const adlinsdata &d)
|
||||
{
|
||||
adlinsdata2 ins;
|
||||
ins.tone = d.tone;
|
||||
ins.flags = d.flags;
|
||||
ins.ms_sound_kon = d.ms_sound_kon;
|
||||
ins.ms_sound_koff = d.ms_sound_koff;
|
||||
ins.midi_velocity_offset = d.midi_velocity_offset;
|
||||
ins.voice2_fine_tune = d.voice2_fine_tune;
|
||||
#ifdef DISABLE_EMBEDDED_BANKS
|
||||
std::memset(ins.adl, 0, sizeof(adldata) * 2);
|
||||
#else
|
||||
ins.adl[0] = ::adl[d.adlno1];
|
||||
ins.adl[1] = ::adl[d.adlno2];
|
||||
#endif
|
||||
return ins;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert external instrument to internal instrument
|
||||
*/
|
||||
void cvt_ADLI_to_FMIns(adlinsdata2 &dst, const struct ADL_Instrument &src);
|
||||
|
||||
/**
|
||||
* @brief Convert internal instrument to external instrument
|
||||
*/
|
||||
void cvt_FMIns_to_ADLI(struct ADL_Instrument &dst, const adlinsdata2 &src);
|
||||
|
||||
#endif //ADLDATA_H
|
274
thirdparty/adlmidi/adlmidi.cpp
vendored
274
thirdparty/adlmidi/adlmidi.cpp
vendored
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
|
||||
* 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-2018 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 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,7 +21,45 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "adlmidi_midiplay.hpp"
|
||||
#include "adlmidi_opl3.hpp"
|
||||
#include "adlmidi_private.hpp"
|
||||
#ifndef ADLMIDI_HW_OPL
|
||||
#include "chips/opl_chip_base.h"
|
||||
#endif
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
#include "midi_sequencer.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
|
||||
#define snprintf c99_snprintf
|
||||
#define vsnprintf c99_vsnprintf
|
||||
|
||||
__inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
|
||||
{
|
||||
int count = -1;
|
||||
|
||||
if (size != 0)
|
||||
count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
|
||||
if (count == -1)
|
||||
count = _vscprintf(format, ap);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
__inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
|
||||
{
|
||||
int count;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
count = c99_vsnprintf(outBuf, size, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Unify MIDI player casting and interface between ADLMIDI and OPNMIDI */
|
||||
#define GET_MIDI_PLAYER(device) reinterpret_cast<MIDIplay *>((device)->adl_midiPlayer)
|
||||
|
@ -112,13 +150,14 @@ ADLMIDI_EXPORT int adl_setNumChips(ADL_MIDIPlayer *device, int numChips)
|
|||
else if(play->m_setup.numFourOps < -1)
|
||||
play->m_setup.numFourOps = -1;
|
||||
|
||||
if(!play->m_synth.setupLocked())
|
||||
Synth &synth = *play->m_synth;
|
||||
if(!synth.setupLocked())
|
||||
{
|
||||
play->m_synth.m_numChips = play->m_setup.numChips;
|
||||
synth.m_numChips = play->m_setup.numChips;
|
||||
if(play->m_setup.numFourOps < 0)
|
||||
adlCalculateFourOpChannels(play, true);
|
||||
else
|
||||
play->m_synth.m_numFourOps = static_cast<uint32_t>(play->m_setup.numFourOps);
|
||||
synth.m_numFourOps = static_cast<uint32_t>(play->m_setup.numFourOps);
|
||||
play->partialReset();
|
||||
return 0;
|
||||
}
|
||||
|
@ -141,7 +180,7 @@ ADLMIDI_EXPORT int adl_getNumChipsObtained(struct ADL_MIDIPlayer *device)
|
|||
return -2;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return (int)play->m_synth.m_numChips;
|
||||
return (int)play->m_synth->m_numChips;
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank)
|
||||
|
@ -155,7 +194,7 @@ ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank)
|
|||
"adl_openBankData() functions instead of adl_setBank().");
|
||||
return -1;
|
||||
#else
|
||||
const uint32_t NumBanks = static_cast<uint32_t>(maxAdlBanks());
|
||||
const uint32_t NumBanks = static_cast<uint32_t>(g_embeddedBanksCount);
|
||||
int32_t bankno = bank;
|
||||
|
||||
if(bankno < 0)
|
||||
|
@ -171,8 +210,9 @@ ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank)
|
|||
return -1;
|
||||
}
|
||||
|
||||
Synth &synth = *play->m_synth;
|
||||
play->m_setup.bankId = static_cast<uint32_t>(bankno);
|
||||
play->m_synth.setEmbeddedBank(play->m_setup.bankId);
|
||||
synth.setEmbeddedBank(play->m_setup.bankId);
|
||||
play->applySetup();
|
||||
|
||||
return 0;
|
||||
|
@ -182,7 +222,7 @@ ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank)
|
|||
ADLMIDI_EXPORT int adl_getBanksCount()
|
||||
{
|
||||
#ifndef DISABLE_EMBEDDED_BANKS
|
||||
return maxAdlBanks();
|
||||
return static_cast<int>(g_embeddedBanksCount);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
@ -191,7 +231,7 @@ ADLMIDI_EXPORT int adl_getBanksCount()
|
|||
ADLMIDI_EXPORT const char *const *adl_getBankNames()
|
||||
{
|
||||
#ifndef DISABLE_EMBEDDED_BANKS
|
||||
return banknames;
|
||||
return g_embeddedBankNames;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
|
@ -203,7 +243,7 @@ ADLMIDI_EXPORT int adl_reserveBanks(ADL_MIDIPlayer *device, unsigned banks)
|
|||
return -1;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
OPL3::BankMap &map = play->m_synth.m_insBanks;
|
||||
Synth::BankMap &map = play->m_synth->m_insBanks;
|
||||
map.reserve(banks);
|
||||
return (int)map.capacity();
|
||||
}
|
||||
|
@ -216,13 +256,13 @@ ADLMIDI_EXPORT int adl_getBank(ADL_MIDIPlayer *device, const ADL_BankId *idp, in
|
|||
ADL_BankId id = *idp;
|
||||
if(id.lsb > 127 || id.msb > 127 || id.percussive > 1)
|
||||
return -1;
|
||||
size_t idnumber = ((id.msb << 8) | id.lsb | (id.percussive ? size_t(OPL3::PercussionTag) : 0));
|
||||
size_t idnumber = ((id.msb << 8) | id.lsb | (id.percussive ? size_t(Synth::PercussionTag) : 0));
|
||||
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
OPL3::BankMap &map = play->m_synth.m_insBanks;
|
||||
Synth::BankMap &map = play->m_synth->m_insBanks;
|
||||
|
||||
OPL3::BankMap::iterator it;
|
||||
Synth::BankMap::iterator it;
|
||||
if(!(flags & ADLMIDI_Bank_Create))
|
||||
{
|
||||
it = map.find(idnumber);
|
||||
|
@ -231,16 +271,16 @@ ADLMIDI_EXPORT int adl_getBank(ADL_MIDIPlayer *device, const ADL_BankId *idp, in
|
|||
}
|
||||
else
|
||||
{
|
||||
std::pair<size_t, OPL3::Bank> value;
|
||||
std::pair<size_t, Synth::Bank> value;
|
||||
value.first = idnumber;
|
||||
memset(&value.second, 0, sizeof(value.second));
|
||||
for (unsigned i = 0; i < 128; ++i)
|
||||
value.second.ins[i].flags = adlinsdata::Flag_NoSound;
|
||||
value.second.ins[i].flags = OplInstMeta::Flag_NoSound;
|
||||
|
||||
std::pair<OPL3::BankMap::iterator, bool> ir;
|
||||
if(flags & ADLMIDI_Bank_CreateRt)
|
||||
std::pair<Synth::BankMap::iterator, bool> ir;
|
||||
if((flags & ADLMIDI_Bank_CreateRt) == ADLMIDI_Bank_CreateRt)
|
||||
{
|
||||
ir = map.insert(value, OPL3::BankMap::do_not_expand_t());
|
||||
ir = map.insert(value, Synth::BankMap::do_not_expand_t());
|
||||
if(ir.first == map.end())
|
||||
return -1;
|
||||
}
|
||||
|
@ -258,11 +298,11 @@ ADLMIDI_EXPORT int adl_getBankId(ADL_MIDIPlayer *device, const ADL_Bank *bank, A
|
|||
if(!device || !bank)
|
||||
return -1;
|
||||
|
||||
OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
OPL3::BankMap::key_type idnumber = it->first;
|
||||
Synth::BankMap::iterator it = Synth::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
Synth::BankMap::key_type idnumber = it->first;
|
||||
id->msb = (idnumber >> 8) & 127;
|
||||
id->lsb = idnumber & 127;
|
||||
id->percussive = (idnumber & OPL3::PercussionTag) ? 1 : 0;
|
||||
id->percussive = (idnumber & Synth::PercussionTag) ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -273,8 +313,8 @@ ADLMIDI_EXPORT int adl_removeBank(ADL_MIDIPlayer *device, ADL_Bank *bank)
|
|||
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
OPL3::BankMap &map = play->m_synth.m_insBanks;
|
||||
OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
Synth::BankMap &map = play->m_synth->m_insBanks;
|
||||
Synth::BankMap::iterator it = Synth::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
size_t size = map.size();
|
||||
map.erase(it);
|
||||
return (map.size() != size) ? 0 : -1;
|
||||
|
@ -287,9 +327,9 @@ ADLMIDI_EXPORT int adl_getFirstBank(ADL_MIDIPlayer *device, ADL_Bank *bank)
|
|||
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
OPL3::BankMap &map = play->m_synth.m_insBanks;
|
||||
Synth::BankMap &map = play->m_synth->m_insBanks;
|
||||
|
||||
OPL3::BankMap::iterator it = map.begin();
|
||||
Synth::BankMap::iterator it = map.begin();
|
||||
if(it == map.end())
|
||||
return -1;
|
||||
|
||||
|
@ -304,9 +344,9 @@ ADLMIDI_EXPORT int adl_getNextBank(ADL_MIDIPlayer *device, ADL_Bank *bank)
|
|||
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
OPL3::BankMap &map = play->m_synth.m_insBanks;
|
||||
Synth::BankMap &map = play->m_synth->m_insBanks;
|
||||
|
||||
OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
Synth::BankMap::iterator it = Synth::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
if(++it == map.end())
|
||||
return -1;
|
||||
|
||||
|
@ -319,7 +359,7 @@ ADLMIDI_EXPORT int adl_getInstrument(ADL_MIDIPlayer *device, const ADL_Bank *ban
|
|||
if(!device || !bank || index > 127 || !ins)
|
||||
return -1;
|
||||
|
||||
OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
Synth::BankMap::iterator it = Synth::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
cvt_FMIns_to_ADLI(*ins, it->second.ins[index]);
|
||||
ins->version = 0;
|
||||
return 0;
|
||||
|
@ -333,7 +373,7 @@ ADLMIDI_EXPORT int adl_setInstrument(ADL_MIDIPlayer *device, ADL_Bank *bank, uns
|
|||
if(ins->version != 0)
|
||||
return -1;
|
||||
|
||||
OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
Synth::BankMap::iterator it = Synth::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
cvt_ADLI_to_FMIns(it->second.ins[index], *ins);
|
||||
return 0;
|
||||
}
|
||||
|
@ -353,16 +393,32 @@ ADLMIDI_EXPORT int adl_loadEmbeddedBank(struct ADL_MIDIPlayer *device, ADL_Bank
|
|||
"adl_openBankData() functions instead of adl_loadEmbeddedBank().");
|
||||
return -1;
|
||||
#else
|
||||
if(num < 0 || num >= maxAdlBanks())
|
||||
if(num < 0 || num >= static_cast<int>(g_embeddedBanksCount))
|
||||
return -1;
|
||||
|
||||
OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
Synth::BankMap::iterator it = Synth::BankMap::iterator::from_ptrs(bank->pointer);
|
||||
size_t id = it->first;
|
||||
|
||||
for (unsigned i = 0; i < 128; ++i) {
|
||||
size_t insno = i + ((id & OPL3::PercussionTag) ? 128 : 0);
|
||||
size_t adlmeta = ::banks[num][insno];
|
||||
it->second.ins[i] = adlinsdata2::from_adldata(::adlins[adlmeta]);
|
||||
const BanksDump::BankEntry &bankEntry = g_embeddedBanks[num];
|
||||
|
||||
bool ss = (id & Synth::PercussionTag);
|
||||
const size_t bankID = 0;
|
||||
|
||||
// bank_count_t maxBanks = ss ? bankEntry.banksPercussionCount : bankEntry.banksMelodicCount;
|
||||
bank_count_t banksOffset = ss ? bankEntry.banksOffsetPercussive : bankEntry.banksOffsetMelodic;
|
||||
size_t bankIndex = g_embeddedBanksMidiIndex[banksOffset + bankID];
|
||||
const BanksDump::MidiBank &bankData = g_embeddedBanksMidi[bankIndex];
|
||||
|
||||
for (unsigned i = 0; i < 128; ++i)
|
||||
{
|
||||
midi_bank_idx_t instIdx = bankData.insts[i];
|
||||
if(instIdx < 0)
|
||||
{
|
||||
it->second.ins[i].flags = OplInstMeta::Flag_NoSound;
|
||||
continue;
|
||||
}
|
||||
BanksDump::InstrumentEntry instIn = g_embeddedBanksInstruments[instIdx];
|
||||
adlFromInstrument(instIn, it->second.ins[i]);
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
|
@ -383,14 +439,15 @@ ADLMIDI_EXPORT int adl_setNumFourOpsChn(ADL_MIDIPlayer *device, int ops4)
|
|||
return -1;
|
||||
}
|
||||
|
||||
Synth &synth = *play->m_synth;
|
||||
play->m_setup.numFourOps = ops4;
|
||||
if(!play->m_synth.setupLocked())
|
||||
if(!synth.setupLocked())
|
||||
{
|
||||
if(play->m_setup.numFourOps < 0)
|
||||
adlCalculateFourOpChannels(play, true);
|
||||
else
|
||||
play->m_synth.m_numFourOps = static_cast<uint32_t>(play->m_setup.numFourOps);
|
||||
play->m_synth.updateChannelCategories();
|
||||
synth.m_numFourOps = static_cast<uint32_t>(play->m_setup.numFourOps);
|
||||
synth.updateChannelCategories();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -411,23 +468,14 @@ ADLMIDI_EXPORT int adl_getNumFourOpsChnObtained(struct ADL_MIDIPlayer *device)
|
|||
return -2;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return (int)play->m_synth.m_numFourOps;
|
||||
return (int)play->m_synth->m_numFourOps;
|
||||
}
|
||||
|
||||
|
||||
/* !!!DEPRECATED!!! AND !!DUMMIED!! */
|
||||
ADLMIDI_EXPORT void adl_setPercMode(ADL_MIDIPlayer *device, int percmod)
|
||||
{
|
||||
if(!device) return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->m_setup.rhythmMode = percmod;
|
||||
if(!play->m_synth.setupLocked())
|
||||
{
|
||||
play->m_synth.m_rhythmMode = play->m_setup.rhythmMode < 0 ?
|
||||
(play->m_synth.m_insBankSetup.adLibPercussions) :
|
||||
(play->m_setup.rhythmMode != 0);
|
||||
play->m_synth.updateChannelCategories();
|
||||
}
|
||||
ADL_UNUSED(device);
|
||||
ADL_UNUSED(percmod);
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT void adl_setHVibrato(ADL_MIDIPlayer *device, int hvibro)
|
||||
|
@ -435,13 +483,14 @@ ADLMIDI_EXPORT void adl_setHVibrato(ADL_MIDIPlayer *device, int hvibro)
|
|||
if(!device) return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
Synth &synth = *play->m_synth;
|
||||
play->m_setup.deepVibratoMode = hvibro;
|
||||
if(!play->m_synth.setupLocked())
|
||||
if(!synth.setupLocked())
|
||||
{
|
||||
play->m_synth.m_deepVibratoMode = play->m_setup.deepVibratoMode < 0 ?
|
||||
play->m_synth.m_insBankSetup.deepVibrato :
|
||||
synth.m_deepVibratoMode = play->m_setup.deepVibratoMode < 0 ?
|
||||
synth.m_insBankSetup.deepVibrato :
|
||||
(play->m_setup.deepVibratoMode != 0);
|
||||
play->m_synth.commitDeepFlags();
|
||||
synth.commitDeepFlags();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,7 +499,7 @@ ADLMIDI_EXPORT int adl_getHVibrato(struct ADL_MIDIPlayer *device)
|
|||
if(!device) return -1;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_synth.m_deepVibratoMode;
|
||||
return play->m_synth->m_deepVibratoMode;
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT void adl_setHTremolo(ADL_MIDIPlayer *device, int htremo)
|
||||
|
@ -458,13 +507,14 @@ ADLMIDI_EXPORT void adl_setHTremolo(ADL_MIDIPlayer *device, int htremo)
|
|||
if(!device) return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
Synth &synth = *play->m_synth;
|
||||
play->m_setup.deepTremoloMode = htremo;
|
||||
if(!play->m_synth.setupLocked())
|
||||
if(!synth.setupLocked())
|
||||
{
|
||||
play->m_synth.m_deepTremoloMode = play->m_setup.deepTremoloMode < 0 ?
|
||||
play->m_synth.m_insBankSetup.deepTremolo :
|
||||
synth.m_deepTremoloMode = play->m_setup.deepTremoloMode < 0 ?
|
||||
synth.m_insBankSetup.deepTremolo :
|
||||
(play->m_setup.deepTremoloMode != 0);
|
||||
play->m_synth.commitDeepFlags();
|
||||
synth.commitDeepFlags();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -473,7 +523,7 @@ ADLMIDI_EXPORT int adl_getHTremolo(struct ADL_MIDIPlayer *device)
|
|||
if(!device) return -1;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_synth.m_deepTremoloMode;
|
||||
return play->m_synth->m_deepTremoloMode;
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT void adl_setScaleModulators(ADL_MIDIPlayer *device, int smod)
|
||||
|
@ -482,11 +532,12 @@ ADLMIDI_EXPORT void adl_setScaleModulators(ADL_MIDIPlayer *device, int smod)
|
|||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
Synth &synth = *play->m_synth;
|
||||
play->m_setup.scaleModulators = smod;
|
||||
if(!play->m_synth.setupLocked())
|
||||
if(!synth.setupLocked())
|
||||
{
|
||||
play->m_synth.m_scaleModulators = play->m_setup.scaleModulators < 0 ?
|
||||
play->m_synth.m_insBankSetup.scaleModulators :
|
||||
synth.m_scaleModulators = play->m_setup.scaleModulators < 0 ?
|
||||
synth.m_insBankSetup.scaleModulators :
|
||||
(play->m_setup.scaleModulators != 0);
|
||||
}
|
||||
}
|
||||
|
@ -502,13 +553,14 @@ ADLMIDI_EXPORT void adl_setFullRangeBrightness(struct ADL_MIDIPlayer *device, in
|
|||
|
||||
ADLMIDI_EXPORT void adl_setLoopEnabled(ADL_MIDIPlayer *device, int loopEn)
|
||||
{
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
if(!device)
|
||||
return;
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->m_sequencer.setLoopEnabled(loopEn != 0);
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->m_sequencer->setLoopEnabled(loopEn != 0);
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
ADL_UNUSED(loopEn);
|
||||
#endif
|
||||
}
|
||||
|
@ -519,7 +571,7 @@ ADLMIDI_EXPORT void adl_setSoftPanEnabled(ADL_MIDIPlayer *device, int softPanEn)
|
|||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->m_synth.m_softPanning = (softPanEn != 0);
|
||||
play->m_synth->m_softPanning = (softPanEn != 0);
|
||||
}
|
||||
|
||||
/* !!!DEPRECATED!!! */
|
||||
|
@ -529,13 +581,14 @@ ADLMIDI_EXPORT void adl_setLogarithmicVolumes(struct ADL_MIDIPlayer *device, int
|
|||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
Synth &synth = *play->m_synth;
|
||||
play->m_setup.logarithmicVolumes = (logvol != 0);
|
||||
if(!play->m_synth.setupLocked())
|
||||
if(!synth.setupLocked())
|
||||
{
|
||||
if(play->m_setup.logarithmicVolumes)
|
||||
play->m_synth.setVolumeScaleModel(ADLMIDI_VolumeModel_NativeOPL3);
|
||||
synth.setVolumeScaleModel(ADLMIDI_VolumeModel_NativeOPL3);
|
||||
else
|
||||
play->m_synth.setVolumeScaleModel(static_cast<ADLMIDI_VolumeModels>(play->m_synth.m_volumeScale));
|
||||
synth.setVolumeScaleModel(static_cast<ADLMIDI_VolumeModels>(synth.m_volumeScale));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,13 +598,14 @@ ADLMIDI_EXPORT void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *device, int v
|
|||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
Synth &synth = *play->m_synth;
|
||||
play->m_setup.volumeScaleModel = volumeModel;
|
||||
if(!play->m_synth.setupLocked())
|
||||
if(!synth.setupLocked())
|
||||
{
|
||||
if(play->m_setup.volumeScaleModel == ADLMIDI_VolumeModel_AUTO)//Use bank default volume model
|
||||
play->m_synth.m_volumeScale = (OPL3::VolumesScale)play->m_synth.m_insBankSetup.volumeModel;
|
||||
synth.m_volumeScale = (Synth::VolumesScale)synth.m_insBankSetup.volumeModel;
|
||||
else
|
||||
play->m_synth.setVolumeScaleModel(static_cast<ADLMIDI_VolumeModels>(volumeModel));
|
||||
synth.setVolumeScaleModel(static_cast<ADLMIDI_VolumeModels>(volumeModel));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,7 +615,7 @@ ADLMIDI_EXPORT int adl_getVolumeRangeModel(struct ADL_MIDIPlayer *device)
|
|||
return -1;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_synth.getVolumeScaleModel();
|
||||
return play->m_synth->getVolumeScaleModel();
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT int adl_openBankFile(struct ADL_MIDIPlayer *device, const char *filePath)
|
||||
|
@ -675,8 +729,9 @@ ADLMIDI_EXPORT const char *adl_chipEmulatorName(struct ADL_MIDIPlayer *device)
|
|||
#ifndef ADLMIDI_HW_OPL
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
if(!play->m_synth.m_chips.empty())
|
||||
return play->m_synth.m_chips[0]->emulatorName();
|
||||
Synth &synth = *play->m_synth;
|
||||
if(!synth.m_chips.empty())
|
||||
return synth.m_chips[0]->emulatorName();
|
||||
#else
|
||||
return "Hardware OPL3 chip on 0x330";
|
||||
#endif
|
||||
|
@ -708,8 +763,9 @@ ADLMIDI_EXPORT int adl_setRunAtPcmRate(ADL_MIDIPlayer *device, int enabled)
|
|||
{
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
Synth &synth = *play->m_synth;
|
||||
play->m_setup.runAtPcmRate = (enabled != 0);
|
||||
if(!play->m_synth.setupLocked())
|
||||
if(!synth.setupLocked())
|
||||
play->partialReset();
|
||||
return 0;
|
||||
}
|
||||
|
@ -763,7 +819,7 @@ ADLMIDI_EXPORT double adl_totalTimeLength(struct ADL_MIDIPlayer *device)
|
|||
return -1.0;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_sequencer.timeLength();
|
||||
return play->m_sequencer->timeLength();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
return -1.0;
|
||||
|
@ -777,7 +833,7 @@ ADLMIDI_EXPORT double adl_loopStartTime(struct ADL_MIDIPlayer *device)
|
|||
return -1.0;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_sequencer.getLoopStart();
|
||||
return play->m_sequencer->getLoopStart();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
return -1.0;
|
||||
|
@ -791,7 +847,7 @@ ADLMIDI_EXPORT double adl_loopEndTime(struct ADL_MIDIPlayer *device)
|
|||
return -1.0;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_sequencer.getLoopEnd();
|
||||
return play->m_sequencer->getLoopEnd();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
return -1.0;
|
||||
|
@ -805,7 +861,7 @@ ADLMIDI_EXPORT double adl_positionTell(struct ADL_MIDIPlayer *device)
|
|||
return -1.0;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_sequencer.tell();
|
||||
return play->m_sequencer->tell();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
return -1.0;
|
||||
|
@ -822,7 +878,7 @@ ADLMIDI_EXPORT void adl_positionSeek(struct ADL_MIDIPlayer *device, double secon
|
|||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->realTime_panic();
|
||||
play->m_setup.delay = play->m_sequencer.seek(seconds, play->m_setup.mindelay);
|
||||
play->m_setup.delay = play->m_sequencer->seek(seconds, play->m_setup.mindelay);
|
||||
play->m_setup.carry = 0.0;
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
|
@ -838,7 +894,7 @@ ADLMIDI_EXPORT void adl_positionRewind(struct ADL_MIDIPlayer *device)
|
|||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->realTime_panic();
|
||||
play->m_sequencer.rewind();
|
||||
play->m_sequencer->rewind();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
#endif
|
||||
|
@ -851,7 +907,7 @@ ADLMIDI_EXPORT void adl_setTempo(struct ADL_MIDIPlayer *device, double tempo)
|
|||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->m_sequencer.setTempo(tempo);
|
||||
play->m_sequencer->setTempo(tempo);
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
ADL_UNUSED(tempo);
|
||||
|
@ -877,7 +933,7 @@ ADLMIDI_EXPORT const char *adl_metaMusicTitle(struct ADL_MIDIPlayer *device)
|
|||
return "";
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_sequencer.getMusicTitle().c_str();
|
||||
return play->m_sequencer->getMusicTitle().c_str();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
return "";
|
||||
|
@ -892,7 +948,7 @@ ADLMIDI_EXPORT const char *adl_metaMusicCopyright(struct ADL_MIDIPlayer *device)
|
|||
return "";
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_sequencer.getMusicCopyright().c_str();
|
||||
return play->m_sequencer->getMusicCopyright().c_str();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
return "";
|
||||
|
@ -906,7 +962,7 @@ ADLMIDI_EXPORT size_t adl_metaTrackTitleCount(struct ADL_MIDIPlayer *device)
|
|||
return 0;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_sequencer.getTrackTitles().size();
|
||||
return play->m_sequencer->getTrackTitles().size();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
return 0;
|
||||
|
@ -920,7 +976,7 @@ ADLMIDI_EXPORT const char *adl_metaTrackTitle(struct ADL_MIDIPlayer *device, siz
|
|||
return "";
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
const std::vector<std::string> &titles = play->m_sequencer.getTrackTitles();
|
||||
const std::vector<std::string> &titles = play->m_sequencer->getTrackTitles();
|
||||
if(index >= titles.size())
|
||||
return "INVALID";
|
||||
return titles[index].c_str();
|
||||
|
@ -939,7 +995,7 @@ ADLMIDI_EXPORT size_t adl_metaMarkerCount(struct ADL_MIDIPlayer *device)
|
|||
return 0;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_sequencer.getMarkers().size();
|
||||
return play->m_sequencer->getMarkers().size();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
return 0;
|
||||
|
@ -962,7 +1018,7 @@ ADLMIDI_EXPORT Adl_MarkerEntry adl_metaMarker(struct ADL_MIDIPlayer *device, siz
|
|||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
|
||||
const std::vector<MidiSequencer::MIDI_MarkerEntry> &markers = play->m_sequencer.getMarkers();
|
||||
const std::vector<MidiSequencer::MIDI_MarkerEntry> &markers = play->m_sequencer->getMarkers();
|
||||
if(index >= markers.size())
|
||||
{
|
||||
marker.label = "INVALID";
|
||||
|
@ -992,8 +1048,8 @@ ADLMIDI_EXPORT void adl_setRawEventHook(struct ADL_MIDIPlayer *device, ADL_RawEv
|
|||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->m_sequencerInterface.onEvent = rawEventHook;
|
||||
play->m_sequencerInterface.onEvent_userData = userData;
|
||||
play->m_sequencerInterface->onEvent = rawEventHook;
|
||||
play->m_sequencerInterface->onEvent_userData = userData;
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
ADL_UNUSED(rawEventHook);
|
||||
|
@ -1022,8 +1078,8 @@ ADLMIDI_EXPORT void adl_setDebugMessageHook(struct ADL_MIDIPlayer *device, ADL_D
|
|||
play->hooks.onDebugMessage = debugMessageHook;
|
||||
play->hooks.onDebugMessage_userData = userData;
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
play->m_sequencerInterface.onDebugMessage = debugMessageHook;
|
||||
play->m_sequencerInterface.onDebugMessage_userData = userData;
|
||||
play->m_sequencerInterface->onDebugMessage = debugMessageHook;
|
||||
play->m_sequencerInterface->onDebugMessage_userData = userData;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1273,7 +1329,7 @@ ADLMIDI_EXPORT int adl_playFormat(ADL_MIDIPlayer *device, int sampleCount,
|
|||
// setup.SkipForward -= 1;
|
||||
//else
|
||||
{
|
||||
if((player->m_sequencer.positionAtEnd()) && (setup.delay <= 0.0))
|
||||
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;
|
||||
|
@ -1290,16 +1346,17 @@ ADLMIDI_EXPORT int adl_playFormat(ADL_MIDIPlayer *device, int sampleCount,
|
|||
//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]));
|
||||
unsigned int chips = player->m_synth.m_numChips;
|
||||
Synth &synth = *player->m_synth;
|
||||
unsigned int chips = synth.m_numChips;
|
||||
if(chips == 1)
|
||||
{
|
||||
player->m_synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
|
||||
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)
|
||||
player->m_synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
|
||||
synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
|
||||
}
|
||||
|
||||
/* Process it */
|
||||
|
@ -1380,14 +1437,15 @@ ADLMIDI_EXPORT int adl_generateFormat(struct ADL_MIDIPlayer *device, int sampleC
|
|||
//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]));
|
||||
unsigned int chips = player->m_synth.m_numChips;
|
||||
Synth &synth = *player->m_synth;
|
||||
unsigned int chips = synth.m_numChips;
|
||||
if(chips == 1)
|
||||
player->m_synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
|
||||
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)
|
||||
player->m_synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
|
||||
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)
|
||||
|
@ -1428,7 +1486,7 @@ ADLMIDI_EXPORT int adl_atEnd(struct ADL_MIDIPlayer *device)
|
|||
return 1;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return (int)play->m_sequencer.positionAtEnd();
|
||||
return (int)play->m_sequencer->positionAtEnd();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
return 1;
|
||||
|
@ -1442,7 +1500,7 @@ ADLMIDI_EXPORT size_t adl_trackCount(struct ADL_MIDIPlayer *device)
|
|||
return 0;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_sequencer.getTrackCount();
|
||||
return play->m_sequencer->getTrackCount();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
return 0;
|
||||
|
@ -1456,7 +1514,7 @@ ADLMIDI_EXPORT int adl_setTrackOptions(struct ADL_MIDIPlayer *device, size_t tra
|
|||
return -1;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
MidiSequencer &seq = play->m_sequencer;
|
||||
MidiSequencer &seq = *play->m_sequencer;
|
||||
|
||||
unsigned enableFlag = trackOptions & 3;
|
||||
trackOptions &= ~3u;
|
||||
|
@ -1497,7 +1555,7 @@ ADLMIDI_EXPORT int adl_setTriggerHandler(struct ADL_MIDIPlayer *device, ADL_Trig
|
|||
return -1;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
MidiSequencer &seq = play->m_sequencer;
|
||||
MidiSequencer &seq = *play->m_sequencer;
|
||||
seq.setTriggerHandler(handler, userData);
|
||||
return 0;
|
||||
#else
|
||||
|
|
273
thirdparty/adlmidi/adlmidi.h
vendored
273
thirdparty/adlmidi/adlmidi.h
vendored
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
|
||||
* 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-2018 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 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
|
||||
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#define ADLMIDI_VERSION_MAJOR 1
|
||||
#define ADLMIDI_VERSION_MINOR 4
|
||||
#define ADLMIDI_VERSION_MINOR 5
|
||||
#define ADLMIDI_VERSION_PATCHLEVEL 0
|
||||
|
||||
#define ADLMIDI_TOSTR_I(s) #s
|
||||
|
@ -39,6 +39,7 @@ extern "C" {
|
|||
ADLMIDI_TOSTR(ADLMIDI_VERSION_MINOR) "." \
|
||||
ADLMIDI_TOSTR(ADLMIDI_VERSION_PATCHLEVEL)
|
||||
|
||||
#define ADL_CHIP_SAMPLE_RATE 49716
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
@ -111,8 +112,20 @@ enum ADLMIDI_VolumeModels
|
|||
ADLMIDI_VolumeModel_DMX = 3,
|
||||
/*! Logarithmic volume scale, used in Apogee Sound System. */
|
||||
ADLMIDI_VolumeModel_APOGEE = 4,
|
||||
/*! Aproximated and shorted volume map table. Similar to general, but has less granularity. */
|
||||
ADLMIDI_VolumeModel_9X = 5
|
||||
/*! Aproximated and shorted volume map table (SB16 driver). Similar to general, but has less granularity. */
|
||||
ADLMIDI_VolumeModel_9X = 5,
|
||||
/*! DMX model with a fixed bug of AM voices */
|
||||
ADLMIDI_VolumeModel_DMX_Fixed = 6,
|
||||
/*! Apogee model with a fixed bug of AM voices*/
|
||||
ADLMIDI_VolumeModel_APOGEE_Fixed = 7,
|
||||
/*! Audio Interface Library volume scaling model */
|
||||
ADLMIDI_VolumeModel_AIL = 8,
|
||||
/*! Aproximated and shorted volume map table (Generic FM driver). Similar to general, but has less granularity. */
|
||||
ADLMIDI_VolumeModel_9X_GENERIC_FM = 9,
|
||||
/*! 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
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -246,7 +259,125 @@ enum ADL_BankAccessFlags
|
|||
ADLMIDI_Bank_CreateRt = 1|2
|
||||
};
|
||||
|
||||
typedef struct ADL_Instrument ADL_Instrument;
|
||||
|
||||
/* ======== Instrument structures ======== */
|
||||
|
||||
/**
|
||||
* @brief Version of the instrument data format
|
||||
*/
|
||||
enum
|
||||
{
|
||||
ADLMIDI_InstrumentVersion = 0
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Instrument flags
|
||||
*/
|
||||
typedef enum ADL_InstrumentFlags
|
||||
{
|
||||
/*! Is two-operator single-voice instrument (no flags) */
|
||||
ADLMIDI_Ins_2op = 0x00,
|
||||
/*! Is true four-operator instrument */
|
||||
ADLMIDI_Ins_4op = 0x01,
|
||||
/*! Is pseudo four-operator (two 2-operator voices) instrument */
|
||||
ADLMIDI_Ins_Pseudo4op = 0x02,
|
||||
/*! Is a blank instrument entry */
|
||||
ADLMIDI_Ins_IsBlank = 0x04,
|
||||
|
||||
/*! RythmMode flags mask */
|
||||
ADLMIDI_Ins_RhythmModeMask = 0x38,
|
||||
|
||||
/*! Mask of the flags range */
|
||||
ADLMIDI_Ins_ALL_MASK = 0x07
|
||||
} ADL_InstrumentFlags;
|
||||
|
||||
/**
|
||||
* @brief Rhythm-mode drum type
|
||||
*/
|
||||
typedef enum ADL_RhythmMode
|
||||
{
|
||||
/*! RythmMode: BassDrum */
|
||||
ADLMIDI_RM_BassDrum = 0x08,
|
||||
/*! RythmMode: Snare */
|
||||
ADLMIDI_RM_Snare = 0x10,
|
||||
/*! RythmMode: TomTom */
|
||||
ADLMIDI_RM_TomTom = 0x18,
|
||||
/*! RythmMode: Cymbal */
|
||||
ADLMIDI_RM_Cymbal = 0x20,
|
||||
/*! RythmMode: HiHat */
|
||||
ADLMIDI_RM_HiHat = 0x28
|
||||
} ADL_RhythmMode;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Operator structure, part of Instrument structure
|
||||
*/
|
||||
typedef struct ADL_Operator
|
||||
{
|
||||
/*! AM/Vib/Env/Ksr/FMult characteristics */
|
||||
ADL_UInt8 avekf_20;
|
||||
/*! Key Scale Level / Total level register data */
|
||||
ADL_UInt8 ksl_l_40;
|
||||
/*! Attack / Decay */
|
||||
ADL_UInt8 atdec_60;
|
||||
/*! Systain and Release register data */
|
||||
ADL_UInt8 susrel_80;
|
||||
/*! Wave form */
|
||||
ADL_UInt8 waveform_E0;
|
||||
} ADL_Operator;
|
||||
|
||||
/**
|
||||
* @brief Instrument structure
|
||||
*/
|
||||
typedef struct ADL_Instrument
|
||||
{
|
||||
/*! Version of the instrument object */
|
||||
int version;
|
||||
/*! MIDI note key (half-tone) offset for an instrument (or a first voice in pseudo-4-op mode) */
|
||||
ADL_SInt16 note_offset1;
|
||||
/*! MIDI note key (half-tone) offset for a second voice in pseudo-4-op mode */
|
||||
ADL_SInt16 note_offset2;
|
||||
/*! MIDI note velocity offset (taken from Apogee TMB format) */
|
||||
ADL_SInt8 midi_velocity_offset;
|
||||
/*! Second voice detune level (taken from DMX OP2) */
|
||||
ADL_SInt8 second_voice_detune;
|
||||
/*! Percussion MIDI base tone number at which this drum will be played */
|
||||
ADL_UInt8 percussion_key_number;
|
||||
/**
|
||||
* @var inst_flags
|
||||
* @brief Instrument flags
|
||||
*
|
||||
* Enums: #ADL_InstrumentFlags and #ADL_RhythmMode
|
||||
*
|
||||
* Bitwise flags bit map:
|
||||
* ```
|
||||
* [0EEEDCBA]
|
||||
* A) 0x00 - 2-operator mode
|
||||
* B) 0x01 - 4-operator mode
|
||||
* C) 0x02 - pseudo-4-operator (two 2-operator voices) mode
|
||||
* D) 0x04 - is 'blank' instrument (instrument which has no sound)
|
||||
* E) 0x38 - Reserved for rhythm-mode percussion type number (three bits number)
|
||||
* -> 0x00 - Melodic or Generic drum (rhythm-mode is disabled)
|
||||
* -> 0x08 - is Bass drum
|
||||
* -> 0x10 - is Snare
|
||||
* -> 0x18 - is Tom-tom
|
||||
* -> 0x20 - is Cymbal
|
||||
* -> 0x28 - is Hi-hat
|
||||
* 0) Reserved / Unused
|
||||
* ```
|
||||
*/
|
||||
ADL_UInt8 inst_flags;
|
||||
/*! Feedback&Connection register for first and second operators */
|
||||
ADL_UInt8 fb_conn1_C0;
|
||||
/*! Feedback&Connection register for third and fourth operators */
|
||||
ADL_UInt8 fb_conn2_C0;
|
||||
/*! Operators register data */
|
||||
ADL_Operator operators[4];
|
||||
/*! Millisecond delay of sounding while key is on */
|
||||
ADL_UInt16 delay_on_ms;
|
||||
/*! Millisecond delay of sounding after key off */
|
||||
ADL_UInt16 delay_off_ms;
|
||||
} ADL_Instrument;
|
||||
|
||||
|
||||
|
||||
|
@ -361,11 +492,14 @@ extern ADLMIDI_DECLSPEC int adl_getNumFourOpsChnObtained(struct ADL_MIDIPlayer *
|
|||
/**
|
||||
* @brief Override Enable(1) or Disable(0) AdLib percussion mode. -1 - use bank default AdLib percussion mode
|
||||
*
|
||||
* [DEPRECATED] This function is no more useful and now it makes nothing. Kept for ABI compatibility. Rhythm mode can be set by the bank data only.
|
||||
*
|
||||
* This function forces rhythm-mode on any bank. The result will work glitchy.
|
||||
*
|
||||
* @param device Instance of the library
|
||||
* @param percmod 0 - disabled, 1 - enabled
|
||||
*/
|
||||
ADLMIDI_DEPRECATED("This function is no more useful and now it makes nothing. Kept for ABI compatibility. Rhythm mode can be set by the bank data only.")
|
||||
extern ADLMIDI_DECLSPEC void adl_setPercMode(struct ADL_MIDIPlayer *device, int percmod);
|
||||
|
||||
/**
|
||||
|
@ -502,6 +636,10 @@ enum ADL_Emulator
|
|||
ADLMIDI_EMU_NUKED_174,
|
||||
/*! DosBox */
|
||||
ADLMIDI_EMU_DOSBOX,
|
||||
/*! Opal */
|
||||
ADLMIDI_EMU_OPAL,
|
||||
/*! Java */
|
||||
ADLMIDI_EMU_JAVA,
|
||||
/*! Count instrument on the level */
|
||||
ADLMIDI_EMU_end
|
||||
};
|
||||
|
@ -588,6 +726,7 @@ extern ADLMIDI_DECLSPEC const char *adl_errorInfo(struct ADL_MIDIPlayer *device)
|
|||
* Tip 1: You can initialize multiple instances and run them in parallel
|
||||
* Tip 2: Library is NOT thread-safe, therefore don't use same instance in different threads or use mutexes
|
||||
* Tip 3: Changing of sample rate on the fly is not supported. Re-create the instance again.
|
||||
* Top 4: To generate output in OPL chip native sample rate, please initialize it with sample rate value as `ADL_CHIP_SAMPLE_RATE`
|
||||
*
|
||||
* @param sample_rate Output sample rate
|
||||
* @return Instance of the library. If NULL was returned, check the `adl_errorString` message for more info.
|
||||
|
@ -1117,128 +1256,6 @@ extern ADLMIDI_DECLSPEC void adl_setDebugMessageHook(struct ADL_MIDIPlayer *devi
|
|||
*/
|
||||
extern ADLMIDI_DECLSPEC int adl_describeChannels(struct ADL_MIDIPlayer *device, char *text, char *attr, size_t size);
|
||||
|
||||
|
||||
|
||||
|
||||
/* ======== Instrument structures ======== */
|
||||
|
||||
/**
|
||||
* @brief Version of the instrument data format
|
||||
*/
|
||||
enum
|
||||
{
|
||||
ADLMIDI_InstrumentVersion = 0
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Instrument flags
|
||||
*/
|
||||
typedef enum ADL_InstrumentFlags
|
||||
{
|
||||
/*! Is two-operator single-voice instrument (no flags) */
|
||||
ADLMIDI_Ins_2op = 0x00,
|
||||
/*! Is true four-operator instrument */
|
||||
ADLMIDI_Ins_4op = 0x01,
|
||||
/*! Is pseudo four-operator (two 2-operator voices) instrument */
|
||||
ADLMIDI_Ins_Pseudo4op = 0x02,
|
||||
/*! Is a blank instrument entry */
|
||||
ADLMIDI_Ins_IsBlank = 0x04,
|
||||
|
||||
/*! RythmMode flags mask */
|
||||
ADLMIDI_Ins_RhythmModeMask = 0x38,
|
||||
|
||||
/*! Mask of the flags range */
|
||||
ADLMIDI_Ins_ALL_MASK = 0x07
|
||||
} ADL_InstrumentFlags;
|
||||
|
||||
/**
|
||||
* @brief Rhythm-mode drum type
|
||||
*/
|
||||
typedef enum ADL_RhythmMode
|
||||
{
|
||||
/*! RythmMode: BassDrum */
|
||||
ADLMIDI_RM_BassDrum = 0x08,
|
||||
/*! RythmMode: Snare */
|
||||
ADLMIDI_RM_Snare = 0x10,
|
||||
/*! RythmMode: TomTom */
|
||||
ADLMIDI_RM_TomTom = 0x18,
|
||||
/*! RythmMode: Cymbal */
|
||||
ADLMIDI_RM_Cymbal = 0x20,
|
||||
/*! RythmMode: HiHat */
|
||||
ADLMIDI_RM_HiHat = 0x28
|
||||
} ADL_RhythmMode;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Operator structure, part of Instrument structure
|
||||
*/
|
||||
typedef struct ADL_Operator
|
||||
{
|
||||
/*! AM/Vib/Env/Ksr/FMult characteristics */
|
||||
ADL_UInt8 avekf_20;
|
||||
/*! Key Scale Level / Total level register data */
|
||||
ADL_UInt8 ksl_l_40;
|
||||
/*! Attack / Decay */
|
||||
ADL_UInt8 atdec_60;
|
||||
/*! Systain and Release register data */
|
||||
ADL_UInt8 susrel_80;
|
||||
/*! Wave form */
|
||||
ADL_UInt8 waveform_E0;
|
||||
} ADL_Operator;
|
||||
|
||||
/**
|
||||
* @brief Instrument structure
|
||||
*/
|
||||
typedef struct ADL_Instrument
|
||||
{
|
||||
/*! Version of the instrument object */
|
||||
int version;
|
||||
/*! MIDI note key (half-tone) offset for an instrument (or a first voice in pseudo-4-op mode) */
|
||||
ADL_SInt16 note_offset1;
|
||||
/*! MIDI note key (half-tone) offset for a second voice in pseudo-4-op mode */
|
||||
ADL_SInt16 note_offset2;
|
||||
/*! MIDI note velocity offset (taken from Apogee TMB format) */
|
||||
ADL_SInt8 midi_velocity_offset;
|
||||
/*! Second voice detune level (taken from DMX OP2) */
|
||||
ADL_SInt8 second_voice_detune;
|
||||
/*! Percussion MIDI base tone number at which this drum will be played */
|
||||
ADL_UInt8 percussion_key_number;
|
||||
/**
|
||||
* @var inst_flags
|
||||
* @brief Instrument flags
|
||||
*
|
||||
* Enums: #ADL_InstrumentFlags and #ADL_RhythmMode
|
||||
*
|
||||
* Bitwise flags bit map:
|
||||
* ```
|
||||
* [0EEEDCBA]
|
||||
* A) 0x00 - 2-operator mode
|
||||
* B) 0x01 - 4-operator mode
|
||||
* C) 0x02 - pseudo-4-operator (two 2-operator voices) mode
|
||||
* D) 0x04 - is 'blank' instrument (instrument which has no sound)
|
||||
* E) 0x38 - Reserved for rhythm-mode percussion type number (three bits number)
|
||||
* -> 0x00 - Melodic or Generic drum (rhythm-mode is disabled)
|
||||
* -> 0x08 - is Bass drum
|
||||
* -> 0x10 - is Snare
|
||||
* -> 0x18 - is Tom-tom
|
||||
* -> 0x20 - is Cymbal
|
||||
* -> 0x28 - is Hi-hat
|
||||
* 0) Reserved / Unused
|
||||
* ```
|
||||
*/
|
||||
ADL_UInt8 inst_flags;
|
||||
/*! Feedback&Connection register for first and second operators */
|
||||
ADL_UInt8 fb_conn1_C0;
|
||||
/*! Feedback&Connection register for third and fourth operators */
|
||||
ADL_UInt8 fb_conn2_C0;
|
||||
/*! Operators register data */
|
||||
ADL_Operator operators[4];
|
||||
/*! Millisecond delay of sounding while key is on */
|
||||
ADL_UInt16 delay_on_ms;
|
||||
/*! Millisecond delay of sounding after key off */
|
||||
ADL_UInt16 delay_off_ms;
|
||||
} ADL_Instrument;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
54
thirdparty/adlmidi/adlmidi.hpp
vendored
54
thirdparty/adlmidi/adlmidi.hpp
vendored
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* 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-2018 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
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ADLMIDI_HPP
|
||||
#define ADLMIDI_HPP
|
||||
|
||||
#include "adlmidi.h"
|
||||
|
||||
struct ADL_MIDIPlayer;
|
||||
|
||||
class ADLMIDI_DECLSPEC AdlInstrumentTester
|
||||
{
|
||||
struct Impl;
|
||||
Impl *P;
|
||||
|
||||
public:
|
||||
explicit AdlInstrumentTester(ADL_MIDIPlayer *device);
|
||||
virtual ~AdlInstrumentTester();
|
||||
|
||||
// Find list of adlib instruments that supposedly implement this GM
|
||||
void FindAdlList();
|
||||
void Touch(unsigned c, unsigned volume);
|
||||
void DoNote(int note);
|
||||
void NextGM(int offset);
|
||||
void NextAdl(int offset);
|
||||
bool HandleInputChar(char ch);
|
||||
|
||||
private:
|
||||
AdlInstrumentTester(const AdlInstrumentTester &);
|
||||
AdlInstrumentTester &operator=(const AdlInstrumentTester &);
|
||||
};
|
||||
|
||||
#endif //ADLMIDI_HPP
|
||||
|
4
thirdparty/adlmidi/adlmidi_bankmap.h
vendored
4
thirdparty/adlmidi/adlmidi_bankmap.h
vendored
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
|
||||
* 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-2018 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 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
|
||||
|
|
2
thirdparty/adlmidi/adlmidi_bankmap.tcc
vendored
2
thirdparty/adlmidi/adlmidi_bankmap.tcc
vendored
|
@ -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-2018 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 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
|
||||
|
|
93
thirdparty/adlmidi/adlmidi_cvt.hpp
vendored
93
thirdparty/adlmidi/adlmidi_cvt.hpp
vendored
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
|
||||
* 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-2018 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 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,89 +21,80 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "adldata.hh"
|
||||
#include "oplinst.h"
|
||||
#include "wopl/wopl_file.h"
|
||||
#include <cmath>
|
||||
|
||||
template <class WOPLI>
|
||||
static void cvt_generic_to_FMIns(adlinsdata2 &ins, const WOPLI &in)
|
||||
static void cvt_generic_to_FMIns(OplInstMeta &ins, const WOPLI &in)
|
||||
{
|
||||
ins.voice2_fine_tune = 0.0;
|
||||
int8_t voice2_fine_tune = in.second_voice_detune;
|
||||
int voice2_fine_tune = in.second_voice_detune;
|
||||
|
||||
if(voice2_fine_tune != 0)
|
||||
{
|
||||
if(voice2_fine_tune == 1)
|
||||
ins.voice2_fine_tune = 0.000025;
|
||||
else if(voice2_fine_tune == -1)
|
||||
ins.voice2_fine_tune = -0.000025;
|
||||
else
|
||||
ins.voice2_fine_tune = voice2_fine_tune * (15.625 / 1000.0);
|
||||
// Simulate behavior of DMX second voice detune
|
||||
ins.voice2_fine_tune = (double)(((voice2_fine_tune + 128) >> 1) - 64) / 32.0;
|
||||
}
|
||||
|
||||
ins.midi_velocity_offset = in.midi_velocity_offset;
|
||||
ins.tone = in.percussion_key_number;
|
||||
ins.flags = (in.inst_flags & WOPL_Ins_4op) && (in.inst_flags & WOPL_Ins_Pseudo4op) ? adlinsdata::Flag_Pseudo4op : 0;
|
||||
ins.flags|= (in.inst_flags & WOPL_Ins_4op) && ((in.inst_flags & WOPL_Ins_Pseudo4op) == 0) ? adlinsdata::Flag_Real4op : 0;
|
||||
ins.flags|= (in.inst_flags & WOPL_Ins_IsBlank) ? adlinsdata::Flag_NoSound : 0;
|
||||
ins.midiVelocityOffset = in.midi_velocity_offset;
|
||||
ins.drumTone = in.percussion_key_number;
|
||||
ins.flags = (in.inst_flags & WOPL_Ins_4op) && (in.inst_flags & WOPL_Ins_Pseudo4op) ? OplInstMeta::Flag_Pseudo4op : 0;
|
||||
ins.flags|= (in.inst_flags & WOPL_Ins_4op) && ((in.inst_flags & WOPL_Ins_Pseudo4op) == 0) ? OplInstMeta::Flag_Real4op : 0;
|
||||
ins.flags|= (in.inst_flags & WOPL_Ins_IsBlank) ? OplInstMeta::Flag_NoSound : 0;
|
||||
ins.flags|= in.inst_flags & WOPL_RhythmModeMask;
|
||||
|
||||
for(size_t op = 0, slt = 0; op < 4; op++, slt++)
|
||||
{
|
||||
ins.adl[slt].carrier_E862 =
|
||||
ins.op[slt].carrier_E862 =
|
||||
((static_cast<uint32_t>(in.operators[op].waveform_E0) << 24) & 0xFF000000) //WaveForm
|
||||
| ((static_cast<uint32_t>(in.operators[op].susrel_80) << 16) & 0x00FF0000) //SusRel
|
||||
| ((static_cast<uint32_t>(in.operators[op].atdec_60) << 8) & 0x0000FF00) //AtDec
|
||||
| ((static_cast<uint32_t>(in.operators[op].avekf_20) << 0) & 0x000000FF); //AVEKM
|
||||
ins.adl[slt].carrier_40 = in.operators[op].ksl_l_40;//KSLL
|
||||
ins.op[slt].carrier_40 = in.operators[op].ksl_l_40;//KSLL
|
||||
|
||||
op++;
|
||||
ins.adl[slt].modulator_E862 =
|
||||
ins.op[slt].modulator_E862 =
|
||||
((static_cast<uint32_t>(in.operators[op].waveform_E0) << 24) & 0xFF000000) //WaveForm
|
||||
| ((static_cast<uint32_t>(in.operators[op].susrel_80) << 16) & 0x00FF0000) //SusRel
|
||||
| ((static_cast<uint32_t>(in.operators[op].atdec_60) << 8) & 0x0000FF00) //AtDec
|
||||
| ((static_cast<uint32_t>(in.operators[op].avekf_20) << 0) & 0x000000FF); //AVEKM
|
||||
ins.adl[slt].modulator_40 = in.operators[op].ksl_l_40;//KSLL
|
||||
ins.op[slt].modulator_40 = in.operators[op].ksl_l_40;//KSLL
|
||||
}
|
||||
|
||||
ins.adl[0].finetune = static_cast<int8_t>(in.note_offset1);
|
||||
ins.adl[0].feedconn = in.fb_conn1_C0;
|
||||
ins.adl[1].finetune = static_cast<int8_t>(in.note_offset2);
|
||||
ins.adl[1].feedconn = in.fb_conn2_C0;
|
||||
ins.op[0].noteOffset = static_cast<int8_t>(in.note_offset1);
|
||||
ins.op[0].feedconn = in.fb_conn1_C0;
|
||||
ins.op[1].noteOffset = static_cast<int8_t>(in.note_offset2);
|
||||
ins.op[1].feedconn = in.fb_conn2_C0;
|
||||
|
||||
ins.ms_sound_kon = in.delay_on_ms;
|
||||
ins.ms_sound_koff = in.delay_off_ms;
|
||||
ins.soundKeyOnMs = in.delay_on_ms;
|
||||
ins.soundKeyOffMs = in.delay_off_ms;
|
||||
}
|
||||
|
||||
template <class WOPLI>
|
||||
static void cvt_FMIns_to_generic(WOPLI &ins, const adlinsdata2 &in)
|
||||
static void cvt_FMIns_to_generic(WOPLI &ins, const OplInstMeta &in)
|
||||
{
|
||||
ins.second_voice_detune = 0;
|
||||
double voice2_fine_tune = in.voice2_fine_tune;
|
||||
if(voice2_fine_tune != 0)
|
||||
{
|
||||
if(voice2_fine_tune > 0 && voice2_fine_tune <= 0.000025)
|
||||
ins.second_voice_detune = 1;
|
||||
else if(voice2_fine_tune < 0 && voice2_fine_tune >= -0.000025)
|
||||
ins.second_voice_detune = -1;
|
||||
else
|
||||
{
|
||||
long value = static_cast<long>(round(voice2_fine_tune * (1000.0 / 15.625)));
|
||||
value = (value < -128) ? -128 : value;
|
||||
value = (value > +127) ? +127 : value;
|
||||
ins.second_voice_detune = static_cast<int8_t>(value);
|
||||
}
|
||||
int m = (int)(voice2_fine_tune * 32.0);
|
||||
m += 64;
|
||||
m <<= 1;
|
||||
m -= 128;
|
||||
ins.second_voice_detune = (uint8_t)m;
|
||||
}
|
||||
|
||||
ins.midi_velocity_offset = in.midi_velocity_offset;
|
||||
ins.percussion_key_number = in.tone;
|
||||
ins.inst_flags = (in.flags & (adlinsdata::Flag_Pseudo4op|adlinsdata::Flag_Real4op)) ? WOPL_Ins_4op : 0;
|
||||
ins.inst_flags|= (in.flags & adlinsdata::Flag_Pseudo4op) ? WOPL_Ins_Pseudo4op : 0;
|
||||
ins.inst_flags|= (in.flags & adlinsdata::Flag_NoSound) ? WOPL_Ins_IsBlank : 0;
|
||||
ins.inst_flags |= in.flags & adlinsdata::Mask_RhythmMode;
|
||||
ins.midi_velocity_offset = in.midiVelocityOffset;
|
||||
ins.percussion_key_number = in.drumTone;
|
||||
ins.inst_flags = (in.flags & (OplInstMeta::Flag_Pseudo4op|OplInstMeta::Flag_Real4op)) ? WOPL_Ins_4op : 0;
|
||||
ins.inst_flags|= (in.flags & OplInstMeta::Flag_Pseudo4op) ? WOPL_Ins_Pseudo4op : 0;
|
||||
ins.inst_flags|= (in.flags & OplInstMeta::Flag_NoSound) ? WOPL_Ins_IsBlank : 0;
|
||||
ins.inst_flags |= in.flags & OplInstMeta::Mask_RhythmMode;
|
||||
|
||||
for(size_t op = 0; op < 4; op++)
|
||||
{
|
||||
const adldata &in2op = in.adl[(op < 2) ? 0 : 1];
|
||||
const OplTimbre &in2op = in.op[(op < 2) ? 0 : 1];
|
||||
uint32_t regE862 = ((op & 1) == 0) ? in2op.carrier_E862 : in2op.modulator_E862;
|
||||
uint8_t reg40 = ((op & 1) == 0) ? in2op.carrier_40 : in2op.modulator_40;
|
||||
|
||||
|
@ -114,11 +105,11 @@ static void cvt_FMIns_to_generic(WOPLI &ins, const adlinsdata2 &in)
|
|||
ins.operators[op].ksl_l_40 = reg40;
|
||||
}
|
||||
|
||||
ins.note_offset1 = in.adl[0].finetune;
|
||||
ins.fb_conn1_C0 = in.adl[0].feedconn;
|
||||
ins.note_offset2 = in.adl[1].finetune;
|
||||
ins.fb_conn2_C0 = in.adl[1].feedconn;
|
||||
ins.note_offset1 = in.op[0].noteOffset;
|
||||
ins.fb_conn1_C0 = in.op[0].feedconn;
|
||||
ins.note_offset2 = in.op[1].noteOffset;
|
||||
ins.fb_conn2_C0 = in.op[1].feedconn;
|
||||
|
||||
ins.delay_on_ms = in.ms_sound_kon;
|
||||
ins.delay_off_ms = in.ms_sound_koff;
|
||||
ins.delay_on_ms = in.soundKeyOnMs;
|
||||
ins.delay_off_ms = in.soundKeyOffMs;
|
||||
}
|
||||
|
|
98
thirdparty/adlmidi/adlmidi_db.h
vendored
Normal file
98
thirdparty/adlmidi/adlmidi_db.h
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ADLDATA_DB_H
|
||||
#define ADLDATA_DB_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <vector>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#define ATTRIB_PACKED __attribute__((__packed__))
|
||||
#else
|
||||
#define ATTRIB_PACKED
|
||||
#endif
|
||||
|
||||
typedef uint16_t bank_count_t;
|
||||
typedef int16_t midi_bank_idx_t;
|
||||
|
||||
#ifndef DISABLE_EMBEDDED_BANKS
|
||||
extern const size_t g_embeddedBanksCount;
|
||||
#endif
|
||||
|
||||
namespace BanksDump
|
||||
{
|
||||
|
||||
struct BankEntry
|
||||
{
|
||||
uint16_t bankSetup;
|
||||
bank_count_t banksMelodicCount;
|
||||
bank_count_t banksPercussionCount;
|
||||
const char *title;
|
||||
bank_count_t banksOffsetMelodic;
|
||||
bank_count_t banksOffsetPercussive;
|
||||
} ATTRIB_PACKED;
|
||||
|
||||
struct MidiBank
|
||||
{
|
||||
uint8_t msb;
|
||||
uint8_t lsb;
|
||||
midi_bank_idx_t insts[128];
|
||||
} ATTRIB_PACKED;
|
||||
|
||||
struct InstrumentEntry
|
||||
{
|
||||
int16_t noteOffset1;
|
||||
int16_t noteOffset2;
|
||||
int8_t midiVelocityOffset;
|
||||
uint8_t percussionKeyNumber;
|
||||
uint8_t instFlags;
|
||||
int8_t secondVoiceDetune;
|
||||
uint16_t fbConn;
|
||||
uint16_t delay_on_ms;
|
||||
uint16_t delay_off_ms;
|
||||
int16_t ops[4];
|
||||
} ATTRIB_PACKED;
|
||||
|
||||
struct Operator
|
||||
{
|
||||
uint32_t d_E862;
|
||||
uint8_t d_40;
|
||||
} ATTRIB_PACKED;
|
||||
|
||||
} /* namespace BanksDump */
|
||||
|
||||
#ifndef DISABLE_EMBEDDED_BANKS
|
||||
extern const char* const g_embeddedBankNames[];
|
||||
extern const BanksDump::BankEntry g_embeddedBanks[];
|
||||
extern const size_t g_embeddedBanksMidiIndex[];
|
||||
extern const BanksDump::MidiBank g_embeddedBanksMidi[];
|
||||
extern const BanksDump::InstrumentEntry g_embeddedBanksInstruments[];
|
||||
extern const BanksDump::Operator g_embeddedBanksOperators[];
|
||||
#endif
|
||||
|
||||
#endif // ADLDATA_DB_H
|
144
thirdparty/adlmidi/adlmidi_load.cpp
vendored
144
thirdparty/adlmidi/adlmidi_load.cpp
vendored
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
|
||||
/*
|
||||
* 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-2018 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 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,8 +21,14 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "adlmidi_midiplay.hpp"
|
||||
#include "adlmidi_opl3.hpp"
|
||||
#include "adlmidi_private.hpp"
|
||||
#include "adlmidi_cvt.hpp"
|
||||
#include "file_reader.hpp"
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
#include "midi_sequencer.hpp"
|
||||
#endif
|
||||
#include "wopl/wopl_file.h"
|
||||
|
||||
bool MIDIplay::LoadBank(const std::string &filename)
|
||||
|
@ -39,12 +45,12 @@ bool MIDIplay::LoadBank(const void *data, size_t size)
|
|||
return LoadBank(file);
|
||||
}
|
||||
|
||||
void cvt_ADLI_to_FMIns(adlinsdata2 &ins, const ADL_Instrument &in)
|
||||
void cvt_ADLI_to_FMIns(OplInstMeta &ins, const ADL_Instrument &in)
|
||||
{
|
||||
return cvt_generic_to_FMIns(ins, in);
|
||||
}
|
||||
|
||||
void cvt_FMIns_to_ADLI(ADL_Instrument &ins, const adlinsdata2 &in)
|
||||
void cvt_FMIns_to_ADLI(ADL_Instrument &ins, const OplInstMeta &in)
|
||||
{
|
||||
cvt_FMIns_to_generic(ins, in);
|
||||
}
|
||||
|
@ -104,17 +110,18 @@ bool MIDIplay::LoadBank(FileAndMemReader &fr)
|
|||
}
|
||||
}
|
||||
|
||||
m_synth.m_insBankSetup.adLibPercussions = false;
|
||||
m_synth.m_insBankSetup.scaleModulators = false;
|
||||
m_synth.m_insBankSetup.deepTremolo = (wopl->opl_flags & WOPL_FLAG_DEEP_TREMOLO) != 0;
|
||||
m_synth.m_insBankSetup.deepVibrato = (wopl->opl_flags & WOPL_FLAG_DEEP_VIBRATO) != 0;
|
||||
m_synth.m_insBankSetup.volumeModel = wopl->volume_model;
|
||||
Synth &synth = *m_synth;
|
||||
|
||||
synth.setEmbeddedBank(m_setup.bankId);
|
||||
|
||||
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.volumeModel = wopl->volume_model;
|
||||
m_setup.deepTremoloMode = -1;
|
||||
m_setup.deepVibratoMode = -1;
|
||||
m_setup.volumeScaleModel = ADLMIDI_VolumeModel_AUTO;
|
||||
|
||||
m_synth.setEmbeddedBank(m_setup.bankId);
|
||||
|
||||
uint16_t slots_counts[2] = {wopl->banks_count_melodic, wopl->banks_count_percussion};
|
||||
WOPLBank *slots_src_ins[2] = { wopl->banks_melodic, wopl->banks_percussive };
|
||||
|
||||
|
@ -124,19 +131,19 @@ bool MIDIplay::LoadBank(FileAndMemReader &fr)
|
|||
{
|
||||
size_t bankno = (slots_src_ins[ss][i].bank_midi_msb * 256) +
|
||||
(slots_src_ins[ss][i].bank_midi_lsb) +
|
||||
(ss ? size_t(OPL3::PercussionTag) : 0);
|
||||
OPL3::Bank &bank = m_synth.m_insBanks[bankno];
|
||||
(ss ? size_t(Synth::PercussionTag) : 0);
|
||||
Synth::Bank &bank = synth.m_insBanks[bankno];
|
||||
for(int j = 0; j < 128; j++)
|
||||
{
|
||||
adlinsdata2 &ins = bank.ins[j];
|
||||
std::memset(&ins, 0, sizeof(adlinsdata2));
|
||||
OplInstMeta &ins = bank.ins[j];
|
||||
std::memset(&ins, 0, sizeof(OplInstMeta));
|
||||
WOPLInstrument &inIns = slots_src_ins[ss][i].ins[j];
|
||||
cvt_generic_to_FMIns(ins, inIns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_synth.m_embeddedBank = OPL3::CustomBankTag; // Use dynamic banks!
|
||||
synth.m_embeddedBank = Synth::CustomBankTag; // Use dynamic banks!
|
||||
//Percussion offset is count of instruments multipled to count of melodic banks
|
||||
applySetup();
|
||||
|
||||
|
@ -150,7 +157,8 @@ bool MIDIplay::LoadBank(FileAndMemReader &fr)
|
|||
bool MIDIplay::LoadMIDI_pre()
|
||||
{
|
||||
#ifdef DISABLE_EMBEDDED_BANKS
|
||||
if((m_synth.m_embeddedBank != OPL3::CustomBankTag) || m_synth.m_insBanks.empty())
|
||||
Synth &synth = *m_synth;
|
||||
if((synth.m_embeddedBank != Synth::CustomBankTag) || synth.m_insBanks.empty())
|
||||
{
|
||||
errorStringOut = "Bank is not set! Please load any instruments bank by using of adl_openBankFile() or adl_openBankData() functions!";
|
||||
return false;
|
||||
|
@ -165,89 +173,97 @@ bool MIDIplay::LoadMIDI_pre()
|
|||
|
||||
bool MIDIplay::LoadMIDI_post()
|
||||
{
|
||||
MidiSequencer::FileFormat format = m_sequencer.getFormat();
|
||||
Synth &synth = *m_synth;
|
||||
MidiSequencer &seq = *m_sequencer;
|
||||
MidiSequencer::FileFormat format = seq.getFormat();
|
||||
if(format == MidiSequencer::Format_CMF)
|
||||
{
|
||||
const std::vector<MidiSequencer::CmfInstrument> &instruments = m_sequencer.getRawCmfInstruments();
|
||||
m_synth.m_insBanks.clear();//Clean up old banks
|
||||
const std::vector<MidiSequencer::CmfInstrument> &instruments = seq.getRawCmfInstruments();
|
||||
synth.m_insBanks.clear();//Clean up old banks
|
||||
|
||||
uint16_t ins_count = static_cast<uint16_t>(instruments.size());
|
||||
for(uint16_t i = 0; i < ins_count; ++i)
|
||||
{
|
||||
const uint8_t *InsData = instruments[i].data;
|
||||
const uint8_t *insData = instruments[i].data;
|
||||
size_t bank = i / 256;
|
||||
bank = ((bank & 127) + ((bank >> 7) << 8));
|
||||
if(bank > 127 + (127 << 8))
|
||||
break;
|
||||
bank += (i % 256 < 128) ? 0 : size_t(OPL3::PercussionTag);
|
||||
bank += (i % 256 < 128) ? 0 : size_t(Synth::PercussionTag);
|
||||
|
||||
/*std::printf("Ins %3u: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
i, InsData[0],InsData[1],InsData[2],InsData[3], InsData[4],InsData[5],InsData[6],InsData[7],
|
||||
InsData[8],InsData[9],InsData[10],InsData[11], InsData[12],InsData[13],InsData[14],InsData[15]);*/
|
||||
adlinsdata2 &adlins = m_synth.m_insBanks[bank].ins[i % 128];
|
||||
adldata adl;
|
||||
OplInstMeta &adlins = synth.m_insBanks[bank].ins[i % 128];
|
||||
OplTimbre adl;
|
||||
adl.modulator_E862 =
|
||||
((static_cast<uint32_t>(InsData[8] & 0x07) << 24) & 0xFF000000) //WaveForm
|
||||
| ((static_cast<uint32_t>(InsData[6]) << 16) & 0x00FF0000) //Sustain/Release
|
||||
| ((static_cast<uint32_t>(InsData[4]) << 8) & 0x0000FF00) //Attack/Decay
|
||||
| ((static_cast<uint32_t>(InsData[0]) << 0) & 0x000000FF); //MultKEVA
|
||||
((static_cast<uint32_t>(insData[8] & 0x07) << 24) & 0xFF000000) //WaveForm
|
||||
| ((static_cast<uint32_t>(insData[6]) << 16) & 0x00FF0000) //Sustain/Release
|
||||
| ((static_cast<uint32_t>(insData[4]) << 8) & 0x0000FF00) //Attack/Decay
|
||||
| ((static_cast<uint32_t>(insData[0]) << 0) & 0x000000FF); //MultKEVA
|
||||
adl.carrier_E862 =
|
||||
((static_cast<uint32_t>(InsData[9] & 0x07) << 24) & 0xFF000000) //WaveForm
|
||||
| ((static_cast<uint32_t>(InsData[7]) << 16) & 0x00FF0000) //Sustain/Release
|
||||
| ((static_cast<uint32_t>(InsData[5]) << 8) & 0x0000FF00) //Attack/Decay
|
||||
| ((static_cast<uint32_t>(InsData[1]) << 0) & 0x000000FF); //MultKEVA
|
||||
adl.modulator_40 = InsData[2];
|
||||
adl.carrier_40 = InsData[3];
|
||||
adl.feedconn = InsData[10] & 0x0F;
|
||||
adl.finetune = 0;
|
||||
adlins.adl[0] = adl;
|
||||
adlins.adl[1] = adl;
|
||||
adlins.ms_sound_kon = 1000;
|
||||
adlins.ms_sound_koff = 500;
|
||||
adlins.tone = 0;
|
||||
((static_cast<uint32_t>(insData[9] & 0x07) << 24) & 0xFF000000) //WaveForm
|
||||
| ((static_cast<uint32_t>(insData[7]) << 16) & 0x00FF0000) //Sustain/Release
|
||||
| ((static_cast<uint32_t>(insData[5]) << 8) & 0x0000FF00) //Attack/Decay
|
||||
| ((static_cast<uint32_t>(insData[1]) << 0) & 0x000000FF); //MultKEVA
|
||||
adl.modulator_40 = insData[2];
|
||||
adl.carrier_40 = insData[3];
|
||||
adl.feedconn = insData[10] & 0x0F;
|
||||
adl.noteOffset = 0;
|
||||
adlins.op[0] = adl;
|
||||
adlins.op[1] = adl;
|
||||
adlins.soundKeyOnMs = 1000;
|
||||
adlins.soundKeyOffMs = 500;
|
||||
adlins.drumTone = 0;
|
||||
adlins.flags = 0;
|
||||
adlins.voice2_fine_tune = 0.0;
|
||||
}
|
||||
|
||||
m_synth.m_embeddedBank = OPL3::CustomBankTag; // Ignore AdlBank number, use dynamic banks instead
|
||||
synth.m_embeddedBank = Synth::CustomBankTag; // Ignore AdlBank number, use dynamic banks instead
|
||||
//std::printf("CMF deltas %u ticks %u, basictempo = %u\n", deltas, ticks, basictempo);
|
||||
m_synth.m_rhythmMode = true;
|
||||
m_synth.m_musicMode = OPL3::MODE_CMF;
|
||||
m_synth.m_volumeScale = OPL3::VOLUME_NATIVE;
|
||||
synth.m_rhythmMode = true;
|
||||
synth.m_musicMode = Synth::MODE_CMF;
|
||||
synth.m_volumeScale = Synth::VOLUME_NATIVE;
|
||||
|
||||
m_synth.m_numChips = 1;
|
||||
m_synth.m_numFourOps = 0;
|
||||
synth.m_numChips = 1;
|
||||
synth.m_numFourOps = 0;
|
||||
}
|
||||
else if(format == MidiSequencer::Format_RSXX)
|
||||
{
|
||||
//opl.CartoonersVolumes = true;
|
||||
m_synth.m_musicMode = OPL3::MODE_RSXX;
|
||||
m_synth.m_volumeScale = OPL3::VOLUME_NATIVE;
|
||||
synth.m_musicMode = Synth::MODE_RSXX;
|
||||
synth.m_volumeScale = Synth::VOLUME_NATIVE;
|
||||
|
||||
m_synth.m_numChips = 1;
|
||||
m_synth.m_numFourOps = 0;
|
||||
synth.m_numChips = 1;
|
||||
synth.m_numFourOps = 0;
|
||||
}
|
||||
else if(format == MidiSequencer::Format_IMF)
|
||||
{
|
||||
//std::fprintf(stderr, "Done reading IMF file\n");
|
||||
m_synth.m_numFourOps = 0; //Don't use 4-operator channels for IMF playing!
|
||||
m_synth.m_musicMode = OPL3::MODE_IMF;
|
||||
synth.m_numFourOps = 0; //Don't use 4-operator channels for IMF playing!
|
||||
synth.m_rhythmMode = false;//Don't enforce rhythm-mode when it's unneeded
|
||||
synth.m_musicMode = Synth::MODE_IMF;
|
||||
|
||||
m_synth.m_numChips = 1;
|
||||
m_synth.m_numFourOps = 0;
|
||||
synth.m_numChips = 1;
|
||||
synth.m_numFourOps = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_synth.m_numChips = m_setup.numChips;
|
||||
if(format == MidiSequencer::Format_XMIDI)
|
||||
synth.m_musicMode = Synth::MODE_XMIDI;
|
||||
|
||||
synth.m_numChips = m_setup.numChips;
|
||||
if(m_setup.numFourOps < 0)
|
||||
adlCalculateFourOpChannels(this, true);
|
||||
}
|
||||
|
||||
resetMIDIDefaults();
|
||||
|
||||
m_setup.tick_skip_samples_delay = 0;
|
||||
m_synth.reset(m_setup.emulator, m_setup.PCM_RATE, this); // Reset OPL3 chip
|
||||
synth.reset(m_setup.emulator, m_setup.PCM_RATE, this); // Reset OPL3 chip
|
||||
//opl.Reset(); // ...twice (just in case someone misprogrammed OPL3 previously)
|
||||
m_chipChannels.clear();
|
||||
m_chipChannels.resize(m_synth.m_numChannels);
|
||||
m_chipChannels.resize(synth.m_numChannels);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -258,9 +274,10 @@ bool MIDIplay::LoadMIDI(const std::string &filename)
|
|||
file.openFile(filename.c_str());
|
||||
if(!LoadMIDI_pre())
|
||||
return false;
|
||||
if(!m_sequencer.loadMIDI(file))
|
||||
MidiSequencer &seq = *m_sequencer;
|
||||
if(!seq.loadMIDI(file))
|
||||
{
|
||||
errorStringOut = m_sequencer.getErrorString();
|
||||
errorStringOut = seq.getErrorString();
|
||||
return false;
|
||||
}
|
||||
if(!LoadMIDI_post())
|
||||
|
@ -274,9 +291,10 @@ bool MIDIplay::LoadMIDI(const void *data, size_t size)
|
|||
file.openData(data, size);
|
||||
if(!LoadMIDI_pre())
|
||||
return false;
|
||||
if(!m_sequencer.loadMIDI(file))
|
||||
MidiSequencer &seq = *m_sequencer;
|
||||
if(!seq.loadMIDI(file))
|
||||
{
|
||||
errorStringOut = m_sequencer.getErrorString();
|
||||
errorStringOut = seq.getErrorString();
|
||||
return false;
|
||||
}
|
||||
if(!LoadMIDI_post())
|
||||
|
|
1190
thirdparty/adlmidi/adlmidi_midiplay.cpp
vendored
1190
thirdparty/adlmidi/adlmidi_midiplay.cpp
vendored
File diff suppressed because it is too large
Load diff
1025
thirdparty/adlmidi/adlmidi_midiplay.hpp
vendored
Normal file
1025
thirdparty/adlmidi/adlmidi_midiplay.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
1340
thirdparty/adlmidi/adlmidi_opl3.cpp
vendored
1340
thirdparty/adlmidi/adlmidi_opl3.cpp
vendored
File diff suppressed because it is too large
Load diff
356
thirdparty/adlmidi/adlmidi_opl3.hpp
vendored
Normal file
356
thirdparty/adlmidi/adlmidi_opl3.hpp
vendored
Normal file
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ADLMIDI_OPL3_HPP
|
||||
#define ADLMIDI_OPL3_HPP
|
||||
|
||||
#include "oplinst.h"
|
||||
#include "adlmidi_ptr.hpp"
|
||||
#include "adlmidi_private.hpp"
|
||||
#include "adlmidi_bankmap.h"
|
||||
|
||||
#define BEND_COEFFICIENT 172.4387
|
||||
|
||||
#define OPL3_CHANNELS_MELODIC_BASE 0
|
||||
#define OPL3_CHANNELS_RHYTHM_BASE 18
|
||||
|
||||
#define NUM_OF_CHANNELS 23
|
||||
#define NUM_OF_4OP_CHANNELS 6
|
||||
#define NUM_OF_2OP_CHANNELS 18
|
||||
#define NUM_OF_2x2_CHANNELS 9
|
||||
#define NUM_OF_RM_CHANNELS 5
|
||||
|
||||
/**
|
||||
* @brief OPL3 Chip management class
|
||||
*/
|
||||
class OPL3
|
||||
{
|
||||
friend class MIDIplay;
|
||||
friend class AdlInstrumentTester;
|
||||
friend int adlCalculateFourOpChannels(MIDIplay *play, bool silent);
|
||||
public:
|
||||
enum
|
||||
{
|
||||
PercussionTag = 1 << 15,
|
||||
CustomBankTag = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
//! Total number of chip channels between all running emulators
|
||||
uint32_t m_numChannels;
|
||||
//! Just a padding. Reserved.
|
||||
char _padding[4];
|
||||
#ifndef ADLMIDI_HW_OPL
|
||||
//! Running chip emulators
|
||||
std::vector<AdlMIDI_SPtr<OPLChipBase > > m_chips;
|
||||
#endif
|
||||
|
||||
private:
|
||||
//! Cached patch data, needed by Touch()
|
||||
std::vector<OplTimbre> m_insCache;
|
||||
//! Value written to B0, cached, needed by NoteOff.
|
||||
/*! Contains Key on/off state, octave block and frequency number values
|
||||
*/
|
||||
std::vector<uint32_t> m_keyBlockFNumCache;
|
||||
//! Cached BD registry value (flags register: DeepTremolo, DeepVibrato, and RhythmMode)
|
||||
std::vector<uint32_t> m_regBD;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief MIDI bank entry
|
||||
*/
|
||||
struct Bank
|
||||
{
|
||||
//! MIDI Bank instruments
|
||||
OplInstMeta ins[128];
|
||||
};
|
||||
typedef BasicBankMap<Bank> BankMap;
|
||||
//! MIDI bank instruments data
|
||||
BankMap m_insBanks;
|
||||
//! MIDI bank-wide setup
|
||||
OplBankSetup m_insBankSetup;
|
||||
|
||||
public:
|
||||
//! Blank instrument template
|
||||
static const OplInstMeta m_emptyInstrument;
|
||||
//! Total number of running concurrent emulated chips
|
||||
uint32_t m_numChips;
|
||||
//! Currently running embedded bank number. "CustomBankTag" means usign of the custom bank.
|
||||
uint32_t m_embeddedBank;
|
||||
//! Total number of needed four-operator channels in all running chips
|
||||
uint32_t m_numFourOps;
|
||||
//! Turn global Deep Tremolo mode on
|
||||
bool m_deepTremoloMode;
|
||||
//! Turn global Deep Vibrato mode on
|
||||
bool m_deepVibratoMode;
|
||||
//! Use Rhythm Mode percussions
|
||||
bool m_rhythmMode;
|
||||
//! Carriers-only are scaled by default by volume level. This flag will tell to scale modulators too.
|
||||
bool m_scaleModulators;
|
||||
//! Run emulator at PCM rate if that possible. Reduces sounding accuracy, but decreases CPU usage on lower rates.
|
||||
bool m_runAtPcmRate;
|
||||
//! Enable soft panning
|
||||
bool m_softPanning;
|
||||
//! Master volume, controlled via SysEx (0...127)
|
||||
uint8_t m_masterVolume;
|
||||
|
||||
//! Just a padding. Reserved.
|
||||
char _padding2[3];
|
||||
|
||||
/**
|
||||
* @brief Music playing mode
|
||||
*/
|
||||
enum MusicMode
|
||||
{
|
||||
//! MIDI mode
|
||||
MODE_MIDI,
|
||||
//! AIL XMIDI mode
|
||||
MODE_XMIDI,
|
||||
//! Id-Software Music mode
|
||||
MODE_IMF,
|
||||
//! Creative Music Files mode
|
||||
MODE_CMF,
|
||||
//! EA-MUS (a.k.a. RSXX) mode
|
||||
MODE_RSXX
|
||||
} m_musicMode;
|
||||
|
||||
/**
|
||||
* @brief Volume models enum
|
||||
*/
|
||||
enum VolumesScale
|
||||
{
|
||||
//! Generic volume model (linearization of logarithmic scale)
|
||||
VOLUME_Generic,
|
||||
//! OPL3 native logarithmic scale
|
||||
VOLUME_NATIVE,
|
||||
//! DMX volume scale logarithmic table
|
||||
VOLUME_DMX,
|
||||
//! Apoge Sound System volume scaling model
|
||||
VOLUME_APOGEE,
|
||||
//! Windows 9x SB16 driver volume scale table
|
||||
VOLUME_9X,
|
||||
//! DMX model with a fixed bug of AM voices
|
||||
VOLUME_DMX_FIXED,
|
||||
//! Apogee model with a fixed bug of AM voices
|
||||
VOLUME_APOGEE_FIXED,
|
||||
//! Audio Interfaces Library volume scaling model
|
||||
VOLUME_AIL,
|
||||
//! Windows 9x Generic FM driver volume scale table
|
||||
VOLUME_9X_GENERIC_FM,
|
||||
//! HMI Sound Operating System volume scale table
|
||||
VOLUME_HMI,
|
||||
//! HMI Sound Operating System volume scale model, older variant
|
||||
VOLUME_HMI_OLD
|
||||
} m_volumeScale;
|
||||
|
||||
//! Reserved
|
||||
char _padding3[8];
|
||||
|
||||
/**
|
||||
* @brief Channel categiry enumeration
|
||||
*/
|
||||
enum ChanCat
|
||||
{
|
||||
//! Regular melodic/percussion channel
|
||||
ChanCat_Regular = 0,
|
||||
//! Four-op first part
|
||||
ChanCat_4op_First = 1,
|
||||
//! Four-op second part
|
||||
ChanCat_4op_Second = 2,
|
||||
//! Rhythm-mode Bass drum
|
||||
ChanCat_Rhythm_Bass = 3,
|
||||
//! Rhythm-mode Snare drum
|
||||
ChanCat_Rhythm_Snare = 4,
|
||||
//! Rhythm-mode Tom-Tom
|
||||
ChanCat_Rhythm_Tom = 5,
|
||||
//! Rhythm-mode Cymbal
|
||||
ChanCat_Rhythm_Cymbal = 6,
|
||||
//! Rhythm-mode Hi-Hat
|
||||
ChanCat_Rhythm_HiHat = 7,
|
||||
//! Rhythm-mode Secondary channel
|
||||
ChanCat_Rhythm_Secondary = 8
|
||||
};
|
||||
|
||||
//! Category of the channel
|
||||
/*! 1 = quad-first, 2 = quad-second, 0 = regular
|
||||
3 = percussion BassDrum
|
||||
4 = percussion Snare
|
||||
5 = percussion Tom
|
||||
6 = percussion Crash cymbal
|
||||
7 = percussion Hihat
|
||||
8 = percussion Secondary
|
||||
*/
|
||||
std::vector<uint32_t> m_channelCategory;
|
||||
|
||||
|
||||
/**
|
||||
* @brief C.O. Constructor
|
||||
*/
|
||||
OPL3();
|
||||
|
||||
/**
|
||||
* @brief C.O. Destructor
|
||||
*/
|
||||
~OPL3();
|
||||
|
||||
/**
|
||||
* @brief Checks are setup locked to be changed on the fly or not
|
||||
* @return true when setup on the fly is locked
|
||||
*/
|
||||
bool setupLocked();
|
||||
|
||||
/**
|
||||
* @brief Choose one of embedded banks
|
||||
* @param bank ID of the bank
|
||||
*/
|
||||
void setEmbeddedBank(uint32_t bank);
|
||||
|
||||
/**
|
||||
* @brief Write data to OPL3 chip register
|
||||
* @param chip Index of emulated chip. In hardware OPL3 builds, this parameter is ignored
|
||||
* @param address Register address to write
|
||||
* @param value Value to write
|
||||
*/
|
||||
void writeReg(size_t chip, uint16_t address, uint8_t value);
|
||||
|
||||
/**
|
||||
* @brief Write data to OPL3 chip register
|
||||
* @param chip Index of emulated chip. In hardware OPL3 builds, this parameter is ignored
|
||||
* @param address Register address to write
|
||||
* @param value Value to write
|
||||
*/
|
||||
void writeRegI(size_t chip, uint32_t address, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Write to soft panning control of OPL3 chip emulator
|
||||
* @param chip Index of emulated chip.
|
||||
* @param address Register of channel to write
|
||||
* @param value Value to write
|
||||
*/
|
||||
void writePan(size_t chip, uint32_t address, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Off the note in specified chip channel
|
||||
* @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
|
||||
*/
|
||||
void noteOff(size_t c);
|
||||
|
||||
/**
|
||||
* @brief On the note in specified chip channel with specified frequency of the tone
|
||||
* @param c1 Channel of chip [or master 4-op channel] (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
|
||||
* @param c2 Second 4-op channel of chip, unused for 2op (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
|
||||
* @param tone The tone to play (integer part - MIDI halftone, decimal part - relative bend offset)
|
||||
*/
|
||||
void noteOn(size_t c1, size_t c2, double tone);
|
||||
|
||||
/**
|
||||
* @brief Change setup of instrument in specified chip channel
|
||||
* @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
|
||||
* @param velocity Note velocity (from 0 to 127)
|
||||
* @param channelVolume Channel volume level (from 0 to 127)
|
||||
* @param channelExpression Channel expression level (from 0 to 127)
|
||||
* @param brightness CC74 Brightness level (from 0 to 127)
|
||||
* @param isDrum Is this a drum note? This flag is needed for some volume model algorithms
|
||||
*/
|
||||
void touchNote(size_t c,
|
||||
uint_fast32_t velocity,
|
||||
uint_fast32_t channelVolume = 127,
|
||||
uint_fast32_t channelExpression = 127,
|
||||
uint_fast32_t brightness = 127,
|
||||
bool isDrum = false);
|
||||
|
||||
/**
|
||||
* @brief Set the instrument into specified chip channel
|
||||
* @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
|
||||
* @param instrument Instrument data to set into the chip channel
|
||||
*/
|
||||
void setPatch(size_t c, const OplTimbre &instrument);
|
||||
|
||||
/**
|
||||
* @brief Set panpot position
|
||||
* @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
|
||||
* @param value 3-bit panpot value
|
||||
*/
|
||||
void setPan(size_t c, uint8_t value);
|
||||
|
||||
/**
|
||||
* @brief Shut up all chip channels
|
||||
*/
|
||||
void silenceAll();
|
||||
|
||||
/**
|
||||
* @brief Commit updated flag states to chip registers
|
||||
*/
|
||||
void updateChannelCategories();
|
||||
|
||||
/**
|
||||
* @brief commit deepTremolo and deepVibrato flags
|
||||
*/
|
||||
void commitDeepFlags();
|
||||
|
||||
/**
|
||||
* @brief Set the volume scaling model
|
||||
* @param volumeModel Type of volume scale model scale
|
||||
*/
|
||||
void setVolumeScaleModel(ADLMIDI_VolumeModels volumeModel);
|
||||
|
||||
/**
|
||||
* @brief Get the volume scaling model
|
||||
*/
|
||||
ADLMIDI_VolumeModels getVolumeScaleModel();
|
||||
|
||||
#ifndef ADLMIDI_HW_OPL
|
||||
/**
|
||||
* @brief Clean up all running emulated chip instances
|
||||
*/
|
||||
void clearChips();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Reset chip properties and initialize them
|
||||
* @param emulator Type of chip emulator
|
||||
* @param PCM_RATE Output sample rate to generate on output
|
||||
* @param audioTickHandler PCM-accurate clock hook
|
||||
*/
|
||||
void reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Check emulator availability
|
||||
* @param emulator Emulator ID (ADL_Emulator)
|
||||
* @return true when emulator is available
|
||||
*/
|
||||
extern bool adl_isEmulatorAvailable(int emulator);
|
||||
|
||||
/**
|
||||
* @brief Find highest emulator
|
||||
* @return The ADL_Emulator enum value which contains ID of highest emulator
|
||||
*/
|
||||
extern int adl_getHighestEmulator();
|
||||
|
||||
/**
|
||||
* @brief Find lowest emulator
|
||||
* @return The ADL_Emulator enum value which contains ID of lowest emulator
|
||||
*/
|
||||
extern int adl_getLowestEmulator();
|
||||
|
||||
#endif // ADLMIDI_OPL3_HPP
|
91
thirdparty/adlmidi/adlmidi_private.cpp
vendored
91
thirdparty/adlmidi/adlmidi_private.cpp
vendored
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
|
||||
* 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-2018 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 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,7 +21,11 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "adlmidi_midiplay.hpp"
|
||||
#include "adlmidi_opl3.hpp"
|
||||
#include "adlmidi_private.hpp"
|
||||
#include "wopl/wopl_file.h"
|
||||
|
||||
|
||||
std::string ADLMIDI_ErrorString;
|
||||
|
||||
|
@ -36,49 +40,33 @@ void adl_audioTickHandler(void *instance, uint32_t chipId, uint32_t rate)
|
|||
|
||||
int adlCalculateFourOpChannels(MIDIplay *play, bool silent)
|
||||
{
|
||||
Synth &synth = *play->m_synth;
|
||||
size_t n_fourop[2] = {0, 0}, n_total[2] = {0, 0};
|
||||
bool rhythmModeNeeded = false;
|
||||
size_t numFourOps = 0;
|
||||
|
||||
//Automatically calculate how much 4-operator channels is necessary
|
||||
#ifndef DISABLE_EMBEDDED_BANKS
|
||||
if(play->m_synth.m_embeddedBank == OPL3::CustomBankTag)
|
||||
#endif
|
||||
{
|
||||
//For custom bank
|
||||
OPL3::BankMap::iterator it = play->m_synth.m_insBanks.begin();
|
||||
OPL3::BankMap::iterator end = play->m_synth.m_insBanks.end();
|
||||
Synth::BankMap::iterator it = synth.m_insBanks.begin();
|
||||
Synth::BankMap::iterator end = synth.m_insBanks.end();
|
||||
for(; it != end; ++it)
|
||||
{
|
||||
size_t bank = it->first;
|
||||
size_t div = (bank & OPL3::PercussionTag) ? 1 : 0;
|
||||
size_t div = (bank & Synth::PercussionTag) ? 1 : 0;
|
||||
for(size_t i = 0; i < 128; ++i)
|
||||
{
|
||||
adlinsdata2 &ins = it->second.ins[i];
|
||||
if(ins.flags & adlinsdata::Flag_NoSound)
|
||||
OplInstMeta &ins = it->second.ins[i];
|
||||
if(ins.flags & OplInstMeta::Flag_NoSound)
|
||||
continue;
|
||||
if((ins.flags & adlinsdata::Flag_Real4op) != 0)
|
||||
if((ins.flags & OplInstMeta::Flag_Real4op) != 0)
|
||||
++n_fourop[div];
|
||||
++n_total[div];
|
||||
if(div && ((ins.flags & OplInstMeta::Mask_RhythmMode) != 0))
|
||||
rhythmModeNeeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef DISABLE_EMBEDDED_BANKS
|
||||
else
|
||||
{
|
||||
//For embedded bank
|
||||
for(size_t a = 0; a < 256; ++a)
|
||||
{
|
||||
size_t insno = banks[play->m_setup.bankId][a];
|
||||
if(insno == 198)
|
||||
continue;
|
||||
++n_total[a / 128];
|
||||
adlinsdata2 ins = adlinsdata2::from_adldata(::adlins[insno]);
|
||||
if((ins.flags & adlinsdata::Flag_Real4op) != 0)
|
||||
++n_fourop[a / 128];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t numFourOps = 0;
|
||||
|
||||
// All 2ops (no 4ops)
|
||||
if((n_fourop[0] == 0) && (n_fourop[1] == 0))
|
||||
|
@ -93,16 +81,47 @@ int adlCalculateFourOpChannels(MIDIplay *play, bool silent)
|
|||
else if(n_fourop[0] > 0)
|
||||
numFourOps = 4;
|
||||
|
||||
/* //Old formula
|
||||
unsigned NumFourOps = ((n_fourop[0] == 0) && (n_fourop[1] == 0)) ? 0
|
||||
: (n_fourop[0] >= (n_total[0] * 7) / 8) ? play->m_setup.NumCards * 6
|
||||
: (play->m_setup.NumCards == 1 ? 1 : play->m_setup.NumCards * 4);
|
||||
*/
|
||||
synth.m_numFourOps = static_cast<unsigned>(numFourOps * synth.m_numChips);
|
||||
|
||||
play->m_synth.m_numFourOps = static_cast<unsigned>(numFourOps * play->m_synth.m_numChips);
|
||||
// Update channel categories and set up four-operator channels
|
||||
if(!silent)
|
||||
play->m_synth.updateChannelCategories();
|
||||
synth.updateChannelCategories();
|
||||
|
||||
// Set rhythm mode when it needed
|
||||
synth.m_rhythmMode = rhythmModeNeeded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_EMBEDDED_BANKS
|
||||
void adlFromInstrument(const BanksDump::InstrumentEntry &instIn, OplInstMeta &instOut)
|
||||
{
|
||||
instOut.voice2_fine_tune = 0.0;
|
||||
if(instIn.secondVoiceDetune != 0)
|
||||
instOut.voice2_fine_tune = (double)((((int)instIn.secondVoiceDetune + 128) >> 1) - 64) / 32.0;
|
||||
|
||||
instOut.midiVelocityOffset = instIn.midiVelocityOffset;
|
||||
instOut.drumTone = instIn.percussionKeyNumber;
|
||||
instOut.flags = (instIn.instFlags & WOPL_Ins_4op) && (instIn.instFlags & WOPL_Ins_Pseudo4op) ? OplInstMeta::Flag_Pseudo4op : 0;
|
||||
instOut.flags|= (instIn.instFlags & WOPL_Ins_4op) && ((instIn.instFlags & WOPL_Ins_Pseudo4op) == 0) ? OplInstMeta::Flag_Real4op : 0;
|
||||
instOut.flags|= (instIn.instFlags & WOPL_Ins_IsBlank) ? OplInstMeta::Flag_NoSound : 0;
|
||||
instOut.flags|= instIn.instFlags & WOPL_RhythmModeMask;
|
||||
|
||||
for(size_t op = 0; op < 2; op++)
|
||||
{
|
||||
if((instIn.ops[(op * 2) + 0] < 0) || (instIn.ops[(op * 2) + 1] < 0))
|
||||
break;
|
||||
const BanksDump::Operator &op1 = g_embeddedBanksOperators[instIn.ops[(op * 2) + 0]];
|
||||
const BanksDump::Operator &op2 = g_embeddedBanksOperators[instIn.ops[(op * 2) + 1]];
|
||||
instOut.op[op].modulator_E862 = op1.d_E862;
|
||||
instOut.op[op].modulator_40 = op1.d_40;
|
||||
instOut.op[op].carrier_E862 = op2.d_E862;
|
||||
instOut.op[op].carrier_40 = op2.d_40;
|
||||
instOut.op[op].feedconn = (instIn.fbConn >> (op * 8)) & 0xFF;
|
||||
instOut.op[op].noteOffset = static_cast<int8_t>(op == 0 ? instIn.noteOffset1 : instIn.noteOffset2);
|
||||
}
|
||||
|
||||
instOut.soundKeyOnMs = instIn.delay_on_ms;
|
||||
instOut.soundKeyOffMs = instIn.delay_off_ms;
|
||||
}
|
||||
#endif
|
||||
|
|
1347
thirdparty/adlmidi/adlmidi_private.hpp
vendored
1347
thirdparty/adlmidi/adlmidi_private.hpp
vendored
File diff suppressed because it is too large
Load diff
6
thirdparty/adlmidi/adlmidi_ptr.hpp
vendored
6
thirdparty/adlmidi/adlmidi_ptr.hpp
vendored
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
|
||||
* 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-2018 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 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
|
||||
|
@ -54,7 +54,7 @@ class AdlMIDI_UPtr
|
|||
{
|
||||
T *m_p;
|
||||
public:
|
||||
explicit AdlMIDI_UPtr(T *p)
|
||||
explicit AdlMIDI_UPtr(T *p = NULL)
|
||||
: m_p(p) {}
|
||||
~AdlMIDI_UPtr()
|
||||
{
|
||||
|
|
160
thirdparty/adlmidi/adlmidi_sequencer.cpp
vendored
Normal file
160
thirdparty/adlmidi/adlmidi_sequencer.cpp
vendored
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
|
||||
// Rename class to avoid ABI collisions
|
||||
#define BW_MidiSequencer AdlMidiSequencer
|
||||
// Inlucde MIDI sequencer class implementation
|
||||
#include "midi_sequencer_impl.hpp"
|
||||
|
||||
#include "adlmidi_midiplay.hpp"
|
||||
#include "adlmidi_opl3.hpp"
|
||||
#include "adlmidi_private.hpp"
|
||||
|
||||
/****************************************************
|
||||
* Real-Time MIDI calls proxies *
|
||||
****************************************************/
|
||||
|
||||
static void rtNoteOn(void *userdata, uint8_t channel, uint8_t note, uint8_t velocity)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
context->realTime_NoteOn(channel, note, velocity);
|
||||
}
|
||||
|
||||
static void rtNoteOff(void *userdata, uint8_t channel, uint8_t note)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
context->realTime_NoteOff(channel, note);
|
||||
}
|
||||
|
||||
static void rtNoteAfterTouch(void *userdata, uint8_t channel, uint8_t note, uint8_t atVal)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
context->realTime_NoteAfterTouch(channel, note, atVal);
|
||||
}
|
||||
|
||||
static void rtChannelAfterTouch(void *userdata, uint8_t channel, uint8_t atVal)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
context->realTime_ChannelAfterTouch(channel, atVal);
|
||||
}
|
||||
|
||||
static void rtControllerChange(void *userdata, uint8_t channel, uint8_t type, uint8_t value)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
context->realTime_Controller(channel, type, value);
|
||||
}
|
||||
|
||||
static void rtPatchChange(void *userdata, uint8_t channel, uint8_t patch)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
context->realTime_PatchChange(channel, patch);
|
||||
}
|
||||
|
||||
static void rtPitchBend(void *userdata, uint8_t channel, uint8_t msb, uint8_t lsb)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
context->realTime_PitchBend(channel, msb, lsb);
|
||||
}
|
||||
|
||||
static void rtSysEx(void *userdata, const uint8_t *msg, size_t size)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
context->realTime_SysEx(msg, size);
|
||||
}
|
||||
|
||||
|
||||
/* NonStandard calls */
|
||||
static void rtRawOPL(void *userdata, uint8_t reg, uint8_t value)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
return context->realTime_rawOPL(reg, value);
|
||||
}
|
||||
|
||||
static void rtDeviceSwitch(void *userdata, size_t track, const char *data, size_t length)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
context->realTime_deviceSwitch(track, data, length);
|
||||
}
|
||||
|
||||
static size_t rtCurrentDevice(void *userdata, size_t track)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
return context->realTime_currentDevice(track);
|
||||
}
|
||||
|
||||
static void rtSongBegin(void *userdata)
|
||||
{
|
||||
MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata);
|
||||
return context->realTime_ResetState();
|
||||
}
|
||||
|
||||
/* NonStandard calls End */
|
||||
|
||||
|
||||
void MIDIplay::initSequencerInterface()
|
||||
{
|
||||
BW_MidiRtInterface *seq = new BW_MidiRtInterface;
|
||||
m_sequencerInterface.reset(seq);
|
||||
|
||||
std::memset(seq, 0, sizeof(BW_MidiRtInterface));
|
||||
|
||||
seq->onDebugMessage = hooks.onDebugMessage;
|
||||
seq->onDebugMessage_userData = hooks.onDebugMessage_userData;
|
||||
|
||||
/* MIDI Real-Time calls */
|
||||
seq->rtUserData = this;
|
||||
seq->rt_noteOn = rtNoteOn;
|
||||
seq->rt_noteOff = rtNoteOff;
|
||||
seq->rt_noteAfterTouch = rtNoteAfterTouch;
|
||||
seq->rt_channelAfterTouch = rtChannelAfterTouch;
|
||||
seq->rt_controllerChange = rtControllerChange;
|
||||
seq->rt_patchChange = rtPatchChange;
|
||||
seq->rt_pitchBend = rtPitchBend;
|
||||
seq->rt_systemExclusive = rtSysEx;
|
||||
|
||||
/* NonStandard calls */
|
||||
seq->rt_rawOPL = rtRawOPL;
|
||||
seq->rt_deviceSwitch = rtDeviceSwitch;
|
||||
seq->rt_currentDevice = rtCurrentDevice;
|
||||
|
||||
seq->onSongStart = rtSongBegin;
|
||||
seq->onSongStart_userData = this;
|
||||
/* NonStandard calls End */
|
||||
|
||||
m_sequencer->setInterface(seq);
|
||||
}
|
||||
|
||||
double MIDIplay::Tick(double s, double granularity)
|
||||
{
|
||||
MidiSequencer &seqr = *m_sequencer;
|
||||
double ret = seqr.Tick(s, granularity);
|
||||
|
||||
s *= seqr.getTempoMultiplier();
|
||||
TickIterators(s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* ADLMIDI_DISABLE_MIDI_SEQUENCER */
|
96
thirdparty/adlmidi/chips/common/mutex.hpp
vendored
Normal file
96
thirdparty/adlmidi/chips/common/mutex.hpp
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <pthread.h>
|
||||
typedef pthread_mutex_t MutexNativeObject;
|
||||
#else
|
||||
#include <windows.h>
|
||||
typedef CRITICAL_SECTION MutexNativeObject;
|
||||
#endif
|
||||
|
||||
class Mutex
|
||||
{
|
||||
public:
|
||||
Mutex();
|
||||
~Mutex();
|
||||
void lock();
|
||||
void unlock();
|
||||
private:
|
||||
MutexNativeObject m;
|
||||
Mutex(const Mutex &);
|
||||
Mutex &operator=(const Mutex &);
|
||||
};
|
||||
|
||||
class MutexHolder
|
||||
{
|
||||
public:
|
||||
explicit MutexHolder(Mutex &m) : m(m) { m.lock(); }
|
||||
~MutexHolder() { m.unlock(); }
|
||||
private:
|
||||
Mutex &m;
|
||||
MutexHolder(const MutexHolder &);
|
||||
MutexHolder &operator=(const MutexHolder &);
|
||||
};
|
||||
|
||||
#if !defined(_WIN32)
|
||||
inline Mutex::Mutex()
|
||||
{
|
||||
pthread_mutex_init(&m, NULL);
|
||||
}
|
||||
|
||||
inline Mutex::~Mutex()
|
||||
{
|
||||
pthread_mutex_destroy(&m);
|
||||
}
|
||||
|
||||
inline void Mutex::lock()
|
||||
{
|
||||
pthread_mutex_lock(&m);
|
||||
}
|
||||
|
||||
inline void Mutex::unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&m);
|
||||
}
|
||||
#else
|
||||
inline Mutex::Mutex()
|
||||
{
|
||||
InitializeCriticalSection(&m);
|
||||
}
|
||||
|
||||
inline Mutex::~Mutex()
|
||||
{
|
||||
DeleteCriticalSection(&m);
|
||||
}
|
||||
|
||||
inline void Mutex::lock()
|
||||
{
|
||||
EnterCriticalSection(&m);
|
||||
}
|
||||
|
||||
inline void Mutex::unlock()
|
||||
{
|
||||
LeaveCriticalSection(&m);
|
||||
}
|
||||
#endif
|
60
thirdparty/adlmidi/chips/dosbox/dbopl.cpp
vendored
60
thirdparty/adlmidi/chips/dosbox/dbopl.cpp
vendored
|
@ -40,6 +40,7 @@
|
|||
#include <vector>
|
||||
#include <memory>
|
||||
#include "dbopl.h"
|
||||
#include "../common/mutex.hpp"
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ > 3
|
||||
#define INLINE inline __attribute__((__always_inline__))
|
||||
|
@ -72,36 +73,16 @@
|
|||
#define PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
struct NoCopy {
|
||||
NoCopy() {}
|
||||
private:
|
||||
NoCopy(const NoCopy &);
|
||||
NoCopy &operator=(const NoCopy &);
|
||||
};
|
||||
#if !defined(_WIN32)
|
||||
#include <pthread.h>
|
||||
struct Mutex : NoCopy {
|
||||
Mutex() { pthread_mutex_init(&m, NULL);}
|
||||
~Mutex() { pthread_mutex_destroy(&m); }
|
||||
void lock() { pthread_mutex_lock(&m); }
|
||||
void unlock() { pthread_mutex_unlock(&m); }
|
||||
pthread_mutex_t m;
|
||||
};
|
||||
#else
|
||||
#include <windows.h>
|
||||
struct Mutex : NoCopy {
|
||||
Mutex() { InitializeCriticalSection(&m); }
|
||||
~Mutex() { DeleteCriticalSection(&m); }
|
||||
void lock() { EnterCriticalSection(&m); }
|
||||
void unlock() { LeaveCriticalSection(&m); }
|
||||
CRITICAL_SECTION m;
|
||||
};
|
||||
/*
|
||||
* Workaround for some compilers are has no those macros in their headers!
|
||||
*/
|
||||
#ifndef INT16_MIN
|
||||
#define INT16_MIN (-0x7fff - 1)
|
||||
#endif
|
||||
struct MutexHolder : NoCopy {
|
||||
explicit MutexHolder(Mutex &m) : m(m) { m.lock(); }
|
||||
~MutexHolder() { m.unlock(); }
|
||||
Mutex &m;
|
||||
};
|
||||
#ifndef INT16_MAX
|
||||
#define INT16_MAX 0x7fff
|
||||
#endif
|
||||
|
||||
|
||||
namespace DBOPL {
|
||||
|
||||
|
@ -1333,10 +1314,14 @@ struct CacheEntry {
|
|||
Bit32u linearRates[76];
|
||||
Bit32u attackRates[76];
|
||||
};
|
||||
struct Cache : NoCopy {
|
||||
~Cache();
|
||||
Mutex mutex;
|
||||
std::vector<CacheEntry *> entries;
|
||||
struct Cache {
|
||||
Cache() {}
|
||||
~Cache();
|
||||
Mutex mutex;
|
||||
std::vector<CacheEntry *> entries;
|
||||
private:
|
||||
Cache(const Cache &);
|
||||
Cache &operator=(const Cache &);
|
||||
};
|
||||
|
||||
static Cache cache;
|
||||
|
@ -1522,11 +1507,15 @@ void Chip::Setup( Bit32u rate ) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool doneTables = false;
|
||||
static volatile bool doneTables = false;
|
||||
static Mutex mutexTables;
|
||||
|
||||
void InitTables( void ) {
|
||||
if ( doneTables )
|
||||
return;
|
||||
doneTables = true;
|
||||
MutexHolder lock( mutexTables );
|
||||
if ( doneTables )
|
||||
return;
|
||||
#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
|
||||
//Exponential volume table, same as the real adlib
|
||||
for ( int i = 0; i < 256; i++ ) {
|
||||
|
@ -1676,6 +1665,7 @@ void InitTables( void ) {
|
|||
}
|
||||
}
|
||||
#endif
|
||||
doneTables = true;
|
||||
}
|
||||
|
||||
Bit32u Handler::WriteAddr( Bit32u port, Bit8u val ) {
|
||||
|
|
2
thirdparty/adlmidi/chips/dosbox/dbopl.h
vendored
2
thirdparty/adlmidi/chips/dosbox/dbopl.h
vendored
|
@ -286,5 +286,7 @@ struct Handler {
|
|||
void Init( Bitu rate );
|
||||
};
|
||||
|
||||
// Pre-Initialize internal tables
|
||||
void InitTables(void);
|
||||
|
||||
} //Namespace
|
||||
|
|
7
thirdparty/adlmidi/chips/dosbox_opl3.cpp
vendored
7
thirdparty/adlmidi/chips/dosbox_opl3.cpp
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (C) 2017-2018 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2020 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
|
||||
|
@ -37,6 +37,11 @@ DosBoxOPL3::~DosBoxOPL3()
|
|||
delete chip_r;
|
||||
}
|
||||
|
||||
void DosBoxOPL3::globalPreInit()
|
||||
{
|
||||
DBOPL::InitTables();
|
||||
}
|
||||
|
||||
void DosBoxOPL3::setRate(uint32_t rate)
|
||||
{
|
||||
OPLChipBaseBufferedT::setRate(rate);
|
||||
|
|
4
thirdparty/adlmidi/chips/dosbox_opl3.h
vendored
4
thirdparty/adlmidi/chips/dosbox_opl3.h
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (C) 2017-2018 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2020 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
|
||||
|
@ -30,6 +30,8 @@ public:
|
|||
DosBoxOPL3();
|
||||
~DosBoxOPL3() override;
|
||||
|
||||
static void globalPreInit();
|
||||
|
||||
bool canRunAtPcmRate() const override { return true; }
|
||||
void setRate(uint32_t rate) override;
|
||||
void reset() override;
|
||||
|
|
1900
thirdparty/adlmidi/chips/java/JavaOPL3.hpp
vendored
Normal file
1900
thirdparty/adlmidi/chips/java/JavaOPL3.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
112
thirdparty/adlmidi/chips/java_opl3.cpp
vendored
Normal file
112
thirdparty/adlmidi/chips/java_opl3.cpp
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 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
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "java_opl3.h"
|
||||
#include "java/JavaOPL3.hpp"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
#ifndef M_SQRT1_2
|
||||
#define M_SQRT1_2 0.70710678118654752440
|
||||
#endif
|
||||
|
||||
JavaOPL3::JavaOPL3() :
|
||||
OPLChipBaseBufferedT(),
|
||||
m_chip(new ADL_JavaOPL3::OPL3(true))
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
JavaOPL3::~JavaOPL3()
|
||||
{
|
||||
ADL_JavaOPL3::OPL3 *chip_r = reinterpret_cast<ADL_JavaOPL3::OPL3 *>(m_chip);
|
||||
delete chip_r;
|
||||
}
|
||||
|
||||
void JavaOPL3::setRate(uint32_t rate)
|
||||
{
|
||||
OPLChipBaseBufferedT::setRate(rate);
|
||||
ADL_JavaOPL3::OPL3 *chip_r = reinterpret_cast<ADL_JavaOPL3::OPL3 *>(m_chip);
|
||||
chip_r->Reset();
|
||||
|
||||
float pan = sinf((float)M_SQRT1_2);
|
||||
for (unsigned channel = 0; channel < 18; ++channel)
|
||||
chip_r->SetPanning(channel, pan, pan);
|
||||
}
|
||||
|
||||
void JavaOPL3::reset()
|
||||
{
|
||||
OPLChipBaseBufferedT::reset();
|
||||
ADL_JavaOPL3::OPL3 *chip_r = reinterpret_cast<ADL_JavaOPL3::OPL3 *>(m_chip);
|
||||
chip_r->Reset();
|
||||
}
|
||||
|
||||
void JavaOPL3::writeReg(uint16_t addr, uint8_t data)
|
||||
{
|
||||
ADL_JavaOPL3::OPL3 *chip_r = reinterpret_cast<ADL_JavaOPL3::OPL3 *>(m_chip);
|
||||
chip_r->WriteReg(addr, data);
|
||||
}
|
||||
|
||||
void JavaOPL3::writePan(uint16_t addr, uint8_t data)
|
||||
{
|
||||
ADL_JavaOPL3::OPL3 *chip_r = reinterpret_cast<ADL_JavaOPL3::OPL3 *>(m_chip);
|
||||
|
||||
unsigned high = (addr >> 8) & 0x01;
|
||||
unsigned regm = addr & 0xff;
|
||||
unsigned channel = 9 * high + (regm & 0x0f);
|
||||
|
||||
float phase = (data == 63 || data == 64) ? 63.5f : (float)data;
|
||||
phase *= (float)(M_PI / 2 / 127);
|
||||
chip_r->SetPanning(channel, cosf(phase), sinf(phase));
|
||||
}
|
||||
|
||||
void JavaOPL3::nativeGenerateN(int16_t *output, size_t frames)
|
||||
{
|
||||
ADL_JavaOPL3::OPL3 *chip_r = reinterpret_cast<ADL_JavaOPL3::OPL3 *>(m_chip);
|
||||
|
||||
enum { maxframes = 256 };
|
||||
|
||||
float buf[2 * maxframes];
|
||||
while(frames > 0)
|
||||
{
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
size_t curframes = (frames < (size_t)maxframes) ? frames : (size_t)maxframes;
|
||||
chip_r->Update(buf, (int)curframes);
|
||||
|
||||
size_t cursamples = 2 * curframes;
|
||||
for(size_t i = 0; i < cursamples; ++i)
|
||||
{
|
||||
int32_t sample = (int32_t)lround(4096 * buf[i]);
|
||||
sample = (sample > -32768) ? sample : -32768;
|
||||
sample = (sample < +32767) ? sample : +32767;
|
||||
output[i] = (int16_t)sample;
|
||||
}
|
||||
|
||||
output += cursamples;
|
||||
frames -= curframes;
|
||||
}
|
||||
}
|
||||
|
||||
const char *JavaOPL3::emulatorName()
|
||||
{
|
||||
return "Java 1.0.6 OPL3";
|
||||
}
|
44
thirdparty/adlmidi/chips/java_opl3.h
vendored
Normal file
44
thirdparty/adlmidi/chips/java_opl3.h
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 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
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef JAVA_OPL3_H
|
||||
#define JAVA_OPL3_H
|
||||
|
||||
#include "opl_chip_base.h"
|
||||
|
||||
class JavaOPL3 final : public OPLChipBaseBufferedT<JavaOPL3>
|
||||
{
|
||||
void *m_chip;
|
||||
public:
|
||||
JavaOPL3();
|
||||
~JavaOPL3() override;
|
||||
|
||||
bool canRunAtPcmRate() const override { return false; }
|
||||
void setRate(uint32_t rate) override;
|
||||
void reset() override;
|
||||
void writeReg(uint16_t addr, uint8_t data) override;
|
||||
void writePan(uint16_t addr, uint8_t data) override;
|
||||
void nativePreGenerate() override {}
|
||||
void nativePostGenerate() override {}
|
||||
void nativeGenerateN(int16_t *output, size_t frames) override;
|
||||
const char *emulatorName() override;
|
||||
};
|
||||
|
||||
#endif // JAVA_OPL3_H
|
224
thirdparty/adlmidi/chips/nuked/nukedopl3.c
vendored
224
thirdparty/adlmidi/chips/nuked/nukedopl3.c
vendored
|
@ -53,6 +53,117 @@ enum {
|
|||
};
|
||||
|
||||
|
||||
#if OPL_FAST_WAVEGEN
|
||||
/*
|
||||
* logsin table
|
||||
*/
|
||||
|
||||
static const Bit16u logsinrom[512] = {
|
||||
0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471,
|
||||
0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365,
|
||||
0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd,
|
||||
0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261,
|
||||
0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f,
|
||||
0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd,
|
||||
0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195,
|
||||
0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166,
|
||||
0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c,
|
||||
0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118,
|
||||
0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8,
|
||||
0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db,
|
||||
0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1,
|
||||
0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9,
|
||||
0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094,
|
||||
0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081,
|
||||
0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070,
|
||||
0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060,
|
||||
0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052,
|
||||
0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045,
|
||||
0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039,
|
||||
0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f,
|
||||
0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026,
|
||||
0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e,
|
||||
0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017,
|
||||
0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011,
|
||||
0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c,
|
||||
0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007,
|
||||
0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004,
|
||||
0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002,
|
||||
0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x002,
|
||||
0x002, 0x002, 0x002, 0x003, 0x003, 0x003, 0x004, 0x004,
|
||||
0x004, 0x005, 0x005, 0x005, 0x006, 0x006, 0x007, 0x007,
|
||||
0x007, 0x008, 0x008, 0x009, 0x009, 0x00a, 0x00a, 0x00b,
|
||||
0x00c, 0x00c, 0x00d, 0x00d, 0x00e, 0x00f, 0x00f, 0x010,
|
||||
0x011, 0x011, 0x012, 0x013, 0x014, 0x014, 0x015, 0x016,
|
||||
0x017, 0x017, 0x018, 0x019, 0x01a, 0x01b, 0x01c, 0x01d,
|
||||
0x01e, 0x01f, 0x020, 0x021, 0x022, 0x023, 0x024, 0x025,
|
||||
0x026, 0x027, 0x028, 0x029, 0x02a, 0x02b, 0x02d, 0x02e,
|
||||
0x02f, 0x030, 0x031, 0x033, 0x034, 0x035, 0x037, 0x038,
|
||||
0x039, 0x03b, 0x03c, 0x03e, 0x03f, 0x040, 0x042, 0x043,
|
||||
0x045, 0x046, 0x048, 0x04a, 0x04b, 0x04d, 0x04e, 0x050,
|
||||
0x052, 0x053, 0x055, 0x057, 0x059, 0x05b, 0x05c, 0x05e,
|
||||
0x060, 0x062, 0x064, 0x066, 0x068, 0x06a, 0x06c, 0x06e,
|
||||
0x070, 0x072, 0x074, 0x076, 0x078, 0x07a, 0x07d, 0x07f,
|
||||
0x081, 0x083, 0x086, 0x088, 0x08a, 0x08d, 0x08f, 0x092,
|
||||
0x094, 0x097, 0x099, 0x09c, 0x09f, 0x0a1, 0x0a4, 0x0a7,
|
||||
0x0a9, 0x0ac, 0x0af, 0x0b2, 0x0b5, 0x0b8, 0x0bb, 0x0be,
|
||||
0x0c1, 0x0c4, 0x0c7, 0x0ca, 0x0cd, 0x0d1, 0x0d4, 0x0d7,
|
||||
0x0db, 0x0de, 0x0e2, 0x0e5, 0x0e9, 0x0ec, 0x0f0, 0x0f4,
|
||||
0x0f8, 0x0fb, 0x0ff, 0x103, 0x107, 0x10b, 0x10f, 0x114,
|
||||
0x118, 0x11c, 0x121, 0x125, 0x129, 0x12e, 0x133, 0x137,
|
||||
0x13c, 0x141, 0x146, 0x14b, 0x150, 0x155, 0x15b, 0x160,
|
||||
0x166, 0x16b, 0x171, 0x177, 0x17c, 0x182, 0x188, 0x18f,
|
||||
0x195, 0x19b, 0x1a2, 0x1a9, 0x1b0, 0x1b7, 0x1be, 0x1c5,
|
||||
0x1cd, 0x1d4, 0x1dc, 0x1e4, 0x1ec, 0x1f5, 0x1fd, 0x206,
|
||||
0x20f, 0x218, 0x222, 0x22c, 0x236, 0x240, 0x24b, 0x256,
|
||||
0x261, 0x26d, 0x279, 0x286, 0x293, 0x2a0, 0x2af, 0x2bd,
|
||||
0x2cd, 0x2dc, 0x2ed, 0x2ff, 0x311, 0x324, 0x339, 0x34e,
|
||||
0x365, 0x37e, 0x398, 0x3b5, 0x3d3, 0x3f5, 0x41a, 0x443,
|
||||
0x471, 0x4a6, 0x4e4, 0x52e, 0x58b, 0x607, 0x6c3, 0x859
|
||||
};
|
||||
|
||||
/*
|
||||
* exp table
|
||||
*/
|
||||
|
||||
static const Bit16u exprom[256] = {
|
||||
0xff4, 0xfea, 0xfde, 0xfd4, 0xfc8, 0xfbe, 0xfb4, 0xfa8,
|
||||
0xf9e, 0xf92, 0xf88, 0xf7e, 0xf72, 0xf68, 0xf5c, 0xf52,
|
||||
0xf48, 0xf3e, 0xf32, 0xf28, 0xf1e, 0xf14, 0xf08, 0xefe,
|
||||
0xef4, 0xeea, 0xee0, 0xed4, 0xeca, 0xec0, 0xeb6, 0xeac,
|
||||
0xea2, 0xe98, 0xe8e, 0xe84, 0xe7a, 0xe70, 0xe66, 0xe5c,
|
||||
0xe52, 0xe48, 0xe3e, 0xe34, 0xe2a, 0xe20, 0xe16, 0xe0c,
|
||||
0xe04, 0xdfa, 0xdf0, 0xde6, 0xddc, 0xdd2, 0xdca, 0xdc0,
|
||||
0xdb6, 0xdac, 0xda4, 0xd9a, 0xd90, 0xd88, 0xd7e, 0xd74,
|
||||
0xd6a, 0xd62, 0xd58, 0xd50, 0xd46, 0xd3c, 0xd34, 0xd2a,
|
||||
0xd22, 0xd18, 0xd10, 0xd06, 0xcfe, 0xcf4, 0xcec, 0xce2,
|
||||
0xcda, 0xcd0, 0xcc8, 0xcbe, 0xcb6, 0xcae, 0xca4, 0xc9c,
|
||||
0xc92, 0xc8a, 0xc82, 0xc78, 0xc70, 0xc68, 0xc60, 0xc56,
|
||||
0xc4e, 0xc46, 0xc3c, 0xc34, 0xc2c, 0xc24, 0xc1c, 0xc12,
|
||||
0xc0a, 0xc02, 0xbfa, 0xbf2, 0xbea, 0xbe0, 0xbd8, 0xbd0,
|
||||
0xbc8, 0xbc0, 0xbb8, 0xbb0, 0xba8, 0xba0, 0xb98, 0xb90,
|
||||
0xb88, 0xb80, 0xb78, 0xb70, 0xb68, 0xb60, 0xb58, 0xb50,
|
||||
0xb48, 0xb40, 0xb38, 0xb32, 0xb2a, 0xb22, 0xb1a, 0xb12,
|
||||
0xb0a, 0xb02, 0xafc, 0xaf4, 0xaec, 0xae4, 0xade, 0xad6,
|
||||
0xace, 0xac6, 0xac0, 0xab8, 0xab0, 0xaa8, 0xaa2, 0xa9a,
|
||||
0xa92, 0xa8c, 0xa84, 0xa7c, 0xa76, 0xa6e, 0xa68, 0xa60,
|
||||
0xa58, 0xa52, 0xa4a, 0xa44, 0xa3c, 0xa36, 0xa2e, 0xa28,
|
||||
0xa20, 0xa18, 0xa12, 0xa0c, 0xa04, 0x9fe, 0x9f6, 0x9f0,
|
||||
0x9e8, 0x9e2, 0x9da, 0x9d4, 0x9ce, 0x9c6, 0x9c0, 0x9b8,
|
||||
0x9b2, 0x9ac, 0x9a4, 0x99e, 0x998, 0x990, 0x98a, 0x984,
|
||||
0x97c, 0x976, 0x970, 0x96a, 0x962, 0x95c, 0x956, 0x950,
|
||||
0x948, 0x942, 0x93c, 0x936, 0x930, 0x928, 0x922, 0x91c,
|
||||
0x916, 0x910, 0x90a, 0x904, 0x8fc, 0x8f6, 0x8f0, 0x8ea,
|
||||
0x8e4, 0x8de, 0x8d8, 0x8d2, 0x8cc, 0x8c6, 0x8c0, 0x8ba,
|
||||
0x8b4, 0x8ae, 0x8a8, 0x8a2, 0x89c, 0x896, 0x890, 0x88a,
|
||||
0x884, 0x87e, 0x878, 0x872, 0x86c, 0x866, 0x860, 0x85a,
|
||||
0x854, 0x850, 0x84a, 0x844, 0x83e, 0x838, 0x832, 0x82c,
|
||||
0x828, 0x822, 0x81c, 0x816, 0x810, 0x80c, 0x806, 0x800
|
||||
};
|
||||
#else
|
||||
/*
|
||||
* logsin table
|
||||
*/
|
||||
|
@ -130,6 +241,7 @@ static const Bit16u exprom[256] = {
|
|||
0x42a, 0x428, 0x425, 0x422, 0x41f, 0x41c, 0x419, 0x416,
|
||||
0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* freq mult table multiplied by 2
|
||||
|
@ -207,8 +319,8 @@ static const Bit16u panlawtable[] =
|
|||
* Envelope generator
|
||||
*/
|
||||
|
||||
#if !OPL_FAST_WAVEGEN
|
||||
typedef Bit16s(*envelope_sinfunc)(Bit16u phase, Bit16u envelope);
|
||||
typedef void(*envelope_genfunc)(opl3_slot *slott);
|
||||
|
||||
static Bit16s OPL3_EnvelopeCalcExp(Bit32u level)
|
||||
{
|
||||
|
@ -366,6 +478,7 @@ static const envelope_sinfunc envelope_sin[8] = {
|
|||
OPL3_EnvelopeCalcSin6,
|
||||
OPL3_EnvelopeCalcSin7
|
||||
};
|
||||
#endif
|
||||
|
||||
enum envelope_gen_num
|
||||
{
|
||||
|
@ -401,6 +514,15 @@ static void OPL3_EnvelopeCalc(opl3_slot *slot)
|
|||
Bit8u reset = 0;
|
||||
slot->eg_out = slot->eg_rout + (slot->reg_tl << 2)
|
||||
+ (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem;
|
||||
|
||||
#if OPL_FAST_WAVEGEN
|
||||
if (slot->eg_out > 0x1ff)
|
||||
{
|
||||
slot->eg_out = 0x1ff;
|
||||
}
|
||||
slot->eg_out <<= 3;
|
||||
#endif
|
||||
|
||||
if (slot->key && slot->eg_gen == envelope_gen_num_release)
|
||||
{
|
||||
reset = 1;
|
||||
|
@ -687,12 +809,92 @@ static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data)
|
|||
{
|
||||
slot->reg_wf &= 0x03;
|
||||
}
|
||||
|
||||
#if OPL_FAST_WAVEGEN
|
||||
switch (slot->reg_wf)
|
||||
{
|
||||
case 1:
|
||||
case 4:
|
||||
case 5:
|
||||
slot->maskzero = 0x200;
|
||||
break;
|
||||
case 3:
|
||||
slot->maskzero = 0x100;
|
||||
break;
|
||||
default:
|
||||
slot->maskzero = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (slot->reg_wf)
|
||||
{
|
||||
case 4:
|
||||
slot->signpos = (31-8); /* sigext of (phase & 0x100) */
|
||||
break;
|
||||
case 0:
|
||||
case 6:
|
||||
case 7:
|
||||
slot->signpos = (31-9); /* sigext of (phase & 0x200) */
|
||||
break;
|
||||
default:
|
||||
slot->signpos = (31-16); /* set "neg" to zero */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (slot->reg_wf)
|
||||
{
|
||||
case 4:
|
||||
case 5:
|
||||
slot->phaseshift = 1;
|
||||
break;
|
||||
case 6:
|
||||
slot->phaseshift = 16; /* set phase to zero and flag for non-sin wave */
|
||||
break;
|
||||
case 7:
|
||||
slot->phaseshift = 32; /* no shift (work by mod 32), but flag for non-sin wave */
|
||||
break;
|
||||
default:
|
||||
slot->phaseshift = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if OPL_FAST_WAVEGEN
|
||||
static void OPL3_SlotGenerate(opl3_slot *slot)
|
||||
{
|
||||
Bit16u phase = slot->pg_phase_out + *slot->mod;
|
||||
Bit32u neg, level;
|
||||
Bit8u phaseshift;
|
||||
|
||||
/* Fast paths for mute segments */
|
||||
if (phase & slot->maskzero)
|
||||
{
|
||||
slot->out = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
neg = (Bit32s)((Bit32u)phase << slot->signpos) >> 31;
|
||||
phaseshift = slot->phaseshift;
|
||||
level = slot->eg_out;
|
||||
|
||||
phase <<= phaseshift;
|
||||
if (phaseshift <= 1)
|
||||
{
|
||||
level += logsinrom[phase & 0x1ff];
|
||||
}
|
||||
else
|
||||
{
|
||||
level += ((phase ^ neg) & 0x3ff) << 3;
|
||||
}
|
||||
slot->out = exprom[level & 0xff] >> (level >> 8) ^ neg;
|
||||
}
|
||||
#else
|
||||
static void OPL3_SlotGenerate(opl3_slot *slot)
|
||||
{
|
||||
slot->out = envelope_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, slot->eg_out);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void OPL3_SlotCalcFB(opl3_slot *slot)
|
||||
{
|
||||
|
@ -1176,7 +1378,7 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf)
|
|||
|
||||
if (chip->eg_timerrem || chip->eg_state)
|
||||
{
|
||||
if (chip->eg_timer == (uint64_t)0xfffffffffU)
|
||||
if (chip->eg_timer == 0xfffffffffULL)
|
||||
{
|
||||
chip->eg_timer = 0;
|
||||
chip->eg_timerrem = 1;
|
||||
|
@ -1231,10 +1433,17 @@ void OPL3_Reset(opl3_chip *chip, Bit32u samplerate)
|
|||
chip->slot[slotnum].chip = chip;
|
||||
chip->slot[slotnum].mod = &chip->zeromod;
|
||||
chip->slot[slotnum].eg_rout = 0x1ff;
|
||||
#if OPL_FAST_WAVEGEN
|
||||
chip->slot[slotnum].eg_out = 0x1ff << 3;
|
||||
#else
|
||||
chip->slot[slotnum].eg_out = 0x1ff;
|
||||
#endif
|
||||
chip->slot[slotnum].eg_gen = envelope_gen_num_release;
|
||||
chip->slot[slotnum].trem = (Bit8u*)&chip->zeromod;
|
||||
chip->slot[slotnum].slot_num = slotnum;
|
||||
#if OPL_FAST_WAVEGEN
|
||||
chip->slot[slotnum].signpos = (31-9); /* for wf=0 need use sigext of (phase & 0x200) */
|
||||
#endif
|
||||
}
|
||||
for (channum = 0; channum < 18; channum++)
|
||||
{
|
||||
|
@ -1420,16 +1629,23 @@ void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples)
|
|||
}
|
||||
}
|
||||
|
||||
#define OPL3_MIN(A, B) (((A) > (B)) ? (B) : (A))
|
||||
#define OPL3_MAX(A, B) (((A) < (B)) ? (B) : (A))
|
||||
#define OPL3_CLAMP(V, MIN, MAX) OPL3_MAX(OPL3_MIN(V, MAX), MIN)
|
||||
|
||||
void OPL3_GenerateStreamMix(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples)
|
||||
{
|
||||
Bit32u i;
|
||||
Bit16s sample[2];
|
||||
Bit32s mix[2];
|
||||
|
||||
for(i = 0; i < numsamples; i++)
|
||||
{
|
||||
OPL3_GenerateResampled(chip, sample);
|
||||
sndptr[0] += sample[0];
|
||||
sndptr[1] += sample[1];
|
||||
mix[0] = sndptr[0] + sample[0];
|
||||
mix[1] = sndptr[1] + sample[1];
|
||||
sndptr[0] = OPL3_CLAMP(mix[0], INT16_MIN, INT16_MAX);
|
||||
sndptr[1] = OPL3_CLAMP(mix[1], INT16_MIN, INT16_MAX);
|
||||
sndptr += 2;
|
||||
}
|
||||
}
|
||||
|
|
9
thirdparty/adlmidi/chips/nuked/nukedopl3.h
vendored
9
thirdparty/adlmidi/chips/nuked/nukedopl3.h
vendored
|
@ -33,13 +33,16 @@
|
|||
#define OPL_OPL3_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define OPL_WRITEBUF_SIZE 1024
|
||||
#define OPL_WRITEBUF_DELAY 2
|
||||
#define OPL_FAST_WAVEGEN 1 /* optimized waveform generation */
|
||||
|
||||
typedef uintptr_t Bitu;
|
||||
typedef intptr_t Bits;
|
||||
|
@ -86,6 +89,12 @@ struct _opl3_slot {
|
|||
Bit32u pg_phase;
|
||||
Bit16u pg_phase_out;
|
||||
Bit8u slot_num;
|
||||
|
||||
#if OPL_FAST_WAVEGEN
|
||||
Bit16u maskzero;
|
||||
Bit8u signpos;
|
||||
Bit8u phaseshift;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _opl3_channel {
|
||||
|
|
2
thirdparty/adlmidi/chips/nuked_opl3.cpp
vendored
2
thirdparty/adlmidi/chips/nuked_opl3.cpp
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (C) 2017-2018 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2020 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
|
||||
|
|
2
thirdparty/adlmidi/chips/nuked_opl3.h
vendored
2
thirdparty/adlmidi/chips/nuked_opl3.h
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (C) 2017-2018 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2020 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
|
||||
|
|
2
thirdparty/adlmidi/chips/nuked_opl3_v174.cpp
vendored
2
thirdparty/adlmidi/chips/nuked_opl3_v174.cpp
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (C) 2017-2018 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2020 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
|
||||
|
|
2
thirdparty/adlmidi/chips/nuked_opl3_v174.h
vendored
2
thirdparty/adlmidi/chips/nuked_opl3_v174.h
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (C) 2017-2018 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2020 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
|
||||
|
|
19
thirdparty/adlmidi/chips/opal/LICENSE.txt
vendored
Normal file
19
thirdparty/adlmidi/chips/opal/LICENSE.txt
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
A quote from a letter sent by Willy Reeve to Vitaly Novichkov
|
||||
as a reply from a letter sent by Reality's (https://www.3eality.com/)
|
||||
contact form
|
||||
----------------------------------------------------------------
|
||||
All source code supplied with RAD is in the public domain.
|
||||
----------------------------------------------------------------
|
||||
|
||||
================================================================
|
||||
The complete letter:
|
||||
================================================================
|
||||
Hi,
|
||||
|
||||
All source code supplied with RAD is in the public domain.
|
||||
We'll clarify that in the documentation for the next release.
|
||||
|
||||
Later...
|
||||
SHAYDE
|
||||
================================================================
|
||||
|
9
thirdparty/adlmidi/chips/opal/README.old
vendored
Normal file
9
thirdparty/adlmidi/chips/opal/README.old
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
Copy opal.cpp here to make this emulator available.
|
||||
This is not distributed with the software while the license is undetermined.
|
||||
|
||||
The opal.cpp file is part of REALITY ADLIB TRACKER V2.
|
||||
SHA1: c034dd637887d81770cee92da309fc547ef5fe18
|
||||
|
||||
Configure the software with the option USE_OPAL_EMULATOR=ON.
|
||||
To enable soft panning, it is needed to patch with the file `opal-pan.diff` provided.
|
||||
for example: `patch -p0 -i opal-pan.diff`
|
131
thirdparty/adlmidi/chips/opal/opal-pan.diff
vendored
Normal file
131
thirdparty/adlmidi/chips/opal/opal-pan.diff
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
--- opal.cpp.orig 2019-02-23 20:32:00.477658789 +0100
|
||||
+++ opal.cpp 2019-02-23 20:46:36.745113958 +0100
|
||||
@@ -13,6 +13,7 @@
|
||||
- Percussion mode
|
||||
|
||||
*/
|
||||
+#define OPAL_HAVE_SOFT_PANNING 1 /* libADLMIDI */
|
||||
|
||||
|
||||
|
||||
@@ -133,6 +134,7 @@
|
||||
void SetOctave(uint16_t oct);
|
||||
void SetLeftEnable(bool on);
|
||||
void SetRightEnable(bool on);
|
||||
+ void SetPan(uint8_t pan);
|
||||
void SetFeedback(uint16_t val);
|
||||
void SetModulationType(uint16_t type);
|
||||
|
||||
@@ -158,6 +160,7 @@
|
||||
Channel * ChannelPair;
|
||||
bool Enable;
|
||||
bool LeftEnable, RightEnable;
|
||||
+ uint16_t LeftPan, RightPan;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -166,6 +169,7 @@
|
||||
|
||||
void SetSampleRate(int sample_rate);
|
||||
void Port(uint16_t reg_num, uint8_t val);
|
||||
+ void Pan(uint16_t reg_num, uint8_t pan);
|
||||
void Sample(int16_t *left, int16_t *right);
|
||||
|
||||
protected:
|
||||
@@ -191,6 +195,7 @@
|
||||
static const uint16_t RateTables[4][8];
|
||||
static const uint16_t ExpTable[256];
|
||||
static const uint16_t LogSinTable[256];
|
||||
+ static const uint16_t PanLawTable[128];
|
||||
};
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const uint16_t Opal::RateTables[4][8] = {
|
||||
@@ -237,6 +242,28 @@
|
||||
7, 7, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2,
|
||||
2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
+//--------------------------------------------------------------------------------------------------
|
||||
+const uint16_t Opal::PanLawTable[128] =
|
||||
+{
|
||||
+ 65535, 65529, 65514, 65489, 65454, 65409, 65354, 65289,
|
||||
+ 65214, 65129, 65034, 64929, 64814, 64689, 64554, 64410,
|
||||
+ 64255, 64091, 63917, 63733, 63540, 63336, 63123, 62901,
|
||||
+ 62668, 62426, 62175, 61914, 61644, 61364, 61075, 60776,
|
||||
+ 60468, 60151, 59825, 59489, 59145, 58791, 58428, 58057,
|
||||
+ 57676, 57287, 56889, 56482, 56067, 55643, 55211, 54770,
|
||||
+ 54320, 53863, 53397, 52923, 52441, 51951, 51453, 50947,
|
||||
+ 50433, 49912, 49383, 48846, 48302, 47750, 47191,
|
||||
+ 46340, // Center left
|
||||
+ 46340, // Center right
|
||||
+ 45472, 44885, 44291, 43690, 43083, 42469, 41848, 41221,
|
||||
+ 40588, 39948, 39303, 38651, 37994, 37330, 36661, 35986,
|
||||
+ 35306, 34621, 33930, 33234, 32533, 31827, 31116, 30400,
|
||||
+ 29680, 28955, 28225, 27492, 26754, 26012, 25266, 24516,
|
||||
+ 23762, 23005, 22244, 21480, 20713, 19942, 19169, 18392,
|
||||
+ 17613, 16831, 16046, 15259, 14469, 13678, 12884, 12088,
|
||||
+ 11291, 10492, 9691, 8888, 8085, 7280, 6473, 5666,
|
||||
+ 4858, 4050, 3240, 2431, 1620, 810, 0
|
||||
+};
|
||||
|
||||
|
||||
|
||||
@@ -342,6 +369,10 @@
|
||||
for (int i = 0; i < NumOperators; i++)
|
||||
Op[i].ComputeRates();
|
||||
|
||||
+ // Initialise channel panning at center.
|
||||
+ for (int i = 0; i < NumChannels; i++)
|
||||
+ Chan[i].SetPan(64);
|
||||
+
|
||||
SetSampleRate(sample_rate);
|
||||
}
|
||||
|
||||
@@ -533,6 +564,19 @@
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
+// Set panning on the channel designated by the register number.
|
||||
+// This is extended functionality.
|
||||
+//==================================================================================================
|
||||
+void Opal::Pan(uint16_t reg_num, uint8_t pan)
|
||||
+{
|
||||
+ uint8_t high = (reg_num >> 8) & 1;
|
||||
+ uint8_t regm = reg_num & 0xff;
|
||||
+ Chan[9 * high + (regm & 0x0f)].SetPan(pan);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+//==================================================================================================
|
||||
// Generate sample. Every time you call this you will get two signed 16-bit samples (one for each
|
||||
// stereo channel) which will sound correct when played back at the sample rate given when the
|
||||
// class was constructed.
|
||||
@@ -727,6 +771,9 @@
|
||||
|
||||
left = LeftEnable ? out : 0;
|
||||
right = RightEnable ? out : 0;
|
||||
+
|
||||
+ left = left * LeftPan / 65536;
|
||||
+ right = right * RightPan / 65536;
|
||||
}
|
||||
|
||||
|
||||
@@ -793,6 +840,18 @@
|
||||
}
|
||||
|
||||
|
||||
+
|
||||
+//==================================================================================================
|
||||
+// Pan the channel to the position given.
|
||||
+//==================================================================================================
|
||||
+void Opal::Channel::SetPan(uint8_t pan)
|
||||
+{
|
||||
+ pan &= 127;
|
||||
+ LeftPan = PanLawTable[pan];
|
||||
+ RightPan = PanLawTable[127 - pan];
|
||||
+}
|
||||
+
|
||||
+
|
||||
|
||||
//==================================================================================================
|
||||
// Set the channel feedback amount.
|
1398
thirdparty/adlmidi/chips/opal/opal.hpp
vendored
Normal file
1398
thirdparty/adlmidi/chips/opal/opal.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
81
thirdparty/adlmidi/chips/opal_opl3.cpp
vendored
Normal file
81
thirdparty/adlmidi/chips/opal_opl3.cpp
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 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
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "opal_opl3.h"
|
||||
#include "opal/opal.hpp"
|
||||
#include <new>
|
||||
#include <cstring>
|
||||
|
||||
OpalOPL3::OpalOPL3() :
|
||||
OPLChipBaseT()
|
||||
{
|
||||
m_chip = new Opal(m_rate);
|
||||
setRate(m_rate);
|
||||
}
|
||||
|
||||
OpalOPL3::~OpalOPL3()
|
||||
{
|
||||
Opal *chip_r = reinterpret_cast<Opal *>(m_chip);
|
||||
delete chip_r;
|
||||
}
|
||||
|
||||
void OpalOPL3::setRate(uint32_t rate)
|
||||
{
|
||||
OPLChipBaseT::setRate(rate);
|
||||
Opal *chip_r = reinterpret_cast<Opal *>(m_chip);
|
||||
chip_r->~Opal();
|
||||
new (chip_r) Opal(effectiveRate());
|
||||
}
|
||||
|
||||
void OpalOPL3::reset()
|
||||
{
|
||||
OPLChipBaseT::reset();
|
||||
Opal *chip_r = reinterpret_cast<Opal *>(m_chip);
|
||||
chip_r->~Opal();
|
||||
new (chip_r) Opal(effectiveRate());
|
||||
}
|
||||
|
||||
void OpalOPL3::writeReg(uint16_t addr, uint8_t data)
|
||||
{
|
||||
Opal *chip_r = reinterpret_cast<Opal *>(m_chip);
|
||||
chip_r->Port(addr, data);
|
||||
}
|
||||
|
||||
void OpalOPL3::writePan(uint16_t addr, uint8_t data)
|
||||
{
|
||||
#ifdef OPAL_HAVE_SOFT_PANNING
|
||||
Opal *chip_r = reinterpret_cast<Opal *>(m_chip);
|
||||
chip_r->Pan(addr, data);
|
||||
#else
|
||||
(void)addr;
|
||||
(void)data;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpalOPL3::nativeGenerate(int16_t *frame)
|
||||
{
|
||||
Opal *chip_r = reinterpret_cast<Opal *>(m_chip);
|
||||
chip_r->Sample(&frame[0], &frame[1]);
|
||||
}
|
||||
|
||||
const char *OpalOPL3::emulatorName()
|
||||
{
|
||||
return "Opal OPL3";
|
||||
}
|
44
thirdparty/adlmidi/chips/opal_opl3.h
vendored
Normal file
44
thirdparty/adlmidi/chips/opal_opl3.h
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 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
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef OPAL_OPL3_H
|
||||
#define OPAL_OPL3_H
|
||||
|
||||
#include "opl_chip_base.h"
|
||||
|
||||
class OpalOPL3 final : public OPLChipBaseT<OpalOPL3>
|
||||
{
|
||||
void *m_chip;
|
||||
public:
|
||||
OpalOPL3();
|
||||
~OpalOPL3() override;
|
||||
|
||||
bool canRunAtPcmRate() const override { return true; }
|
||||
void setRate(uint32_t rate) override;
|
||||
void reset() override;
|
||||
void writeReg(uint16_t addr, uint8_t data) override;
|
||||
void writePan(uint16_t addr, uint8_t data) override;
|
||||
void nativePreGenerate() override {}
|
||||
void nativePostGenerate() override {}
|
||||
void nativeGenerate(int16_t *frame) override;
|
||||
const char *emulatorName() override;
|
||||
};
|
||||
|
||||
#endif // NUKED_OPL3_H
|
2
thirdparty/adlmidi/chips/opl_chip_base.h
vendored
2
thirdparty/adlmidi/chips/opl_chip_base.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2017-2018 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2020 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
|
||||
|
|
4
thirdparty/adlmidi/chips/opl_chip_base.tcc
vendored
4
thirdparty/adlmidi/chips/opl_chip_base.tcc
vendored
|
@ -236,8 +236,8 @@ void OPLChipBaseT<T>::resampledGenerate(int32_t *output)
|
|||
rsm->out_count = 1;
|
||||
rsm->out_data = f_out;
|
||||
}
|
||||
output[0] = static_cast<int32_t>(std::lround(f_out[0]));
|
||||
output[1] = static_cast<int32_t>(std::lround(f_out[1]));
|
||||
output[0] = static_cast<int32_t>(lround(f_out[0]));
|
||||
output[1] = static_cast<int32_t>(lround(f_out[1]));
|
||||
}
|
||||
#else
|
||||
template <class T>
|
||||
|
|
9
thirdparty/adlmidi/file_reader.hpp
vendored
9
thirdparty/adlmidi/file_reader.hpp
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* FileAndMemoryReader - a tiny helper to utify file reading from a disk and memory block
|
||||
*
|
||||
* Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* Copyright (c) 2015-2020 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"),
|
||||
|
@ -110,15 +110,15 @@ public:
|
|||
/**
|
||||
* @brief Open file from memory block
|
||||
* @param mem Pointer to the memory block
|
||||
* @param lenght Size of given block
|
||||
* @param length Size of given block
|
||||
*/
|
||||
void openData(const void *mem, size_t lenght)
|
||||
void openData(const void *mem, size_t length)
|
||||
{
|
||||
if(m_fp)
|
||||
this->close();//Close previously opened file first!
|
||||
m_fp = NULL;
|
||||
m_mp = mem;
|
||||
m_mp_size = lenght;
|
||||
m_mp_size = length;
|
||||
m_mp_tell = 0;
|
||||
}
|
||||
|
||||
|
@ -140,6 +140,7 @@ public:
|
|||
{
|
||||
switch(rel_to)
|
||||
{
|
||||
default:
|
||||
case SET:
|
||||
m_mp_tell = static_cast<size_t>(pos);
|
||||
break;
|
||||
|
|
220
thirdparty/adlmidi/fraction.hpp
vendored
Normal file
220
thirdparty/adlmidi/fraction.hpp
vendored
Normal file
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Fraction number handling.
|
||||
* Copyright (C) 1992,2001 Bisqwit (http://iki.fi/bisqwit/)
|
||||
*
|
||||
* The license of this file is in Public Domain:
|
||||
* https://bisqwit.iki.fi/src/index.html
|
||||
*
|
||||
* "... and orphan source code files are copyrighted public domain."
|
||||
*/
|
||||
|
||||
#ifndef bqw_fraction_h
|
||||
#define bqw_fraction_h
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
template<typename inttype=int>
|
||||
class fraction
|
||||
{
|
||||
inttype num1, num2;
|
||||
typedef fraction<inttype> self;
|
||||
void Optim();
|
||||
|
||||
#if 1
|
||||
inline void Debug(char, const self &) { }
|
||||
#else
|
||||
inline void Debug(char op, const self &b)
|
||||
{
|
||||
cerr << nom() << '/' << denom() << ' ' << op
|
||||
<< ' ' << b.nom() << '/' << denom()
|
||||
<< ":\n";
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
void set(inttype n, inttype d) { num1=n; num2=d; Optim(); }
|
||||
|
||||
fraction() : num1(0), num2(1) { }
|
||||
fraction(inttype value) : num1(value), num2(1) { }
|
||||
fraction(inttype n, inttype d) : num1(n), num2(d) { }
|
||||
fraction(int value) : num1(value), num2(1) { }
|
||||
template<typename floattype>
|
||||
explicit fraction(const floattype value) { operator= (value); }
|
||||
inline double value() const {return nom() / (double)denom(); }
|
||||
inline long double valuel() const {return nom() / (long double)denom(); }
|
||||
self &operator+= (const inttype &value) { num1+=value*denom(); Optim(); return *this; }
|
||||
self &operator-= (const inttype &value) { num1-=value*denom(); Optim(); return *this; }
|
||||
self &operator*= (const inttype &value) { num1*=value; Optim(); return *this; }
|
||||
self &operator/= (const inttype &value) { num2*=value; Optim(); return *this; }
|
||||
self &operator+= (const self &b);
|
||||
self &operator-= (const self &b);
|
||||
self &operator*= (const self &b) { Debug('*',b);num1*=b.nom(); num2*=b.denom(); Optim(); return *this; }
|
||||
self &operator/= (const self &b) { Debug('/',b);num1*=b.denom(); num2*=b.nom(); Optim(); return *this; }
|
||||
self operator- () const { return self(-num1, num2); }
|
||||
|
||||
#define fraction_blah_func(op1, op2) \
|
||||
self operator op1 (const self &b) const { self tmp(*this); tmp op2 b; return tmp; }
|
||||
|
||||
fraction_blah_func( +, += )
|
||||
fraction_blah_func( -, -= )
|
||||
fraction_blah_func( /, /= )
|
||||
fraction_blah_func( *, *= )
|
||||
|
||||
#undef fraction_blah_func
|
||||
#define fraction_blah_func(op) \
|
||||
bool operator op(const self &b) const { return value() op b.value(); } \
|
||||
bool operator op(inttype b) const { return value() op b; }
|
||||
|
||||
fraction_blah_func( < )
|
||||
fraction_blah_func( > )
|
||||
fraction_blah_func( <= )
|
||||
fraction_blah_func( >= )
|
||||
|
||||
#undef fraction_blah_func
|
||||
|
||||
const inttype &nom() const { return num1; }
|
||||
const inttype &denom() const { return num2; }
|
||||
inline bool operator == (inttype b) const { return denom() == 1 && nom() == b; }
|
||||
inline bool operator != (inttype b) const { return denom() != 1 || nom() != b; }
|
||||
inline bool operator == (const self &b) const { return denom()==b.denom() && nom()==b.nom(); }
|
||||
inline bool operator != (const self &b) const { return denom()!=b.denom() || nom()!=b.nom(); }
|
||||
//operator bool () const { return nom() != 0; }
|
||||
inline bool negative() const { return (nom() < 0) ^ (denom() < 0); }
|
||||
|
||||
self &operator= (const inttype value) { num2=1; num1=value; return *this; }
|
||||
//self &operator= (int value) { num2=1; num1=value; return *this; }
|
||||
|
||||
self &operator= (double orig) { return *this = (long double)orig; }
|
||||
self &operator= (long double orig);
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4146)
|
||||
#endif
|
||||
|
||||
template<typename inttype>
|
||||
void fraction<inttype>::Optim()
|
||||
{
|
||||
/* Euclidean algorithm */
|
||||
inttype n1, n2, nn1, nn2;
|
||||
|
||||
nn1 = std::numeric_limits<inttype>::is_signed ? (num1 >= 0 ? num1 : -num1) : num1;
|
||||
nn2 = std::numeric_limits<inttype>::is_signed ? (num2 >= 0 ? num2 : -num2) : num2;
|
||||
|
||||
if(nn1 < nn2)
|
||||
n1 = num1, n2 = num2;
|
||||
else
|
||||
n1 = num2, n2 = num1;
|
||||
|
||||
if(!num1) { num2 = 1; return; }
|
||||
for(;;)
|
||||
{
|
||||
//fprintf(stderr, "%d/%d: n1=%d,n2=%d\n", nom(),denom(),n1,n2);
|
||||
inttype tmp = n2 % n1;
|
||||
if(!tmp)break;
|
||||
n2 = n1;
|
||||
n1 = tmp;
|
||||
}
|
||||
num1 /= n1;
|
||||
num2 /= n1;
|
||||
//fprintf(stderr, "result: %d/%d\n\n", nom(), denom());
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(default:4146)
|
||||
#endif
|
||||
|
||||
template<typename inttype>
|
||||
inline const fraction<inttype> abs(const fraction<inttype> &f)
|
||||
{
|
||||
return fraction<inttype>(abs(f.nom()), abs(f.denom()));
|
||||
}
|
||||
|
||||
#define fraction_blah_func(op) \
|
||||
template<typename inttype> \
|
||||
fraction<inttype> operator op \
|
||||
(const inttype bla, const fraction<inttype> &b) \
|
||||
{ return fraction<inttype> (bla) op b; }
|
||||
fraction_blah_func( + )
|
||||
fraction_blah_func( - )
|
||||
fraction_blah_func( * )
|
||||
fraction_blah_func( / )
|
||||
#undef fraction_blah_func
|
||||
|
||||
#define fraction_blah_func(op1, op2) \
|
||||
template<typename inttype> \
|
||||
fraction<inttype> &fraction<inttype>::operator op2 (const fraction<inttype> &b) \
|
||||
{ \
|
||||
inttype newnom = nom()*b.denom() op1 denom()*b.nom(); \
|
||||
num2 *= b.denom(); \
|
||||
num1 = newnom; \
|
||||
Optim(); \
|
||||
return *this; \
|
||||
}
|
||||
fraction_blah_func( +, += )
|
||||
fraction_blah_func( -, -= )
|
||||
#undef fraction_blah_func
|
||||
|
||||
template<typename inttype>
|
||||
fraction<inttype> &fraction<inttype>::operator= (long double orig)
|
||||
{
|
||||
if(orig == 0.0)
|
||||
{
|
||||
set(0, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inttype cf[25];
|
||||
for(int maxdepth=1; maxdepth<25; ++maxdepth)
|
||||
{
|
||||
inttype u,v;
|
||||
long double virhe, a=orig;
|
||||
int i, viim;
|
||||
|
||||
for(i = 0; i < maxdepth; ++i)
|
||||
{
|
||||
cf[i] = (inttype)a;
|
||||
if(cf[i]-1 > cf[i])break;
|
||||
a = 1.0 / (a - cf[i]);
|
||||
}
|
||||
|
||||
for(viim=i-1; i < maxdepth; ++i)
|
||||
cf[i] = 0;
|
||||
|
||||
u = cf[viim];
|
||||
v = 1;
|
||||
for(i = viim-1; i >= 0; --i)
|
||||
{
|
||||
inttype w = cf[i] * u + v;
|
||||
v = u;
|
||||
u = w;
|
||||
}
|
||||
|
||||
virhe = (orig - (u / (long double)v)) / orig;
|
||||
|
||||
set(u, v);
|
||||
//if(verbose > 4)
|
||||
// cerr << "Guess: " << *this << " - error = " << virhe*100 << "%\n";
|
||||
|
||||
if(virhe < 1e-8 && virhe > -1e-8)break;
|
||||
}
|
||||
|
||||
//if(verbose > 4)
|
||||
//{
|
||||
// cerr << "Fraction=" << orig << ": " << *this << endl;
|
||||
//}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
template<typename inttype>
|
||||
ostream &operator << (ostream &dest, const fraction<inttype> &m)
|
||||
{
|
||||
if(m.denom() == (inttype)1) return dest << m.nom();
|
||||
return dest << m.nom() << '/' << m.denom();
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
6474
thirdparty/adlmidi/inst_db.cpp
vendored
Normal file
6474
thirdparty/adlmidi/inst_db.cpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
121
thirdparty/adlmidi/oplinst.h
vendored
Normal file
121
thirdparty/adlmidi/oplinst.h
vendored
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPLINST_H
|
||||
#define OPLINST_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
#define OPLINST_BYTE_COMPARABLE(T) \
|
||||
inline bool operator==(const T &a, const T &b) \
|
||||
{ return !memcmp(&a, &b, sizeof(T)); } \
|
||||
inline bool operator!=(const T &a, const T &b) \
|
||||
{ return !operator==(a, b); }
|
||||
|
||||
/**
|
||||
* @brief OPL3 Operator data for single tumbre
|
||||
*/
|
||||
struct OplTimbre
|
||||
{
|
||||
//! WaveForm, Sustain/Release, AttackDecay, and AM/VIB/EG/KSR/F-Mult settings
|
||||
uint32_t modulator_E862, carrier_E862;
|
||||
//! KSL/attenuation settings
|
||||
uint8_t modulator_40, carrier_40;
|
||||
//! Feedback/connection bits for the channel
|
||||
uint8_t feedconn;
|
||||
//! Semi-tone offset
|
||||
int8_t noteOffset;
|
||||
};
|
||||
OPLINST_BYTE_COMPARABLE(struct OplTimbre)
|
||||
|
||||
|
||||
enum { OPLNoteOnMaxTime = 40000 };
|
||||
|
||||
|
||||
/**
|
||||
* @brief Instrument data with operators included
|
||||
*/
|
||||
struct OplInstMeta
|
||||
{
|
||||
enum
|
||||
{
|
||||
Flag_Pseudo4op = 0x01,
|
||||
Flag_NoSound = 0x02,
|
||||
Flag_Real4op = 0x04
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Flag_RM_BassDrum = 0x08,
|
||||
Flag_RM_Snare = 0x10,
|
||||
Flag_RM_TomTom = 0x18,
|
||||
Flag_RM_Cymbal = 0x20,
|
||||
Flag_RM_HiHat = 0x28,
|
||||
Mask_RhythmMode = 0x38
|
||||
};
|
||||
|
||||
//! Operator data
|
||||
OplTimbre op[2];
|
||||
//! Fixed note for drum instruments
|
||||
uint8_t drumTone;
|
||||
//! Instrument flags
|
||||
uint8_t flags;
|
||||
//! Number of milliseconds it produces sound while key on
|
||||
uint16_t soundKeyOnMs;
|
||||
//! Number of milliseconds it produces sound while releasing after key off
|
||||
uint16_t soundKeyOffMs;
|
||||
//! MIDI velocity offset
|
||||
int8_t midiVelocityOffset;
|
||||
//! Second voice detune
|
||||
double voice2_fine_tune;
|
||||
};
|
||||
OPLINST_BYTE_COMPARABLE(struct OplInstMeta)
|
||||
|
||||
#undef OPLINST_BYTE_COMPARABLE
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* @brief Bank global setup
|
||||
*/
|
||||
struct OplBankSetup
|
||||
{
|
||||
int volumeModel;
|
||||
bool deepTremolo;
|
||||
bool deepVibrato;
|
||||
bool scaleModulators;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Convert external instrument to internal instrument
|
||||
*/
|
||||
void cvt_ADLI_to_FMIns(OplInstMeta &dst, const struct ADL_Instrument &src);
|
||||
|
||||
/**
|
||||
* @brief Convert internal instrument to external instrument
|
||||
*/
|
||||
void cvt_FMIns_to_ADLI(struct ADL_Instrument &dst, const OplInstMeta &src);
|
||||
|
||||
#endif // OPLINST_H
|
133
thirdparty/adlmidi/structures/pl_list.hpp
vendored
Normal file
133
thirdparty/adlmidi/structures/pl_list.hpp
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
// Copyright Jean Pierre Cimalando 2018.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef PL_LIST_HPP
|
||||
#define PL_LIST_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <cstddef>
|
||||
|
||||
/*
|
||||
pl_cell: the linked list cell
|
||||
*/
|
||||
template <class T>
|
||||
struct pl_cell;
|
||||
|
||||
template <class T>
|
||||
struct pl_basic_cell
|
||||
{
|
||||
pl_cell<T> *prev, *next;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct pl_cell : pl_basic_cell<T>
|
||||
{
|
||||
T value;
|
||||
};
|
||||
|
||||
/*
|
||||
pl_iterator: the linked list iterator
|
||||
*/
|
||||
template <class Cell>
|
||||
class pl_iterator
|
||||
{
|
||||
public:
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
typedef Cell value_type;
|
||||
typedef Cell &reference;
|
||||
typedef Cell *pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
pl_iterator(Cell *cell = NULL);
|
||||
bool is_end() const;
|
||||
Cell &operator*() const;
|
||||
Cell *operator->() const;
|
||||
bool operator==(const pl_iterator &i) const;
|
||||
bool operator!=(const pl_iterator &i) const;
|
||||
pl_iterator &operator++();
|
||||
pl_iterator operator++(int);
|
||||
pl_iterator &operator--();
|
||||
pl_iterator operator--(int);
|
||||
|
||||
private:
|
||||
Cell *cell_;
|
||||
};
|
||||
|
||||
/*
|
||||
pl_list: the preallocated linked list
|
||||
*/
|
||||
template <class T>
|
||||
class pl_list
|
||||
{
|
||||
public:
|
||||
typedef pl_cell<T> value_type;
|
||||
typedef value_type *pointer;
|
||||
typedef value_type &reference;
|
||||
typedef const value_type *const_pointer;
|
||||
typedef const value_type &const_reference;
|
||||
typedef pl_iterator< pl_cell<T> > iterator;
|
||||
typedef pl_iterator< const pl_cell<T> > const_iterator;
|
||||
|
||||
pl_list(std::size_t capacity = 0);
|
||||
~pl_list();
|
||||
|
||||
struct external_storage_policy {};
|
||||
pl_list(pl_cell<T> *cells, std::size_t ncells, external_storage_policy);
|
||||
|
||||
pl_list(const pl_list &other);
|
||||
pl_list &operator=(const pl_list &other);
|
||||
|
||||
std::size_t size() const;
|
||||
std::size_t capacity() const;
|
||||
bool empty() const;
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
void clear();
|
||||
|
||||
pl_cell<T> &front();
|
||||
const pl_cell<T> &front() const;
|
||||
pl_cell<T> &back();
|
||||
const pl_cell<T> &back() const;
|
||||
|
||||
iterator insert(iterator pos, const T &x);
|
||||
iterator erase(iterator pos);
|
||||
void push_front(const T &x);
|
||||
void push_back(const T &x);
|
||||
void pop_front();
|
||||
void pop_back();
|
||||
|
||||
iterator find(const T &x);
|
||||
const_iterator find(const T &x) const;
|
||||
template <class Pred> iterator find_if(const Pred &p);
|
||||
template <class Pred> const_iterator find_if(const Pred &p) const;
|
||||
|
||||
private:
|
||||
// number of cells in the list
|
||||
std::size_t size_;
|
||||
// number of cells allocated
|
||||
std::size_t capacity_;
|
||||
// array of cells allocated
|
||||
pl_cell<T> *cells_;
|
||||
// pointer to the head cell
|
||||
pl_cell<T> *first_;
|
||||
// pointer to the next free cell
|
||||
pl_cell<T> *free_;
|
||||
// value-less cell which terminates the linked list
|
||||
pl_basic_cell<T> endcell_;
|
||||
// whether cell storage is allocated
|
||||
bool cells_allocd_;
|
||||
|
||||
void initialize(std::size_t capacity, pl_cell<T> *extcells = NULL);
|
||||
pl_cell<T> *allocate(pl_cell<T> *pos);
|
||||
void deallocate(pl_cell<T> *cell);
|
||||
};
|
||||
|
||||
#include "pl_list.tcc"
|
||||
|
||||
#endif // PL_LIST_HPP
|
338
thirdparty/adlmidi/structures/pl_list.tcc
vendored
Normal file
338
thirdparty/adlmidi/structures/pl_list.tcc
vendored
Normal file
|
@ -0,0 +1,338 @@
|
|||
// Copyright Jean Pierre Cimalando 2018.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "pl_list.hpp"
|
||||
|
||||
template <class Cell>
|
||||
pl_iterator<Cell>::pl_iterator(Cell *cell)
|
||||
: cell_(cell)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Cell>
|
||||
bool pl_iterator<Cell>::is_end() const
|
||||
{
|
||||
return cell_->next == NULL;
|
||||
}
|
||||
|
||||
template <class Cell>
|
||||
Cell &pl_iterator<Cell>::operator*() const
|
||||
{
|
||||
return *cell_;
|
||||
}
|
||||
|
||||
template <class Cell>
|
||||
Cell *pl_iterator<Cell>::operator->() const
|
||||
{
|
||||
return cell_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool pl_iterator<T>::operator==(const pl_iterator &i) const
|
||||
{
|
||||
return cell_ == i.cell_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool pl_iterator<T>::operator!=(const pl_iterator &i) const
|
||||
{
|
||||
return cell_ != i.cell_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_iterator<T> &pl_iterator<T>::operator++()
|
||||
{
|
||||
cell_ = cell_->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_iterator<T> pl_iterator<T>::operator++(int)
|
||||
{
|
||||
pl_iterator i(cell_);
|
||||
cell_ = cell_->next;
|
||||
return i;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_iterator<T> &pl_iterator<T>::operator--()
|
||||
{
|
||||
cell_ = cell_->prev;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_iterator<T> pl_iterator<T>::operator--(int)
|
||||
{
|
||||
pl_iterator i(cell_);
|
||||
cell_ = cell_->prev;
|
||||
return i;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_list<T>::pl_list(std::size_t capacity)
|
||||
{
|
||||
initialize(capacity);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_list<T>::~pl_list()
|
||||
{
|
||||
if (cells_allocd_)
|
||||
delete[] cells_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_list<T>::pl_list(pl_cell<T> *cells, std::size_t ncells, external_storage_policy)
|
||||
{
|
||||
initialize(ncells, cells);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_list<T>::pl_list(const pl_list &other)
|
||||
{
|
||||
initialize(other.capacity());
|
||||
for(const_iterator i = other.end(), b = other.begin(); i-- != b;)
|
||||
push_front(i->value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_list<T> &pl_list<T>::operator=(const pl_list &other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
std::size_t size = other.size();
|
||||
if(size > capacity())
|
||||
{
|
||||
pl_cell<T> *oldcells = cells_;
|
||||
bool allocd = cells_allocd_;
|
||||
initialize(other.capacity());
|
||||
if (allocd)
|
||||
delete[] oldcells;
|
||||
}
|
||||
clear();
|
||||
for(const_iterator i = other.end(), b = other.begin(); i-- != b;)
|
||||
push_front(i->value);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t pl_list<T>::size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t pl_list<T>::capacity() const
|
||||
{
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool pl_list<T>::empty() const
|
||||
{
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename pl_list<T>::iterator pl_list<T>::begin()
|
||||
{
|
||||
return iterator(first_);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename pl_list<T>::iterator pl_list<T>::end()
|
||||
{
|
||||
return iterator(reinterpret_cast<pl_cell<T> *>(&endcell_));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename pl_list<T>::const_iterator pl_list<T>::begin() const
|
||||
{
|
||||
return const_iterator(first_);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename pl_list<T>::const_iterator pl_list<T>::end() const
|
||||
{
|
||||
return const_iterator(reinterpret_cast<const pl_cell<T> *>(&endcell_));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void pl_list<T>::clear()
|
||||
{
|
||||
std::size_t capacity = capacity_;
|
||||
pl_cell<T> *cells = cells_;
|
||||
pl_cell<T> *endcell = &*end();
|
||||
size_ = 0;
|
||||
first_ = endcell;
|
||||
free_ = cells;
|
||||
endcell->prev = NULL;
|
||||
for(std::size_t i = 0; i < capacity; ++i)
|
||||
{
|
||||
cells[i].prev = (i > 0) ? &cells[i - 1] : NULL;
|
||||
cells[i].next = (i + 1 < capacity) ? &cells[i + 1] : NULL;
|
||||
cells[i].value = T();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_cell<T> &pl_list<T>::front()
|
||||
{
|
||||
return *first_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const pl_cell<T> &pl_list<T>::front() const
|
||||
{
|
||||
return *first_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_cell<T> &pl_list<T>::back()
|
||||
{
|
||||
iterator i = end();
|
||||
return *--i;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const pl_cell<T> &pl_list<T>::back() const
|
||||
{
|
||||
const_iterator i = end();
|
||||
return *--i;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename pl_list<T>::iterator pl_list<T>::insert(iterator pos, const T &x)
|
||||
{
|
||||
pl_cell<T> *cell = allocate(&*pos);
|
||||
if (!cell)
|
||||
throw std::bad_alloc();
|
||||
cell->value = x;
|
||||
return iterator(cell);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename pl_list<T>::iterator pl_list<T>::erase(iterator pos)
|
||||
{
|
||||
deallocate(&*(pos++));
|
||||
return pos;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void pl_list<T>::push_front(const T &x)
|
||||
{
|
||||
insert(begin(), x);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void pl_list<T>::push_back(const T &x)
|
||||
{
|
||||
insert(end(), x);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void pl_list<T>::pop_front()
|
||||
{
|
||||
deallocate(first_);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void pl_list<T>::pop_back()
|
||||
{
|
||||
iterator i(&*end());
|
||||
deallocate(&*--i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename pl_list<T>::iterator pl_list<T>::find(const T &x)
|
||||
{
|
||||
const_iterator i = const_cast<const pl_list<T> *>(this)->find(x);
|
||||
return iterator(&const_cast<reference>(*i));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename pl_list<T>::const_iterator pl_list<T>::find(const T &x) const
|
||||
{
|
||||
const_iterator e = end();
|
||||
for (const_iterator i = begin(); i != e; ++i)
|
||||
{
|
||||
if(i->value == x)
|
||||
return i;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class Pred>
|
||||
typename pl_list<T>::iterator pl_list<T>::find_if(const Pred &p)
|
||||
{
|
||||
const_iterator i = const_cast<const pl_list<T> *>(this)->find_if(p);
|
||||
return iterator(&const_cast<reference>(*i));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class Pred>
|
||||
typename pl_list<T>::const_iterator pl_list<T>::find_if(const Pred &p) const
|
||||
{
|
||||
const_iterator e = end();
|
||||
for (const_iterator i = begin(); i != e; ++i)
|
||||
{
|
||||
if(p(i->value))
|
||||
return i;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void pl_list<T>::initialize(std::size_t capacity, pl_cell<T> *extcells)
|
||||
{
|
||||
cells_ = extcells ? extcells : new pl_cell<T>[capacity];
|
||||
cells_allocd_ = extcells ? false : true;
|
||||
capacity_ = capacity;
|
||||
endcell_.next = NULL;
|
||||
clear();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
pl_cell<T> *pl_list<T>::allocate(pl_cell<T> *pos)
|
||||
{
|
||||
// remove free cells front
|
||||
pl_cell<T> *cell = free_;
|
||||
if(!cell)
|
||||
return NULL;
|
||||
free_ = cell->next;
|
||||
if(free_)
|
||||
free_->prev = NULL;
|
||||
|
||||
// insert at position
|
||||
if (pos == first_)
|
||||
first_ = cell;
|
||||
cell->prev = pos->prev;
|
||||
if (cell->prev)
|
||||
cell->prev->next = cell;
|
||||
cell->next = pos;
|
||||
pos->prev = cell;
|
||||
|
||||
++size_;
|
||||
return cell;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void pl_list<T>::deallocate(pl_cell<T> *cell)
|
||||
{
|
||||
if(cell->prev)
|
||||
cell->prev->next = cell->next;
|
||||
if(cell->next)
|
||||
cell->next->prev = cell->prev;
|
||||
if(cell == first_)
|
||||
first_ = cell->next;
|
||||
cell->prev = NULL;
|
||||
cell->next = free_;
|
||||
cell->value = T();
|
||||
free_ = cell;
|
||||
--size_;
|
||||
}
|
39
thirdparty/adlmidi/wopl/wopl_file.c
vendored
39
thirdparty/adlmidi/wopl/wopl_file.c
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Wohlstand's OPL3 Bank File - a bank format to store OPL3 timbre data and setup
|
||||
*
|
||||
* Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* Copyright (c) 2015-2020 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"),
|
||||
|
@ -77,18 +77,30 @@ static void fromSint16BE(int16_t in, uint8_t *arr)
|
|||
|
||||
WOPLFile *WOPL_Init(uint16_t melodic_banks, uint16_t percussive_banks)
|
||||
{
|
||||
WOPLFile *file = NULL;
|
||||
if(melodic_banks == 0)
|
||||
return NULL;
|
||||
if(percussive_banks == 0)
|
||||
return NULL;
|
||||
file = (WOPLFile*)calloc(1, sizeof(WOPLFile));
|
||||
WOPLFile *file = (WOPLFile*)calloc(1, sizeof(WOPLFile));
|
||||
if(!file)
|
||||
return NULL;
|
||||
file->banks_count_melodic = melodic_banks;
|
||||
file->banks_count_percussion = percussive_banks;
|
||||
file->banks_melodic = (WOPLBank*)calloc(1, sizeof(WOPLBank) * melodic_banks );
|
||||
file->banks_percussive = (WOPLBank*)calloc(1, sizeof(WOPLBank) * percussive_banks );
|
||||
|
||||
file->banks_count_melodic = (melodic_banks != 0) ? melodic_banks : 1;
|
||||
file->banks_melodic = (WOPLBank*)calloc(file->banks_count_melodic, sizeof(WOPLBank));
|
||||
|
||||
if(melodic_banks == 0)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < 128; ++i)
|
||||
file->banks_melodic[0].ins[i].inst_flags = WOPL_Ins_IsBlank;
|
||||
}
|
||||
|
||||
file->banks_count_percussion = (percussive_banks != 0) ? percussive_banks : 1;
|
||||
file->banks_percussive = (WOPLBank*)calloc(file->banks_count_percussion, sizeof(WOPLBank));
|
||||
|
||||
if(percussive_banks == 0)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < 128; ++i)
|
||||
file->banks_percussive[0].ins[i].inst_flags = WOPL_Ins_IsBlank;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
@ -161,7 +173,8 @@ static void WOPL_parseInstrument(WOPLInstrument *ins, uint8_t *cursor, uint16_t
|
|||
static void WOPL_writeInstrument(WOPLInstrument *ins, uint8_t *cursor, uint16_t version, uint8_t has_sounding_delays)
|
||||
{
|
||||
int l;
|
||||
strncpy((char*)cursor, ins->inst_name, 32);
|
||||
memcpy((char*)cursor, ins->inst_name, 32);
|
||||
cursor[32] = '\0';
|
||||
fromSint16BE(ins->note_offset1, cursor + 32);
|
||||
fromSint16BE(ins->note_offset2, cursor + 34);
|
||||
cursor[36] = (uint8_t)ins->midi_velocity_offset;
|
||||
|
@ -266,7 +279,7 @@ WOPLFile *WOPL_LoadBankFromMem(void *mem, size_t length, int *error)
|
|||
outFile->version = version;
|
||||
outFile->opl_flags = head[4];
|
||||
outFile->volume_model = head[5];
|
||||
}
|
||||
}
|
||||
|
||||
bankslots_sizes[0] = count_melodic_banks;
|
||||
bankslots[0] = outFile->banks_melodic;
|
||||
|
|
23
thirdparty/adlmidi/wopl/wopl_file.h
vendored
23
thirdparty/adlmidi/wopl/wopl_file.h
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Wohlstand's OPL3 Bank File - a bank format to store OPL3 timbre data and setup
|
||||
*
|
||||
* Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* Copyright (c) 2015-2020 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"),
|
||||
|
@ -56,7 +56,12 @@ typedef enum WOPL_VolumeModel
|
|||
WOPL_VM_Native,
|
||||
WOPL_VM_DMX,
|
||||
WOPL_VM_Apogee,
|
||||
WOPL_VM_Win9x
|
||||
WOPL_VM_Win9x,
|
||||
WOPL_VM_DMX_Fixed,
|
||||
WOPL_VM_Apogee_Fixed,
|
||||
WOPL_VM_AIL,
|
||||
WOPL_VM_Win9x_GenericFM,
|
||||
WOPL_VM_HMI
|
||||
} WOPL_VolumeModel;
|
||||
|
||||
typedef enum WOPL_InstrumentFlags
|
||||
|
@ -242,7 +247,7 @@ extern WOPLFile *WOPL_LoadBankFromMem(void *mem, size_t length, int *error);
|
|||
/**
|
||||
* @brief Load WOPI instrument file from the memory.
|
||||
* You must allocate WOPIFile structure by yourself and give the pointer to it.
|
||||
* @param file Pointer to destinition WOPIFile structure to fill it with parsed data.
|
||||
* @param file Pointer to destination WOPIFile structure to fill it with parsed data.
|
||||
* @param mem Pointer to memory block contains raw WOPI instrument file data
|
||||
* @param length Length of given memory block
|
||||
* @return 0 if no errors occouped, or an error code of WOPL_ErrorCodes enumeration
|
||||
|
@ -252,7 +257,7 @@ extern int WOPL_LoadInstFromMem(WOPIFile *file, void *mem, size_t length);
|
|||
/**
|
||||
* @brief Calculate the size of the output memory block
|
||||
* @param file Heap-allocated WOPL file data structure
|
||||
* @param version Destinition version of the file
|
||||
* @param version Destination version of the file
|
||||
* @return Size of the raw WOPL file data
|
||||
*/
|
||||
extern size_t WOPL_CalculateBankFileSize(WOPLFile *file, uint16_t version);
|
||||
|
@ -260,7 +265,7 @@ extern size_t WOPL_CalculateBankFileSize(WOPLFile *file, uint16_t version);
|
|||
/**
|
||||
* @brief Calculate the size of the output memory block
|
||||
* @param file Pointer to WOPI file data structure
|
||||
* @param version Destinition version of the file
|
||||
* @param version Destination version of the file
|
||||
* @return Size of the raw WOPI file data
|
||||
*/
|
||||
extern size_t WOPL_CalculateInstFileSize(WOPIFile *file, uint16_t version);
|
||||
|
@ -268,8 +273,8 @@ extern size_t WOPL_CalculateInstFileSize(WOPIFile *file, uint16_t version);
|
|||
/**
|
||||
* @brief Write raw WOPL into given memory block
|
||||
* @param file Heap-allocated WOPL file data structure
|
||||
* @param dest_mem Destinition memory block pointer
|
||||
* @param length Length of destinition memory block
|
||||
* @param dest_mem Destination memory block pointer
|
||||
* @param length Length of destination memory block
|
||||
* @param version Wanted WOPL version
|
||||
* @param force_gm Force GM set in saved bank file
|
||||
* @return Error code or 0 on success
|
||||
|
@ -279,8 +284,8 @@ extern int WOPL_SaveBankToMem(WOPLFile *file, void *dest_mem, size_t length, uin
|
|||
/**
|
||||
* @brief Write raw WOPI into given memory block
|
||||
* @param file Pointer to WOPI file data structure
|
||||
* @param dest_mem Destinition memory block pointer
|
||||
* @param length Length of destinition memory block
|
||||
* @param dest_mem Destination memory block pointer
|
||||
* @param length Length of destination memory block
|
||||
* @param version Wanted WOPI version
|
||||
* @return Error code or 0 on success
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue