aboutsummaryrefslogtreecommitdiff
path: root/src/chips/dosbox/dbopl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/chips/dosbox/dbopl.cpp')
-rw-r--r--src/chips/dosbox/dbopl.cpp143
1 files changed, 112 insertions, 31 deletions
diff --git a/src/chips/dosbox/dbopl.cpp b/src/chips/dosbox/dbopl.cpp
index 4eb79f8..2d31708 100644
--- a/src/chips/dosbox/dbopl.cpp
+++ b/src/chips/dosbox/dbopl.cpp
@@ -37,6 +37,7 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
+#include <vector>
#include "dbopl.h"
#if defined(__GNUC__) && __GNUC__ > 3
@@ -70,6 +71,36 @@
#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() : m(PTHREAD_MUTEX_INITIALIZER) {}
+ 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;
+};
+#endif
+struct MutexHolder : NoCopy {
+ explicit MutexHolder(Mutex &m) : m(m) { m.lock(); }
+ ~MutexHolder() { m.unlock(); }
+ Mutex &m;
+};
+
namespace DBOPL {
#define OPLRATE ((double)(14318180.0 / 288.0))
@@ -222,24 +253,24 @@ static const Bit8u KslShiftTable[4] = {
// Pan law table
static const Bit16u PanLawTable[] =
{
- 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
+ 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
};
//Generate a table index and table shift value using input value from a selected rate
@@ -465,7 +496,7 @@ Bits Operator::TemplateVolume( ) {
return vol;
}
//In sustain phase, but not sustaining, do regular release
- /* fall through */
+ /* fall through */
case RELEASE:
vol += RateForward( releaseAdd );;
if ( GCC_UNLIKELY(vol >= ENV_MAX) ) {
@@ -1294,21 +1325,40 @@ void Chip::GenerateBlock3_Mix( Bitu total, Bit32s* output ) {
}
}
-void Chip::Setup( Bit32u rate ) {
+struct CacheEntry {
+ Bit32u rate;
+ Bit32u freqMul[16];
+ Bit32u linearRates[76];
+ Bit32u attackRates[76];
+};
+static std::vector<CacheEntry> cache;
+static Mutex cacheMutex;
+
+static const CacheEntry *CacheLookupRateDependent( Bit32u rate )
+{
+ for ( size_t i = 0, n = cache.size(); i < n; ++i ) {
+ if (cache[i].rate == rate)
+ return &cache[i];
+ }
+ return NULL;
+}
+
+static const CacheEntry &ComputeRateDependent( Bit32u rate )
+{
+ {
+ MutexHolder lock( cacheMutex );
+ if (const CacheEntry *entry = CacheLookupRateDependent( rate ))
+ return *entry;
+ }
+
double original = OPLRATE;
-// double original = rate;
double scale = original / (double)rate;
- //Noise counter is run at the same precision as general waves
- noiseAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
- noiseCounter = 0;
- noiseValue = 1; //Make sure it triggers the noise xor the first time
- //The low frequency oscillation counter
- //Every time his overflows vibrato and tremoloindex are increased
- lfoAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
- lfoCounter = 0;
- vibratoIndex = 0;
- tremoloIndex = 0;
+ CacheEntry entry;
+ entry.rate = rate;
+ Bit32u *freqMul = entry.freqMul;
+ Bit32u *linearRates = entry.linearRates;
+ Bit32u *attackRates = entry.attackRates;
//With higher octave this gets shifted up
//-1 since the freqCreateTable = *2
@@ -1330,6 +1380,7 @@ void Chip::Setup( Bit32u rate ) {
EnvelopeSelect( i, index, shift );
linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 )));
}
+
// Bit32s attackDiffs[62];
//Generate the best matching attack rate
for ( Bit8u i = 0; i < 62; i++ ) {
@@ -1382,6 +1433,36 @@ void Chip::Setup( Bit32u rate ) {
//This should provide instant volume maximizing
attackRates[i] = 8 << RATE_SH;
}
+
+ MutexHolder lock( cacheMutex );
+ if (const CacheEntry *entry = CacheLookupRateDependent( rate ))
+ return *entry;
+
+ cache.push_back(entry);
+ return cache.back();
+}
+
+void Chip::Setup( Bit32u rate ) {
+ double original = OPLRATE;
+// double original = rate;
+ double scale = original / (double)rate;
+
+ //Noise counter is run at the same precision as general waves
+ noiseAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
+ noiseCounter = 0;
+ noiseValue = 1; //Make sure it triggers the noise xor the first time
+ //The low frequency oscillation counter
+ //Every time his overflows vibrato and tremoloindex are increased
+ lfoAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
+ lfoCounter = 0;
+ vibratoIndex = 0;
+ tremoloIndex = 0;
+
+ const CacheEntry &entry = ComputeRateDependent( rate );
+ freqMul = entry.freqMul;
+ linearRates = entry.linearRates;
+ attackRates = entry.attackRates;
+
//Setup the channels with the correct four op flags
//Channels are accessed through a table so they appear linear here
chan[ 0].fourMask = 0x00 | ( 1 << 0 );