libADLMIDI: Apply the set of recent bugfixes

This commit is contained in:
Wohlstand 2020-10-15 13:40:09 +03:00
parent d97ec56b8e
commit 2d5fa2bba6
16 changed files with 160 additions and 176 deletions

View file

@ -6,18 +6,18 @@ use_fast_math()
add_definitions(-DADLMIDI_DISABLE_MIDI_SEQUENCER)
add_library( adl STATIC
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/java_opl3.cpp
chips/nuked_opl3.cpp
chips/nuked_opl3_v174.cpp
chips/opal_opl3.cpp
inst_db.cpp
chips/nuked/nukedopl3_174.c
chips/nuked/nukedopl3.c
wopl/wopl_file.c

View file

@ -403,14 +403,16 @@ static inline double s_dmxFreq(double tone)
int_fast32_t oct = 0;
int_fast32_t freqIndex = (noteI << 5) + bendI;
#define MAX_FREQ_IDX 283 // 284 - with the DMX side bug
if(freqIndex < 0)
freqIndex = 0;
else if(freqIndex >= 284)
else if(freqIndex >= MAX_FREQ_IDX)
{
freqIndex -= 284;
freqIndex -= MAX_FREQ_IDX;
oct = freqIndex / 384;
freqIndex = (freqIndex % 384) + 284;
freqIndex = (freqIndex % 384) + MAX_FREQ_IDX;
}
#undef MAX_FREQ_IDX
outHz = s_dmx_freq_table[freqIndex];

View file

@ -1,160 +0,0 @@
/*
* 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 */

View file

@ -0,0 +1,110 @@
/*
* 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 MY_PTR_HPP_THING
#define MY_PTR_HPP_THING
#include <stddef.h>
#include <stdlib.h>
/*
Generic deleters for smart pointers
*/
template <class T>
struct My_DefaultDelete
{
void operator()(T *x) { delete x; }
};
template <class T>
struct My_DefaultArrayDelete
{
void operator()(T *x) { delete[] x; }
};
struct My_CDelete
{
void operator()(void *x) { free(x); }
};
/*
Safe unique pointer for C++98, non-copyable but swappable.
*/
template< class T, class Deleter = My_DefaultDelete<T> >
class My_UPtr
{
T *m_p;
public:
explicit My_UPtr(T *p = NULL)
: m_p(p) {}
~My_UPtr()
{
reset();
}
void reset(T *p = NULL)
{
if(p != m_p)
{
if(m_p)
{
Deleter del;
del(m_p);
}
m_p = p;
}
}
T *get() const
{
return m_p;
}
T *release()
{
T *ret = m_p;
m_p = NULL;
return ret;
}
T &operator*() const
{
return *m_p;
}
T *operator->() const
{
return m_p;
}
T &operator[](size_t index) const
{
return m_p[index];
}
private:
My_UPtr(const My_UPtr &);
My_UPtr &operator=(const My_UPtr &);
};
#endif // MY_PTR_HPP_THING

View file

@ -41,6 +41,7 @@
#include <memory>
#include "dbopl.h"
#include "../common/mutex.hpp"
#include "../common/ptr.hpp"
#if defined(__GNUC__) && __GNUC__ > 3
#define INLINE inline __attribute__((__always_inline__))
@ -1353,11 +1354,7 @@ static const CacheEntry &ComputeRateDependent( Bit32u rate )
double original = OPLRATE;
double scale = original / (double)rate;
#if __cplusplus >= 201103L
std::unique_ptr<CacheEntry> entry(new CacheEntry);
#else
std::auto_ptr<CacheEntry> entry(new CacheEntry);
#endif
My_UPtr<CacheEntry> entry(new CacheEntry);
entry->rate = rate;
Bit32u *freqMul = entry->freqMul;
Bit32u *linearRates = entry->linearRates;
@ -1438,8 +1435,8 @@ static const CacheEntry &ComputeRateDependent( Bit32u rate )
}
MutexHolder lock( cache.mutex );
if (const CacheEntry *entry = CacheLookupRateDependent( rate ))
return *entry;
if (const CacheEntry *e = CacheLookupRateDependent( rate ))
return *e;
cache.entries.push_back(entry.get());
return *entry.release();

View file

@ -83,3 +83,8 @@ const char *DosBoxOPL3::emulatorName()
{
return "DOSBox 0.74-r4111 OPL3";
}
OPLChipBase::ChipType DosBoxOPL3::chipType()
{
return CHIPTYPE_OPL3;
}

View file

@ -41,6 +41,7 @@ public:
void nativePostGenerate() override {}
void nativeGenerateN(int16_t *output, size_t frames) override;
const char *emulatorName() override;
ChipType chipType() override;
};
#endif // DOSBOX_OPL3_H

View file

@ -110,3 +110,8 @@ const char *JavaOPL3::emulatorName()
{
return "Java 1.0.6 OPL3";
}
OPLChipBase::ChipType JavaOPL3::chipType()
{
return CHIPTYPE_OPL3;
}

View file

@ -39,6 +39,7 @@ public:
void nativePostGenerate() override {}
void nativeGenerateN(int16_t *output, size_t frames) override;
const char *emulatorName() override;
ChipType chipType() override;
};
#endif // JAVA_OPL3_H

View file

@ -73,3 +73,8 @@ const char *NukedOPL3::emulatorName()
{
return "Nuked OPL3 (v 1.8)";
}
OPLChipBase::ChipType NukedOPL3::chipType()
{
return CHIPTYPE_OPL3;
}

View file

@ -39,6 +39,7 @@ public:
void nativePostGenerate() override {}
void nativeGenerate(int16_t *frame) override;
const char *emulatorName() override;
ChipType chipType() override;
};
#endif // NUKED_OPL3_H

View file

@ -73,3 +73,8 @@ const char *NukedOPL3v174::emulatorName()
{
return "Nuked OPL3 (v 1.7.4)";
}
OPLChipBase::ChipType NukedOPL3v174::chipType()
{
return CHIPTYPE_OPL3;
}

View file

@ -39,6 +39,7 @@ public:
void nativePostGenerate() override {}
void nativeGenerate(int16_t *frame) override;
const char *emulatorName() override;
ChipType chipType() override;
};
#endif // NUKED_OPL3174_H

View file

@ -79,3 +79,8 @@ const char *OpalOPL3::emulatorName()
{
return "Opal OPL3";
}
OPLChipBase::ChipType OpalOPL3::chipType()
{
return CHIPTYPE_OPL3;
}

View file

@ -39,6 +39,7 @@ public:
void nativePostGenerate() override {}
void nativeGenerate(int16_t *frame) override;
const char *emulatorName() override;
ChipType chipType() override;
};
#endif // NUKED_OPL3_H

View file

@ -39,6 +39,10 @@ class OPLChipBase
{
public:
enum { nativeRate = 49716 };
enum ChipType
{
CHIPTYPE_OPL3 = 0, CHIPTYPE_OPL2 = 1
};
protected:
uint32_t m_id;
uint32_t m_rate;
@ -74,6 +78,7 @@ public:
virtual void generateAndMix32(int32_t *output, size_t frames) = 0;
virtual const char* emulatorName() = 0;
virtual ChipType chipType() = 0;
private:
OPLChipBase(const OPLChipBase &c);
OPLChipBase &operator=(const OPLChipBase &c);