mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 15:22:15 +00:00
- removed all ZDoom dependencies from the OPL backend code.
This commit is contained in:
parent
2aa03e8e8a
commit
17eac1c57b
12 changed files with 286 additions and 41 deletions
|
@ -140,6 +140,18 @@ protected:
|
||||||
|
|
||||||
// OPL dumper implementation of a MIDI output device ------------------------
|
// OPL dumper implementation of a MIDI output device ------------------------
|
||||||
|
|
||||||
|
struct DiskWriterIO : public OPLio
|
||||||
|
{
|
||||||
|
DiskWriterIO(const char* filename);
|
||||||
|
~DiskWriterIO();
|
||||||
|
|
||||||
|
int Init(uint32_t numchips, bool notused, bool initopl3);
|
||||||
|
void SetClockRate(double samples_per_tick);
|
||||||
|
void WriteDelay(int ticks);
|
||||||
|
|
||||||
|
FString Filename;
|
||||||
|
};
|
||||||
|
|
||||||
class OPLDumperMIDIDevice : public OPLMIDIDevice
|
class OPLDumperMIDIDevice : public OPLMIDIDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -45,15 +45,13 @@
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "doomtype.h"
|
|
||||||
#include "opl.h"
|
#include "opl.h"
|
||||||
#include "m_random.h"
|
#include "opl3_Float.h"
|
||||||
#include "xs_Float.h"
|
|
||||||
|
|
||||||
static FRandom pr_opl3;
|
|
||||||
|
|
||||||
#define VOLUME_MUL 0.3333
|
#define VOLUME_MUL 0.3333
|
||||||
|
|
||||||
|
static const double OPL_PI = 3.14159265358979323846; // matches value in gcc v2 math.h
|
||||||
|
|
||||||
namespace JavaOPL3
|
namespace JavaOPL3
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1645,7 +1643,8 @@ double HighHatOperator::getOperatorOutput(OPL3 *OPL3, double modulator) {
|
||||||
// Top Cymbal, so we use the parent method and modify its output
|
// Top Cymbal, so we use the parent method and modify its output
|
||||||
// accordingly afterwards.
|
// accordingly afterwards.
|
||||||
double operatorOutput = TopCymbalOperator::getOperatorOutput(OPL3, modulator, topCymbalOperatorPhase);
|
double operatorOutput = TopCymbalOperator::getOperatorOutput(OPL3, modulator, topCymbalOperatorPhase);
|
||||||
if(operatorOutput == 0) operatorOutput = pr_opl3.GenRand_Real1()*envelope;
|
double randval = rand() / (double)RAND_MAX;
|
||||||
|
if(operatorOutput == 0) operatorOutput = randval*envelope;
|
||||||
return operatorOutput;
|
return operatorOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1667,7 +1666,8 @@ double SnareDrumOperator::getOperatorOutput(OPL3 *OPL3, double modulator) {
|
||||||
|
|
||||||
double operatorOutput = getOutput(modulator, phase, waveform);
|
double operatorOutput = getOutput(modulator, phase, waveform);
|
||||||
|
|
||||||
double noise = pr_opl3.GenRand_Real1() * envelope;
|
double randval = rand() / (double)RAND_MAX;
|
||||||
|
double noise = randval * envelope;
|
||||||
|
|
||||||
if(operatorOutput/envelope != 1 && operatorOutput/envelope != -1) {
|
if(operatorOutput/envelope != 1 && operatorOutput/envelope != -1) {
|
||||||
if(operatorOutput > 0) operatorOutput = noise;
|
if(operatorOutput > 0) operatorOutput = noise;
|
||||||
|
@ -1777,7 +1777,7 @@ void OPL3DataStruct::loadTremoloTable()
|
||||||
void OperatorDataStruct::loadWaveforms() {
|
void OperatorDataStruct::loadWaveforms() {
|
||||||
int i;
|
int i;
|
||||||
// 1st waveform: sinusoid.
|
// 1st waveform: sinusoid.
|
||||||
double theta = 0, thetaIncrement = 2*M_PI / 1024;
|
double theta = 0, thetaIncrement = 2*OPL_PI / 1024;
|
||||||
|
|
||||||
for(i=0, theta=0; i<1024; i++, theta += thetaIncrement)
|
for(i=0, theta=0; i<1024; i++, theta += thetaIncrement)
|
||||||
waveforms[0][i] = sin(theta);
|
waveforms[0][i] = sin(theta);
|
||||||
|
|
|
@ -24,12 +24,8 @@
|
||||||
* Ken Silverman's official web site: "http://www.advsys.net/ken"
|
* Ken Silverman's official web site: "http://www.advsys.net/ken"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "doomtype.h"
|
|
||||||
#include "../opl.h"
|
#include "../opl.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "m_random.h"
|
|
||||||
|
|
||||||
static FRandom pr_opl;
|
|
||||||
|
|
||||||
typedef uintptr_t Bitu;
|
typedef uintptr_t Bitu;
|
||||||
typedef intptr_t Bits;
|
typedef intptr_t Bits;
|
||||||
|
@ -153,7 +149,7 @@ void operator_advance_drums(op_type* op_pt1, Bit32s vib1, op_type* op_pt2, Bit32
|
||||||
Bit32u c3 = op_pt3->tcount/FIXEDPT;
|
Bit32u c3 = op_pt3->tcount/FIXEDPT;
|
||||||
Bit32u phasebit = (((c1 & 0x88) ^ ((c1<<5) & 0x80)) | ((c3 ^ (c3<<2)) & 0x20)) ? 0x02 : 0x00;
|
Bit32u phasebit = (((c1 & 0x88) ^ ((c1<<5) & 0x80)) | ((c3 ^ (c3<<2)) & 0x20)) ? 0x02 : 0x00;
|
||||||
|
|
||||||
Bit32u noisebit = pr_opl.GenRand32() & 1;
|
Bit32u noisebit = rand() & 1;
|
||||||
|
|
||||||
Bit32u snare_phase_bit = (Bit32u)(((Bitu)((op_pt1->tcount/FIXEDPT) / 0x100))&1);
|
Bit32u snare_phase_bit = (Bit32u)(((Bitu)((op_pt1->tcount/FIXEDPT) / 0x100))&1);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,16 @@
|
||||||
#include "doomtype.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
// With versions of GCC newer than 4.2, it appears it was determined that the
|
||||||
|
// cost of an unaligned pointer on PPC was high enough to add padding to the
|
||||||
|
// end of packed structs. For whatever reason __packed__ and pragma pack are
|
||||||
|
// handled differently in this regard. Note that this only needs to be applied
|
||||||
|
// to types which are used in arrays or sizeof is needed. This also prevents
|
||||||
|
// code from taking references to the struct members.
|
||||||
|
#define FORCE_PACKED __attribute__((__packed__))
|
||||||
|
#else
|
||||||
|
#define FORCE_PACKED
|
||||||
|
#endif
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct genmidi_op_t
|
struct genmidi_op_t
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "musicblock.h"
|
#include "musicblock.h"
|
||||||
|
|
||||||
#include "c_cvars.h"
|
|
||||||
|
|
||||||
musicBlock::musicBlock ()
|
musicBlock::musicBlock ()
|
||||||
{
|
{
|
||||||
memset (this, 0, sizeof(*this));
|
memset (this, 0, sizeof(*this));
|
||||||
|
@ -186,7 +184,7 @@ void musicBlock::voiceKeyOn(uint32_t slot, uint32_t channo, GenMidiInstrument *i
|
||||||
//
|
//
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
CVAR(Bool, opl_singlevoice, 0, 0)
|
bool opl_singlevoice;
|
||||||
|
|
||||||
void musicBlock::noteOn(uint32_t channel, uint8_t key, int volume)
|
void musicBlock::noteOn(uint32_t channel, uint8_t key, int volume)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "doomtype.h"
|
#include <stdint.h>
|
||||||
#include "genmidi.h"
|
#include "genmidi.h"
|
||||||
#include "oplio.h"
|
#include "oplio.h"
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef OPL_H
|
#ifndef OPL_H
|
||||||
#define OPL_H
|
#define OPL_H
|
||||||
|
|
||||||
#include "zstring.h"
|
|
||||||
|
|
||||||
// Abstract base class for OPL emulators
|
// Abstract base class for OPL emulators
|
||||||
|
|
||||||
class OPLEmul
|
class OPLEmul
|
||||||
|
|
238
src/sound/oplsynth/opl3_Float.h
Normal file
238
src/sound/oplsynth/opl3_Float.h
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
// ====================================================================================================================
|
||||||
|
// ====================================================================================================================
|
||||||
|
// xs_Float.h
|
||||||
|
//
|
||||||
|
// Source: "Know Your FPU: Fixing Floating Fast"
|
||||||
|
// http://www.stereopsis.com/sree/fpu2006.html
|
||||||
|
//
|
||||||
|
// xs_CRoundToInt: Round toward nearest, but ties round toward even (just like FISTP)
|
||||||
|
// xs_ToInt: Round toward zero, just like the C (int) cast
|
||||||
|
// xs_FloorToInt: Round down
|
||||||
|
// xs_CeilToInt: Round up
|
||||||
|
// xs_RoundToInt: Round toward nearest, but ties round up
|
||||||
|
// ====================================================================================================================
|
||||||
|
// ====================================================================================================================
|
||||||
|
#ifndef _xs_FLOAT_H_
|
||||||
|
#define _xs_FLOAT_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
// Defines
|
||||||
|
// ====================================================================================================================
|
||||||
|
#ifndef _xs_DEFAULT_CONVERSION
|
||||||
|
#define _xs_DEFAULT_CONVERSION 0
|
||||||
|
#endif //_xs_DEFAULT_CONVERSION
|
||||||
|
|
||||||
|
|
||||||
|
#if __BIG_ENDIAN__
|
||||||
|
#define _xs_iexp_ 0
|
||||||
|
#define _xs_iman_ 1
|
||||||
|
#else
|
||||||
|
#define _xs_iexp_ 1 //intel is little endian
|
||||||
|
#define _xs_iman_ 0
|
||||||
|
#endif //BigEndian_
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define finline inline
|
||||||
|
#else
|
||||||
|
#define finline __forceinline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef double real64;
|
||||||
|
|
||||||
|
|
||||||
|
union _xs_doubleints
|
||||||
|
{
|
||||||
|
real64 val;
|
||||||
|
uint32_t ival[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define _xs_doublecopysgn(a,b) ((int32_t*)&a)[_xs_iexp_]&=~(((int32_t*)&b)[_xs_iexp_]&0x80000000)
|
||||||
|
#define _xs_doubleisnegative(a) ((((int32_t*)&a)[_xs_iexp_])|0x80000000)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
// Constants
|
||||||
|
// ====================================================================================================================
|
||||||
|
const real64 _xs_doublemagic = real64 (6755399441055744.0); //2^52 * 1.5, uses limited precisicion to floor
|
||||||
|
const real64 _xs_doublemagicdelta = (1.5e-8); //almost .5f = .5f + 1e^(number of exp bit)
|
||||||
|
const real64 _xs_doublemagicroundeps = (.5f-_xs_doublemagicdelta); //almost .5f = .5f - 1e^(number of exp bit)
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
// Prototypes
|
||||||
|
// ====================================================================================================================
|
||||||
|
static int32_t xs_CRoundToInt (real64 val, real64 dmr = _xs_doublemagic);
|
||||||
|
static int32_t xs_ToInt (real64 val, real64 dme = -_xs_doublemagicroundeps);
|
||||||
|
static int32_t xs_FloorToInt (real64 val, real64 dme = _xs_doublemagicroundeps);
|
||||||
|
static int32_t xs_CeilToInt (real64 val, real64 dme = _xs_doublemagicroundeps);
|
||||||
|
static int32_t xs_RoundToInt (real64 val);
|
||||||
|
|
||||||
|
//int32_t versions
|
||||||
|
finline static int32_t xs_CRoundToInt (int32_t val) {return val;}
|
||||||
|
finline static int32_t xs_ToInt (int32_t val) {return val;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
// Fix Class
|
||||||
|
// ====================================================================================================================
|
||||||
|
template <int32_t N> class xs_Fix
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int32_t Fix;
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
// Basic Conversion from Numbers
|
||||||
|
// ====================================================================================================================
|
||||||
|
finline static Fix ToFix (int32_t val) {return val<<N;}
|
||||||
|
finline static Fix ToFix (real64 val) {return xs_ConvertToFixed(val);}
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
// Basic Conversion to Numbers
|
||||||
|
// ====================================================================================================================
|
||||||
|
finline static real64 ToReal (Fix f) {return real64(f)/real64(1<<N);}
|
||||||
|
finline static int32_t ToInt (Fix f) {return f>>N;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// ====================================================================================================================
|
||||||
|
// Helper function - mainly to preserve _xs_DEFAULT_CONVERSION
|
||||||
|
// ====================================================================================================================
|
||||||
|
finline static int32_t xs_ConvertToFixed (real64 val)
|
||||||
|
{
|
||||||
|
#if _xs_DEFAULT_CONVERSION==0
|
||||||
|
return xs_CRoundToInt(val, _xs_doublemagic/(1<<N));
|
||||||
|
#else
|
||||||
|
return (long)((val)*(1<<N));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
finline static int32_t xs_ToFixed(int32_t n, real64 val)
|
||||||
|
{
|
||||||
|
#if _xs_DEFAULT_CONVERSION==0
|
||||||
|
return xs_CRoundToInt(val, _xs_doublemagic/(1<<n));
|
||||||
|
#else
|
||||||
|
return (long)((val)*(1<<N));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
// ====================================================================================================================
|
||||||
|
// Inline implementation
|
||||||
|
// ====================================================================================================================
|
||||||
|
// ====================================================================================================================
|
||||||
|
finline static int32_t xs_CRoundToInt(real64 val, real64 dmr)
|
||||||
|
{
|
||||||
|
#if _xs_DEFAULT_CONVERSION==0
|
||||||
|
_xs_doubleints uval;
|
||||||
|
uval.val = val + dmr;
|
||||||
|
return uval.ival[_xs_iman_];
|
||||||
|
#else
|
||||||
|
return int32_t(floor(val+.5));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
finline static int32_t xs_ToInt(real64 val, real64 dme)
|
||||||
|
{
|
||||||
|
/* unused - something else I tried...
|
||||||
|
_xs_doublecopysgn(dme,val);
|
||||||
|
return xs_CRoundToInt(val+dme);
|
||||||
|
return 0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1400
|
||||||
|
// VC++ 2005's standard cast is a little bit faster than this
|
||||||
|
// magic number code. (Which is pretty amazing!) SSE has the
|
||||||
|
// fastest C-style float->int conversion, but unfortunately,
|
||||||
|
// checking for SSE support every time you need to do a
|
||||||
|
// conversion completely negates its performance advantage.
|
||||||
|
return int32_t(val);
|
||||||
|
#else
|
||||||
|
#if _xs_DEFAULT_CONVERSION==0
|
||||||
|
return (val<0) ? xs_CRoundToInt(val-dme) :
|
||||||
|
xs_CRoundToInt(val+dme);
|
||||||
|
#else
|
||||||
|
return int32_t(val);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
finline static int32_t xs_FloorToInt(real64 val, real64 dme)
|
||||||
|
{
|
||||||
|
#if _xs_DEFAULT_CONVERSION==0
|
||||||
|
return xs_CRoundToInt (val - dme);
|
||||||
|
#else
|
||||||
|
return floor(val);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
finline static int32_t xs_CeilToInt(real64 val, real64 dme)
|
||||||
|
{
|
||||||
|
#if _xs_DEFAULT_CONVERSION==0
|
||||||
|
return xs_CRoundToInt (val + dme);
|
||||||
|
#else
|
||||||
|
return ceil(val);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
finline static int32_t xs_RoundToInt(real64 val)
|
||||||
|
{
|
||||||
|
#if _xs_DEFAULT_CONVERSION==0
|
||||||
|
// Yes, it is important that two fadds be generated, so you cannot override the dmr
|
||||||
|
// passed to xs_CRoundToInt with _xs_doublemagic + _xs_doublemagicdelta. If you do,
|
||||||
|
// you'll end up with Banker's Rounding again.
|
||||||
|
return xs_CRoundToInt (val + _xs_doublemagicdelta);
|
||||||
|
#else
|
||||||
|
return floor(val+.5);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
// ====================================================================================================================
|
||||||
|
// Unsigned variants
|
||||||
|
// ====================================================================================================================
|
||||||
|
// ====================================================================================================================
|
||||||
|
finline static uint32_t xs_CRoundToUInt(real64 val)
|
||||||
|
{
|
||||||
|
return (uint32_t)xs_CRoundToInt(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
finline static uint32_t xs_FloorToUInt(real64 val)
|
||||||
|
{
|
||||||
|
return (uint32_t)xs_FloorToInt(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
finline static uint32_t xs_CeilToUInt(real64 val)
|
||||||
|
{
|
||||||
|
return (uint32_t)xs_CeilToInt(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
finline static uint32_t xs_RoundToUInt(real64 val)
|
||||||
|
{
|
||||||
|
return (uint32_t)xs_RoundToInt(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
// ====================================================================================================================
|
||||||
|
#endif // _xs_FLOAT_H_
|
|
@ -43,6 +43,8 @@
|
||||||
#include "w_wad.h"
|
#include "w_wad.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
|
#include "doomtype.h"
|
||||||
|
#include "i_musicinterns.h"
|
||||||
|
|
||||||
#define IMF_RATE 700.0
|
#define IMF_RATE 700.0
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#pragma once
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "musicblock.h"
|
#include "musicblock.h"
|
||||||
|
|
||||||
|
|
|
@ -24,13 +24,13 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <algorithm>
|
||||||
#include "genmidi.h"
|
#include "genmidi.h"
|
||||||
#include "oplio.h"
|
#include "oplio.h"
|
||||||
#include "opl.h"
|
#include "opl.h"
|
||||||
#include "c_cvars.h"
|
|
||||||
#include "templates.h"
|
|
||||||
|
|
||||||
const double HALF_PI = (M_PI*0.5);
|
const double HALF_PI = (3.14159265358979323846 * 0.5);
|
||||||
|
|
||||||
OPLio::~OPLio()
|
OPLio::~OPLio()
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,7 @@ void OPLio::WriteDelay(int ticks)
|
||||||
|
|
||||||
int OPLio::Init(int core, uint32_t numchips, bool stereo, bool initopl3)
|
int OPLio::Init(int core, uint32_t numchips, bool stereo, bool initopl3)
|
||||||
{
|
{
|
||||||
assert(numchips >= 1 && numchips <= countof(chips));
|
assert(numchips >= 1 && numchips <= OPL_NUM_VOICES);
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
IsOPL3 = (core == 1 || core == 2 || core == 3);
|
IsOPL3 = (core == 1 || core == 2 || core == 3);
|
||||||
|
|
||||||
|
@ -113,12 +113,12 @@ void OPLio::WriteInitState(bool initopl3)
|
||||||
|
|
||||||
void OPLio::Reset(void)
|
void OPLio::Reset(void)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < countof(chips); ++i)
|
for (auto &c : chips)
|
||||||
{
|
{
|
||||||
if (chips[i] != NULL)
|
if (c != nullptr)
|
||||||
{
|
{
|
||||||
delete chips[i];
|
delete c;
|
||||||
chips[i] = NULL;
|
c = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,7 @@ void OPLio::WriteVolume(uint32_t channel, struct GenMidiVoice *voice, uint32_t v
|
||||||
{
|
{
|
||||||
if (voice != nullptr)
|
if (voice != nullptr)
|
||||||
{
|
{
|
||||||
uint32_t full_volume = volumetable[MIN<uint32_t>(127, (uint32_t)((uint64_t)vol1*vol2*vol3) / (127 * 127))];
|
uint32_t full_volume = volumetable[std::min<uint32_t>(127, (uint32_t)((uint64_t)vol1*vol2*vol3) / (127 * 127))];
|
||||||
int reg_volume2 = ((0x3f - voice->carrier.level) * full_volume) / 128;
|
int reg_volume2 = ((0x3f - voice->carrier.level) * full_volume) / 128;
|
||||||
reg_volume2 = (0x3f - reg_volume2) | voice->carrier.scale;
|
reg_volume2 = (0x3f - reg_volume2) | voice->carrier.scale;
|
||||||
WriteOperator(OPL_REGS_LEVEL, channel, 1, reg_volume2);
|
WriteOperator(OPL_REGS_LEVEL, channel, 1, reg_volume2);
|
||||||
|
|
|
@ -84,18 +84,6 @@ struct OPLio
|
||||||
bool IsOPL3;
|
bool IsOPL3;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DiskWriterIO : public OPLio
|
|
||||||
{
|
|
||||||
DiskWriterIO(const char *filename);
|
|
||||||
~DiskWriterIO();
|
|
||||||
|
|
||||||
int Init(uint32_t numchips, bool notused, bool initopl3);
|
|
||||||
void SetClockRate(double samples_per_tick);
|
|
||||||
void WriteDelay(int ticks);
|
|
||||||
|
|
||||||
FString Filename;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OPLChannel
|
struct OPLChannel
|
||||||
{
|
{
|
||||||
uint32_t Instrument;
|
uint32_t Instrument;
|
||||||
|
|
Loading…
Reference in a new issue